Merge branch 'main' of https://github.com/roc-lang/roc into list-splitting

This commit is contained in:
Isaac Van Doren 2024-11-15 21:12:51 -06:00
commit 35f221d9de
No known key found for this signature in database
GPG key ID: CFA524CD470E5B94
28 changed files with 295 additions and 370 deletions

View file

@ -525,7 +525,7 @@ fn gen_from_mono_module_dev_wasm32<'a>(
let host_bytes = std::fs::read(built_host_path).unwrap_or_else(|_| {
internal_error!(
"Failed to read host object file {}! Try omitting --prebuilt-platform",
"Failed to read host object file {}!",
built_host_path.display()
)
});

View file

@ -482,7 +482,6 @@ pub fn find_type_def_symbols(
AssignedField::LabelOnly(_) => {}
AssignedField::SpaceBefore(inner, _)
| AssignedField::SpaceAfter(inner, _) => inner_stack.push(inner),
AssignedField::Malformed(_) => {}
}
}
@ -507,7 +506,6 @@ pub fn find_type_def_symbols(
Tag::SpaceBefore(inner, _) | Tag::SpaceAfter(inner, _) => {
inner_stack.push(inner)
}
Tag::Malformed(_) => {}
}
}
@ -1355,7 +1353,7 @@ fn can_assigned_fields<'a>(
// field names we've seen so far in this record
let mut seen = std::collections::HashMap::with_capacity(fields.len());
'outer: for loc_field in fields.iter() {
for loc_field in fields.iter() {
let mut field = &loc_field.value;
// use this inner loop to unwrap the SpaceAfter/SpaceBefore
@ -1430,12 +1428,6 @@ fn can_assigned_fields<'a>(
field = nested;
continue 'inner;
}
Malformed(string) => {
malformed(env, region, string);
// completely skip this element, advance to the next tag
continue 'outer;
}
}
};
@ -1522,7 +1514,7 @@ fn can_tags<'a>(
// tag names we've seen so far in this tag union
let mut seen = std::collections::HashMap::with_capacity(tags.len());
'outer: for loc_tag in tags.iter() {
for loc_tag in tags.iter() {
let mut tag = &loc_tag.value;
// use this inner loop to unwrap the SpaceAfter/SpaceBefore
@ -1561,12 +1553,6 @@ fn can_tags<'a>(
tag = nested;
continue 'inner;
}
Tag::Malformed(string) => {
malformed(env, region, string);
// completely skip this element, advance to the next tag
continue 'outer;
}
}
};

View file

@ -715,10 +715,6 @@ fn canonicalize_claimed_ability_impl<'a>(
});
Err(())
}
AssignedField::Malformed(_) => {
// An error will already have been reported
Err(())
}
AssignedField::SpaceBefore(_, _)
| AssignedField::SpaceAfter(_, _)
| AssignedField::IgnoredValue(_, _, _) => {

View file

@ -407,7 +407,6 @@ pub fn desugar_expr<'a>(
| AccessorFunction(_)
| Underscore { .. }
| MalformedIdent(_, _)
| MalformedClosure
| MalformedSuffixed(..)
| PrecedenceConflict { .. }
| EmptyRecordBuilder(_)
@ -712,7 +711,6 @@ pub fn desugar_expr<'a>(
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => {
unreachable!("Should have been desugared in `desugar_field`")
}
AssignedField::Malformed(_name) => continue,
};
field_data.push(FieldData {
@ -1316,8 +1314,6 @@ fn desugar_field<'a>(
}
SpaceBefore(field, _spaces) => desugar_field(env, scope, field),
SpaceAfter(field, _spaces) => desugar_field(env, scope, field),
Malformed(string) => Malformed(string),
}
}

View file

@ -1391,10 +1391,6 @@ pub fn canonicalize_expr<'a>(
Output::default(),
)
}
ast::Expr::MalformedClosure => {
use roc_problem::can::RuntimeError::*;
(RuntimeError(MalformedClosure(region)), Output::default())
}
ast::Expr::MalformedIdent(name, bad_ident) => {
use roc_problem::can::RuntimeError::*;
@ -1976,10 +1972,6 @@ fn canonicalize_field<'a>(
SpaceBefore(sub_field, _) | SpaceAfter(sub_field, _) => {
canonicalize_field(env, var_store, scope, sub_field)
}
Malformed(_string) => {
internal_error!("TODO canonicalize malformed record field");
}
}
}
@ -2568,8 +2560,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
| ast::Expr::Underscore(_)
| ast::Expr::MalformedIdent(_, _)
| ast::Expr::Tag(_)
| ast::Expr::OpaqueRef(_)
| ast::Expr::MalformedClosure => true,
| ast::Expr::OpaqueRef(_) => true,
// Newlines are disallowed inside interpolation, and these all require newlines
ast::Expr::DbgStmt(_, _)
| ast::Expr::LowLevelDbg(_, _, _)
@ -2604,7 +2595,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
}
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
ast::AssignedField::LabelOnly(_) => true,
ast::AssignedField::SpaceBefore(_, _) | ast::AssignedField::SpaceAfter(_, _) => false,
}),
ast::Expr::Tuple(fields) => fields
@ -2655,7 +2646,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
}
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
ast::AssignedField::LabelOnly(_) => true,
ast::AssignedField::SpaceBefore(_, _)
| ast::AssignedField::SpaceAfter(_, _) => false,
})
@ -2668,7 +2659,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
| ast::AssignedField::IgnoredValue(_label, loc_comments, loc_val) => {
loc_comments.is_empty() && is_valid_interpolation(&loc_val.value)
}
ast::AssignedField::Malformed(_) | ast::AssignedField::LabelOnly(_) => true,
ast::AssignedField::LabelOnly(_) => true,
ast::AssignedField::SpaceBefore(_, _)
| ast::AssignedField::SpaceAfter(_, _) => false,
})

View file

@ -438,7 +438,6 @@ fn is_multiline_assigned_field_help<T: Formattable>(afield: &AssignedField<'_, T
| IgnoredValue(_, spaces, ann) => !spaces.is_empty() || ann.value.is_multiline(),
LabelOnly(_) => false,
AssignedField::SpaceBefore(_, _) | AssignedField::SpaceAfter(_, _) => true,
Malformed(text) => text.chars().any(|c| c == '\n'),
}
}
@ -522,9 +521,6 @@ fn format_assigned_field_help<T>(
format_assigned_field_help(sub_field, buf, indent, separator_spaces, is_multiline);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
}
Malformed(raw) => {
buf.push_str(raw);
}
}
}
@ -535,7 +531,6 @@ impl<'a> Formattable for Tag<'a> {
match self {
Apply { args, .. } => args.iter().any(|arg| arg.value.is_multiline()),
Tag::SpaceBefore(_, _) | Tag::SpaceAfter(_, _) => true,
Malformed(text) => text.chars().any(|c| c == '\n'),
}
}
@ -572,10 +567,6 @@ impl<'a> Formattable for Tag<'a> {
}
}
Tag::SpaceBefore(_, _) | Tag::SpaceAfter(_, _) => unreachable!(),
Tag::Malformed(raw) => {
buf.indent(indent);
buf.push_str(raw);
}
}
}
}

View file

@ -44,7 +44,6 @@ impl<'a> Formattable for Expr<'a> {
| Var { .. }
| Underscore { .. }
| MalformedIdent(_, _)
| MalformedClosure
| Tag(_)
| OpaqueRef(_)
| Crash
@ -557,7 +556,6 @@ impl<'a> Formattable for Expr<'a> {
buf.indent(indent);
loc_expr.format_with_options(buf, parens, newlines, indent);
}
MalformedClosure => {}
PrecedenceConflict { .. } => {}
EmptyRecordBuilder { .. } => {}
SingleFieldRecordBuilder { .. } => {}
@ -1646,9 +1644,6 @@ fn format_assigned_field_multiline<T>(
format_assigned_field_multiline(buf, sub_field, indent, separator_prefix);
fmt_comments_only(buf, spaces.iter(), NewlineAt::Top, indent);
}
Malformed(raw) => {
buf.push_str(raw);
}
}
}

View file

@ -476,7 +476,7 @@ fn contains_unexposed_type(
return true;
}
}
AssignedField::Malformed(_) | AssignedField::LabelOnly(_) => {
AssignedField::LabelOnly(_) => {
// contains no unexposed types, so continue
}
AssignedField::SpaceBefore(field, _) | AssignedField::SpaceAfter(field, _) => {
@ -524,9 +524,6 @@ fn contains_unexposed_type(
}
}
}
Tag::Malformed(_) => {
// contains no unexposed types, so continue
}
Tag::SpaceBefore(tag, _) | Tag::SpaceAfter(tag, _) => {
tags_to_process.push(*tag);
}
@ -728,7 +725,7 @@ fn record_field_to_doc(
AssignedField::LabelOnly(label) => Some(RecordField::LabelOnly {
name: label.value.to_string(),
}),
AssignedField::Malformed(_) | AssignedField::IgnoredValue(_, _, _) => None,
AssignedField::IgnoredValue(_, _, _) => None,
}
}
@ -749,7 +746,6 @@ fn tag_to_doc(in_func_ann: bool, tag: ast::Tag) -> Option<Tag> {
}),
ast::Tag::SpaceBefore(&sub_tag, _) => tag_to_doc(in_func_ann, sub_tag),
ast::Tag::SpaceAfter(&sub_tag, _) => tag_to_doc(in_func_ann, sub_tag),
ast::Tag::Malformed(_) => None,
}
}

View file

@ -68,7 +68,7 @@ use roc_solve_problem::TypeError;
use roc_target::Target;
use roc_types::subs::{CopiedImport, ExposedTypesStorageSubs, Subs, VarStore, Variable};
use roc_types::types::{Alias, Types};
use roc_worker::{ChannelProblem, WorkerMsg};
use roc_worker::ChannelProblem;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::io;
@ -1035,14 +1035,14 @@ type MsgSender<'a> = Sender<Msg<'a>>;
/// Add a task to the queue, and notify all the listeners.
fn enqueue_task<'a>(
injector: &Injector<BuildTask<'a>>,
listeners: &[Sender<WorkerMsg>],
listeners: &[Sender<()>],
task: BuildTask<'a>,
) -> Result<(), LoadingProblem<'a>> {
injector.push(task);
for listener in listeners {
listener
.send(WorkerMsg::TaskAdded)
.send(())
.map_err(|_| LoadingProblem::ChannelProblem(ChannelProblem::FailedToEnqueueTask))?;
}
@ -1569,9 +1569,9 @@ pub fn load_single_threaded<'a>(
// We'll add tasks to this, and then worker threads will take tasks from it.
let injector = Injector::new();
let (worker_msg_tx, worker_msg_rx) = bounded(1024);
let worker_listener = worker_msg_tx;
let worker_listeners = arena.alloc([worker_listener]);
let (worker_wakup_tx, worker_wakup_rx) = bounded(1024);
let worker_waker = worker_wakup_tx;
let worker_wakers = [worker_waker];
let worker = Worker::new_fifo();
let stealer = worker.stealer();
@ -1579,7 +1579,7 @@ pub fn load_single_threaded<'a>(
// now we just manually interleave stepping the state "thread" and the worker "thread"
loop {
match state_thread_step(arena, state, worker_listeners, &injector, &msg_tx, &msg_rx) {
match state_thread_step(arena, state, &worker_wakers, &injector, &msg_tx, &msg_rx) {
Ok(ControlFlow::Break(done)) => return Ok(done),
Ok(ControlFlow::Continue(new_state)) => {
state = new_state;
@ -1589,7 +1589,7 @@ pub fn load_single_threaded<'a>(
// then check if the worker can step
let control_flow =
roc_worker::worker_task_step(&worker, &injector, stealers, &worker_msg_rx, |task| {
roc_worker::worker_task_step(&worker, &injector, stealers, &worker_wakup_rx, |task| {
run_task(task, arena, &src_dir, msg_tx.clone(), roc_cache_dir, target)
});
@ -1606,7 +1606,7 @@ pub fn load_single_threaded<'a>(
fn state_thread_step<'a>(
arena: &'a Bump,
state: State<'a>,
worker_listeners: &'a [Sender<WorkerMsg>],
worker_wakers: &[Sender<()>],
injector: &Injector<BuildTask<'a>>,
msg_tx: &crossbeam::channel::Sender<Msg<'a>>,
msg_rx: &crossbeam::channel::Receiver<Msg<'a>>,
@ -1712,14 +1712,8 @@ fn state_thread_step<'a>(
let render = state.render;
let palette = state.palette;
let res_state = update(
state,
msg,
msg_tx.clone(),
injector,
worker_listeners,
arena,
);
let res_state =
update(state, msg, msg_tx.clone(), injector, worker_wakers, arena);
match res_state {
Ok(new_state) => Ok(ControlFlow::Continue(new_state)),
@ -1993,15 +1987,21 @@ fn load_multi_threaded<'a>(
{
let thread_result = thread::scope(|thread_scope| {
let mut worker_listeners =
bumpalo::collections::Vec::with_capacity_in(num_workers, arena);
// Careful! It's important that worker listeners aren't allocated in the arena,
// since they need to be correctly dropped if we have a panic in this thread::scope code.
// Making sure they're owned means they'll be dropped correctly on either normal exit
// of this thread::scope block or on panicking. When they're dropped, the worker threads
// will correctly exit their message processing loops.
// If these were allocated in the arena, we might panic without shutting down the worker threads,
// causing the thread::scope block to hang while it waits for the worker threads to exit.
let mut worker_wakers = Vec::with_capacity(num_workers);
for worker_arena in it {
let msg_tx = msg_tx.clone();
let worker = worker_queues.pop().unwrap();
let (worker_msg_tx, worker_msg_rx) = bounded(1024);
worker_listeners.push(worker_msg_tx);
let (worker_wakup_tx, worker_wakup_rx) = bounded(1024);
worker_wakers.push(worker_wakup_tx);
// We only want to move a *reference* to the main task queue's
// injector in the thread, not the injector itself
@ -2015,16 +2015,22 @@ fn load_multi_threaded<'a>(
.stack_size(EXPANDED_STACK_SIZE)
.spawn(move |_| {
// will process messages until we run out
roc_worker::worker_task(worker, injector, stealers, worker_msg_rx, |task| {
run_task(
task,
worker_arena,
src_dir,
msg_tx.clone(),
roc_cache_dir,
target,
)
})
roc_worker::worker_task(
worker,
injector,
stealers,
worker_wakup_rx,
|task| {
run_task(
task,
worker_arena,
src_dir,
msg_tx.clone(),
roc_cache_dir,
target,
)
},
)
});
res_join_handle.unwrap_or_else(|_| {
@ -2039,31 +2045,13 @@ fn load_multi_threaded<'a>(
// Grab a reference to these Senders outside the loop, so we can share
// it across each iteration of the loop.
let worker_listeners = worker_listeners.into_bump_slice();
let msg_tx = msg_tx.clone();
macro_rules! shut_down_worker_threads {
() => {
for listener in worker_listeners {
// 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.");
}
}
};
}
// The root module will have already queued up messages to process,
// and processing those messages will in turn queue up more messages.
loop {
match state_thread_step(arena, state, worker_listeners, &injector, &msg_tx, &msg_rx)
{
match state_thread_step(arena, state, &worker_wakers, &injector, &msg_tx, &msg_rx) {
Ok(ControlFlow::Break(load_result)) => {
shut_down_worker_threads!();
return Ok(load_result);
}
Ok(ControlFlow::Continue(new_state)) => {
@ -2071,8 +2059,6 @@ fn load_multi_threaded<'a>(
continue;
}
Err(e) => {
shut_down_worker_threads!();
return Err(e);
}
}
@ -2111,13 +2097,13 @@ fn start_tasks<'a>(
state: &mut State<'a>,
work: MutSet<(ModuleId, Phase)>,
injector: &Injector<BuildTask<'a>>,
worker_listeners: &'a [Sender<WorkerMsg>],
worker_wakers: &[Sender<()>],
) -> Result<(), LoadingProblem<'a>> {
for (module_id, phase) in work {
let tasks = start_phase(module_id, phase, arena, state);
for task in tasks {
enqueue_task(injector, worker_listeners, task)?
enqueue_task(injector, worker_wakers, task)?
}
}
@ -2179,7 +2165,7 @@ fn update<'a>(
msg: Msg<'a>,
msg_tx: MsgSender<'a>,
injector: &Injector<BuildTask<'a>>,
worker_listeners: &'a [Sender<WorkerMsg>],
worker_wakers: &[Sender<()>],
arena: &'a Bump,
) -> Result<State<'a>, LoadingProblem<'a>> {
use self::Msg::*;
@ -2305,7 +2291,7 @@ fn update<'a>(
work.extend(state.dependencies.notify(home, Phase::LoadHeader));
work.insert((home, Phase::Parse));
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
Ok(state)
}
@ -2382,7 +2368,7 @@ fn update<'a>(
}
};
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
state
.module_cache
@ -2393,7 +2379,7 @@ fn update<'a>(
let work = state.dependencies.notify(module_id, Phase::Parse);
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
Ok(state)
}
@ -2445,7 +2431,7 @@ fn update<'a>(
.dependencies
.notify(module_id, Phase::CanonicalizeAndConstrain);
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
Ok(state)
}
@ -2652,7 +2638,7 @@ fn update<'a>(
work
};
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
}
Ok(state)
@ -2700,7 +2686,7 @@ fn update<'a>(
.dependencies
.notify(module_id, Phase::FindSpecializations);
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
Ok(state)
}
@ -2990,13 +2976,13 @@ fn update<'a>(
let work = state.dependencies.reload_make_specialization_pass();
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
Ok(state)
}
NextStep::MakingInPhase => {
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
Ok(state)
}

View file

@ -539,7 +539,6 @@ pub enum Expr<'a> {
// Problems
MalformedIdent(&'a str, crate::ident::BadIdent),
MalformedClosure,
MalformedSuffixed(&'a Loc<Expr<'a>>),
// Both operators were non-associative, e.g. (True == False == False).
// We should tell the author to disambiguate by grouping them with parens.
@ -687,7 +686,6 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
Expr::SpaceBefore(a, _) => is_expr_suffixed(a),
Expr::SpaceAfter(a, _) => is_expr_suffixed(a),
Expr::MalformedIdent(_, _) => false,
Expr::MalformedClosure => false,
Expr::MalformedSuffixed(_) => false,
Expr::PrecedenceConflict(_) => false,
Expr::EmptyRecordBuilder(_) => false,
@ -713,7 +711,6 @@ fn is_assigned_value_suffixed<'a>(value: &AssignedField<'a, Expr<'a>>) -> bool {
AssignedField::SpaceBefore(a, _) | AssignedField::SpaceAfter(a, _) => {
is_assigned_value_suffixed(a)
}
AssignedField::Malformed(_) => false,
}
}
@ -889,7 +886,7 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
| OptionalValue(_, _, loc_val)
| IgnoredValue(_, _, loc_val) => break expr_stack.push(&loc_val.value),
SpaceBefore(next, _) | SpaceAfter(next, _) => current = *next,
LabelOnly(_) | Malformed(_) => break,
LabelOnly(_) => break,
}
}
}
@ -1038,7 +1035,6 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
| Tag(_)
| OpaqueRef(_)
| MalformedIdent(_, _)
| MalformedClosure
| PrecedenceConflict(_)
| MalformedSuffixed(_) => { /* terminal */ }
}
@ -1614,9 +1610,6 @@ pub enum Tag<'a> {
// We preserve this for the formatter; canonicalization ignores it.
SpaceBefore(&'a Tag<'a>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a Tag<'a>, &'a [CommentOrNewline<'a>]),
/// A malformed tag, which will code gen to a runtime error
Malformed(&'a str),
}
#[derive(Debug, Clone, Copy, PartialEq)]
@ -1639,9 +1632,6 @@ pub enum AssignedField<'a, Val> {
// We preserve this for the formatter; canonicalization ignores it.
SpaceBefore(&'a AssignedField<'a, Val>, &'a [CommentOrNewline<'a>]),
SpaceAfter(&'a AssignedField<'a, Val>, &'a [CommentOrNewline<'a>]),
/// A malformed assigned field, which will code gen to a runtime error
Malformed(&'a str),
}
impl<'a, Val> AssignedField<'a, Val> {
@ -1653,7 +1643,7 @@ impl<'a, Val> AssignedField<'a, Val> {
Self::RequiredValue(_, _, val)
| Self::OptionalValue(_, _, val)
| Self::IgnoredValue(_, _, val) => break Some(val),
Self::LabelOnly(_) | Self::Malformed(_) => break None,
Self::LabelOnly(_) => break None,
Self::SpaceBefore(next, _) | Self::SpaceAfter(next, _) => current = *next,
}
}
@ -2518,7 +2508,6 @@ impl<'a> Malformed for Expr<'a> {
ParensAround(expr) => expr.is_malformed(),
MalformedIdent(_, _) |
MalformedClosure |
MalformedSuffixed(..) |
PrecedenceConflict(_) |
EmptyRecordBuilder(_) |
@ -2593,7 +2582,6 @@ impl<'a, T: Malformed> Malformed for AssignedField<'a, T> {
AssignedField::SpaceBefore(field, _) | AssignedField::SpaceAfter(field, _) => {
field.is_malformed()
}
AssignedField::Malformed(_) => true,
}
}
}
@ -2815,7 +2803,6 @@ impl<'a> Malformed for Tag<'a> {
match self {
Tag::Apply { name: _, args } => args.iter().any(|arg| arg.is_malformed()),
Tag::SpaceBefore(tag, _) | Tag::SpaceAfter(tag, _) => tag.is_malformed(),
Tag::Malformed(_) => true,
}
}
}

View file

@ -2180,7 +2180,6 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
| Expr::DbgStmt(_, _)
| Expr::LowLevelDbg(_, _, _)
| Expr::Return(_, _)
| Expr::MalformedClosure
| Expr::MalformedSuffixed(..)
| Expr::PrecedenceConflict { .. }
| Expr::EmptyRecordBuilder(_)
@ -2254,7 +2253,6 @@ fn assigned_expr_field_to_pattern_help<'a>(
arena.alloc(assigned_expr_field_to_pattern_help(arena, nested)?),
spaces,
),
AssignedField::Malformed(string) => Pattern::Malformed(string),
AssignedField::IgnoredValue(_, _, _) => return Err(()),
})
}

View file

@ -556,7 +556,6 @@ impl<'a, T: Normalize<'a> + Copy + std::fmt::Debug> Normalize<'a> for AssignedFi
arena.alloc(c.normalize(arena)),
),
AssignedField::LabelOnly(a) => AssignedField::LabelOnly(a.normalize(arena)),
AssignedField::Malformed(a) => AssignedField::Malformed(a),
AssignedField::SpaceBefore(a, _) => a.normalize(arena),
AssignedField::SpaceAfter(a, _) => a.normalize(arena),
}
@ -784,7 +783,6 @@ impl<'a> Normalize<'a> for Expr<'a> {
a.normalize(arena)
}
Expr::MalformedIdent(a, b) => Expr::MalformedIdent(a, remove_spaces_bad_ident(b)),
Expr::MalformedClosure => Expr::MalformedClosure,
Expr::MalformedSuffixed(a) => Expr::MalformedSuffixed(a),
Expr::PrecedenceConflict(a) => Expr::PrecedenceConflict(a),
Expr::SpaceBefore(a, _) => a.normalize(arena),
@ -938,7 +936,6 @@ impl<'a> Normalize<'a> for Tag<'a> {
name: name.normalize(arena),
args: args.normalize(arena),
},
Tag::Malformed(a) => Tag::Malformed(a),
Tag::SpaceBefore(a, _) => a.normalize(arena),
Tag::SpaceAfter(a, _) => a.normalize(arena),
}

