Current syntax of pattern types as used in the standard library

I'm writing some code that walks through Rust code using rust-analyzer's APIs.

My code should be able to walk through the standard library just as well, but that contains a lot of unstable and not public things that I would not have to deal with in common Rust code.

Now I'm trying to wrap my head around the pattern_type!() macro, which I think I understand is a placeholder for the syntax of pattern types where whey will become stable.

I think I've understood the idea of pattern types in general, but then for example in the documentation for std::marker::Freeze trait, I find it is implemented for *const T is !null.

I thought pattern types accepted a pattern on the right. What's !null instead in this case?

1 Like

!null is a "magic" pattern, as in only core can use it, and it is completely made up in the compiler, and as such is not truly comparable to real patterns, but we can still explain how it was thought of :

it behaves as a negative pattern, which is something that does not exist and afaik has no plan to exist in normal code.
an example one could think of with negative patterns would be

match opt  {
     Ok(5) => 7,
     Ok(!5) => 12,
     Err(_) => 3
}

null is ofc a pattern that matches a null pointer, which also does not exist.

it is not currently possible to use !null, null, or any !$pat outside of the standard library, not even on nightly

so !null is a pattern for pointers which are not null. it is a necessary invention, because pointers do not have patterns by default like numbers.

it is unknown wether users will be able to use this pattern when pattern types get stabilized, but even if we do, i strongly doubt we will get things like general negative patterns.

the source of the !null pattern is here Add NonNull pattern types by oli-obk · Pull Request #142339 · rust-lang/rust · GitHub

3 Likes

I see, thanks!

It's sad negative patterns are not planned, they would be useful for forbidding a specific variant of an enum instead of listing all the others!

They'd definitely be useful. They'd need a bunch of care to avoid turning match exhaustiveness checking and "unreachable match arm" linting into Boolean satisfiability problem - Wikipedia though :upside_down_face:

2 Likes

Yes that's true. Maybe restricting the syntax to Horn clauses may help. Is there any open issue on the matter?

Match exhaustiveness is already NP-complete. Compiling Rust is NP-hard

2 Likes

That's cool!