I am looking into implementing this. That lint pass basically has to be implemented on MIR, so it seems I cannot use the normal lint pass infrastructure. I figured I'd follow unsafety checking, which also is on the MIR, but I cannot even properly figure out how that is invoked... it's a query, so everything is very indirect. The only call to the query is in a function called
mir_const which I assume is for consts only. I am a bit lost here. Also I am not sure if adding a new query for my lint is really appropriate, but I'd rather not make this part of unsafety checking which is critical code and already too complicated.
oh, found some docs which seems to indicate that
mir_const is not just for consts. That's... a very confusingly chosen name.
so I could just call that lint directly from
mir_const after unsafety checking, I guess?
clippy has MIR lints
basically a lint that is run on all functions and processes them
but yea, in rustc we can just create a
MirPass that doesn't modify anything
There's also the
unconditional_recursion lint, which is run right after MIR building. See https://github.com/rust-lang/rust/blob/master/src/librustc_mir_build/lints.rs
There's also the
unconditional_recursionlint, which is run right after MIR building. See https://github.com/rust-lang/rust/blob/master/src/librustc_mir_build/lints.rs
interesting. so we have unsafety checking,
unconditional_recursion and now my proposed https://github.com/rust-lang/rust/pull/72270 basically all being MIR lint passes and using entirely different infrastructures...
I mean... it makes some sense, right?
At least having Clippy vs rustc to check for correctness, I think, makes sense for the sake of compile times
Like maybe you have a check in Clippy that is somewhat costly to run all the time
Now, with regards to mir lints existing at different stages of rustc... that's really intriguing. I'd guess it makes sense if we, say, can run a certain lint with less difficulty at the beginning of the MIR stage and can run another one with less difficulty at the end or middle of the MIR stage
Sometimes there are checks that are obvious once you look at the optimized MIR, like some code that's rejected because upon constant propagation + folding, the compiler realizes that a code assertion is being invalidated (like when dividing by 0)
I dunno. It's interesting tho :3
I didn't know there was more than one part inside the compiler where MIR lints were issued
the three passes (unsafety checking is not a lint but a lot like it -- it doesnt modify MIR) run on basically the same MIR -- just before initial construction, just after initial construction, and just a bit after that. I don't immediately see any good reason for that. but then unsafety checking is a query and I do not understand why it should be, so there might be stuff I am missing.
I looked at unsafety checking today for #72394 and I don't see a good reason for it to be a query. The query is used to bundle up all the unsafety violations for closures and generators so that it can apply
unsafe blocks from the parent item. However, I think we can assume that there is only one
DefId. If that's true, we can simply recurse when we see it instead of storing the results in the query table.
I suppose the downside is that unsafety checking would depend on
mir_built for both the parent item and the closure, whereas it only depends on
unsafety_check_result for the closure today.