Description
Specifically, this line of code failed to compile on 1.15.1, but successfully compiles on 1.16: https://github.com/m4b/goblin/blob/8188a8a15017cbdadfdbb807e08db968f1c634c9/src/mach/exports.rs#L94
For context, here is the important snippet:
impl<'a> ExportInfo<'a> {
/// Parse out the export info from `bytes`, at `offset`
pub fn parse(bytes: &'a [u8], libs: &[&'a str], flags: Flag, mut offset: usize) -> error::Result<ExportInfo<'a>> {
use self::ExportInfo::*;
let regular = |offset| -> error::Result<ExportInfo> {
let address = bytes.pread::<Uleb128>(offset)?;
Ok(Regular {
address: address.into(),
flags: flags
})
};
let reexport = |mut offset| -> error::Result<ExportInfo> {
let lib_ordinal: u64 = {
let tmp = bytes.pread::<Uleb128>(offset)?;
offset += tmp.size();
tmp.into()
};
// THIS line has lifetime issues on 1.15
let lib_symbol_name = bytes.pread::<&str>(offset)?;
let lib = libs[lib_ordinal as usize];
let lib_symbol_name = if lib_symbol_name == "" { None } else { Some (lib_symbol_name)};
Ok(Reexport {
lib: lib,
lib_symbol_name: lib_symbol_name,
flags: flags
})
};
So, the fix (for 1.15) is adding explicit lifetime annotation to the closure return (e.g., let reexport = |mut offset| -> error::Result<ExportInfo<'a>>{..}
)
Consequently, it seems that this is an undocumented lifetime elision fix, or substantially less likely, 1.16 incorrectly compiles invalid lifetime code in closures.
I suspect its the former.
So, I dunno why, maybe I'm being an alarmist, but I find this somewhat serious, and fairly annoying; the only reason I upgraded to 1.16 was that I wanted cargo check
for development, but upstream projects using my crate use 1.15 for CI, recommended version, etc; consequently, when 1.16 was released I noted that there were no major compiler fixes in this cycle, or major issues in compatibility notes, etc., which would cause a difference between a client compiling on 1.15 versus 1.16, so it should be safe to develop on 1.16 stable for cargo check; but alas, this is not the case.