Skip to content

Weaken the closure parameters in calls using rust-call #46

@coord-e

Description

@coord-e

4e2836c

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions