mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-18 17:49:47 +00:00
Merge pull request #7409 from joshuawarner32/fuzzing-bugs-5
Fix another batch of parsing/formatting bugs found in fuzzing
This commit is contained in:
commit
f7dbf850b9
31 changed files with 750 additions and 74 deletions
|
@ -1329,6 +1329,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
|
||||||
item,
|
item,
|
||||||
after,
|
after,
|
||||||
},
|
},
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Spaces {
|
Spaces {
|
||||||
|
@ -1369,7 +1370,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
|
||||||
after: new_res.after,
|
after: new_res.after,
|
||||||
};
|
};
|
||||||
if parens == Parens::InCollection || parens == Parens::InApply {
|
if parens == Parens::InCollection || parens == Parens::InApply {
|
||||||
parens_around_node(arena, inner)
|
parens_around_node(arena, inner, true)
|
||||||
} else {
|
} else {
|
||||||
inner
|
inner
|
||||||
}
|
}
|
||||||
|
@ -1382,7 +1383,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
|
||||||
after: lifted.after,
|
after: lifted.after,
|
||||||
};
|
};
|
||||||
if parens == Parens::InApply || parens == Parens::InAsPattern {
|
if parens == Parens::InApply || parens == Parens::InAsPattern {
|
||||||
parens_around_node(arena, item)
|
parens_around_node(arena, item, true)
|
||||||
} else {
|
} else {
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
@ -1402,12 +1403,24 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
|
||||||
fn parens_around_node<'a, 'b: 'a>(
|
fn parens_around_node<'a, 'b: 'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
item: Spaces<'b, Node<'b>>,
|
item: Spaces<'b, Node<'b>>,
|
||||||
|
allow_spaces_before: bool,
|
||||||
) -> Spaces<'a, Node<'a>> {
|
) -> Spaces<'a, Node<'a>> {
|
||||||
Spaces {
|
Spaces {
|
||||||
before: &[],
|
before: if allow_spaces_before {
|
||||||
|
item.before
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
},
|
||||||
item: Node::DelimitedSequence(
|
item: Node::DelimitedSequence(
|
||||||
Braces::Round,
|
Braces::Round,
|
||||||
arena.alloc_slice_copy(&[(item.before.into(), item.item)]),
|
arena.alloc_slice_copy(&[(
|
||||||
|
if allow_spaces_before {
|
||||||
|
Sp::empty()
|
||||||
|
} else {
|
||||||
|
item.before.into()
|
||||||
|
},
|
||||||
|
item.item,
|
||||||
|
)]),
|
||||||
Sp::empty(),
|
Sp::empty(),
|
||||||
),
|
),
|
||||||
// We move the comments/newlines to the outer scope, since they tend to migrate there when re-parsed
|
// We move the comments/newlines to the outer scope, since they tend to migrate there when re-parsed
|
||||||
|
@ -1432,6 +1445,10 @@ impl<'a, T: Copy> ExtractSpaces<'a> for NodeSpaces<'a, T> {
|
||||||
after: self.after,
|
after: self.after,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn without_spaces(&self) -> T {
|
||||||
|
self.item
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, V: Formattable> Formattable for NodeSpaces<'a, V> {
|
impl<'a, V: Formattable> Formattable for NodeSpaces<'a, V> {
|
||||||
|
|
|
@ -291,7 +291,7 @@ fn format_expr_only(
|
||||||
let inner_parens = if needs_parens {
|
let inner_parens = if needs_parens {
|
||||||
Parens::NotNeeded
|
Parens::NotNeeded
|
||||||
} else {
|
} else {
|
||||||
Parens::InApply
|
Parens::InApplyLastArg
|
||||||
};
|
};
|
||||||
|
|
||||||
if !before_all_newlines {
|
if !before_all_newlines {
|
||||||
|
@ -1314,13 +1314,21 @@ pub fn expr_lift_spaces<'a, 'b: 'a>(
|
||||||
after: right_lifted.after,
|
after: right_lifted.after,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::UnaryOp(expr, op) => {
|
Expr::UnaryOp(inner, op) => {
|
||||||
let expr_lifted = expr_lift_spaces_after(Parens::InOperator, arena, &expr.value);
|
if parens == Parens::InApply && matches!(inner.without_spaces(), Expr::Closure(..)) {
|
||||||
|
return Spaces {
|
||||||
|
before: &[],
|
||||||
|
item: Expr::ParensAround(arena.alloc(*expr)),
|
||||||
|
after: &[],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let inner_lifted = expr_lift_spaces_after(Parens::InOperator, arena, &inner.value);
|
||||||
|
|
||||||
Spaces {
|
Spaces {
|
||||||
before: &[],
|
before: &[],
|
||||||
item: Expr::UnaryOp(arena.alloc(Loc::at(expr.region, expr_lifted.item)), *op),
|
item: Expr::UnaryOp(arena.alloc(Loc::at(inner.region, inner_lifted.item)), *op),
|
||||||
after: expr_lifted.after,
|
after: inner_lifted.after,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@ impl<'a, T: Copy> ExtractSpaces<'a> for Spaces<'a, T> {
|
||||||
fn extract_spaces(&self) -> Spaces<'a, T> {
|
fn extract_spaces(&self) -> Spaces<'a, T> {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn without_spaces(&self) -> T {
|
||||||
|
self.item
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
@ -111,6 +115,7 @@ impl<'a, T: Debug> Debug for Spaced<'a, T> {
|
||||||
pub trait ExtractSpaces<'a>: Sized + Copy {
|
pub trait ExtractSpaces<'a>: Sized + Copy {
|
||||||
type Item;
|
type Item;
|
||||||
fn extract_spaces(&self) -> Spaces<'a, Self::Item>;
|
fn extract_spaces(&self) -> Spaces<'a, Self::Item>;
|
||||||
|
fn without_spaces(&self) -> Self::Item;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for &'a T {
|
impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for &'a T {
|
||||||
|
@ -118,6 +123,10 @@ impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for &'a T {
|
||||||
fn extract_spaces(&self) -> Spaces<'a, Self::Item> {
|
fn extract_spaces(&self) -> Spaces<'a, Self::Item> {
|
||||||
(*self).extract_spaces()
|
(*self).extract_spaces()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn without_spaces(&self) -> Self::Item {
|
||||||
|
(*self).without_spaces()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for Loc<T> {
|
impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for Loc<T> {
|
||||||
|
@ -130,6 +139,10 @@ impl<'a, T: ExtractSpaces<'a>> ExtractSpaces<'a> for Loc<T> {
|
||||||
after: spaces.after,
|
after: spaces.after,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn without_spaces(&self) -> Self::Item {
|
||||||
|
self.value.without_spaces()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Header<'a> {
|
impl<'a> Header<'a> {
|
||||||
|
@ -2350,6 +2363,17 @@ macro_rules! impl_extract_spaces {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn without_spaces(&self) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
$t::SpaceBefore(item, _) => {
|
||||||
|
item.without_spaces()
|
||||||
|
},
|
||||||
|
$t::SpaceAfter(item, _) => {
|
||||||
|
item.without_spaces()
|
||||||
|
},
|
||||||
|
_ => *self,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2412,6 +2436,14 @@ impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn without_spaces(&self) -> T {
|
||||||
|
match self {
|
||||||
|
Spaced::SpaceBefore(item, _) => item.without_spaces(),
|
||||||
|
Spaced::SpaceAfter(item, _) => item.without_spaces(),
|
||||||
|
Spaced::Item(item) => *item,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ExtractSpaces<'a> for AbilityImpls<'a> {
|
impl<'a> ExtractSpaces<'a> for AbilityImpls<'a> {
|
||||||
|
@ -2454,6 +2486,14 @@ impl<'a> ExtractSpaces<'a> for AbilityImpls<'a> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn without_spaces(&self) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
AbilityImpls::AbilityImpls(inner) => *inner,
|
||||||
|
AbilityImpls::SpaceBefore(item, _) => item.without_spaces(),
|
||||||
|
AbilityImpls::SpaceAfter(item, _) => item.without_spaces(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Malformed {
|
pub trait Malformed {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::ast::{Collection, Implements, Pattern, PatternAs, Spaceable};
|
use crate::ast::{Collection, ExtractSpaces, Implements, Pattern, PatternAs, Spaceable};
|
||||||
use crate::blankspace::{space0_e, spaces, spaces_before};
|
use crate::blankspace::{space0_e, spaces, spaces_before};
|
||||||
use crate::ident::{lowercase_ident, parse_ident, Accessor, Ident};
|
use crate::ident::{lowercase_ident, parse_ident, Accessor, Ident};
|
||||||
use crate::keyword;
|
use crate::keyword;
|
||||||
|
@ -150,7 +150,7 @@ fn loc_tag_pattern_arg<'a>(
|
||||||
|
|
||||||
if stop_on_has_kw
|
if stop_on_has_kw
|
||||||
&& matches!(
|
&& matches!(
|
||||||
value,
|
value.without_spaces(),
|
||||||
Pattern::Identifier {
|
Pattern::Identifier {
|
||||||
ident: crate::keyword::IMPLEMENTS,
|
ident: crate::keyword::IMPLEMENTS,
|
||||||
..
|
..
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
AbilityImpls, AssignedField, CommentOrNewline, Expr, FunctionArrow, ImplementsAbilities,
|
AbilityImpls, AssignedField, Collection, CommentOrNewline, Expr, FunctionArrow,
|
||||||
ImplementsAbility, ImplementsClause, Pattern, Spaceable, Spaced, Tag, TypeAnnotation,
|
ImplementsAbilities, ImplementsAbility, ImplementsClause, Pattern, Spaceable, Spaced, Tag,
|
||||||
TypeHeader,
|
TypeAnnotation, TypeHeader,
|
||||||
};
|
};
|
||||||
use crate::blankspace::{
|
use crate::blankspace::{
|
||||||
space0_around_ee, space0_before_e, space0_before_optional_after, space0_e,
|
space0_around_ee, space0_before_e, space0_before_optional_after, space0_e,
|
||||||
|
spaces_before_optional_after,
|
||||||
};
|
};
|
||||||
use crate::expr::record_field;
|
use crate::expr::record_field;
|
||||||
use crate::ident::{lowercase_ident, lowercase_ident_keyword_e};
|
use crate::ident::{lowercase_ident, lowercase_ident_keyword_e};
|
||||||
|
@ -12,7 +13,7 @@ use crate::keyword;
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
absolute_column_min_indent, and, collection_trailing_sep_e, either, error_on_byte,
|
absolute_column_min_indent, and, collection_trailing_sep_e, either, error_on_byte,
|
||||||
increment_min_indent, indented_seq, loc, map, map_with_arena, skip_first, skip_second, succeed,
|
increment_min_indent, indented_seq, loc, map, map_with_arena, skip_first, skip_second, succeed,
|
||||||
then, zero_or_more, ERecord, ETypeAbilityImpl,
|
then, zero_or_more, ERecord, ETypeAbilityImpl, ParseResult,
|
||||||
};
|
};
|
||||||
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,
|
||||||
|
@ -256,40 +257,259 @@ fn loc_applied_arg<'a>(
|
||||||
fn loc_type_in_parens<'a>(
|
fn loc_type_in_parens<'a>(
|
||||||
stop_at_surface_has: bool,
|
stop_at_surface_has: bool,
|
||||||
) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, ETypeInParens<'a>> {
|
) -> impl Parser<'a, Loc<TypeAnnotation<'a>>, ETypeInParens<'a>> {
|
||||||
then(
|
(move |arena, state: State<'a>, min_indent: u32| {
|
||||||
loc(and(
|
// This used to just be the following code (roughly):
|
||||||
collection_trailing_sep_e(
|
// loc(and(
|
||||||
byte(b'(', ETypeInParens::Open),
|
// collection_trailing_sep_e(
|
||||||
specialize_err_ref(ETypeInParens::Type, expression(true, false)),
|
// byte(b'(', ETypeInParens::Open),
|
||||||
byte(b',', ETypeInParens::End),
|
// specialize_err_ref(ETypeInParens::Type, expression(true, false)),
|
||||||
byte(b')', ETypeInParens::End),
|
// byte(b',', ETypeInParens::End),
|
||||||
TypeAnnotation::SpaceBefore,
|
// byte(b')', ETypeInParens::End),
|
||||||
|
// TypeAnnotation::SpaceBefore,
|
||||||
|
// ),
|
||||||
|
// optional(allocated(specialize_err_ref(
|
||||||
|
// ETypeInParens::Type,
|
||||||
|
// term(stop_at_surface_has),
|
||||||
|
// ))),
|
||||||
|
// )),
|
||||||
|
//
|
||||||
|
// However, we need to implement this manually in order to performantly handle both function types and tuples.
|
||||||
|
// For example:
|
||||||
|
// We might have a long list of items in a tuple, e.g. `(a, b, c, d, e, f)`,
|
||||||
|
// and if we were simply parsing a collection of expressions, we would start by trying to
|
||||||
|
// parse `a, b, c, d, e, f` as part of `expression`, see that there is no `->` token next,
|
||||||
|
// then backtrack and return just `a` as the result.
|
||||||
|
// Repeat for b, and so on.
|
||||||
|
// This can lead to exponential behavior, repeating the parsing of the same items over and over.
|
||||||
|
//
|
||||||
|
// Instead, here we integrate the parsing of function types directly into the parsing of the tuple loop,
|
||||||
|
// so that we don't have to discard the work we've done so far.
|
||||||
|
|
||||||
|
let mut fields = Vec::new_in(arena);
|
||||||
|
let mut state = state;
|
||||||
|
let start = state.pos();
|
||||||
|
|
||||||
|
let mut func_base = 0;
|
||||||
|
|
||||||
|
// Parse the opening parenthesis
|
||||||
|
let (_, _, new_state) = byte(b'(', ETypeInParens::Open).parse(arena, state, min_indent)?;
|
||||||
|
state = new_state;
|
||||||
|
|
||||||
|
// Parse the initial comments if any
|
||||||
|
let (_, spaces, new_state) = space0_e(ETypeInParens::IndentEnd).parse(arena, state, 0)?;
|
||||||
|
state = new_state;
|
||||||
|
|
||||||
|
match spaces_before_optional_after(specialize_err_ref(
|
||||||
|
ETypeInParens::Type,
|
||||||
|
term_or_apply_with_as(false),
|
||||||
|
))
|
||||||
|
.parse(arena, state.clone(), 0)
|
||||||
|
{
|
||||||
|
Ok((progress, first_field, next_state)) => {
|
||||||
|
debug_assert_eq!(progress, MadeProgress);
|
||||||
|
state = next_state;
|
||||||
|
fields.push(first_field);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
enum Sep {
|
||||||
|
Comma,
|
||||||
|
FunctionArrow(FunctionArrow),
|
||||||
|
Where,
|
||||||
|
}
|
||||||
|
let sep = one_of![
|
||||||
|
map(byte(b',', ETypeInParens::End), |_| Sep::Comma),
|
||||||
|
map(
|
||||||
|
specialize_err_ref(ETypeInParens::Type, arrow()),
|
||||||
|
Sep::FunctionArrow
|
||||||
),
|
),
|
||||||
optional(allocated(specialize_err_ref(
|
map(word(keyword::WHERE, ETypeInParens::End), |_| Sep::Where),
|
||||||
|
];
|
||||||
|
|
||||||
|
match sep.parse(arena, state.clone(), 0) {
|
||||||
|
Ok((_, Sep::Comma, next_state)) => {
|
||||||
|
match spaces_before_optional_after(specialize_err_ref(
|
||||||
|
ETypeInParens::Type,
|
||||||
|
term_or_apply_with_as(false),
|
||||||
|
))
|
||||||
|
.parse(arena, next_state.clone(), 0)
|
||||||
|
{
|
||||||
|
Ok((element_progress, next_field, next_state)) => {
|
||||||
|
debug_assert_eq!(element_progress, MadeProgress);
|
||||||
|
state = next_state;
|
||||||
|
fields.push(next_field);
|
||||||
|
}
|
||||||
|
Err((_, _fail)) => {
|
||||||
|
state = next_state;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((_, Sep::FunctionArrow(arrow), next_state)) => {
|
||||||
|
state = next_state;
|
||||||
|
|
||||||
|
let (_, return_type, new_state) = specialize_err_ref(
|
||||||
|
ETypeInParens::Type,
|
||||||
|
space0_before_e(arrow_sequence(), EType::TIndentStart),
|
||||||
|
)
|
||||||
|
.parse(arena, state.clone(), min_indent)
|
||||||
|
.map_err(|(_, e)| (MadeProgress, e))?;
|
||||||
|
|
||||||
|
state = new_state;
|
||||||
|
|
||||||
|
let region = Region::between(
|
||||||
|
fields
|
||||||
|
.get(func_base)
|
||||||
|
.map(|f| f.region.start())
|
||||||
|
.unwrap_or(start),
|
||||||
|
return_type.region.end(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// prepare arguments
|
||||||
|
let arguments = arena.alloc_slice_copy(&fields[func_base..]);
|
||||||
|
debug_assert!(!arguments.is_empty());
|
||||||
|
fields.truncate(func_base);
|
||||||
|
|
||||||
|
let output = arena.alloc(arguments);
|
||||||
|
|
||||||
|
let result = Loc {
|
||||||
|
region,
|
||||||
|
value: TypeAnnotation::Function(
|
||||||
|
output,
|
||||||
|
arrow,
|
||||||
|
arena.alloc(return_type),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
fields.push(result);
|
||||||
|
func_base = fields.len();
|
||||||
|
}
|
||||||
|
Ok((_, Sep::Where, new_state)) => {
|
||||||
|
let (_, implements_clauses, new_state) =
|
||||||
|
parse_implements_clause_chain_after_where(arena, 0, new_state)
|
||||||
|
.map_err(|(_, e)| {
|
||||||
|
(MadeProgress, ETypeInParens::Type(arena.alloc(e), start))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
state = new_state;
|
||||||
|
let end = state.pos();
|
||||||
|
|
||||||
|
let last = fields[fields.len() - 1];
|
||||||
|
fields.pop();
|
||||||
|
let region = Region::between(last.region.start(), end);
|
||||||
|
fields.push(Loc::at(
|
||||||
|
region,
|
||||||
|
TypeAnnotation::Where(arena.alloc(last), implements_clauses),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Err((delim_progress, fail)) => match delim_progress {
|
||||||
|
MadeProgress => return Err((MadeProgress, fail)),
|
||||||
|
NoProgress => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err((element_progress, fail)) => match element_progress {
|
||||||
|
MadeProgress => return Err((MadeProgress, fail)),
|
||||||
|
NoProgress => {}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the final comments if any
|
||||||
|
let (_, mut final_comments, new_state) =
|
||||||
|
space0_e(ETypeInParens::IndentEnd).parse(arena, state, 0)?;
|
||||||
|
state = new_state;
|
||||||
|
|
||||||
|
// Parse the closing parenthesis
|
||||||
|
let (_, _, new_state) = byte(b')', ETypeInParens::End)
|
||||||
|
.trace("end")
|
||||||
|
.parse(arena, state, 0)
|
||||||
|
.map_err(|(_, e)| (MadeProgress, e))?;
|
||||||
|
state = new_state;
|
||||||
|
|
||||||
|
if !spaces.is_empty() {
|
||||||
|
if let Some(first) = fields.first_mut() {
|
||||||
|
first.value = TypeAnnotation::SpaceBefore(arena.alloc(first.value), spaces);
|
||||||
|
} else {
|
||||||
|
debug_assert!(final_comments.is_empty());
|
||||||
|
final_comments = spaces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fields =
|
||||||
|
Collection::with_items_and_comments(arena, fields.into_bump_slice(), final_comments);
|
||||||
|
|
||||||
|
// Optionally parse the extension
|
||||||
|
let (progress, ext, state) = optional(allocated(specialize_err_ref(
|
||||||
ETypeInParens::Type,
|
ETypeInParens::Type,
|
||||||
term(stop_at_surface_has),
|
term(stop_at_surface_has),
|
||||||
))),
|
)))
|
||||||
)),
|
.parse(arena, state, min_indent)?;
|
||||||
|_arena, state, progress, item| {
|
|
||||||
let Loc {
|
let end = state.pos();
|
||||||
region,
|
|
||||||
value: (fields, ext),
|
// Determine the result based on the parsed fields and extension
|
||||||
} = item;
|
let result = if fields.len() > 1 || ext.is_some() {
|
||||||
if fields.len() > 1 || ext.is_some() {
|
TypeAnnotation::Tuple { elems: fields, ext }
|
||||||
Ok((
|
|
||||||
MadeProgress,
|
|
||||||
Loc::at(region, TypeAnnotation::Tuple { elems: fields, ext }),
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
} else if fields.len() == 1 {
|
} else if fields.len() == 1 {
|
||||||
Ok((MadeProgress, fields.items[0], state))
|
return Ok((MadeProgress, fields.items[0], state));
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(fields.is_empty());
|
debug_assert!(fields.is_empty());
|
||||||
Err((progress, ETypeInParens::Empty(state.pos())))
|
return Err((progress, ETypeInParens::Empty(state.pos())));
|
||||||
|
};
|
||||||
|
|
||||||
|
let region = Region::between(start, end);
|
||||||
|
Ok((MadeProgress, Loc::at(region, result), state))
|
||||||
|
})
|
||||||
|
.trace("type_annotation:type_in_parens")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arrow<'a>() -> impl Parser<'a, FunctionArrow, EType<'a>> {
|
||||||
|
one_of![
|
||||||
|
map(two_bytes(b'-', b'>', EType::TStart), |_| {
|
||||||
|
FunctionArrow::Pure
|
||||||
|
}),
|
||||||
|
map(two_bytes(b'=', b'>', EType::TStart), |_| {
|
||||||
|
FunctionArrow::Effectful
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arrow_sequence<'a>() -> impl Parser<'a, Loc<TypeAnnotation<'a>>, EType<'a>> {
|
||||||
|
// A sequence of a -> b -> c -> etc
|
||||||
|
map_with_arena(
|
||||||
|
and(
|
||||||
|
term_or_apply_with_as(false),
|
||||||
|
zero_or_more(and(arrow(), term_or_apply_with_as(false))),
|
||||||
|
),
|
||||||
|
|arena, (first, rest)| {
|
||||||
|
let mut it = rest.into_iter().rev();
|
||||||
|
if let Some((mut arrow, mut item)) = it.next() {
|
||||||
|
for (n_arrow, next) in it {
|
||||||
|
let region = Region::span_across(&next.region, &item.region);
|
||||||
|
let value = TypeAnnotation::Function(
|
||||||
|
arena.alloc_slice_copy(&[next]),
|
||||||
|
arrow,
|
||||||
|
arena.alloc(item),
|
||||||
|
);
|
||||||
|
item = Loc::at(region, value);
|
||||||
|
arrow = n_arrow;
|
||||||
|
}
|
||||||
|
let region = Region::span_across(&first.region, &item.region);
|
||||||
|
Loc::at(
|
||||||
|
region,
|
||||||
|
TypeAnnotation::Function(
|
||||||
|
arena.alloc_slice_copy(&[first]),
|
||||||
|
arrow,
|
||||||
|
arena.alloc(item),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
first
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.trace("type_annotation:type_in_parens")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -518,6 +738,17 @@ fn implements_clause_chain<'a>(
|
||||||
)
|
)
|
||||||
.parse(arena, state, min_indent)?;
|
.parse(arena, state, min_indent)?;
|
||||||
|
|
||||||
|
let (_, clauses, state) =
|
||||||
|
parse_implements_clause_chain_after_where(arena, min_indent, state)?;
|
||||||
|
Ok((MadeProgress, (spaces_before, clauses), state))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_implements_clause_chain_after_where<'a>(
|
||||||
|
arena: &'a Bump,
|
||||||
|
min_indent: u32,
|
||||||
|
state: State<'a>,
|
||||||
|
) -> ParseResult<'a, &'a [Loc<ImplementsClause<'a>>], EType<'a>> {
|
||||||
// Parse the first clause (there must be one), then the rest
|
// Parse the first clause (there must be one), then the rest
|
||||||
let (_, first_clause, state) = implements_clause().parse(arena, state, min_indent)?;
|
let (_, first_clause, state) = implements_clause().parse(arena, state, min_indent)?;
|
||||||
|
|
||||||
|
@ -530,12 +761,7 @@ fn implements_clause_chain<'a>(
|
||||||
// Usually the number of clauses shouldn't be too large, so this is okay
|
// Usually the number of clauses shouldn't be too large, so this is okay
|
||||||
clauses.insert(0, first_clause);
|
clauses.insert(0, first_clause);
|
||||||
|
|
||||||
Ok((
|
Ok((MadeProgress, clauses.into_bump_slice(), state))
|
||||||
MadeProgress,
|
|
||||||
(spaces_before, clauses.into_bump_slice()),
|
|
||||||
state,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a implements-abilities clause, e.g. `implements [Eq, Hash]`.
|
/// Parse a implements-abilities clause, e.g. `implements [Eq, Hash]`.
|
||||||
|
@ -643,7 +869,8 @@ fn expression<'a>(
|
||||||
term_or_apply_with_as(stop_at_surface_has),
|
term_or_apply_with_as(stop_at_surface_has),
|
||||||
EType::TIndentStart,
|
EType::TIndentStart,
|
||||||
)
|
)
|
||||||
.parse(arena, state, min_indent)?;
|
.parse(arena, state, min_indent)
|
||||||
|
.map_err(|(_, e)| (MadeProgress, e))?;
|
||||||
|
|
||||||
let region = Region::span_across(&first.region, &return_type.region);
|
let region = Region::span_across(&first.region, &return_type.region);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Expr(BackpassArrow(@3), @0)
|
|
@ -0,0 +1,3 @@
|
||||||
|
n,U(implements
|
||||||
|
)<-t
|
||||||
|
9
|
|
@ -1 +1 @@
|
||||||
Expr(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(Type(TInParens(End(@78), @74), @72), @71), @69), @68), @66), @65), @61), @60), @58), @57), @53), @52), @50), @49), @47), @46), @44), @43), @41), @40), @39), @38), @36), @35), @31), @30), @28), @27), @23), @22), @20), @19), @17), @16), @11), @10), @8), @7), @3), @2), @2), @0)
|
Expr(Type(TInParens(End(@7), @2), @2), @0)
|
|
@ -0,0 +1 @@
|
||||||
|
Expr(Type(TIndentEnd(@397), @2), @0)
|
|
@ -0,0 +1,14 @@
|
||||||
|
K:bMM,(
|
||||||
|
A0,AectAfects,(
|
||||||
|
A0,AenAA1M,(
|
||||||
|
A0,Ae,(
|
||||||
|
A0bMprovi0,A=>A1,MA,M,e,M,A ,A ,s,(
|
||||||
|
AbMM,(A0
|
||||||
|
,Ae,(
|
||||||
|
A0bMprovi0,A=>A1,MA,M,e,M,e8,ActAfects,(
|
||||||
|
A0,AenAA1M,(
|
||||||
|
A0,Ae,(
|
||||||
|
A0bMprovi0,A=>A1,MA,M,e,M,A ,A ,s,(
|
||||||
|
AbMM,(A0
|
||||||
|
,Ae,(
|
||||||
|
A0bMprovi0,A=>A1,MA,M,e,M,e8,A)WM,ulsee,M,e8,A)db1,MA,M,e,M,e8,A)WM,ulsee,M,e8,A)dbgMA,MO,e,M,e4,A)WA)WenA1)WM,ulsee,M,e8,A)db1,MA,M,e,M,e8,A)WM,ulsee,M,e8,A)dbgMA,MO,e,M,e4,A)WA)WenA1,A)W
|
|
@ -1,5 +1,6 @@
|
||||||
1 : (
|
1 : (
|
||||||
f,
|
f,
|
||||||
(ww -> p),
|
ww
|
||||||
|
-> p,
|
||||||
)e
|
)e
|
||||||
Mh
|
Mh
|
|
@ -21,6 +21,8 @@
|
||||||
),
|
),
|
||||||
@2-13 Tuple {
|
@2-13 Tuple {
|
||||||
elems: [
|
elems: [
|
||||||
|
@3-11 Function(
|
||||||
|
[
|
||||||
@3-4 SpaceAfter(
|
@3-4 SpaceAfter(
|
||||||
BoundVariable(
|
BoundVariable(
|
||||||
"f",
|
"f",
|
||||||
|
@ -29,8 +31,6 @@
|
||||||
Newline,
|
Newline,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@6-11 Function(
|
|
||||||
[
|
|
||||||
@6-8 BoundVariable(
|
@6-8 BoundVariable(
|
||||||
"ww",
|
"ww",
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
\L z -> 42
|
|
@ -0,0 +1,32 @@
|
||||||
|
@0-13 SpaceAfter(
|
||||||
|
Closure(
|
||||||
|
[
|
||||||
|
@1-5 Apply(
|
||||||
|
@1-2 Tag(
|
||||||
|
"L",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
@4-5 SpaceAfter(
|
||||||
|
SpaceAfter(
|
||||||
|
Identifier {
|
||||||
|
ident: "z",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@11-13 Num(
|
||||||
|
"42",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
\L((z
|
||||||
|
)
|
||||||
|
)->42
|
|
@ -0,0 +1,3 @@
|
||||||
|
m
|
||||||
|
^ (-\w -> m)
|
||||||
|
w
|
|
@ -0,0 +1,49 @@
|
||||||
|
@0-14 SpaceAfter(
|
||||||
|
BinOps(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
@0-1 SpaceAfter(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "m",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@3-4 Caret,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@5-14 Apply(
|
||||||
|
@5-11 UnaryOp(
|
||||||
|
@6-11 Closure(
|
||||||
|
[
|
||||||
|
@7-8 Identifier {
|
||||||
|
ident: "w",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
@10-11 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "m",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
@5-6 Negate,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
@13-14 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "w",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
m
|
||||||
|
^ -\w->m
|
||||||
|
w
|
|
@ -0,0 +1,2 @@
|
||||||
|
1 : w -> (w -> p)
|
||||||
|
h
|
|
@ -0,0 +1,58 @@
|
||||||
|
@0-13 SpaceAfter(
|
||||||
|
Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
EitherIndex(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@0-11,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
spaces: [],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Annotation(
|
||||||
|
@0-1 NumLiteral(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
@3-10 Function(
|
||||||
|
[
|
||||||
|
@3-4 BoundVariable(
|
||||||
|
"w",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Pure,
|
||||||
|
@6-10 Function(
|
||||||
|
[
|
||||||
|
@6-7 BoundVariable(
|
||||||
|
"w",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Pure,
|
||||||
|
@9-10 BoundVariable(
|
||||||
|
"p",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@12-13 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "h",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
1:(w->w->p)
|
||||||
|
h
|
|
@ -0,0 +1,5 @@
|
||||||
|
1 : (
|
||||||
|
w -> p,
|
||||||
|
(w -> p),
|
||||||
|
)
|
||||||
|
h
|
|
@ -0,0 +1,71 @@
|
||||||
|
@0-16 SpaceAfter(
|
||||||
|
Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
EitherIndex(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@0-14,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
spaces: [],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Annotation(
|
||||||
|
@0-1 NumLiteral(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
@2-14 Tuple {
|
||||||
|
elems: [
|
||||||
|
@3-7 Function(
|
||||||
|
[
|
||||||
|
@3-4 BoundVariable(
|
||||||
|
"w",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Pure,
|
||||||
|
@6-7 BoundVariable(
|
||||||
|
"p",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
@9-13 Function(
|
||||||
|
[
|
||||||
|
@9-10 SpaceBefore(
|
||||||
|
BoundVariable(
|
||||||
|
"w",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Pure,
|
||||||
|
@12-13 BoundVariable(
|
||||||
|
"p",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ext: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@15-16 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "h",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
1:(w->p,
|
||||||
|
w->p)
|
||||||
|
h
|
|
@ -0,0 +1,3 @@
|
||||||
|
!\t ->
|
||||||
|
m, i <- 0
|
||||||
|
s
|
|
@ -0,0 +1,42 @@
|
||||||
|
@0-16 SpaceAfter(
|
||||||
|
UnaryOp(
|
||||||
|
@1-16 Closure(
|
||||||
|
[
|
||||||
|
@2-3 Identifier {
|
||||||
|
ident: "t",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
@7-16 SpaceBefore(
|
||||||
|
Backpassing(
|
||||||
|
[
|
||||||
|
@7-8 Identifier {
|
||||||
|
ident: "m",
|
||||||
|
},
|
||||||
|
@9-10 Identifier {
|
||||||
|
ident: "i",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
@12-13 Num(
|
||||||
|
"0",
|
||||||
|
),
|
||||||
|
@15-16 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "s",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
@0-1 Not,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
!\t->
|
||||||
|
m,i<-0
|
||||||
|
s
|
|
@ -0,0 +1,2 @@
|
||||||
|
f : (a, b -> c, (d -> e), g)
|
||||||
|
f
|
|
@ -0,0 +1,72 @@
|
||||||
|
@0-27 SpaceAfter(
|
||||||
|
Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
EitherIndex(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@0-25,
|
||||||
|
],
|
||||||
|
space_before: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
space_after: [
|
||||||
|
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
|
||||||
|
],
|
||||||
|
spaces: [],
|
||||||
|
type_defs: [],
|
||||||
|
value_defs: [
|
||||||
|
Annotation(
|
||||||
|
@0-1 Identifier {
|
||||||
|
ident: "f",
|
||||||
|
},
|
||||||
|
@3-25 Tuple {
|
||||||
|
elems: [
|
||||||
|
@4-13 Function(
|
||||||
|
[
|
||||||
|
@4-5 BoundVariable(
|
||||||
|
"a",
|
||||||
|
),
|
||||||
|
@7-8 BoundVariable(
|
||||||
|
"b",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Pure,
|
||||||
|
@12-13 BoundVariable(
|
||||||
|
"c",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
@15-21 Function(
|
||||||
|
[
|
||||||
|
@15-16 BoundVariable(
|
||||||
|
"d",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Pure,
|
||||||
|
@20-21 BoundVariable(
|
||||||
|
"e",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
@23-24 BoundVariable(
|
||||||
|
"g",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ext: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@26-27 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "f",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
f: (a, b -> c, d -> e, g)
|
||||||
|
f
|
|
@ -209,6 +209,7 @@ mod test_snapshots {
|
||||||
fail/if_outdented_else_branch.expr,
|
fail/if_outdented_else_branch.expr,
|
||||||
fail/if_outdented_then.expr,
|
fail/if_outdented_then.expr,
|
||||||
fail/ifbang_eqeq.expr,
|
fail/ifbang_eqeq.expr,
|
||||||
|
fail/implements_in_multibackpassing_parens.expr,
|
||||||
fail/import_with_lowercase_alias.moduledefs,
|
fail/import_with_lowercase_alias.moduledefs,
|
||||||
fail/imports_missing_comma.header,
|
fail/imports_missing_comma.header,
|
||||||
fail/inline_hastype.expr,
|
fail/inline_hastype.expr,
|
||||||
|
@ -228,6 +229,7 @@ mod test_snapshots {
|
||||||
fail/nested_tuples_annotation_terrible_perf.expr,
|
fail/nested_tuples_annotation_terrible_perf.expr,
|
||||||
fail/nested_when_expect_binop_when.expr,
|
fail/nested_when_expect_binop_when.expr,
|
||||||
fail/newline_before_operator_with_defs.expr,
|
fail/newline_before_operator_with_defs.expr,
|
||||||
|
fail/oom_repro.expr,
|
||||||
fail/opaque_type_def_with_newline.expr,
|
fail/opaque_type_def_with_newline.expr,
|
||||||
fail/pattern_binds_keyword.expr,
|
fail/pattern_binds_keyword.expr,
|
||||||
fail/pattern_in_parens_end.expr,
|
fail/pattern_in_parens_end.expr,
|
||||||
|
@ -351,7 +353,9 @@ mod test_snapshots {
|
||||||
pass/closure_in_apply_in_binop.expr,
|
pass/closure_in_apply_in_binop.expr,
|
||||||
pass/closure_in_binop_with_spaces.expr,
|
pass/closure_in_binop_with_spaces.expr,
|
||||||
pass/closure_newline_empty_record_newline.expr,
|
pass/closure_newline_empty_record_newline.expr,
|
||||||
|
pass/closure_parens_double_newlines.expr,
|
||||||
pass/closure_pat_reccord_comment.expr,
|
pass/closure_pat_reccord_comment.expr,
|
||||||
|
pass/closure_with_binops_and_unary.expr,
|
||||||
pass/closure_with_underscores.expr,
|
pass/closure_with_underscores.expr,
|
||||||
pass/comma_prefixed_indented_record.expr,
|
pass/comma_prefixed_indented_record.expr,
|
||||||
pass/comment_after_annotation.expr,
|
pass/comment_after_annotation.expr,
|
||||||
|
@ -380,6 +384,7 @@ mod test_snapshots {
|
||||||
pass/crazy_backpassing_parens.expr,
|
pass/crazy_backpassing_parens.expr,
|
||||||
pass/crazy_implements_bangs.expr,
|
pass/crazy_implements_bangs.expr,
|
||||||
pass/crazy_pat_ann.expr,
|
pass/crazy_pat_ann.expr,
|
||||||
|
pass/curried_function_type.expr,
|
||||||
pass/dbg.expr,
|
pass/dbg.expr,
|
||||||
pass/dbg_bang_neg_bang_if_bang.expr,
|
pass/dbg_bang_neg_bang_if_bang.expr,
|
||||||
pass/dbg_double.expr,
|
pass/dbg_double.expr,
|
||||||
|
@ -397,6 +402,7 @@ mod test_snapshots {
|
||||||
pass/destructure_tag_assignment.expr,
|
pass/destructure_tag_assignment.expr,
|
||||||
pass/docs.expr,
|
pass/docs.expr,
|
||||||
pass/double_closure_newlines_binop.expr,
|
pass/double_closure_newlines_binop.expr,
|
||||||
|
pass/double_function_tuple.expr,
|
||||||
pass/double_parens_as_in_backpassing_pat.expr,
|
pass/double_parens_as_in_backpassing_pat.expr,
|
||||||
pass/double_parens_comment_tuple_pat.expr,
|
pass/double_parens_comment_tuple_pat.expr,
|
||||||
pass/double_question_binop.expr,
|
pass/double_question_binop.expr,
|
||||||
|
@ -552,6 +558,7 @@ mod test_snapshots {
|
||||||
pass/nonempty_hosted_header.header,
|
pass/nonempty_hosted_header.header,
|
||||||
pass/nonempty_package_header.header,
|
pass/nonempty_package_header.header,
|
||||||
pass/nonempty_platform_header.header,
|
pass/nonempty_platform_header.header,
|
||||||
|
pass/not_closure_with_multibackpassing.expr,
|
||||||
pass/not_double_parens.expr,
|
pass/not_double_parens.expr,
|
||||||
pass/not_multiline_string.expr,
|
pass/not_multiline_string.expr,
|
||||||
pass/not_record_updater.expr,
|
pass/not_record_updater.expr,
|
||||||
|
@ -700,6 +707,7 @@ mod test_snapshots {
|
||||||
pass/tuple_accessor_function.expr,
|
pass/tuple_accessor_function.expr,
|
||||||
pass/tuple_apply_parens_comment.expr,
|
pass/tuple_apply_parens_comment.expr,
|
||||||
pass/tuple_destructure_bang.expr,
|
pass/tuple_destructure_bang.expr,
|
||||||
|
pass/tuple_funcs_in_parens.expr,
|
||||||
pass/tuple_function_annotation.expr,
|
pass/tuple_function_annotation.expr,
|
||||||
pass/tuple_type.expr,
|
pass/tuple_type.expr,
|
||||||
pass/tuple_type_ext.expr,
|
pass/tuple_type_ext.expr,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue