4e2836c
fnapply<F>(f:F) -> i32whereF:FnMut(i32) -> i32,{f(1)}fnmain(){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-optimizedfn main::{closure#0}(_1:&{closure@closure_param_weaken.rs:10:19:10:27},_2:i32) -> i32{
debug y => _2;debug x => (*((*_1).0:&i32));letmut _0:i32;letmut _3:i32;letmut _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-optimizedfnapply(_1:F) -> i32{
debug f => _1;letmut _0:i32;letmut _2:&mutF;letmut _3:(i32,);
bb0:{
_2 = &mut _1;
_3 = (const1_i32,);
_0 = <FasFnMut<(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.
4e2836c
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:
However, in
apply, the closurefis called via FnMut (call_mut), so it takes&muteven though FnMut::call_mut resolves tomain::{closure#0}:This leads to a type mismatch during subtyping.