Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What types are special to the Scala compiler?

Tags:

scala

Scala makes a big deal about how what seem to be language features are implemented as library features.

Is there a list of types that are treated specially by the language?

Either in the specification or as an implementation detail?

That would include, for example, optimizing away matches on tuples.

What about special conventions related to pattern matching, for comprehensions, try-catch blocks and other language constructs?

Is String somehow special to the compiler? I see that String enhancement is just a library implicit conversion, and that String concatenation is supported by Predef, but is that somehow special-cased by the language?

Similarly, I see questions about <:< and classOf and asInstanceOf, and it's not clear what is a magical intrinsic. Is there a way to tell the difference, either with a compiler option or by looking at byte code?

I would like to understand if a feature is supported uniformly by implementations such as Scala.JS and Scala-native, or if a feature might actually prove to be implementation-dependent, depending on the library implementation.

like image 245
som-snytt Avatar asked Oct 16 '16 22:10

som-snytt


People also ask

Which compiler is used in Scala?

Scala Native is a Scala compiler that targets the LLVM compiler infrastructure to create executable code that uses a lightweight managed runtime, which uses the Boehm garbage collector.

What language is the Scala compiler written in?

Scala is [now] written in Scala. This process (of creating a language/compiler that can be used to build itself) is known as "bootstrapping".

Is Scala compiled or interpreted?

Scala gives you an illusion of an interpreted language. But actually it is a compiled language, wherein everything you type gets compiled to the byte code and it runs within the JVM.

What is a plugin in Scala?

A compiler plugin is a compiler component that lives in a separate JAR file from the main compiler. The compiler can then load that plugin and gain extra functionality. This tutorial briefly walks you through writing a plugin for the Scala compiler.


1 Answers

There is an incredible amount of types that are "known" of the compiler, and are special to varying degrees. You can find a complete list in scalac's Definitions.scala.

We can probably classify them according to the degree of specialness they bear.

Disclaimer: I have probably forgotten a few more.

Special for the type system

The following types are crucial to Scala's type system. They have an influence on how type checking itself is performed. All these types are mentioned in the specification (or at least, they definitely should be).

  • Any, AnyRef, AnyVal, Null, Nothing: the five types that sit at the top and bottom of Scala's type system.
  • scala.FunctionN, the (canonical) type given of anonymous functions (including eta-expansion). Even in 2.12, which has the SAM treatment of anonymous functions, FunctionN remains special in some cases (notably in overloading resolution).
  • scala.PartialFunction (has an impact on how type inference works)
  • Unit
  • All types with literal notation: Int, Long, Float, Double, Char, Boolean, String, Symbol, java.lang.Class
  • All numeric primitive types and Chars, for weak conformance (together, these two bullets cover all primitive types)
  • Option and tuples (for pattern matching and auto-tupling)
  • java.lang.Throwable
  • scala.Dynamic
  • scala.Singleton
  • Most of scala.reflect.*, in particular ClassTag, TypeTag, etc.
  • scala.annotation.{,ClassFile,Static}Annotation
  • Almost all of the annotations in scala.annotation.* (e.g., unchecked)
  • scala.language.*
  • scala.math.ScalaNumber (for obscure reasons)

Known to the compiler as the desugaring of some language features

The following types are not crucial to the type system. They do not have an influence on type checking. However, the Scala language does feature a number of constructs which desugar into expressions of those types.

These types would also be mentioned in the specification.

  • scala.collection.Seq, Nil and WrappedArray, which are used for varargs parameters.
  • TupleN types
  • Product and Serializable (for case classes)
  • MatchError, generated by pattern matching constructs
  • scala.xml.*
  • scala.DelayedInit
  • List (the compiler performs some trivial optimizations on those, such as rewriting List() as Nil)

Known to the implementation of the language

This is probably the list that you care most about, given that you said you were interested in knowing what could go differently on different back-ends. The previous categories are handled by early (front-end) phases of the compiler, and are therefore shared by Scala/JVM, Scala.js and Scala Native. This category is typically known of the compiler back-end, and so potentially have different treatments. Note that both Scala.js and Scala Native do try to mimic the semantics of Scala/JVM to a reasonable degree.

Those types might not be mentioned in the language specification per se, at least not all of them.

Here are those where the back-ends agree (re Scala Native, to the best of my knowledge):

  • All primitive types: Boolean, Char, Byte, Short, Int, Long, Float, Double, Unit.
  • scala.Array.
  • Cloneable (currently not supported in Scala Native, see #334)
  • String and StringBuilder (mostly for string concatenation)
  • Object, for virtually all its methods

And here are those where they disagree:

  • Boxed versions of primitive types (such as java.lang.Integer)
  • Serializable
  • java.rmi.Remote and java.rmi.RemoteException
  • Some the annotations in scala.annotation.* (e.g., strictfp)
  • Some stuff in java.lang.reflect.*, used by Scala/JVM to implement structural types

Also, although not types per se, but a long list of primitive methods are also handled specifically by the back-ends.

Platform-specific types

In addition to the types mentioned above, which are available on all platforms, non-JVM platforms add their own special types for interoperability purposes.

Scala.js-specific types

See JSDefinitions.scala

  • js.Any: conceptually a third subtype of Any, besides AnyVal and AnyRef. They have JavaScript semantics instead of Scala semantics.
  • String and the boxed versions of all primitive types (heavily rewritten--so-called "hijacked"--by the compiler)
  • js.ThisFunctionN: their apply methods behave differently than that of other JavaScript types (the first actual argument becomes the thisArgument of the called function)
  • js.UndefOr and js.| (they behave as JS types even though they do not extend js.Any)
  • js.Object (new js.Object() is special-cased as an empty JS object literal {})
  • js.JavaScriptException (behaves very specially in throw and catch)
  • js.WrappedArray (used by the desugaring of varargs)
  • js.ConstructorTag (similar to ClassTag)
  • The annotation js.native, and all annotations in js.annotation.*

Plus, a dozen more primitive methods.

Scala Native-specific types

See NirDefinitions.scala

  • Unsigned integers: UByte, UShort, UInt and ULong
  • Ptr, the pointer type
  • FunctionPtrN, the function pointer types
  • The annotations in native.*
  • A number of extra primitive methods in scala.scalanative.runtime
like image 101
sjrd Avatar answered Sep 23 '22 01:09

sjrd