Avoiding Type Inference to Nothing

I’m using a technique using a contravariant type class to stop the compiler from implicitly resolving to a Nothing type, based off this blog post.

@implicitNotFound("Nothing was inferred")
sealed trait NotNothing[-T]

object NotNothing {
  implicit object notNothing extends NotNothing[Any]
  //We do not want Nothing to be inferred, so make an ambigous implicit
  implicit object `\n The error is because the type parameter was resolved to Nothing`
      extends NotNothing[Nothing]
}

It seems to work fine, but part of me is wondering if there’s a more elegant solution, and if it’s a reasonable thing to provide a library that makes use of this:

trait Logger {
  // ...
  def semantic[MessageType: NotNothing]: SemanticLogger[MessageType]
}

logger.semantic.info("Will not compile, because message type is nothing")
1 Like

What’s wrong with inferring Nothing?

1 Like

Nothing :slight_smile:

3 Likes

I use wartremover in most of my projects, which is a compiler plugin to catch several types of common problems or disallow certain features. One of the options does exactly this, it gives a compile time error or warning (depending on configuration), if the compiler infers Nothing.

It can’t be used as selectively as your approach, but in my experience, the cases where I want Nothing to be inferred are so rare, that I’d rather add a type annotation there than changing the signature of my types everywhere else.

I’m aware of the WartRemover, but that requires people to add it in their own projects. I haven’t released this library yet, so there’s no cost to me adding this to the method signatures.

Ah, sorry, I misunderstood. I thought your question was if it was reasonable to create a library providing the NotNothing typeclass. So it’s more to make the type argument to semantic mandatory, right?

In that case, I don’t see any downsides to using this, as the client of the library shouldn’t really see a difference except in cases where you don’t want it to compile.