Skip to content

Mapping to black_box crashes compiler #98299

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

Closed
SUPERCILEX opened this issue Jun 20, 2022 · 5 comments · Fixed by #98329
Closed

Mapping to black_box crashes compiler #98299

SUPERCILEX opened this issue Jun 20, 2022 · 5 comments · Fixed by #98329
Assignees
Labels
C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ P-medium Medium priority regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@SUPERCILEX
Copy link
Contributor

Code

https://godbolt.org/z/fhv5voE5E

#![feature(core_intrinsics)]
#![feature(untagged_unions)]
#![feature(bench_black_box)]

use std::convert::{TryFrom, TryInto};
use std::error::Error;
use std::ffi::{CStr, CString};
use std::mem::{ManuallyDrop, MaybeUninit};
use std::ops::Deref;
use std::path::Path;
use std::slice;
use std::{io, mem, ptr};
use std::os::unix::ffi::OsStrExt;
use std::hint::black_box;

fn test_usage(p: &Path) {
    SmallCString::try_from(p).map(|cstr| black_box(cstr));
}

// Make sure to stay under 4096 so the compiler doesn't insert a probe frame:
// https://docs.rs/compiler_builtins/latest/compiler_builtins/probestack/index.html
#[cfg(not(target_os = "espidf"))]
const MAX_STACK_ALLOCATION: usize = 384;
#[cfg(target_os = "espidf")]
const MAX_STACK_ALLOCATION: usize = 32;

union Data<const N: usize> {
    stack: MaybeUninit<[u8; N]>,
    heap: ManuallyDrop<CString>,
}

#[derive(Debug)]
pub struct UnexpectedNulError {}

impl<E: Error> From<E> for UnexpectedNulError {
    fn from(_: E) -> Self {
        UnexpectedNulError {}
    }
}

impl From<UnexpectedNulError> for io::Error {
    fn from(_: UnexpectedNulError) -> Self {
        todo!()
    }
}

/// Fast, immutable CStr view allocated on the stack when possible with a fallback heap allocation.
pub struct SmallCString<const N: usize = MAX_STACK_ALLOCATION> {
    len: usize,
    data: Data<N>,
}

impl<const N: usize> TryFrom<&Path> for SmallCString<N> {
    type Error = UnexpectedNulError;

    fn try_from(path: &Path) -> Result<Self, Self::Error> {
        path.as_os_str().as_bytes().try_into()
    }
}

impl<const N: usize> TryFrom<&[u8]> for SmallCString<N> {
    type Error = UnexpectedNulError;

    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
        if bytes.len() >= N {
            return Self::alloc_cstring(bytes);
        }

        // Validate the bytes
        if bytes.iter().any(|b|*b == 0) {
            return Self::invalid_bytes_err();
        }

        let mut buf = MaybeUninit::uninit();
        let buf_ptr = buf.as_mut_ptr() as *mut u8;

        unsafe {
            ptr::copy_nonoverlapping(bytes.as_ptr(), buf_ptr, bytes.len());
            buf_ptr.add(bytes.len()).write(0);
        }

        Ok(SmallCString { data: Data { stack: buf }, len: bytes.len() + 1 })
    }
}

impl<const N: usize> SmallCString<N> {
    #[cold]
    #[inline(never)]
    fn alloc_cstring(bytes: &[u8]) -> Result<SmallCString<N>, UnexpectedNulError> {
        Ok(SmallCString {
            data: Data { heap: ManuallyDrop::new(CString::new(bytes)?) },
            len: bytes.len() + 1,
        })
    }

    #[cold]
    #[inline(never)]
    fn invalid_bytes_err() -> Result<SmallCString<N>, UnexpectedNulError> {
        Err(UnexpectedNulError {})
    }
}

impl Deref for SmallCString {
    type Target = CStr;

    fn deref(&self) -> &Self::Target {
        self.as_ref()
    }
}

