Repository navigation
Weaken the closure parameters in calls using rust-call #46
Copy link
Copy link
Labels
bugSomething isn't workingSomething isn't working
Description
fn apply<F>(f: F) -> i32
where
F: FnMut(i32) -> i32,
{
f(1)
}
fn main() {
let x = 1;
let closure = |y: i32| x + y;
let result = apply(closure);
assert!(result == 2);
}In the example above, the closure only refers to the outer environment via an immutable reference. This results in a MIR function for the closure that takes the environment by immutable reference:
// MIR for `main::{closure#0}` after runtime-optimized
fn main::{closure#0}(_1: &{closure@closure_param_weaken.rs:10:19: 10:27}, _2: i32) -> i32 {
debug y => _2;
debug x => (*((*_1).0: &i32));
let mut _0: i32;
let mut _3: i32;
let mut _4: &i32;
bb0: {
_4 = deref_copy ((*_1).0: &i32);
_3 = (*_4);
_0 = Add(move _3, _2);
return;
}
}However, in apply, the closure f is called via FnMut (call_mut), so it takes &mut even though FnMut::call_mut resolves to main::{closure#0}:
// MIR for `apply` after runtime-optimized
fn apply(_1: F) -> i32 {
debug f => _1;
let mut _0: i32;
let mut _2: &mut F;
let mut _3: (i32,);
bb0: {
_2 = &mut _1;
_3 = (const 1_i32,);
_0 = <F as FnMut<(i32,)>>::call_mut(move _2, move _3) -> [return: bb1, unwind: bb3];
}
bb1: {
drop(_1) -> [return: bb2, unwind continue];
}
bb2: {
return;
}
bb3 (cleanup): {
drop(_1) -> [return: bb4, unwind terminate(cleanup)];
}
bb4 (cleanup): {
resume;
}
}This leads to a type mismatch during subtyping.
thread 'rustc' panicked at src/rty/subtyping.rs:117:18:
inconsistent types: got=&mut (own (&immut int),
), expected=&immut (own (&immut int),
)
stack backtrace:
0: rust_begin_unwind
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/library/std/src/panicking.rs:645:5
1: core::panicking::panic_fmt
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/library/core/src/panicking.rs:72:14
2: <C as thrust::rty::subtyping::Subtyping>::relate_sub_type
at ./src/rty/subtyping.rs:117:18
3: thrust::analyze::basic_block::Analyzer::relate_fn_sub_type
at ./src/analyze/basic_block.rs:155:28
4: thrust::analyze::basic_block::Analyzer::type_call
at ./src/analyze/basic_block.rs:595:27
5: thrust::analyze::basic_block::Analyzer::analyze_terminator_binds
at ./src/analyze/basic_block.rs:785:13
6: thrust::analyze::basic_block::Analyzer::run
at ./src/analyze/basic_block.rs:1129:9
7: thrust::analyze::local_def::Analyzer::analyze_basic_blocks
at ./src/analyze/local_def.rs:683:13
8: thrust::analyze::local_def::Analyzer::run
at ./src/analyze/local_def.rs:816:9
9: thrust::analyze::Analyzer::def_ty_with_args
at ./src/analyze.rs:343:9
10: thrust::analyze::basic_block::Analyzer::type_call
at ./src/analyze/basic_block.rs:582:13
11: thrust::analyze::basic_block::Analyzer::analyze_terminator_binds
at ./src/analyze/basic_block.rs:785:13
12: thrust::analyze::basic_block::Analyzer::run
at ./src/analyze/basic_block.rs:1129:9
13: thrust::analyze::local_def::Analyzer::analyze_basic_blocks
at ./src/analyze/local_def.rs:683:13
14: thrust::analyze::local_def::Analyzer::run
at ./src/analyze/local_def.rs:816:9
15: thrust::analyze::crate_::Analyzer::analyze_local_defs
at ./src/analyze/crate_.rs:135:13
16: thrust::analyze::crate_::Analyzer::run
at ./src/analyze/crate_.rs:240:9
17: <thrust_rustc::CompilerCalls as rustc_driver_impl::Callbacks>::after_analysis::{{closure}}
at ./src/main.rs:54:13
18: rustc_middle::ty::context::GlobalCtxt::enter::{{closure}}
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/compiler/rustc_middle/src/ty/context.rs:649:37
19: rustc_middle::ty::context::tls::enter_context::{{closure}}
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/compiler/rustc_middle/src/ty/context/tls.rs:82:9
20: std::thread::local::LocalKey<T>::try_with
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/library/std/src/thread/local.rs:284:16
21: std::thread::local::LocalKey<T>::with
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/library/std/src/thread/local.rs:260:9
22: rustc_middle::ty::context::tls::enter_context
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/compiler/rustc_middle/src/ty/context/tls.rs:79:9
23: rustc_middle::ty::context::GlobalCtxt::enter
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/compiler/rustc_middle/src/ty/context.rs:649:9
24: rustc_interface::queries::QueryResult<&rustc_middle::ty::context::GlobalCtxt>::enter
at /rustc/9c3ad802d9b9633d60d3a74668eb1be819212d34/compiler/rustc_interface/src/queries.rs:71:9
25: <thrust_rustc::CompilerCalls as rustc_driver_impl::Callbacks>::after_analysis
at ./src/main.rs:51:9
26: rustc_interface::interface::run_compiler::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#0}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
coord-e commentedon Feb 11, 2026
#48 addresses the case mentioned above, but calling an FnMut closure via FnOnce seems to require more work.
The following patch fixes the panics, but it cannot prove the assertion (incompleteness), so further investigation is required.
Weaken closure parameter for FnMut closures called via FnOnce (#120)