Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICE: Ok([Binder { ... } is not fully resolved #116525

Closed
lunarpulse opened this issue Oct 8, 2023 · 7 comments · Fixed by #116663
Closed

ICE: Ok([Binder { ... } is not fully resolved #116525

lunarpulse opened this issue Oct 8, 2023 · 7 comments · Fixed by #116663
Assignees
Labels
C-bug Category: This is a bug. F-async_fn_in_trait Static async fn in traits I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@lunarpulse
Copy link

lunarpulse commented Oct 8, 2023

rustc-ice-2023-10-08T05:52:57.573161602Z-313198.txt

Code

#![macro_use]
#![feature(type_alias_impl_trait)]
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
#![feature(associated_type_bounds)]
use embassy_sync::channel::DynamicSender;

use {
    ector::*,
    embassy_time::{Duration, Timer},
    futures::future::join,
    heapless::Vec,
};

#[derive(Debug)]
pub enum CommandOperator {
    RfTx(u32),
    RfRx(u32),
    RfSleep(bool),
}

#[derive(Debug)]
pub enum ResultOperator {
    RfSuccessBinary(bool),
    RfSuccess(u32),
    RfErrorBinary(bool),
    RfError(u32),
}

async fn test(addr: DynamicAddress<Request<CommandOperator, ResultOperator>>) {
    let led_address = LED.dyn_address();
    let operator_address = OPERATOR.dyn_address();
    let server_address = SERVER.dyn_address();

    operator_address.notify(DeviceState { target_addr: operator_address, report_addr: operator_address, message: PeriperalMessages::Command(PeriperalState::LED(SwitchState::On)) }).await;
    let r = addr.request(CommandOperator::RfRx(42u32)).await;
    println!("Server returned {:#?}", r);
    Timer::after(Duration::from_secs(1)).await;
    let r = addr.request(CommandOperator::RfTx(21u32)).await;
    println!("Server returned {:#?}", r);
    Timer::after(Duration::from_secs(1)).await;
    let r = addr.request(CommandOperator::RfSleep(false)).await;
    println!("Server returned {:#?}", r);
    Timer::after(Duration::from_secs(1)).await;
}

#[embassy_executor::task]
async fn led_task() {
    let led_device = LED.mount(Periperal);
    led_device.await;
}

#[embassy_executor::task]
async fn  operator_task() {
    let operator = OPERATOR.mount(Operator);
    operator.await;
}

static SERVER: ActorContext<Server> = ActorContext::new();
static LED: ActorContext<Periperal> = ActorContext::new();
static OPERATOR: ActorContext<Operator> = ActorContext::new();

#[embassy_executor::main]
async fn main(spawner: embassy_executor::Spawner) {

    let send_spawner = spawner.make_send();
    send_spawner.spawn(led_task()).unwrap();
    send_spawner.spawn(operator_task()).unwrap();

    // Example of request response
    let server_address = SERVER.dyn_address();
    let server = SERVER.mount(Server);

    let test = test(server_address);
    join(server, test).await;
    
}

pub struct Server;

impl Actor for Server {
    type Message = Request<CommandOperator, ResultOperator>;

    async fn on_mount<M>(
        &mut self,
        _: DynamicAddress<Request<CommandOperator, ResultOperator>>,
        mut inbox: M,
    ) -> !
    where
        M: Inbox<Self::Message>,
    {
        println!("Server started!");

        loop {
            let motd = inbox.next().await;
            let result = match motd.as_ref() {
                CommandOperator::RfTx(num) => ResultOperator::RfSuccess(*num),
                CommandOperator::RfRx(num) => ResultOperator::RfErrorBinary(*num > 2),
                CommandOperator::RfSleep(binary) => ResultOperator::RfErrorBinary(*binary),
            };
            motd.reply(result).await;
        }
    }
}

#[derive(Clone, Copy, Ord, Eq, PartialEq, PartialOrd)]
pub enum PeriperalType {
    Led,
    Lora,
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SwitchState {
    On,
    Transiting,
    Off,
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum CommunicatorState {
    Idle,
    Sending,
    Sent,
    Receiving,
    Received,
    Transiting,
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum PeriperalState {
    LED(SwitchState),
    Lora(CommunicatorState),
}

pub struct TargetDeviceState<'a> {
    pub device_type: PeriperalType,
    pub device_state_message: DeviceState<'a>,
}

pub struct Operator;

impl<'a> Actor for Operator {
    type Message = DeviceState<'a>;

    async fn on_mount<M>(&mut self, _: DynamicAddress<Self::Message>, mut inbox: M) -> !
    where
        M: Inbox<Self::Message>,
    {
        // init queue vector
        let mut in_progress: Vec<TargetDeviceState, 10> = Vec::new();
        println!("Operator started!");

        loop {
            // check inbox
            let request_pending = inbox.next().await;

            // process the message
            let device_type = match request_pending.message {
                PeriperalMessages::Command(msg) | PeriperalMessages::Result(msg) => match msg {
                    PeriperalState::LED(_) => PeriperalType::Led,
                    PeriperalState::Lora(_) => PeriperalType::Lora,
                },
            };

            // command to periperal
            match request_pending.message {
                PeriperalMessages::Command(command) => {
                    // send it to the periperal if not existing in the in_progress
                    // check if the type of the device_type already used in the in_progress vector

                    if let Ok(index) =
                        in_progress.binary_search_by_key(&device_type, |a| a.device_type)
                    {
                        // if the report device was found in the in_progress with the device_type, then skip it with transiting
                        let registered_target_device =
                            in_progress.get(index).expect("failed to get it unwarpped");

                        let report_progress_message =
                            if let PeriperalState::Lora(_communicator_state) = command {
                                PeriperalState::Lora(CommunicatorState::Transiting)
                            } else {
                                PeriperalState::LED(SwitchState::Transiting)
                            };

                        let report_address =
                            registered_target_device.device_state_message.report_addr;
                        report_address
                            .notify(PeriperalMessages::Command(report_progress_message))
                            .await;
                        continue;
                    } else {
                        // not registered send the command message to the target address
                        let target_address = request_pending.target_addr;

                        // find the periperal from the context address vector pair or target
                        target_address
                            .notify(PeriperalMessages::Command(command))
                            .await;

                        let target_device_state = TargetDeviceState {
                            device_type,
                            device_state_message: DeviceState {
                                target_addr: request_pending.target_addr,
                                report_addr: request_pending.report_addr,
                                message: PeriperalMessages::Result(command),
                            },
                        };
                        // register to the report structure
                        let _ = in_progress.push(target_device_state);
                    }
                }
                PeriperalMessages::Result(result) => {
                    // send it to the periperal if not existing in the in_progress
                    // check if the type of the device_type already used in the in_progress vector

                    if let Ok(index) =
                        in_progress.binary_search_by_key(&device_type, |a| a.device_type)
                    {
                        // if it is a result, report back and pop it from the vector
                        let registered_target_device =
                            in_progress.get(index).expect("failed to get it unwarpped");

                        // check if report device type equals to the mesge result type.
                        registered_target_device
                            .device_state_message
                            .report_addr
                            .notify(PeriperalMessages::Result(result))
                            .await;

                        in_progress.remove(index);
                        continue;
                        // if it is a command then send it back to the caller that it is still in progress
                    } else {
                        // not registered result came from the potentially from the peripherals and what should we do?
                        // log error?
                        continue;
                    }
                }
            };
        }
    }
}

#[derive(Clone, Copy)]
pub struct DeviceState<'a> {
    pub target_addr: DynamicSender<'a, PeriperalMessages>,
    pub report_addr: DynamicSender<'a, PeriperalMessages>,
    pub message: PeriperalMessages,
}

#[derive(Clone, Copy)]
pub enum PeriperalMessages {
    Command(PeriperalState),
    Result(PeriperalState),
}

pub struct Periperal;
impl <'a>Actor for Periperal {
    type Message = DeviceState<'a>;

    async fn on_mount<M>(&mut self, _: DynamicAddress<Self::Message>, mut inbox: M) -> !
    where
        M: Inbox<Self::Message>,
    {
        // init queue vector
        println!("Periperal started!");

        loop {
            // check inbox
            let device_sate_message = inbox.next().await;

            // process the message
            println!("led transitiing");
            device_sate_message
                .report_addr
                .notify(PeriperalMessages::Result(PeriperalState::LED(
                    SwitchState::Transiting,
                )))
                .await;

            // register to the report structure
            match device_sate_message.message {
                PeriperalMessages::Command(target_state) => match target_state {
                    PeriperalState::LED(target_led_state) => match target_led_state {
                        SwitchState::On => {
                            println!("led on");
                            // led on here
                            device_sate_message
                                .report_addr
                                .notify(PeriperalMessages::Result(PeriperalState::LED(
                                    SwitchState::On,
                                )))
                                .await;
                        }
                        SwitchState::Off => {
                            println!("led off");
                            // led off
                            device_sate_message
                                .report_addr
                                .notify(PeriperalMessages::Result(PeriperalState::LED(
                                    SwitchState::Off,
                                )))
                                .await;
                        }
                        _ => continue,
                    },
                    _ => continue,
                },
                _ => continue,
            }
        }
    }
}

Meta

rustc --version --verbose:

rustc 1.73.0-nightly (d06ca0ffa 2023-08-18)
binary: rustc
commit-hash: d06ca0ffaf4ac72732665f99dd9ad962194cd0b3
commit-date: 2023-08-18
host: x86_64-unknown-linux-gnu
release: 1.73.0-nightly
LLVM version: 17.0.0

Error output

   Compiling ector v0.5.0 (/home/lunarpulse/Projects/Rust/RustPatterns/ector/ector)
thread 'rustc' panicked at /rustc/d06ca0ffaf4ac72732665f99dd9ad962194cd0b3/compiler/rustc_infer/src/infer/mod.rs:1381:9:
`Ok([Binder { value: TraitPredicate(<M as ector::Inbox<DeviceState<'_>>>, polarity:Positive), bound_vars: [] }, Binder { value: TraitPredicate(<M as std::marker::Sized>, polarity:Positive), bound_vars: [] }])` is not fully resolved
stack backtrace:
   0: rust_begin_unwind
             at /rustc/d06ca0ffaf4ac72732665f99dd9ad962194cd0b3/library/std/src/panicking.rs:617:5
   1: core::panicking::panic_fmt
             at /rustc/d06ca0ffaf4ac72732665f99dd9ad962194cd0b3/library/core/src/panicking.rs:67:14
   2: rustc_trait_selection::traits::do_normalize_predicates
   3: rustc_trait_selection::traits::normalize_param_env_or_error
      [... omitted 7 frames ...]
   4: rustc_middle::query::plumbing::query_get_at::<rustc_query_system::query::caches::DefaultCache<rustc_span::def_id::DefId, rustc_middle::query::erase::Erased<[u8; 8]>>>
   5: <core::iter::adapters::map::Map<core::iter::adapters::flatten::FlatMap<core::slice::iter::Iter<rustc_span::def_id::DefId>, alloc::vec::Vec<rustc_hir_analysis::constrained_generic_params::Parameter>, rustc_hir_analysis::impl_wf_check::enforce_impl_params_are_constrained::{closure#0}>, <hashbrown::set::HashSet<rustc_hir_analysis::constrained_generic_params::Parameter, core::hash::BuildHasherDefault<rustc_hash::FxHasher>> as core::iter::traits::collect::Extend<rustc_hir_analysis::constrained_generic_params::Parameter>>::extend<core::iter::adapters::flatten::FlatMap<core::slice::iter::Iter<rustc_span::def_id::DefId>, alloc::vec::Vec<rustc_hir_analysis::constrained_generic_params::Parameter>, rustc_hir_analysis::impl_wf_check::enforce_impl_params_are_constrained::{closure#0}>>::{closure#0}> as core::iter::traits::iterator::Iterator>::fold::<(), core::iter::traits::iterator::Iterator::for_each::call<(rustc_hir_analysis::constrained_generic_params::Parameter, ()), <hashbrown::map::HashMap<rustc_hir_analysis::constrained_generic_params::Parameter, (), core::hash::BuildHasherDefault<rustc_hash::FxHasher>> as core::iter::traits::collect::Extend<(rustc_hir_analysis::constrained_generic_params::Parameter, ())>>::extend<core::iter::adapters::map::Map<core::iter::adapters::flatten::FlatMap<core::slice::iter::Iter<rustc_span::def_id::DefId>, alloc::vec::Vec<rustc_hir_analysis::constrained_generic_params::Parameter>, rustc_hir_analysis::impl_wf_check::enforce_impl_params_are_constrained::{closure#0}>, <hashbrown::set::HashSet<rustc_hir_analysis::constrained_generic_params::Parameter, core::hash::BuildHasherDefault<rustc_hash::FxHasher>> as core::iter::traits::collect::Extend<rustc_hir_analysis::constrained_generic_params::Parameter>>::extend<core::iter::adapters::flatten::FlatMap<core::slice::iter::Iter<rustc_span::def_id::DefId>, alloc::vec::Vec<rustc_hir_analysis::constrained_generic_params::Parameter>, rustc_hir_analysis::impl_wf_check::enforce_impl_params_are_constrained::{closure#0}>>::{closure#0}>>::{closure#0}>::{closure#0}>
   6: <hashbrown::map::HashMap<rustc_hir_analysis::constrained_generic_params::Parameter, (), core::hash::BuildHasherDefault<rustc_hash::FxHasher>> as core::iter::traits::collect::Extend<(rustc_hir_analysis::constrained_generic_params::Parameter, ())>>::extend::<core::iter::adapters::map::Map<core::iter::adapters::flatten::FlatMap<core::slice::iter::Iter<rustc_span::def_id::DefId>, alloc::vec::Vec<rustc_hir_analysis::constrained_generic_params::Parameter>, rustc_hir_analysis::impl_wf_check::enforce_impl_params_are_constrained::{closure#0}>, <hashbrown::set::HashSet<rustc_hir_analysis::constrained_generic_params::Parameter, core::hash::BuildHasherDefault<rustc_hash::FxHasher>> as core::iter::traits::collect::Extend<rustc_hir_analysis::constrained_generic_params::Parameter>>::extend<core::iter::adapters::flatten::FlatMap<core::slice::iter::Iter<rustc_span::def_id::DefId>, alloc::vec::Vec<rustc_hir_analysis::constrained_generic_params::Parameter>, rustc_hir_analysis::impl_wf_check::enforce_impl_params_are_constrained::{closure#0}>>::{closure#0}>>
   7: rustc_hir_analysis::impl_wf_check::check_mod_impl_wf
      [... omitted 2 frames ...]
   8: <rustc_middle::hir::map::Map>::for_each_module::<rustc_hir_analysis::check_crate::{closure#2}::{closure#0}::{closure#0}>
   9: rustc_hir_analysis::check_crate
  10: rustc_interface::passes::analysis
      [... omitted 2 frames ...]
  11: <rustc_interface::queries::QueryResult<&rustc_middle::ty::context::GlobalCtxt>>::enter::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#1}::{closure#2}::{closure#6}>
  12: <rustc_interface::interface::Compiler>::enter::<rustc_driver_impl::run_compiler::{closure#1}::{closure#2}, core::result::Result<core::option::Option<rustc_interface::queries::Linker>, rustc_span::ErrorGuaranteed>>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

error: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please attach the file at `/home/lunarpulse/Projects/Rust/RustPatterns/ector/rustc-ice-2023-10-08T05:54:18.194961654Z-313535.txt` to your bug report

note: compiler flags: --crate-type bin -C embed-bitcode=no -C debuginfo=2 -C incremental=[REDACTED]

note: some of the compiler flags provided by cargo are hidden

query stack during panic:
#0 [param_env] computing normalized predicates of `<impl at ector/examples/request.rs:142:1: 142:28>::on_mount`
#1 [type_of] computing type of `<impl at ector/examples/request.rs:142:1: 142:28>::{opaque#0}`
#2 [check_mod_impl_wf] checking that impls are well-formed in top-level module
#3 [analysis] running analysis passes on this crate
end of query stack
there was a panic while trying to force a dep node
try_mark_green dep node stack:
#0 collect_return_position_impl_trait_in_trait_tys(request[6c6f]::{impl#1}::on_mount)
#1 type_of(request[6c6f]::{impl#1}::{opaque#0})
end of try_mark_green dep node stack
error: could not compile `ector` (example "request")
Backtrace

<backtrace>

[rustc-ice-2023-10-08T05:54:18.194961654Z-313535.txt](https://github.com/rust-lang/rust/files/12839880/rustc-ice-2023-10-08T05.54.18.194961654Z-313535.txt) [rustc-ice-2023-10-08T05:54:18.194961654Z-313535.txt](https://github.com/rust-lang/rust/files/12839882/rustc-ice-2023-10-08T05.54.18.194961654Z-313535.txt)
@lunarpulse lunarpulse added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 8, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Oct 8, 2023
@Rageking8
Copy link
Contributor

@rustbot label +E-needs-mcve

@rustbot rustbot added the E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example label Oct 8, 2023
@saethlin saethlin added F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` F-async_fn_in_trait Static async fn in traits and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Oct 8, 2023
@Luk-ESC
Copy link
Contributor

Luk-ESC commented Oct 8, 2023

Minimized to:

#![feature(async_fn_in_trait)]

pub(crate) trait Inbox<M> {
    async fn next(self) -> M;
}

pub(crate) trait Actor: Sized {
    type Message;

    async fn on_mount(self, _: impl Inbox<Self::Message>);
}

impl<'a> Actor for () {
    type Message = &'a ();
    async fn on_mount(self, _: impl Inbox<&'a ()>) {}
}

fn main(){}

@matthiaskrgr
Copy link
Member

might be similar to #103708 , cc @compiler-errors who self-assigned #103708 and probably knows more about this stuff ^^

@matthiaskrgr matthiaskrgr added S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue and removed E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example labels Oct 8, 2023
@compiler-errors compiler-errors self-assigned this Oct 8, 2023
@compiler-errors compiler-errors removed the F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` label Oct 9, 2023
@matthiaskrgr
Copy link
Member

in case we need more code snippets, here are 60 of them that that can trigger the ice in some way or another 🙃
fully_resolved.zip

@compiler-errors
Copy link
Member

@matthiaskrgr I'm pretty sure all (or at least most) of these examples are not related. This issue is specifically the case where the code used to emit:

error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates

and now ICEs. #103708 is unrelated except for the ICE message.

@matthiaskrgr
Copy link
Member

Ah so this (116525) is a new one?
Need to put some though into automatic ice distinction (perhaps based on query stack?)

@compiler-errors
Copy link
Member

Yeah, there's a class of ICEs that have the same name and often very different root causes (i.e. ICEs in snapshot-vec) and this is one of them.

@matthiaskrgr matthiaskrgr changed the title the compiler unexpectedly panicked. this is a bug. ICE: Ok([Binder { ... } is not fully resolved Oct 9, 2023
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Oct 18, 2023
…=lcnr

Don't ICE when encountering unresolved regions in `fully_resolve`

We can encounter unresolved regions due to unconstrained impl lifetime arguments because `collect_return_position_impl_trait_in_trait_tys` runs before WF actually checks that the impl is well-formed.

Fixes rust-lang#116525
@bors bors closed this as completed in 2dd1c8f Oct 19, 2023
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Oct 19, 2023
Rollup merge of rust-lang#116663 - compiler-errors:resolve-regions, r=lcnr

Don't ICE when encountering unresolved regions in `fully_resolve`

We can encounter unresolved regions due to unconstrained impl lifetime arguments because `collect_return_position_impl_trait_in_trait_tys` runs before WF actually checks that the impl is well-formed.

Fixes rust-lang#116525
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. F-async_fn_in_trait Static async fn in traits I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
Development

Successfully merging a pull request may close this issue.

7 participants