impl<const N: usize> AsRef<CStr> for SmallCString<N> {
    fn as_ref(&self) -> &CStr {
        unsafe {
            if self.len <= N {
                let path = slice::from_raw_parts(self.data.stack.as_ptr() as *const u8, self.len);
                // SAFETY: the bytes were validated in ::new with memchr
                CStr::from_bytes_with_nul_unchecked(mem::transmute(path))
            } else {
                self.data.heap.as_c_str()
            }
        }
    }
}

impl<const N: usize> Drop for SmallCString<N> {
    fn drop(&mut self) {
        unsafe {
            if self.len > N {
                ManuallyDrop::drop(&mut self.data.heap)
            }
        }
    }
}

Error output

error: internal compiler error: /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/compiler/rustc_infer/src/infer/nll_relate/mod.rs:665:17: unexpected inference var Const { ty: usize, kind: Infer(Var(_#0c)) }

thread 'rustc' panicked at 'Box<dyn Any>', /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/compiler/rustc_errors/src/lib.rs:1391:9
stack backtrace:
   0:     0x7ffbeacfbfad - std::backtrace_rs::backtrace::libunwind::trace::h72e50fb92da0949e
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x7ffbeacfbfad - std::backtrace_rs::backtrace::trace_unsynchronized::hbae920ae073134bd
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x7ffbeacfbfad - std::sys_common::backtrace::_print_fmt::h75c75895c2dc7a02
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/sys_common/backtrace.rs:66:5
   3:     0x7ffbeacfbfad - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h22f51d8130e18285
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/sys_common/backtrace.rs:45:22
   4:     0x7ffbead57d7c - core::fmt::write::h34460b9cb19018a8
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/core/src/fmt/mod.rs:1196:17
   5:     0x7ffbeaced6d1 - std::io::Write::write_fmt::hdf3a96965a9806fb
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/io/mod.rs:1654:15
   6:     0x7ffbeacfec85 - std::sys_common::backtrace::_print::h1bcfb7d99cf40e04
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/sys_common/backtrace.rs:48:5
   7:     0x7ffbeacfec85 - std::sys_common::backtrace::print::h65fadbbd0f516d99
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/sys_common/backtrace.rs:35:9
   8:     0x7ffbeacfec85 - std::panicking::default_hook::{{closure}}::h20497521a47f65d6
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/panicking.rs:295:22
   9:     0x7ffbeacfe9a6 - std::panicking::default_hook::h9d02598e8fa9348e
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/panicking.rs:314:9
  10:     0x7ffbeb4d7d41 - rustc_driver[5d44a3b446ca22b6]::DEFAULT_HOOK::{closure#0}::{closure#0}
  11:     0x7ffbeacff35a - std::panicking::rust_panic_with_hook::ha09262393f7932d5
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/panicking.rs:702:17
  12:     0x7ffbec5899f1 - std[3d85facbacbebd2b]::panicking::begin_panic::<rustc_errors[3cd36318e3613d20]::ExplicitBug>::{closure#0}
  13:     0x7ffbec5894d6 - std[3d85facbacbebd2b]::sys_common::backtrace::__rust_end_short_backtrace::<std[3d85facbacbebd2b]::panicking::begin_panic<rustc_errors[3cd36318e3613d20]::ExplicitBug>::{closure#0}, !>
  14:     0x7ffbec5005a6 - std[3d85facbacbebd2b]::panicking::begin_panic::<rustc_errors[3cd36318e3613d20]::ExplicitBug>
  15:     0x7ffbec51b2f6 - std[3d85facbacbebd2b]::panic::panic_any::<rustc_errors[3cd36318e3613d20]::ExplicitBug>
  16:     0x7ffbec51b205 - <rustc_errors[3cd36318e3613d20]::HandlerInner>::bug::<&alloc[4ac2d0ae555384fc]::string::String>
  17:     0x7ffbec51af60 - <rustc_errors[3cd36318e3613d20]::Handler>::bug::<&alloc[4ac2d0ae555384fc]::string::String>
  18:     0x7ffbec59866d - rustc_middle[4273fc7dbb432e13]::ty::context::tls::with_opt::<rustc_middle[4273fc7dbb432e13]::util::bug::opt_span_bug_fmt<rustc_span[77aaf738596ebdf0]::span_encoding::Span>::{closure#0}, ()>
  19:     0x7ffbec5987a6 - rustc_middle[4273fc7dbb432e13]::util::bug::opt_span_bug_fmt::<rustc_span[77aaf738596ebdf0]::span_encoding::Span>
  20:     0x7ffbec598723 - rustc_middle[4273fc7dbb432e13]::util::bug::bug_fmt
  21:     0x7ffbeb869f1d - <rustc_infer[3a3407b7085d6b2d]::infer::nll_relate::TypeRelating<rustc_infer[3a3407b7085d6b2d]::infer::canonical::query_response::QueryTypeRelatingDelegate> as rustc_middle[4273fc7dbb432e13]::ty::relate::TypeRelation>::consts
  22:     0x7ffbeb88d14c - <rustc_infer[3a3407b7085d6b2d]::infer::InferCtxt>::instantiate_nll_query_response_and_region_obligations::<alloc[4ac2d0ae555384fc]::vec::Vec<rustc_middle[4273fc7dbb432e13]::traits::query::OutlivesBound>>
  23:     0x7ffbecac2bee - <rustc_infer[3a3407b7085d6b2d]::infer::outlives::env::OutlivesEnvironment as rustc_typeck[51fdd47d43b4ce75]::check::regionck::OutlivesEnvironmentExt>::add_implied_bounds
  24:     0x7ffbecb77e91 - <rustc_typeck[51fdd47d43b4ce75]::check::regionck::RegionCtxt>::visit_fn_body
  25:     0x7ffbecb7bbba - <rustc_typeck[51fdd47d43b4ce75]::check::regionck::RegionCtxt as rustc_hir[a7fd3971f7dac1b2]::intravisit::Visitor>::visit_expr
  26:     0x7ffbecb7a7d9 - <rustc_typeck[51fdd47d43b4ce75]::check::regionck::RegionCtxt as rustc_hir[a7fd3971f7dac1b2]::intravisit::Visitor>::visit_expr
  27:     0x7ffbecb7a4ae - <rustc_typeck[51fdd47d43b4ce75]::check::regionck::RegionCtxt as rustc_hir[a7fd3971f7dac1b2]::intravisit::Visitor>::visit_expr
  28:     0x7ffbecb7823e - <rustc_typeck[51fdd47d43b4ce75]::check::regionck::RegionCtxt>::visit_fn_body
  29:     0x7ffbecb3658f - <rustc_infer[3a3407b7085d6b2d]::infer::InferCtxtBuilder>::enter::<&rustc_middle[4273fc7dbb432e13]::ty::context::TypeckResults, <rustc_typeck[51fdd47d43b4ce75]::check::inherited::InheritedBuilder>::enter<rustc_typeck[51fdd47d43b4ce75]::check::typeck_with_fallback<rustc_typeck[51fdd47d43b4ce75]::check::typeck::{closure#0}>::{closure#1}, &rustc_middle[4273fc7dbb432e13]::ty::context::TypeckResults>::{closure#0}>
  30:     0x7ffbecae09da - rustc_typeck[51fdd47d43b4ce75]::check::typeck
  31:     0x7ffbed0854e4 - rustc_query_system[5d3fbf9a023977e0]::query::plumbing::try_execute_query::<rustc_query_impl[5a39a0883fba8866]::plumbing::QueryCtxt, rustc_query_system[5d3fbf9a023977e0]::query::caches::DefaultCache<rustc_span[77aaf738596ebdf0]::def_id::LocalDefId, &rustc_middle[4273fc7dbb432e13]::ty::context::TypeckResults>>
  32:     0x7ffbed05ba6e - <rustc_query_impl[5a39a0883fba8866]::Queries as rustc_middle[4273fc7dbb432e13]::ty::query::QueryEngine>::typeck
  33:     0x7ffbecae0b6f - rustc_typeck[51fdd47d43b4ce75]::check::typeck
  34:     0x7ffbed0854e4 - rustc_query_system[5d3fbf9a023977e0]::query::plumbing::try_execute_query::<rustc_query_impl[5a39a0883fba8866]::plumbing::QueryCtxt, rustc_query_system[5d3fbf9a023977e0]::query::caches::DefaultCache<rustc_span[77aaf738596ebdf0]::def_id::LocalDefId, &rustc_middle[4273fc7dbb432e13]::ty::context::TypeckResults>>
  35:     0x7ffbed05ba6e - <rustc_query_impl[5a39a0883fba8866]::Queries as rustc_middle[4273fc7dbb432e13]::ty::query::QueryEngine>::typeck
  36:     0x7ffbecb905c8 - <rustc_middle[4273fc7dbb432e13]::hir::map::Map>::par_body_owners::<rustc_typeck[51fdd47d43b4ce75]::check::typeck_item_bodies::{closure#0}>
  37:     0x7ffbed93794c - rustc_typeck[51fdd47d43b4ce75]::check::typeck_item_bodies
  38:     0x7ffbedc2979c - rustc_query_system[5d3fbf9a023977e0]::query::plumbing::try_execute_query::<rustc_query_impl[5a39a0883fba8866]::plumbing::QueryCtxt, rustc_query_system[5d3fbf9a023977e0]::query::caches::DefaultCache<(), ()>>
  39:     0x7ffbedc56271 - rustc_query_system[5d3fbf9a023977e0]::query::plumbing::get_query::<rustc_query_impl[5a39a0883fba8866]::queries::typeck_item_bodies, rustc_query_impl[5a39a0883fba8866]::plumbing::QueryCtxt>
  40:     0x7ffbed972be3 - <rustc_session[eca3025ea6d0d057]::session::Session>::time::<(), rustc_typeck[51fdd47d43b4ce75]::check_crate::{closure#7}>
  41:     0x7ffbed94ef43 - rustc_typeck[51fdd47d43b4ce75]::check_crate
  42:     0x7ffbed6bfdc7 - rustc_interface[60df96b8be8199a0]::passes::analysis
  43:     0x7ffbedc1eccf - rustc_query_system[5d3fbf9a023977e0]::query::plumbing::try_execute_query::<rustc_query_impl[5a39a0883fba8866]::plumbing::QueryCtxt, rustc_query_system[5d3fbf9a023977e0]::query::caches::DefaultCache<(), core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>>>
  44:     0x7ffbedc687ce - rustc_query_system[5d3fbf9a023977e0]::query::plumbing::get_query::<rustc_query_impl[5a39a0883fba8866]::queries::analysis, rustc_query_impl[5a39a0883fba8866]::plumbing::QueryCtxt>
  45:     0x7ffbed6a3a37 - <rustc_interface[60df96b8be8199a0]::passes::QueryContext>::enter::<rustc_driver[5d44a3b446ca22b6]::run_compiler::{closure#1}::{closure#2}::{closure#3}, core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>>
  46:     0x7ffbed68dbff - <rustc_interface[60df96b8be8199a0]::interface::Compiler>::enter::<rustc_driver[5d44a3b446ca22b6]::run_compiler::{closure#1}::{closure#2}, core[9a54cb3e01ba0ce9]::result::Result<core[9a54cb3e01ba0ce9]::option::Option<rustc_interface[60df96b8be8199a0]::queries::Linker>, rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>>
  47:     0x7ffbed6871cf - rustc_span[77aaf738596ebdf0]::with_source_map::<core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>, rustc_interface[60df96b8be8199a0]::interface::create_compiler_and_run<core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>, rustc_driver[5d44a3b446ca22b6]::run_compiler::{closure#1}>::{closure#1}>
  48:     0x7ffbed68ea92 - <scoped_tls[c0f8d1e57fdb1e9d]::ScopedKey<rustc_span[77aaf738596ebdf0]::SessionGlobals>>::set::<rustc_interface[60df96b8be8199a0]::interface::run_compiler<core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>, rustc_driver[5d44a3b446ca22b6]::run_compiler::{closure#1}>::{closure#0}, core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>>
  49:     0x7ffbed6a40bf - std[3d85facbacbebd2b]::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface[60df96b8be8199a0]::util::run_in_thread_pool_with_globals<rustc_interface[60df96b8be8199a0]::interface::run_compiler<core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>, rustc_driver[5d44a3b446ca22b6]::run_compiler::{closure#1}>::{closure#0}, core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>>::{closure#0}, core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>>
  50:     0x7ffbed6a4229 - <<std[3d85facbacbebd2b]::thread::Builder>::spawn_unchecked_<rustc_interface[60df96b8be8199a0]::util::run_in_thread_pool_with_globals<rustc_interface[60df96b8be8199a0]::interface::run_compiler<core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>, rustc_driver[5d44a3b446ca22b6]::run_compiler::{closure#1}>::{closure#0}, core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>>::{closure#0}, core[9a54cb3e01ba0ce9]::result::Result<(), rustc_errors[3cd36318e3613d20]::ErrorGuaranteed>>::{closure#1} as core[9a54cb3e01ba0ce9]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  51:     0x7ffbead09293 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hed131aa6d8ddd60e
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/alloc/src/boxed.rs:1951:9
  52:     0x7ffbead09293 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h5cfd39886a9bb055
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/alloc/src/boxed.rs:1951:9
  53:     0x7ffbead09293 - std::sys::unix::thread::Thread::new::thread_start::h3f6b40ab851a8ecd
                               at /rustc/21e9336fe81a1fce364349bb7a35a0347c369f34/library/std/src/sys/unix/thread.rs:108:17
  54:     0x7ffbeac33609 - start_thread
  55:     0x7ffbeab56163 - clone
  56:                0x0 - <unknown>

note: 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: rustc 1.63.0-nightly (21e9336fe 2022-06-18) running on x86_64-unknown-linux-gnu

note: compiler flags: -C debuginfo=1 -C llvm-args=--x86-asm-syntax=intel --crate-type rlib -C opt-level=3

query stack during panic:
#0 [typeck] type-checking `test_usage`
#1 [typeck] type-checking `test_usage::{closure#0}`
#2 [typeck_item_bodies] type-checking all item bodies
#3 [analysis] running analysis passes on this crate
end of query stack
error: aborting due to previous error

Compiler returned: 101
@SUPERCILEX SUPERCILEX 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 Jun 20, 2022
@SUPERCILEX
Copy link
Contributor Author

Removing .map(|cstr| black_box(cstr)); seems to fix it.

@SNCPlay42
Copy link
Contributor

Reduced, with no nightly features (playground):

use std::convert::TryFrom;

pub fn test_usage(p: ()) {
    SmallCString::try_from(p).map(|cstr| cstr);
}

pub struct SmallCString<const N: usize> {}

impl<const N: usize> TryFrom<()> for SmallCString<N> {
    type Error = ();

    fn try_from(path: ()) -> Result<Self, Self::Error> {
        unimplemented!();
    }
}

Output on stable and beta:

error[E0282]: type annotations needed
 --> <source>:4:31
  |
4 |     SmallCString::try_from(p).map(|cstr| cstr);
  |                               ^^^ cannot infer type for enum `Result<SmallCString<{_: usize}>, ()>`

@rustbot label regression-from-stable-to-nightly

@rustbot rustbot added regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jun 20, 2022
@apiraino
Copy link
Contributor

bisection cc: @oli-obk

searched nightlies: from nightly-2022-01-01 to nightly-2022-06-20
regressed nightly: nightly-2022-06-09
searched commit range: 5435ed6...7466d54
regressed commit: b17e9d7

bisected with cargo-bisect-rustc v0.6.3

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --start=2022-01-01 --regress ice 

@apiraino
Copy link
Contributor

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-medium

@rustbot rustbot added P-medium Medium priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jun 20, 2022
@oli-obk oli-obk self-assigned this Jun 20, 2022
@JohnTitor
Copy link
Member

Another snippet from #98300 (comment):

struct S<const K: usize> {
    xs: Vec<[u8; K]>,
}

impl<const K: usize> S<K> {
    fn f(&self, a: [u8; K], cs: i32) -> S<K> {
        g(a).map(|ws| S{xs: ws.to_vec()})
    }
}

fn main() {}

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. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ P-medium Medium priority regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants