How about adding an attribute “should not pass borrow checker”?


#1

The attribute #[should_not_pass_borrow_checker] is analogy to #[should_panic] for test functions, but it checks the correctness of lifetime bounds.


#2

The implementation of the borrow checker is already thoroughly tested. Why would you need this?


#3

One reason that I’ve used the crates version of compile-test for is checking that lifetime bounds are behaving as you expect and prohibiting misuse of your code (where the internals are unsafe).

The most complicated use I’ve done is with an interner that gave out &str to members on an append-only HashSet<String>. I needed to make sure that the lifetimes given were bound correctly when I conjured them from thin air.

(To gloss over details, I had a StringInterner(&'a mut HashSet<String> and fn StringInterner(&self, &str) -> &'a str. This required unsafe to implement and I was checking that the lifetime did guarantee what I wanted it to (and the first few iterations didn’t).)


#4

You can set compile_fail attribute to your doc test.


#5

I have no doubt about the soundness of the borrow checker. Quite the opposite, I rely on it to check the soundness of my library which is implemented in unsafe code and use lifetime bounds in public interface to prevent the library user from misuse. However thanks for your link, I will read those code later.


#6

That does help. But it is not specified with borrow check errors, and applicable only for doc test.


#7

I don’t know of a reason why compile-fail should only exist for doctests, and it’s easy to imagine APIs where you’d want to verify that invalid client code fails in type checking or const eval or whatever instead of the borrow checker. There’s probably a backwards compatibility risk with making compile-fail detect overly specific kinds of compilation failure, but I think we can postpone that question.

I guess we need some compiler people to answer whether there is a serious obstacle to supporting compile-fail on regular non-doc tests. I imagine we’d have to require all tests at least parse successfully or else you wouldn’t even know what the tests are, but that seems fine. Macros could get weird though; we’d definitely want to write tests verifying that some invocations of my macro fail to compile.


#8

Well, the compilation model makes it easy for doctests and hard for #[test]s. It feels weird to spend effort making rustc capable of still running code after having an error.

And there’s a ton of corner cases here. If you fail to compile because overlapping impls, what impls are available in typechecking? If you mark a function as #[compile_fail], what happens to something that was trying to call it? What if that things trying to call it was also marked #[compile_fail]?


#9

You can use the compiletest crate to setup tests like the compiler’s tests, including compilation failures, and specifying the error messages that should be thrown, and where they should be thrown at.

It does require a little setup and separate files per tests, but it is usable.