If a mock method's expectations aren't satisfied, Mockall will print an error message that, if possible, includes every method argument formatted with Debug::fmt. That's been the case with stable rust ever since #425 . But with nightly rust, when using Mockall's nightly feature, it's been the case for much longer.
The problem is that Mockall actually formats the error message before checking if the mock method call would fail, in MockFunction::desc1. That has two problems:
- It wastes CPU cycles, potentially lots of them if
Debug::fmt is expensive on that object.
- It calls
Debug::fmt on objects where that shouldn't be allowed. That's a problem for implementers of std::io::Read::read, which by contractgentlemen's agreement aren't supposed to read data from their arguments. If the argument is an uninitialized buffer (a common case), then formatting that argument with Debug::fmt could even technically be UB. And Miri will complain about it.
We should fix this problem by changing MockFunction::desc to return a closure which will produce a format string, rather than the format string itself. And ripple that through the stack accordingly.
If a mock method's expectations aren't satisfied, Mockall will print an error message that, if possible, includes every method argument formatted with
Debug::fmt. That's been the case with stable rust ever since #425 . But with nightly rust, when using Mockall'snightlyfeature, it's been the case for much longer.The problem is that Mockall actually formats the error message before checking if the mock method call would fail, in
MockFunction::desc1. That has two problems:Debug::fmtis expensive on that object.Debug::fmton objects where that shouldn't be allowed. That's a problem for implementers ofstd::io::Read::read, which bycontractgentlemen's agreement aren't supposed to read data from their arguments. If the argument is an uninitialized buffer (a common case), then formatting that argument withDebug::fmtcould even technically be UB. And Miri will complain about it.We should fix this problem by changing
MockFunction::descto return a closure which will produce a format string, rather than the format string itself. And ripple that through the stack accordingly.Footnotes
https://github.com/asomers/mockall/blob/aeb460c5aca3f8f38b855cd459d718af265b32fb/mockall_derive/src/mock_function.rs#L632 ↩