Un-macro map_with_arena

This commit is contained in:
Jackson Wambolt 2024-04-15 20:35:08 -05:00
parent f6c977fb96
commit a9724dda5e
No known key found for this signature in database
GPG key ID: 76F29A42FEE8811C
5 changed files with 74 additions and 124 deletions

View file

@ -11,10 +11,10 @@ use crate::ident::{integer_ident, lowercase_ident, parse_ident, Accessor, Ident}
use crate::keyword; use crate::keyword;
use crate::parser::{ use crate::parser::{
self, and, backtrackable, between, byte, byte_indent, increment_min_indent, indented_seq, self, and, backtrackable, between, byte, byte_indent, increment_min_indent, indented_seq,
line_min_indent, loc, map, optional, reset_min_indent, sep_by1, sep_by1_e, set_min_indent, line_min_indent, loc, map, map_with_arena, optional, reset_min_indent, sep_by1, sep_by1_e,
skip_first, skip_second, specialize_err, specialize_err_ref, then, two_bytes, EClosure, set_min_indent, skip_first, skip_second, specialize_err, specialize_err_ref, then, two_bytes,
EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern, ERecord, EString, EType, EWhen, EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern, ERecord, EString, EType,
Either, ParseResult, Parser, EWhen, Either, ParseResult, Parser,
}; };
use crate::pattern::{closure_param, loc_implements_parser}; use crate::pattern::{closure_param, loc_implements_parser};
use crate::state::State; use crate::state::State;
@ -131,10 +131,10 @@ fn loc_expr_in_parens_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EInParens<'a>
} }
fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> { fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
map_with_arena!( map_with_arena(
loc(and( loc(and(
specialize_err(EExpr::InParens, loc_expr_in_parens_help()), specialize_err(EExpr::InParens, loc_expr_in_parens_help()),
record_field_access_chain() record_field_access_chain(),
)), )),
move |arena: &'a Bump, value: Loc<(Loc<Expr<'a>>, Vec<'a, Accessor<'a>>)>| { move |arena: &'a Bump, value: Loc<(Loc<Expr<'a>>, Vec<'a, Accessor<'a>>)>| {
let Loc { let Loc {
@ -153,7 +153,7 @@ fn loc_expr_in_parens_etc_help<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>
} }
Loc::at(region, value) Loc::at(region, value)
} },
) )
} }
@ -189,7 +189,7 @@ fn loc_term_or_underscore_or_conditional<'a>(
loc(underscore_expression()), loc(underscore_expression()),
loc(record_literal_help()), loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())), loc(specialize_err(EExpr::List, list_literal_help())),
loc(map_with_arena!( loc(map_with_arena(
assign_or_destructure_identifier(), assign_or_destructure_identifier(),
ident_to_expr ident_to_expr
)), )),
@ -212,7 +212,7 @@ fn loc_term_or_underscore<'a>(
loc(underscore_expression()), loc(underscore_expression()),
loc(record_literal_help()), loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())), loc(specialize_err(EExpr::List, list_literal_help())),
loc(map_with_arena!( loc(map_with_arena(
assign_or_destructure_identifier(), assign_or_destructure_identifier(),
ident_to_expr ident_to_expr
)), )),
@ -230,7 +230,7 @@ fn loc_term<'a>(options: ExprParseOptions) -> impl Parser<'a, Loc<Expr<'a>>, EEx
loc(specialize_err(EExpr::Closure, closure_help(options))), loc(specialize_err(EExpr::Closure, closure_help(options))),
loc(record_literal_help()), loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())), loc(specialize_err(EExpr::List, list_literal_help())),
loc(map_with_arena!( loc(map_with_arena(
assign_or_destructure_identifier(), assign_or_destructure_identifier(),
ident_to_expr ident_to_expr
)), )),
@ -281,7 +281,7 @@ fn loc_possibly_negative_or_negated_term<'a>(
}, },
// this will parse negative numbers, which the unary negate thing up top doesn't (for now) // this will parse negative numbers, which the unary negate thing up top doesn't (for now)
loc(specialize_err(EExpr::Number, number_literal_help())), loc(specialize_err(EExpr::Number, number_literal_help())),
loc(map_with_arena!( loc(map_with_arena(
and( and(
loc(byte(b'!', EExpr::Start)), loc(byte(b'!', EExpr::Start)),
space0_before_e(loc_term(options), EExpr::IndentStart) space0_before_e(loc_term(options), EExpr::IndentStart)
@ -2359,7 +2359,7 @@ pub fn toplevel_defs<'a>() -> impl Parser<'a, Defs<'a>, EExpr<'a>> {
fn closure_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EClosure<'a>> { fn closure_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
// closure_help_help(options) // closure_help_help(options)
map_with_arena!( map_with_arena(
// After the first token, all other tokens must be indented past the start of the line // After the first token, all other tokens must be indented past the start of the line
indented_seq( indented_seq(
// All closures start with a '\' - e.g. (\x -> x + 1) // All closures start with a '\' - e.g. (\x -> x + 1)
@ -2384,16 +2384,16 @@ fn closure_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EClo
// Parse the body // Parse the body
space0_before_e( space0_before_e(
specialize_err_ref(EClosure::Body, expr_start(options)), specialize_err_ref(EClosure::Body, expr_start(options)),
EClosure::IndentBody EClosure::IndentBody,
) ),
) ),
) ),
), ),
|arena: &'a Bump, (params, body)| { |arena: &'a Bump, (params, body)| {
let params: Vec<'a, Loc<Pattern<'a>>> = params; let params: Vec<'a, Loc<Pattern<'a>>> = params;
let params: &'a [Loc<Pattern<'a>>] = params.into_bump_slice(); let params: &'a [Loc<Pattern<'a>>] = params.into_bump_slice();
Expr::Closure(params, arena.alloc(body)) Expr::Closure(params, arena.alloc(body))
} },
) )
} }
@ -2403,7 +2403,7 @@ mod when {
/// Parser for when expressions. /// Parser for when expressions.
pub fn expr_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EWhen<'a>> { pub fn expr_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EWhen<'a>> {
map_with_arena!( map_with_arena(
and( and(
indented_seq( indented_seq(
parser::keyword(keyword::WHEN, EWhen::When), parser::keyword(keyword::WHEN, EWhen::When),
@ -2847,7 +2847,7 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
} }
fn list_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EList<'a>> { fn list_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EList<'a>> {
map_with_arena!( map_with_arena(
collection_trailing_sep_e!( collection_trailing_sep_e!(
byte(b'[', EList::Open), byte(b'[', EList::Open),
specialize_err_ref(EList::Expr, loc_expr(false)), specialize_err_ref(EList::Expr, loc_expr(false)),
@ -2858,7 +2858,7 @@ fn list_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EList<'a>> {
|arena, elements: Collection<'a, _>| { |arena, elements: Collection<'a, _>| {
let elements = elements.ptrify_items(arena); let elements = elements.ptrify_items(arena);
Expr::List(elements) Expr::List(elements)
} },
) )
.trace("list_literal") .trace("list_literal")
} }
@ -2978,7 +2978,7 @@ impl<'a> Spaceable<'a> for RecordField<'a> {
pub fn record_field<'a>() -> impl Parser<'a, RecordField<'a>, ERecord<'a>> { pub fn record_field<'a>() -> impl Parser<'a, RecordField<'a>, ERecord<'a>> {
use RecordField::*; use RecordField::*;
map_with_arena!( map_with_arena(
and( and(
specialize_err(|_, pos| ERecord::Field(pos), loc(lowercase_ident())), specialize_err(|_, pos| ERecord::Field(pos), loc(lowercase_ident())),
and( and(
@ -2989,8 +2989,8 @@ pub fn record_field<'a>() -> impl Parser<'a, RecordField<'a>, ERecord<'a>> {
byte(b'?', ERecord::QuestionMark), byte(b'?', ERecord::QuestionMark),
spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false))) spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false)))
) )
)) )),
) ),
), ),
|arena: &'a bumpalo::Bump, (loc_label, (spaces, opt_loc_val))| { |arena: &'a bumpalo::Bump, (loc_label, (spaces, opt_loc_val))| {
match opt_loc_val { match opt_loc_val {
@ -3016,7 +3016,7 @@ pub fn record_field<'a>() -> impl Parser<'a, RecordField<'a>, ERecord<'a>> {
} }
} }
} }
} },
) )
} }
@ -3026,7 +3026,7 @@ enum RecordFieldExpr<'a> {
} }
fn record_field_expr<'a>() -> impl Parser<'a, RecordFieldExpr<'a>, ERecord<'a>> { fn record_field_expr<'a>() -> impl Parser<'a, RecordFieldExpr<'a>, ERecord<'a>> {
map_with_arena!( map_with_arena(
and( and(
spaces(), spaces(),
either!( either!(
@ -3035,29 +3035,27 @@ fn record_field_expr<'a>() -> impl Parser<'a, RecordFieldExpr<'a>, ERecord<'a>>
spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false))) spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false)))
), ),
specialize_err_ref(ERecord::Expr, loc_expr(false)) specialize_err_ref(ERecord::Expr, loc_expr(false))
) ),
), ),
|arena: &'a bumpalo::Bump, (spaces, either)| { |arena: &'a bumpalo::Bump, (spaces, either)| match either {
match either { Either::First((_, loc_expr)) => RecordFieldExpr::Apply(spaces, loc_expr),
Either::First((_, loc_expr)) => RecordFieldExpr::Apply(spaces, loc_expr), Either::Second(loc_expr) => RecordFieldExpr::Value({
Either::Second(loc_expr) => RecordFieldExpr::Value({ if spaces.is_empty() {
if spaces.is_empty() { loc_expr
loc_expr } else {
} else { arena
arena .alloc(loc_expr.value)
.alloc(loc_expr.value) .with_spaces_before(spaces, loc_expr.region)
.with_spaces_before(spaces, loc_expr.region) }
} }),
}), },
}
}
) )
} }
fn record_updateable_identifier<'a>() -> impl Parser<'a, Expr<'a>, ERecord<'a>> { fn record_updateable_identifier<'a>() -> impl Parser<'a, Expr<'a>, ERecord<'a>> {
specialize_err( specialize_err(
|_, pos| ERecord::Updateable(pos), |_, pos| ERecord::Updateable(pos),
map_with_arena!(parse_ident, ident_to_expr), map_with_arena(parse_ident, ident_to_expr),
) )
} }
@ -3184,7 +3182,7 @@ fn apply_expr_access_chain<'a>(
} }
fn string_like_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EString<'a>> { fn string_like_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EString<'a>> {
map_with_arena!( map_with_arena(
crate::string_literal::parse_str_like_literal(), crate::string_literal::parse_str_like_literal(),
|arena, lit| match lit { |arena, lit| match lit {
StrLikeLiteral::Str(s) => Expr::Str(s), StrLikeLiteral::Str(s) => Expr::Str(s),
@ -3192,7 +3190,7 @@ fn string_like_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EString<'a>> {
// TODO: preserve the original escaping // TODO: preserve the original escaping
Expr::SingleQuote(s.to_str_in(arena)) Expr::SingleQuote(s.to_str_in(arena))
} }
} },
) )
} }

View file

@ -5,7 +5,8 @@ use crate::blankspace::space0_e;
use crate::expr::merge_spaces; use crate::expr::merge_spaces;
use crate::ident::{lowercase_ident, UppercaseIdent}; use crate::ident::{lowercase_ident, UppercaseIdent};
use crate::parser::{ use crate::parser::{
and, byte, loc, skip_second, specialize_err, EPackageEntry, EPackageName, Parser, and, byte, loc, map_with_arena, skip_second, specialize_err, EPackageEntry, EPackageName,
Parser,
}; };
use crate::parser::{optional, then}; use crate::parser::{optional, then};
use crate::string_literal; use crate::string_literal;
@ -339,7 +340,7 @@ pub struct PackageEntry<'a> {
} }
pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPackageEntry<'a>> { pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPackageEntry<'a>> {
map_with_arena!( map_with_arena(
// You may optionally have a package shorthand, // You may optionally have a package shorthand,
// e.g. "uc" in `uc: roc/unicode 1.0.0` // e.g. "uc" in `uc: roc/unicode 1.0.0`
// //
@ -349,13 +350,13 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
skip_second( skip_second(
and( and(
specialize_err(|_, pos| EPackageEntry::Shorthand(pos), lowercase_ident()), specialize_err(|_, pos| EPackageEntry::Shorthand(pos), lowercase_ident()),
space0_e(EPackageEntry::IndentPackage) space0_e(EPackageEntry::IndentPackage),
), ),
byte(b':', EPackageEntry::Colon) byte(b':', EPackageEntry::Colon),
), ),
space0_e(EPackageEntry::IndentPackage) space0_e(EPackageEntry::IndentPackage),
)), )),
loc(specialize_err(EPackageEntry::BadPackage, package_name())) loc(specialize_err(EPackageEntry::BadPackage, package_name())),
), ),
move |arena, (opt_shorthand, package_or_path)| { move |arena, (opt_shorthand, package_or_path)| {
let entry = match opt_shorthand { let entry = match opt_shorthand {
@ -376,7 +377,7 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
}; };
Spaced::Item(entry) Spaced::Item(entry)
} },
) )
} }

View file

@ -1457,24 +1457,24 @@ where
#[macro_export] #[macro_export]
macro_rules! collection_inner { macro_rules! collection_inner {
($elem:expr, $delimiter:expr, $space_before:expr) => { ($elem:expr, $delimiter:expr, $space_before:expr) => {
map_with_arena!( $crate::parser::map_with_arena(
$crate::parser::and( $crate::parser::and(
$crate::parser::and( $crate::parser::and(
$crate::blankspace::spaces(), $crate::blankspace::spaces(),
$crate::parser::trailing_sep_by0( $crate::parser::trailing_sep_by0(
$delimiter, $delimiter,
$crate::blankspace::spaces_before_optional_after($elem,) $crate::blankspace::spaces_before_optional_after($elem),
) ),
), ),
$crate::blankspace::spaces() $crate::blankspace::spaces(),
), ),
|arena: &'a bumpalo::Bump, |arena: &'a bumpalo::Bump,
((spaces, mut parsed_elems), mut final_comments): ( ((spaces, mut parsed_elems), mut final_comments): (
( (
&'a [$crate::ast::CommentOrNewline<'a>], &'a [$crate::ast::CommentOrNewline<'a>],
bumpalo::collections::vec::Vec<'a, Loc<_>> bumpalo::collections::vec::Vec<'a, Loc<_>>,
), ),
&'a [$crate::ast::CommentOrNewline<'a>] &'a [$crate::ast::CommentOrNewline<'a>],
)| { )| {
if !spaces.is_empty() { if !spaces.is_empty() {
if let Some(first) = parsed_elems.first_mut() { if let Some(first) = parsed_elems.first_mut() {
@ -1490,7 +1490,7 @@ macro_rules! collection_inner {
parsed_elems.into_bump_slice(), parsed_elems.into_bump_slice(),
final_comments, final_comments,
) )
} },
) )
}; };
} }
@ -2214,53 +2214,6 @@ pub fn map<'a, Output, MappedOutput, E: 'a>(
} }
} }
/// Maps/transforms the `Ok` result of parsing using the given function.
/// Similar to [`map`], but the transform function also takes a bump allocator.
///
/// # Example
///
/// ```
/// # #![forbid(unused_imports)]
/// # use roc_parse::state::State;
/// # use crate::roc_parse::parser::{Parser, Progress, word};
/// # use roc_region::all::Position;
/// # use roc_parse::map_with_arena;
/// # use bumpalo::Bump;
/// # #[derive(Debug, PartialEq)]
/// # enum Problem {
/// # NotFound(Position),
/// # }
/// # let arena = Bump::new();
/// let parser = map_with_arena!(
/// word("hello", Problem::NotFound),
/// |_arena, _output| "new output!"
/// );
///
/// // Success case
/// let (progress, output, state) = parser.parse(&arena, State::new("hello, world".as_bytes()), 0).unwrap();
/// assert_eq!(progress, Progress::MadeProgress);
/// assert_eq!(output, "new output!");
/// assert_eq!(state.pos(), Position::new(5));
///
/// // Error case
/// let (progress, err) = parser.parse(&arena, State::new("bye, world".as_bytes()), 0).unwrap_err();
/// assert_eq!(progress, Progress::NoProgress);
/// assert_eq!(err, Problem::NotFound(Position::zero()));
/// ```
#[macro_export]
macro_rules! map_with_arena {
($parser:expr, $transform:expr) => {
move |arena, state, min_indent| {
#[allow(clippy::redundant_closure_call)]
$parser
.parse(arena, state, min_indent)
.map(|(progress, output, next_state)| {
(progress, $transform(arena, output), next_state)
})
}
};
}
/// Applies the parser as many times as possible. /// Applies the parser as many times as possible.
/// This parser will only fail if the given parser makes partial progress. /// This parser will only fail if the given parser makes partial progress.
#[macro_export] #[macro_export]
@ -2538,9 +2491,6 @@ pub fn between<'a, Before, Inner, After, Err: 'a>(
/// Maps/transforms the `Ok` result of parsing using the given function. /// Maps/transforms the `Ok` result of parsing using the given function.
/// Similar to [`map`], but the transform function also takes a bump allocator. /// Similar to [`map`], but the transform function also takes a bump allocator.
/// ///
/// For some reason, some usages won't compile unless they use this instead of the macro version.
/// This is likely because the lifetime `'a` is not defined at the call site.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -2577,14 +2527,14 @@ pub fn map_with_arena<'a, P, F, Before, After, E>(
) -> impl Parser<'a, After, E> ) -> impl Parser<'a, After, E>
where where
P: Parser<'a, Before, E>, P: Parser<'a, Before, E>,
P: 'a,
F: Fn(&'a Bump, Before) -> After, F: Fn(&'a Bump, Before) -> After,
F: 'a,
Before: 'a,
After: 'a,
E: 'a, E: 'a,
{ {
map_with_arena!(parser, transform) move |arena, state, min_indent| {
parser
.parse(arena, state, min_indent)
.map(|(progress, output, next_state)| (progress, transform(arena, output), next_state))
}
} }
/// Creates a new parser that does not progress but still forwards the output of /// Creates a new parser that does not progress but still forwards the output of

View file

@ -4,8 +4,9 @@ use crate::ident::{lowercase_ident, parse_ident, Accessor, Ident};
use crate::keyword; use crate::keyword;
use crate::parser::Progress::{self, *}; use crate::parser::Progress::{self, *};
use crate::parser::{ use crate::parser::{
self, backtrackable, byte, fail_when, loc, map, optional, skip_first, specialize_err, self, backtrackable, byte, fail_when, loc, map, map_with_arena, optional, skip_first,
specialize_err_ref, then, three_bytes, two_bytes, EPattern, PInParens, PList, PRecord, Parser, specialize_err, specialize_err_ref, then, three_bytes, two_bytes, EPattern, PInParens, PList,
PRecord, Parser,
}; };
use crate::state::State; use crate::state::State;
use crate::string_literal::StrLikeLiteral; use crate::string_literal::StrLikeLiteral;
@ -255,7 +256,7 @@ fn number_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>> {
fn string_like_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>> { fn string_like_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>> {
specialize_err( specialize_err(
|_, pos| EPattern::Start(pos), |_, pos| EPattern::Start(pos),
map_with_arena!( map_with_arena(
crate::string_literal::parse_str_like_literal(), crate::string_literal::parse_str_like_literal(),
|arena, lit| match lit { |arena, lit| match lit {
StrLikeLiteral::Str(s) => Pattern::StrLiteral(s), StrLikeLiteral::Str(s) => Pattern::StrLiteral(s),
@ -263,7 +264,7 @@ fn string_like_pattern_help<'a>() -> impl Parser<'a, Pattern<'a>, EPattern<'a>>
// TODO: preserve the original escaping // TODO: preserve the original escaping
Pattern::SingleQuote(s.to_str_in(arena)) Pattern::SingleQuote(s.to_str_in(arena))
} }
} },
), ),
) )
} }

View file

@ -9,8 +9,8 @@ use crate::expr::{record_field, FoundApplyValue};
use crate::ident::{lowercase_ident, lowercase_ident_keyword_e}; use crate::ident::{lowercase_ident, lowercase_ident_keyword_e};
use crate::keyword; use crate::keyword;
use crate::parser::{ use crate::parser::{
absolute_column_min_indent, and, increment_min_indent, loc, map, skip_first, skip_second, absolute_column_min_indent, and, increment_min_indent, loc, map, map_with_arena, skip_first,
succeed, then, ERecord, ETypeAbilityImpl, skip_second, succeed, then, ERecord, ETypeAbilityImpl,
}; };
use crate::parser::{ use crate::parser::{
allocated, backtrackable, byte, fail, optional, specialize_err, specialize_err_ref, two_bytes, allocated, backtrackable, byte, fail, optional, specialize_err, specialize_err_ref, two_bytes,
@ -116,7 +116,7 @@ fn parse_type_alias_after_as<'a>() -> impl Parser<'a, TypeHeader<'a>, EType<'a>>
} }
fn term<'a>(stop_at_surface_has: bool) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> { fn term<'a>(stop_at_surface_has: bool) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> {
map_with_arena!( map_with_arena(
and( and(
one_of!( one_of!(
loc_wildcard(), loc_wildcard(),
@ -147,7 +147,7 @@ fn term<'a>(stop_at_surface_has: bool) -> impl Parser<'a, Loc<TypeAnnotation<'a>
Some Some
), ),
succeed(None) succeed(None)
] ],
), ),
|arena: &'a Bump, |arena: &'a Bump,
(loc_ann, opt_as): (Loc<TypeAnnotation<'a>>, Option<(&'a [_], TypeHeader<'a>)>)| { (loc_ann, opt_as): (Loc<TypeAnnotation<'a>>, Option<(&'a [_], TypeHeader<'a>)>)| {
@ -163,7 +163,7 @@ fn term<'a>(stop_at_surface_has: bool) -> impl Parser<'a, Loc<TypeAnnotation<'a>
None => loc_ann, None => loc_ann,
} }
} },
) )
.trace("type_annotation:term") .trace("type_annotation:term")
} }
@ -208,7 +208,7 @@ fn loc_inferred<'a>() -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> {
fn loc_applied_arg<'a>( fn loc_applied_arg<'a>(
stop_at_surface_has: bool, stop_at_surface_has: bool,
) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> { ) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> {
map_with_arena!( map_with_arena(
and( and(
backtrackable(space0_e(EType::TIndentStart)), backtrackable(space0_e(EType::TIndentStart)),
one_of!( one_of!(
@ -225,7 +225,7 @@ fn loc_applied_arg<'a>(
)), )),
loc(specialize_err(EType::TApply, concrete_type())), loc(specialize_err(EType::TApply, concrete_type())),
loc(parse_type_variable(stop_at_surface_has)) loc(parse_type_variable(stop_at_surface_has))
) ),
), ),
|arena: &'a Bump, (spaces, argument): (&'a [_], Loc<TypeAnnotation<'a>>)| { |arena: &'a Bump, (spaces, argument): (&'a [_], Loc<TypeAnnotation<'a>>)| {
if spaces.is_empty() { if spaces.is_empty() {
@ -234,7 +234,7 @@ fn loc_applied_arg<'a>(
let Loc { region, value } = argument; let Loc { region, value } = argument;
arena.alloc(value).with_spaces_before(spaces, region) arena.alloc(value).with_spaces_before(spaces, region)
} }
} },
) )
} }