Проверка утверждения о том, что что-то не должно компилироваться

Проблема

Когда я работаю с библиотеками, которые поддерживают программирование на уровне типов, я часто пишу комментарии, подобные следующим (изпример представленныйПол Снайвли на Странной Петле 2012):

// But these invalid sequences don't compile:
// isValid(_3 :: _1 :: _5 :: _8 :: _8 :: _2 :: _8 :: _6 :: _5 :: HNil)
// isValid(_3 :: _4 :: _5 :: _8 :: _8 :: _2 :: _8 :: _6 :: HNil)

Или это изпример вбесформенный репозиторий:

/**
 * If we wanted to confirm that the list uniquely contains `Foo` or any
 * subtype of `Foo`, we could first use `unifySubtypes` to upcast any
 * subtypes of `Foo` in the list to `Foo`.
 *
 * The following would not compile, for example:
 */
 //stuff.unifySubtypes[Foo].unique[Foo]

Это очень грубый способ указать на некоторые факты о поведении этих методов, и мы можем представить, что хотим сделать эти утверждения более формальными - для модульного или регрессионного тестирования и т. Д.

Чтобы привести конкретный пример того, почему это может быть полезно в контексте такой библиотеки, как Shapeless, несколько дней назад я написал следующее в качестве быстрой первой попытки ответа наэтот вопрос:

import shapeless._

implicit class Uniqueable[L <: HList](l: L) {
  def unique[A](implicit ev: FilterAux[L, A, A :: HNil]) = ev(l).head
}

Где предполагается, что это скомпилируется:

('a' :: 'b :: HNil).unique[Char]

Пока этого не будет

('a' :: 'b' :: HNil).unique[Char]

Я был удивлен, обнаружив, что эта реализация уровня типаunique заHList не работает, потому что Shapeless с удовольствием найдетFilterAux экземпляр в последнем случае. Другими словами, следующее будет компилироваться, даже если вы, вероятно, ожидаете, что это не так:

implicitly[FilterAux[Char :: Char :: HNil, Char, Char :: HNil]]

В этом случае то, что я видел, былоЖук- или, по крайней мере, что-то ошибочное - и этос тех пор был исправлен.

В более общем смысле, мы можем представить, что хотим проверить вид инварианта, который подразумевался в моих ожиданиях о том, какFilterAux должен работать с чем-то вроде модульного теста - как бы странно это ни звучало, если говорить о тестировании кода на уровне типа, подобного этому, со всеми недавними дебатами об относительной значимости типовпротив тесты.

Мой вопрос

Проблема в том, что я не знаю какой-либо среды тестирования (для любой платформы), которая позволяет программисту утверждать, что что-то не должнокомпилировать.

Один подход, который я могу представить дляFilterAux дело будет использовать старыйтрюк неявного аргумента с нулевым значением по умолчанию:

def assertNoInstanceOf[T](implicit instance: T = null) = assert(instance == null)

Что позволит вам написать следующее в вашем модульном тесте:

assertNoInstanceOf[FilterAux[Char :: Char :: HNil, Char, Char :: HNil]]

Следующее будет чертовски намного более удобным и выразительным, хотя:

assertDoesntCompile(('a' :: 'b' :: HNil).unique[Char])

Я хочу этот. Мой вопрос заключается в том, знает ли кто-нибудь о какой-либо библиотеке тестирования или фреймворке, который поддерживает что-либо вроде этого удаленно - в идеале для Scala, но я согласен на все.

Ответы на вопрос(5)

Ваш ответ на вопрос