diff --git a/src/machine.rs b/src/machine.rs index 61871e745894..91a83a8acf40 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -297,7 +297,8 @@ pub struct Evaluator<'mir, 'tcx> { string_cache: FxHashMap, /// Cache of `Instance` exported under the given `Symbol` name. - pub(crate) exported_symbols_cache: FxHashMap>, + /// `None` means no `Instance` exported under the given name is found. + pub(crate) exported_symbols_cache: FxHashMap>>, /// Whether to raise a panic in the context of the evaluated process when unsupported /// functionality is encountered. If `false`, an error is propagated in the Miri application context diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index f193751518e1..380ddac6c86a 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -135,7 +135,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // If the result was cached, just return it. if let Some(instance) = this.machine.exported_symbols_cache.get(&link_name) { - return Ok(Some(this.load_mir(instance.def, None)?)); + return instance.map(|instance| this.load_mir(instance.def, None)).transpose(); } // Find it if it was not cached. @@ -187,13 +187,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } } + let instance = instance_and_crate.map(|ic| ic.0); // Cache it and load its MIR, if found. - instance_and_crate - .map(|(instance, _)| { - this.machine.exported_symbols_cache.insert(link_name, instance); - this.load_mir(instance.def, None) - }) - .transpose() + this.machine.exported_symbols_cache.insert(link_name, instance); + instance.map(|instance| this.load_mir(instance.def, None)).transpose() } /// Emulates calling a foreign item, failing if the item is not supported. diff --git a/tests/run-pass/function_calls/exported_symbol.rs b/tests/run-pass/function_calls/exported_symbol.rs index c141f557e1d7..58115542332f 100644 --- a/tests/run-pass/function_calls/exported_symbol.rs +++ b/tests/run-pass/function_calls/exported_symbol.rs @@ -20,10 +20,15 @@ fn main() { for _ in 0..3 { extern "C" { fn foo() -> i32; + fn free(_: *mut std::ffi::c_void); } assert_eq!(unsafe { foo() }, -1); + // `free()` is a built-in shim, so calling it will add ("free", None) to the cache. + // Test that the cache is not broken with ("free", None). + unsafe { free(std::ptr::null_mut()) } + extern "Rust" { fn bar() -> i32; fn baz() -> i32;