From a13a3231c76a7af5943391ac34417fed40575446 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 14 Oct 2023 15:48:49 -0400 Subject: [PATCH 01/10] Exit the process instead of deadlocking on panic --- crates/compiler/load_internal/src/file.rs | 76 ++++++++++++++++------- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 4a112656756..d3d70e90784 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -954,7 +954,6 @@ pub enum LoadingProblem<'a> { ParsingFailed(FileError<'a, SyntaxError<'a>>), UnexpectedHeader(String), - MsgChannelDied, ErrJoiningWorkerThreads, TriedToImportAppModule, @@ -964,6 +963,19 @@ pub enum LoadingProblem<'a> { ImportCycle(PathBuf, Vec), IncorrectModuleName(FileError<'a, IncorrectModuleName<'a>>), CouldNotFindCacheDir, + ChannelProblem(ChannelProblem), +} + +#[derive(Debug)] +pub enum ChannelProblem { + FailedToEnqueueTask, + FailedToSendRootMsg, + FailedToSendWorkerShutdownMsg, + ChannelDisconnected, + FailedToSendManyMsg, + FailedToSendFinishedSpecializationsMsg, + FailedToSendTaskMsg, + FailedToSendFinishedTypeCheckingMsg, } pub enum Phases { @@ -984,9 +996,9 @@ fn enqueue_task<'a>( injector.push(task); for listener in listeners { - listener - .send(WorkerMsg::TaskAdded) - .map_err(|_| LoadingProblem::MsgChannelDied)?; + listener.send(WorkerMsg::TaskAdded).map_err(|_| { + LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask) + })?; } Ok(()) @@ -1325,7 +1337,7 @@ pub fn load_single_threaded<'a>( msg_tx .send(root_msg) - .map_err(|_| LoadingProblem::MsgChannelDied)?; + .map_err(|_| LoadingProblem::ChannelProblem(ChannelProblem::FailedToSendRootMsg))?; let number_of_workers = 1; let mut state = State::new( @@ -1575,7 +1587,9 @@ fn state_thread_step<'a>( } Err(err) => match err { crossbeam::channel::TryRecvError::Empty => Ok(ControlFlow::Continue(state)), - crossbeam::channel::TryRecvError::Disconnected => Err(LoadingProblem::MsgChannelDied), + crossbeam::channel::TryRecvError::Disconnected => Err(LoadingProblem::ChannelProblem( + ChannelProblem::ChannelDisconnected, + )), }, } } @@ -1647,7 +1661,7 @@ fn load_multi_threaded<'a>( let (msg_tx, msg_rx) = bounded(1024); msg_tx .send(root_msg) - .map_err(|_| LoadingProblem::MsgChannelDied)?; + .map_err(|_| LoadingProblem::ChannelProblem(ChannelProblem::FailedToSendRootMsg))?; // Reserve one CPU for the main thread, and let all the others be eligible // to spawn workers. @@ -1744,7 +1758,9 @@ fn load_multi_threaded<'a>( ) }); - res_join_handle.unwrap(); + res_join_handle.unwrap_or_else(|_| { + panic!("Join handle panicked!"); + }); } // We've now distributed one worker queue to each thread. @@ -1760,9 +1776,11 @@ fn load_multi_threaded<'a>( macro_rules! shut_down_worker_threads { () => { for listener in worker_listeners { - listener - .send(WorkerMsg::Shutdown) - .map_err(|_| LoadingProblem::MsgChannelDied)?; + listener.send(WorkerMsg::Shutdown).map_err(|_| { + LoadingProblem::ChannelProblem( + ChannelProblem::FailedToSendWorkerShutdownMsg, + ) + })?; } }; } @@ -1788,6 +1806,14 @@ fn load_multi_threaded<'a>( state = new_state; continue; } + Err(LoadingProblem::ChannelProblem(problem)) => { + // Note: shut_down_worker_threads! results in the system + // looping indefinitely (possibly on a deadlock?) when + // we hit one of these problems due to a panic (e.g. in mono). + eprintln!("{:?}", problem); + + std::process::exit(101); + } Err(e) => { shut_down_worker_threads!(); @@ -1843,8 +1869,8 @@ fn worker_task_step<'a>( match result { Ok(()) => {} - Err(LoadingProblem::MsgChannelDied) => { - panic!("Msg channel closed unexpectedly.") + Err(LoadingProblem::ChannelProblem(problem)) => { + panic!("Channel problem: {:?}", problem); } Err(LoadingProblem::ParsingFailed(problem)) => { msg_tx.send(Msg::FailedToParse(problem)).unwrap(); @@ -1942,8 +1968,8 @@ fn worker_task<'a>( match result { Ok(()) => {} - Err(LoadingProblem::MsgChannelDied) => { - panic!("Msg channel closed unexpectedly.") + Err(LoadingProblem::ChannelProblem(problem)) => { + panic!("Channel problem: {:?}", problem); } Err(LoadingProblem::ParsingFailed(problem)) => { msg_tx.send(Msg::FailedToParse(problem)).unwrap(); @@ -2086,9 +2112,9 @@ fn update<'a>( Many(messages) => { // enqueue all these message for msg in messages { - msg_tx - .send(msg) - .map_err(|_| LoadingProblem::MsgChannelDied)?; + msg_tx.send(msg).map_err(|_| { + LoadingProblem::ChannelProblem(ChannelProblem::FailedToSendManyMsg) + })?; } Ok(state) @@ -2552,7 +2578,11 @@ fn update<'a>( #[cfg(debug_assertions)] checkmate, }) - .map_err(|_| LoadingProblem::MsgChannelDied)?; + .map_err(|_| { + LoadingProblem::ChannelProblem( + ChannelProblem::FailedToSendFinishedTypeCheckingMsg, + ) + })?; // bookkeeping state.declarations_by_id.insert(module_id, decls); @@ -2874,7 +2904,11 @@ fn update<'a>( exposed_to_host: state.exposed_to_host.clone(), module_expectations, }) - .map_err(|_| LoadingProblem::MsgChannelDied)?; + .map_err(|_| { + LoadingProblem::ChannelProblem( + ChannelProblem::FailedToSendFinishedSpecializationsMsg, + ) + })?; Ok(state) } @@ -6308,7 +6342,7 @@ fn run_task<'a>( msg_tx .send(msg) - .map_err(|_| LoadingProblem::MsgChannelDied)?; + .map_err(|_| LoadingProblem::ChannelProblem(ChannelProblem::FailedToSendTaskMsg))?; Ok(()) } From 8ee88ba7cb690401e2391d45aec0abb8c8cfee53 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 14 Oct 2023 16:30:01 -0400 Subject: [PATCH 02/10] Minor cleanups --- crates/compiler/load_internal/src/file.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index d3d70e90784..0330896a69e 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -1042,7 +1042,7 @@ pub fn load_and_typecheck_str<'a>( roc_cache_dir, load_config, )? { - Monomorphized(_) => unreachable!(""), + Monomorphized(_) => unreachable!(), TypeChecked(module) => Ok(module), } } @@ -1719,8 +1719,8 @@ fn load_multi_threaded<'a>( // Get a reference to the completed stealers, so we can send that // reference to each worker. (Slices are Sync, but bumpalo Vecs are not.) let stealers = stealers.into_bump_slice(); - let it = worker_arenas.iter_mut(); + { thread::scope(|thread_scope| { let mut worker_listeners = From 97f252c68bdee143b415f48177a52f921b097f04 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 14 Oct 2023 16:37:54 -0400 Subject: [PATCH 03/10] Fix shut_down_worker_threads! in presence of panic --- crates/compiler/load_internal/src/file.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 0330896a69e..f2f12ea6b13 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -1776,11 +1776,13 @@ fn load_multi_threaded<'a>( macro_rules! shut_down_worker_threads { () => { for listener in worker_listeners { - listener.send(WorkerMsg::Shutdown).map_err(|_| { - LoadingProblem::ChannelProblem( - ChannelProblem::FailedToSendWorkerShutdownMsg, - ) - })?; + // We intentionally don't propagate this Result, because even if + // shutting down a worker failed (which can happen if a a panic + // occurred on that thread), we want to continue shutting down + // the others regardless. + if listener.send(WorkerMsg::Shutdown).is_err() { + log!("There was an error trying to shutdown a worker thread. One reason this can happen is if the thread panicked."); + } } }; } From eb135637ef6908778ff82a08a3d831777eb9e07d Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 14 Oct 2023 21:18:42 -0400 Subject: [PATCH 04/10] Compute total_problems rather than asking for it --- crates/compiler/build/src/program.rs | 2 -- crates/compiler/load/build.rs | 1 - crates/compiler/load_internal/src/module.rs | 16 ---------------- crates/reporting/src/cli.rs | 13 +++++++++++-- 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index c8e6fd2496d..ee3a70fb106 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -41,7 +41,6 @@ pub struct CodeGenTiming { pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Problems { report_problems( - loaded.total_problems(), &loaded.sources, &loaded.interns, &mut loaded.can_problems, @@ -51,7 +50,6 @@ pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Proble pub fn report_problems_typechecked(loaded: &mut LoadedModule) -> Problems { report_problems( - loaded.total_problems(), &loaded.sources, &loaded.interns, &mut loaded.can_problems, diff --git a/crates/compiler/load/build.rs b/crates/compiler/load/build.rs index 6655800ad31..bb963c50b48 100644 --- a/crates/compiler/load/build.rs +++ b/crates/compiler/load/build.rs @@ -105,7 +105,6 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path: }; let problems = report_problems( - module.total_problems(), &module.sources, &module.interns, &mut module.can_problems, diff --git a/crates/compiler/load_internal/src/module.rs b/crates/compiler/load_internal/src/module.rs index 089c22a4097..2d5869311c7 100644 --- a/crates/compiler/load_internal/src/module.rs +++ b/crates/compiler/load_internal/src/module.rs @@ -223,22 +223,6 @@ pub struct ExposedToHost { pub getters: Vec, } -impl<'a> MonomorphizedModule<'a> { - pub fn total_problems(&self) -> usize { - let mut total = 0; - - for problems in self.can_problems.values() { - total += problems.len(); - } - - for problems in self.type_problems.values() { - total += problems.len(); - } - - total - } -} - #[derive(Debug)] pub struct ModuleTiming { pub read_roc_file: Duration, diff --git a/crates/reporting/src/cli.rs b/crates/reporting/src/cli.rs index a31533f35fe..433465b6daa 100644 --- a/crates/reporting/src/cli.rs +++ b/crates/reporting/src/cli.rs @@ -46,13 +46,12 @@ impl Problems { 1 => "warning", _ => "warnings", }, - total_time.as_millis(), + total_time.as_millis() ); } } pub fn report_problems( - total_problems: usize, sources: &MutMap)>, interns: &Interns, can_problems: &mut MutMap>, @@ -60,7 +59,17 @@ pub fn report_problems( ) -> Problems { use crate::report::{can_problem, type_problem, Report, RocDocAllocator, DEFAULT_PALETTE}; use roc_problem::Severity::*; + let palette = DEFAULT_PALETTE; + let mut total_problems = 0; + + for problems in can_problems.values() { + total_problems += problems.len(); + } + + for problems in type_problems.values() { + total_problems += problems.len(); + } // This will often over-allocate total memory, but it means we definitely // never need to re-allocate either the warnings or the errors vec! From f0a91b8ce1d11a66c3854e711dd1fbe353a26f47 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 14 Oct 2023 21:19:33 -0400 Subject: [PATCH 05/10] Add some debug assertions --- crates/reporting/src/cli.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/reporting/src/cli.rs b/crates/reporting/src/cli.rs index 433465b6daa..9447fdf0d6d 100644 --- a/crates/reporting/src/cli.rs +++ b/crates/reporting/src/cli.rs @@ -135,6 +135,9 @@ pub fn report_problems( } } + debug_assert!(can_problems.is_empty() && type_problems.is_empty(), "After reporting problems, there were {:?} can_problems and {:?} type_problems that could not be reported because they did not have corresponding entries in `sources`.", can_problems.len(), type_problems.len()); + debug_assert_eq!(errors.len() + warnings.len(), total_problems); + let problems_reported; // Only print warnings if there are no errors From 08c6a044c47f4332de6b6f8fc9e7355ce067df59 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 14 Oct 2023 21:20:02 -0400 Subject: [PATCH 06/10] Improve error handling when mono panics --- crates/compiler/load_internal/src/file.rs | 95 ++++++++++++++++++++--- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index f2f12ea6b13..e5bf4019127 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -968,7 +968,12 @@ pub enum LoadingProblem<'a> { #[derive(Debug)] pub enum ChannelProblem { - FailedToEnqueueTask, + FailedToEnqueueTask { + can_problems: MutMap>, + type_problems: MutMap>, + sources: MutMap)>, + interns: Interns, + }, FailedToSendRootMsg, FailedToSendWorkerShutdownMsg, ChannelDisconnected, @@ -992,12 +997,35 @@ fn enqueue_task<'a>( injector: &Injector>, listeners: &[Sender], task: BuildTask<'a>, + state: &State<'a>, ) -> Result<(), LoadingProblem<'a>> { injector.push(task); for listener in listeners { listener.send(WorkerMsg::TaskAdded).map_err(|_| { - LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask) + let module_ids = { (&*state.arc_modules).lock().clone() }.into_module_ids(); + + let interns = Interns { + module_ids, + all_ident_ids: state.constrained_ident_ids.clone(), + }; + + LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask { + can_problems: state.module_cache.can_problems.clone(), + type_problems: state.module_cache.type_problems.clone(), + interns, + sources: state + .module_cache + .sources + .iter() + .map(|(key, (path, str_ref))| { + ( + key.clone(), + (path.clone(), str_ref.to_string().into_boxed_str()), + ) + }) + .collect(), + }) })?; } @@ -1721,8 +1749,13 @@ fn load_multi_threaded<'a>( let stealers = stealers.into_bump_slice(); let it = worker_arenas.iter_mut(); + let mut can_problems_recorded = MutMap::default(); + let mut type_problems_recorded = MutMap::default(); + let mut sources_recorded = MutMap::default(); + let mut interns_recorded = Interns::default(); + { - thread::scope(|thread_scope| { + let thread_result = thread::scope(|thread_scope| { let mut worker_listeners = bumpalo::collections::Vec::with_capacity_in(num_workers, arena); @@ -1808,13 +1841,31 @@ fn load_multi_threaded<'a>( state = new_state; continue; } - Err(LoadingProblem::ChannelProblem(problem)) => { - // Note: shut_down_worker_threads! results in the system - // looping indefinitely (possibly on a deadlock?) when - // we hit one of these problems due to a panic (e.g. in mono). - eprintln!("{:?}", problem); + Err(LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask { + can_problems, + type_problems, + sources, + interns, + })) => { + // Record these for later. + can_problems_recorded = can_problems; + type_problems_recorded = type_problems; + sources_recorded = sources; + interns_recorded = interns; - std::process::exit(101); + shut_down_worker_threads!(); + + return Err(LoadingProblem::ChannelProblem( + ChannelProblem::FailedToEnqueueTask { + // This return value never gets used, so don't bother + // cloning these in order to be able to return them. + // Really, anything could go here. + can_problems: Default::default(), + type_problems: Default::default(), + sources: Default::default(), + interns: Default::default(), + }, + )); } Err(e) => { shut_down_worker_threads!(); @@ -1823,9 +1874,27 @@ fn load_multi_threaded<'a>( } } } + }); + + thread_result.unwrap_or_else(|_| { + // This most likely means a panic occurred in one of the threads. + // Therefore, print all the error info we've accumulated, and note afterwards + // that there was a compiler crash. + // + // Unfortunately, this often has no information to report if there's a panic in mono. + report_problems( + &sources_recorded, + &mut interns_recorded, + &mut can_problems_recorded, + &mut type_problems_recorded, + ) + .print_to_stdout(Duration::default()); // TODO determine total elapsed time and use it here + + Err(LoadingProblem::FormattedReport( + "\n\nThere was an unrecoverable error in the Roc compiler. Try using the `roc check` command; that may give a more helpful error report.\n\n".to_string(), + )) }) } - .unwrap() } fn worker_task_step<'a>( @@ -2004,8 +2073,10 @@ fn start_tasks<'a>( worker_listeners: &'a [Sender], ) -> Result<(), LoadingProblem<'a>> { for (module_id, phase) in work { - for task in start_phase(module_id, phase, arena, state) { - enqueue_task(injector, worker_listeners, task)? + let tasks = start_phase(module_id, phase, arena, state); + + for task in tasks { + enqueue_task(injector, worker_listeners, task, &state)? } } From 73f3250b8f6c0ee0eb69c5278800384265f164b4 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 14 Oct 2023 21:30:53 -0400 Subject: [PATCH 07/10] Don't report unhelpful things. --- crates/compiler/load_internal/src/file.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index e5bf4019127..671dba59b98 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -1882,13 +1882,15 @@ fn load_multi_threaded<'a>( // that there was a compiler crash. // // Unfortunately, this often has no information to report if there's a panic in mono. - report_problems( - &sources_recorded, - &mut interns_recorded, - &mut can_problems_recorded, - &mut type_problems_recorded, - ) - .print_to_stdout(Duration::default()); // TODO determine total elapsed time and use it here + // Consequently, the following ends up being more misleading than helpful. + // + // roc_reporting::cli::report_problems( + // &sources_recorded, + // &mut interns_recorded, + // &mut can_problems_recorded, + // &mut type_problems_recorded, + // ) + // .print_to_stdout(Duration::default()); // TODO determine total elapsed time and use it here Err(LoadingProblem::FormattedReport( "\n\nThere was an unrecoverable error in the Roc compiler. Try using the `roc check` command; that may give a more helpful error report.\n\n".to_string(), From f2782e94d5332f5f4af2ba2cff45da19409991a5 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 14 Oct 2023 21:36:14 -0400 Subject: [PATCH 08/10] clippy --- crates/compiler/load_internal/src/file.rs | 70 ++++++++++++----------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 671dba59b98..87f132b2082 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -968,12 +968,7 @@ pub enum LoadingProblem<'a> { #[derive(Debug)] pub enum ChannelProblem { - FailedToEnqueueTask { - can_problems: MutMap>, - type_problems: MutMap>, - sources: MutMap)>, - interns: Interns, - }, + FailedToEnqueueTask(Box), FailedToSendRootMsg, FailedToSendWorkerShutdownMsg, ChannelDisconnected, @@ -983,6 +978,14 @@ pub enum ChannelProblem { FailedToSendFinishedTypeCheckingMsg, } +#[derive(Debug)] +pub struct PanicReportInfo { + can_problems: MutMap>, + type_problems: MutMap>, + sources: MutMap)>, + interns: Interns, +} + pub enum Phases { /// Parse, canonicalize, check types TypeCheck, @@ -1003,29 +1006,28 @@ fn enqueue_task<'a>( for listener in listeners { listener.send(WorkerMsg::TaskAdded).map_err(|_| { - let module_ids = { (&*state.arc_modules).lock().clone() }.into_module_ids(); + let module_ids = { (*state.arc_modules).lock().clone() }.into_module_ids(); let interns = Interns { module_ids, all_ident_ids: state.constrained_ident_ids.clone(), }; - LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask { - can_problems: state.module_cache.can_problems.clone(), - type_problems: state.module_cache.type_problems.clone(), - interns, - sources: state - .module_cache - .sources - .iter() - .map(|(key, (path, str_ref))| { - ( - key.clone(), - (path.clone(), str_ref.to_string().into_boxed_str()), - ) - }) - .collect(), - }) + LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask(Box::new( + PanicReportInfo { + can_problems: state.module_cache.can_problems.clone(), + type_problems: state.module_cache.type_problems.clone(), + interns, + sources: state + .module_cache + .sources + .iter() + .map(|(key, (path, str_ref))| { + (*key, (path.clone(), str_ref.to_string().into_boxed_str())) + }) + .collect(), + }, + ))) })?; } @@ -1841,12 +1843,16 @@ fn load_multi_threaded<'a>( state = new_state; continue; } - Err(LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask { - can_problems, - type_problems, - sources, - interns, - })) => { + Err(LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask( + info, + ))) => { + let PanicReportInfo { + can_problems, + type_problems, + sources, + interns, + } = *info; + // Record these for later. can_problems_recorded = can_problems; type_problems_recorded = type_problems; @@ -1856,7 +1862,7 @@ fn load_multi_threaded<'a>( shut_down_worker_threads!(); return Err(LoadingProblem::ChannelProblem( - ChannelProblem::FailedToEnqueueTask { + ChannelProblem::FailedToEnqueueTask(Box::new(PanicReportInfo { // This return value never gets used, so don't bother // cloning these in order to be able to return them. // Really, anything could go here. @@ -1864,7 +1870,7 @@ fn load_multi_threaded<'a>( type_problems: Default::default(), sources: Default::default(), interns: Default::default(), - }, + })), )); } Err(e) => { @@ -2078,7 +2084,7 @@ fn start_tasks<'a>( let tasks = start_phase(module_id, phase, arena, state); for task in tasks { - enqueue_task(injector, worker_listeners, task, &state)? + enqueue_task(injector, worker_listeners, task, state)? } } From 1f1b981110009f4cf39eb00915dc4271d68c2462 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 15 Oct 2023 20:22:03 -0400 Subject: [PATCH 09/10] Fix for future clippy --- crates/compiler/load_internal/src/file.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 87f132b2082..a9b70ba169b 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -1949,7 +1949,7 @@ fn worker_task_step<'a>( match result { Ok(()) => {} Err(LoadingProblem::ChannelProblem(problem)) => { - panic!("Channel problem: {:?}", problem); + panic!("Channel problem: {problem:?}"); } Err(LoadingProblem::ParsingFailed(problem)) => { msg_tx.send(Msg::FailedToParse(problem)).unwrap(); @@ -2048,7 +2048,7 @@ fn worker_task<'a>( match result { Ok(()) => {} Err(LoadingProblem::ChannelProblem(problem)) => { - panic!("Channel problem: {:?}", problem); + panic!("Channel problem: {problem:?}"); } Err(LoadingProblem::ParsingFailed(problem)) => { msg_tx.send(Msg::FailedToParse(problem)).unwrap(); From 20199099225be7f4ea1094bb0903ab7604702f66 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 15 Oct 2023 20:32:20 -0400 Subject: [PATCH 10/10] Use concat! to break up a long string literal --- crates/compiler/load_internal/src/file.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index a9b70ba169b..2063746d7e3 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -1899,7 +1899,11 @@ fn load_multi_threaded<'a>( // .print_to_stdout(Duration::default()); // TODO determine total elapsed time and use it here Err(LoadingProblem::FormattedReport( - "\n\nThere was an unrecoverable error in the Roc compiler. Try using the `roc check` command; that may give a more helpful error report.\n\n".to_string(), + concat!( + "\n\nThere was an unrecoverable error in the Roc compiler. The `roc check` ", + "command can sometimes give a more helpful error report than other commands.\n\n" + ) + .to_string(), )) }) }