View file

@ -435,7 +435,6 @@ impl Problem {
| Problem::RuntimeError(RuntimeError::InvalidPrecedence(_, region))
| Problem::RuntimeError(RuntimeError::MalformedIdentifier(_, _, region))
| Problem::RuntimeError(RuntimeError::MalformedTypeName(_, region))
| Problem::RuntimeError(RuntimeError::MalformedClosure(region))
| Problem::RuntimeError(RuntimeError::MalformedSuffixed(region))
| Problem::RuntimeError(RuntimeError::InvalidRecordUpdate { region })
| Problem::RuntimeError(RuntimeError::InvalidFloat(_, region, _))
@ -678,7 +677,6 @@ pub enum RuntimeError {
InvalidPrecedence(PrecedenceProblem, Region),
MalformedIdentifier(Box<str>, roc_parse::ident::BadIdent, Region),
MalformedTypeName(Box<str>, Region),
MalformedClosure(Region),
InvalidRecordUpdate {
region: Region,
},
@ -750,7 +748,6 @@ impl RuntimeError {
| RuntimeError::InvalidPrecedence(_, region)
| RuntimeError::MalformedIdentifier(_, _, region)
| RuntimeError::MalformedTypeName(_, region)
| RuntimeError::MalformedClosure(region)
| RuntimeError::MalformedSuffixed(region)
| RuntimeError::InvalidRecordUpdate { region }
| RuntimeError::InvalidFloat(_, region, _)

View file

@ -7,12 +7,6 @@ use roc_module::symbol::ModuleId;
use roc_work::Phase;
use std::ops::ControlFlow;
#[derive(Debug)]
pub enum WorkerMsg {
Shutdown,
TaskAdded,
}
#[derive(Debug)]
pub enum ChannelProblem {
FailedToSendRootMsg,
@ -29,41 +23,31 @@ pub fn worker_task_step<Task>(
worker: &Worker<Task>,
injector: &Injector<Task>,
stealers: &[Stealer<Task>],
worker_msg_rx: &Receiver<WorkerMsg>,
worker_wakeup_rx: &Receiver<()>,
run_task: impl Fn(Task) -> Result<(), ChannelProblem>,
) -> Result<ControlFlow<(), ()>, ChannelProblem> {
match worker_msg_rx.try_recv() {
Ok(msg) => {
match msg {
WorkerMsg::Shutdown => {
// We've finished all our work. It's time to
// shut down the thread, so when the main thread
// blocks on joining with all the worker threads,
// it can finally exit too!
Ok(ControlFlow::Break(()))
}
WorkerMsg::TaskAdded => {
// Find a task - either from this thread's queue,
// or from the main queue, or from another worker's
// queue - and run it.
//
// There might be no tasks to work on! That could
// happen if another thread is working on a task
// which will later result in more tasks being
// added. In that case, do nothing, and keep waiting
// until we receive a Shutdown message.
if let Some(task) = find_task(worker, injector, stealers) {
run_task(task)?;
}
Ok(ControlFlow::Continue(()))
}
match worker_wakeup_rx.try_recv() {
Ok(()) => {
// Find a task - either from this thread's queue,
// or from the main queue, or from another worker's
// queue - and run it.
//
// There might be no tasks to work on! That could
// happen if another thread is working on a task
// which will later result in more tasks being
// added. In that case, do nothing, and keep waiting
// until we receive a Shutdown message.
if let Some(task) = find_task(worker, injector, stealers) {
run_task(task)?;
}
Ok(ControlFlow::Continue(()))
}
Err(err) => match err {
crossbeam::channel::TryRecvError::Empty => Ok(ControlFlow::Continue(())),
crossbeam::channel::TryRecvError::Disconnected => {
Err(ChannelProblem::ChannelDisconnected)
// The channel sender has been dropped, which means we want to shut down
Ok(ControlFlow::Break(()))
}
},
}
@ -73,33 +57,22 @@ pub fn worker_task<Task>(
worker: Worker<Task>,
injector: &Injector<Task>,
stealers: &[Stealer<Task>],
worker_msg_rx: crossbeam::channel::Receiver<WorkerMsg>,
worker_wakeup_rx: crossbeam::channel::Receiver<()>,
run_task: impl Fn(Task) -> Result<(), ChannelProblem>,
) -> Result<(), ChannelProblem> {
// Keep listening until we receive a Shutdown msg
for msg in worker_msg_rx.iter() {
match msg {
WorkerMsg::Shutdown => {
// We've finished all our work. It's time to
// shut down the thread, so when the main thread
// blocks on joining with all the worker threads,
// it can finally exit too!
return Ok(());
}
WorkerMsg::TaskAdded => {
// Find a task - either from this thread's queue,
// or from the main queue, or from another worker's
// queue - and run it.
//
// There might be no tasks to work on! That could
// happen if another thread is working on a task
// which will later result in more tasks being
// added. In that case, do nothing, and keep waiting
// until we receive a Shutdown message.
if let Some(task) = find_task(&worker, injector, stealers) {
run_task(task)?;
}
}
for () in worker_wakeup_rx.iter() {
// Find a task - either from this thread's queue,
// or from the main queue, or from another worker's
// queue - and run it.
//
// There might be no tasks to work on! That could
// happen if another thread is working on a task
// which will later result in more tasks being
// added. In that case, do nothing, and keep waiting
// until we receive a Shutdown message.
if let Some(task) = find_task(&worker, injector, stealers) {
run_task(task)?;
}
}
@ -110,17 +83,17 @@ pub fn start_tasks<State, Task, Tasks: IntoIterator<Item = Task>>(
state: &mut State,
work: MutSet<(ModuleId, Phase)>,
injector: &Injector<Task>,
worker_listeners: &[Sender<WorkerMsg>],
worker_wakers: &[Sender<()>],
mut start_phase: impl FnMut(ModuleId, Phase, &mut State) -> Tasks,
) -> Result<(), SendError<WorkerMsg>> {
) -> Result<(), SendError<()>> {
for (module_id, phase) in work {
let tasks = start_phase(module_id, phase, state);
for task in tasks {
injector.push(task);
for listener in worker_listeners {
listener.send(WorkerMsg::TaskAdded)?;
for listener in worker_wakers {
listener.send(())?;
}
}
}