Remove a gazillion allocations from reporting

This commit is contained in:
Richard Feldman 2022-04-19 20:22:17 -04:00
parent 7fc01a0a9b
commit 3f698c9878
No known key found for this signature in database
GPG key ID: 7E4127D1E4241798
5 changed files with 316 additions and 338 deletions

View file

@ -4518,7 +4518,7 @@ fn to_file_problem_report(filename: &Path, error: io::ErrorKind) -> String {
alloc alloc
.parser_suggestion(filename.to_str().unwrap()) .parser_suggestion(filename.to_str().unwrap())
.indent(4), .indent(4),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"Is the file supposed to be there? "), alloc.reflow(r"Is the file supposed to be there? "),
alloc.reflow("Maybe there is a typo in the file name?"), alloc.reflow("Maybe there is a typo in the file name?"),
]), ]),
@ -4537,9 +4537,8 @@ fn to_file_problem_report(filename: &Path, error: io::ErrorKind) -> String {
alloc alloc
.parser_suggestion(filename.to_str().unwrap()) .parser_suggestion(filename.to_str().unwrap())
.indent(4), .indent(4),
alloc.concat(vec![ alloc
alloc.reflow(r"Is it the right file? Maybe change its permissions?") .concat([alloc.reflow(r"Is it the right file? Maybe change its permissions?")]),
]),
]); ]);
Report { Report {
@ -4552,7 +4551,7 @@ fn to_file_problem_report(filename: &Path, error: io::ErrorKind) -> String {
_ => { _ => {
let error = std::io::Error::from(error); let error = std::io::Error::from(error);
let formatted = format!("{}", error); let formatted = format!("{}", error);
let doc = alloc.concat(vec![ let doc = alloc.concat([
alloc.reflow(r"I tried to read this file, but ran into a "), alloc.reflow(r"I tried to read this file, but ran into a "),
alloc.text(formatted), alloc.text(formatted),
alloc.reflow(r" problem."), alloc.reflow(r" problem."),
@ -4650,7 +4649,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: PlatformPath) -> Strin
RootIsInterface => { RootIsInterface => {
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"The input file is an interface module, but only app modules can be ran."), alloc.reflow(r"The input file is an interface module, but only app modules can be ran."),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies, "), alloc.reflow(r"I will still parse and typecheck the input file and its dependencies, "),
alloc.reflow(r"but won't output any executable."), alloc.reflow(r"but won't output any executable."),
]) ])
@ -4666,7 +4665,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: PlatformPath) -> Strin
RootIsHosted => { RootIsHosted => {
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"The input file is a hosted module, but only app modules can be ran."), alloc.reflow(r"The input file is a hosted module, but only app modules can be ran."),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies, "), alloc.reflow(r"I will still parse and typecheck the input file and its dependencies, "),
alloc.reflow(r"but won't output any executable."), alloc.reflow(r"but won't output any executable."),
]) ])
@ -4682,7 +4681,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: PlatformPath) -> Strin
RootIsPkgConfig => { RootIsPkgConfig => {
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.reflow(r"The input file is a package config file, but only app modules can be ran."), alloc.reflow(r"The input file is a package config file, but only app modules can be ran."),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"I will still parse and typecheck the input file and its dependencies, "), alloc.reflow(r"I will still parse and typecheck the input file and its dependencies, "),
alloc.reflow(r"but won't output any executable."), alloc.reflow(r"but won't output any executable."),
]) ])

View file

@ -77,13 +77,13 @@ pub fn can_problem<'b>(
} }
Problem::UnusedImport(module_id, region) => { Problem::UnusedImport(module_id, region) => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("Nothing from "), alloc.reflow("Nothing from "),
alloc.module(module_id), alloc.module(module_id),
alloc.reflow(" is used in this module."), alloc.reflow(" is used in this module."),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("Since "), alloc.reflow("Since "),
alloc.module(module_id), alloc.module(module_id),
alloc.reflow(" isn't used, you don't need to import it."), alloc.reflow(" isn't used, you don't need to import it."),
@ -128,14 +128,14 @@ pub fn can_problem<'b>(
let line = "\". Adding an underscore at the start of a variable name is a way of saying that the variable is not used."; let line = "\". Adding an underscore at the start of a variable name is a way of saying that the variable is not used.";
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.symbol_unqualified(closure_symbol), alloc.symbol_unqualified(closure_symbol),
alloc.reflow(" doesn't use "), alloc.reflow(" doesn't use "),
alloc.symbol_unqualified(argument_symbol), alloc.symbol_unqualified(argument_symbol),
alloc.text("."), alloc.text("."),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("If you don't need "), alloc.reflow("If you don't need "),
alloc.symbol_unqualified(argument_symbol), alloc.symbol_unqualified(argument_symbol),
alloc.reflow(", then you can just remove it. However, if you really do need "), alloc.reflow(", then you can just remove it. However, if you really do need "),
@ -154,7 +154,7 @@ pub fn can_problem<'b>(
Problem::PrecedenceProblem(BothNonAssociative(region, left_bin_op, right_bin_op)) => { Problem::PrecedenceProblem(BothNonAssociative(region, left_bin_op, right_bin_op)) => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
if left_bin_op.value == right_bin_op.value { if left_bin_op.value == right_bin_op.value {
alloc.concat(vec![ alloc.concat([
alloc.reflow("Using more than one "), alloc.reflow("Using more than one "),
alloc.binop(left_bin_op.value), alloc.binop(left_bin_op.value),
alloc.reflow(concat!( alloc.reflow(concat!(
@ -163,7 +163,7 @@ pub fn can_problem<'b>(
)), )),
]) ])
} else { } else {
alloc.concat(vec![ alloc.concat([
alloc.reflow("Using "), alloc.reflow("Using "),
alloc.binop(left_bin_op.value), alloc.binop(left_bin_op.value),
alloc.reflow(" and "), alloc.reflow(" and "),
@ -243,7 +243,7 @@ pub fn can_problem<'b>(
variable_name, variable_name,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The "), alloc.reflow("The "),
alloc.type_variable(variable_name), alloc.type_variable(variable_name),
alloc.reflow(" type parameter is not used in the "), alloc.reflow(" type parameter is not used in the "),
@ -270,13 +270,13 @@ pub fn can_problem<'b>(
} => { } => {
let mut stack = Vec::with_capacity(4); let mut stack = Vec::with_capacity(4);
if num_unbound == 1 { if num_unbound == 1 {
stack.push(alloc.concat(vec![ stack.push(alloc.concat([
alloc.reflow("The definition of "), alloc.reflow("The definition of "),
alloc.symbol_unqualified(alias), alloc.symbol_unqualified(alias),
alloc.reflow(" has an unbound type variable:"), alloc.reflow(" has an unbound type variable:"),
])); ]));
} else { } else {
stack.push(alloc.concat(vec![ stack.push(alloc.concat([
alloc.reflow("The definition of "), alloc.reflow("The definition of "),
alloc.symbol_unqualified(alias), alloc.symbol_unqualified(alias),
alloc.reflow(" has "), alloc.reflow(" has "),
@ -286,7 +286,7 @@ pub fn can_problem<'b>(
stack.push(alloc.reflow("Here is one occurrence:")); stack.push(alloc.reflow("Here is one occurrence:"));
} }
stack.push(alloc.region(lines.convert_region(one_occurrence))); stack.push(alloc.region(lines.convert_region(one_occurrence)));
stack.push(alloc.tip().append(alloc.concat(vec![ stack.push(alloc.tip().append(alloc.concat([
alloc.reflow("Type variables must be bound before the "), alloc.reflow("Type variables must be bound before the "),
alloc.keyword(match kind { alloc.keyword(match kind {
AliasKind::Structural => ":", AliasKind::Structural => ":",
@ -311,7 +311,7 @@ pub fn can_problem<'b>(
replaced_region, replaced_region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This record defines the "), alloc.reflow("This record defines the "),
alloc.record_field(field_name.clone()), alloc.record_field(field_name.clone()),
alloc.reflow(" field twice!"), alloc.reflow(" field twice!"),
@ -329,7 +329,7 @@ pub fn can_problem<'b>(
lines.convert_region(field_region), lines.convert_region(field_region),
Annotation::TypoSuggestion, Annotation::TypoSuggestion,
), ),
alloc.concat(vec![ alloc.concat([
alloc.reflow("For clarity, remove the previous "), alloc.reflow("For clarity, remove the previous "),
alloc.record_field(field_name), alloc.record_field(field_name),
alloc.reflow(" definitions from this record."), alloc.reflow(" definitions from this record."),
@ -360,7 +360,7 @@ pub fn can_problem<'b>(
replaced_region, replaced_region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This record type defines the "), alloc.reflow("This record type defines the "),
alloc.record_field(field_name.clone()), alloc.record_field(field_name.clone()),
alloc.reflow(" field twice!"), alloc.reflow(" field twice!"),
@ -378,7 +378,7 @@ pub fn can_problem<'b>(
lines.convert_region(field_region), lines.convert_region(field_region),
Annotation::TypoSuggestion, Annotation::TypoSuggestion,
), ),
alloc.concat(vec![ alloc.concat([
alloc.reflow("For clarity, remove the previous "), alloc.reflow("For clarity, remove the previous "),
alloc.record_field(field_name), alloc.record_field(field_name),
alloc.reflow(" definitions from this record type."), alloc.reflow(" definitions from this record type."),
@ -395,7 +395,7 @@ pub fn can_problem<'b>(
replaced_region, replaced_region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This tag union type defines the "), alloc.reflow("This tag union type defines the "),
alloc.tag_name(tag_name.clone()), alloc.tag_name(tag_name.clone()),
alloc.reflow(" tag twice!"), alloc.reflow(" tag twice!"),
@ -413,7 +413,7 @@ pub fn can_problem<'b>(
lines.convert_region(tag_region), lines.convert_region(tag_region),
Annotation::TypoSuggestion, Annotation::TypoSuggestion,
), ),
alloc.concat(vec![ alloc.concat([
alloc.reflow("For clarity, remove the previous "), alloc.reflow("For clarity, remove the previous "),
alloc.tag_name(tag_name), alloc.tag_name(tag_name),
alloc.reflow(" definitions from this tag union type."), alloc.reflow(" definitions from this tag union type."),
@ -445,13 +445,13 @@ pub fn can_problem<'b>(
region, region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This pattern in the definition of "), alloc.reflow("This pattern in the definition of "),
alloc.symbol_unqualified(type_name), alloc.symbol_unqualified(type_name),
alloc.reflow(" is not what I expect:"), alloc.reflow(" is not what I expect:"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("Only type variables like "), alloc.reflow("Only type variables like "),
alloc.type_variable("a".into()), alloc.type_variable("a".into()),
alloc.reflow(" or "), alloc.reflow(" or "),
@ -467,7 +467,7 @@ pub fn can_problem<'b>(
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.reflow("This unicode code point is invalid:"), alloc.reflow("This unicode code point is invalid:"),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"I was expecting a hexadecimal number, like "), alloc.reflow(r"I was expecting a hexadecimal number, like "),
alloc.parser_suggestion("\\u(1100)"), alloc.parser_suggestion("\\u(1100)"),
alloc.reflow(" or "), alloc.reflow(" or "),
@ -494,7 +494,7 @@ pub fn can_problem<'b>(
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.reflow("This string interpolation is invalid:"), alloc.reflow("This string interpolation is invalid:"),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"I was expecting an identifier, like "), alloc.reflow(r"I was expecting an identifier, like "),
alloc.parser_suggestion("\\u(message)"), alloc.parser_suggestion("\\u(message)"),
alloc.reflow(" or "), alloc.reflow(" or "),
@ -520,19 +520,19 @@ pub fn can_problem<'b>(
differing_recursion_region, differing_recursion_region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.symbol_unqualified(alias), alloc.symbol_unqualified(alias),
alloc.reflow(" is a nested datatype. Here is one recursive usage of it:"), alloc.reflow(" is a nested datatype. Here is one recursive usage of it:"),
]), ]),
alloc.region(lines.convert_region(differing_recursion_region)), alloc.region(lines.convert_region(differing_recursion_region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("But recursive usages of "), alloc.reflow("But recursive usages of "),
alloc.symbol_unqualified(alias), alloc.symbol_unqualified(alias),
alloc.reflow(" must match its definition:"), alloc.reflow(" must match its definition:"),
]), ]),
alloc.region(lines.convert_region(def_region)), alloc.region(lines.convert_region(def_region)),
alloc.reflow("Nested datatypes are not supported in Roc."), alloc.reflow("Nested datatypes are not supported in Roc."),
alloc.concat(vec![ alloc.concat([
alloc.hint("Consider rewriting the definition of "), alloc.hint("Consider rewriting the definition of "),
alloc.symbol_unqualified(alias), alloc.symbol_unqualified(alias),
alloc.text(" to use the recursive type with the same arguments."), alloc.text(" to use the recursive type with the same arguments."),
@ -552,13 +552,13 @@ pub fn can_problem<'b>(
}; };
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This "), alloc.reflow("This "),
alloc.text(kind_str), alloc.text(kind_str),
alloc.reflow(" extension type is invalid:"), alloc.reflow(" extension type is invalid:"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.note("A "), alloc.note("A "),
alloc.reflow(kind_str), alloc.reflow(kind_str),
alloc.reflow(" extension variable can only contain "), alloc.reflow(" extension variable can only contain "),
@ -576,7 +576,7 @@ pub fn can_problem<'b>(
variables_region, variables_region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The definition of the "), alloc.reflow("The definition of the "),
alloc.symbol_unqualified(name), alloc.symbol_unqualified(name),
alloc.reflow(" ability includes type variables:"), alloc.reflow(" ability includes type variables:"),
@ -609,7 +609,7 @@ pub fn can_problem<'b>(
ability, ability,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The definition of the "), alloc.reflow("The definition of the "),
alloc.symbol_unqualified(name), alloc.symbol_unqualified(name),
alloc.reflow(" aliases references the ability "), alloc.reflow(" aliases references the ability "),
@ -617,12 +617,12 @@ pub fn can_problem<'b>(
alloc.reflow(":"), alloc.reflow(":"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("Abilities are not types, but you can add an ability constraint to a type variable "), alloc.reflow("Abilities are not types, but you can add an ability constraint to a type variable "),
alloc.type_variable("a".into()), alloc.type_variable("a".into()),
alloc.reflow(" by writing"), alloc.reflow(" by writing"),
]), ]),
alloc.type_block(alloc.concat(vec![ alloc.type_block(alloc.concat([
alloc.reflow("| a has "), alloc.reflow("| a has "),
alloc.symbol_unqualified(ability), alloc.symbol_unqualified(ability),
])), ])),
@ -634,13 +634,13 @@ pub fn can_problem<'b>(
Problem::IllegalHasClause { region } => { Problem::IllegalHasClause { region } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("A "), alloc.reflow("A "),
alloc.keyword("has"), alloc.keyword("has"),
alloc.reflow(" clause is not allowed here:"), alloc.reflow(" clause is not allowed here:"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.keyword("has"), alloc.keyword("has"),
alloc.reflow(" clauses can only be specified on the top-level type annotation of an ability member."), alloc.reflow(" clauses can only be specified on the top-level type annotation of an ability member."),
]), ]),
@ -655,7 +655,7 @@ pub fn can_problem<'b>(
region, region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The definition of the ability member "), alloc.reflow("The definition of the ability member "),
alloc.symbol_unqualified(member), alloc.symbol_unqualified(member),
alloc.reflow(" does not include a "), alloc.reflow(" does not include a "),
@ -665,21 +665,20 @@ pub fn can_problem<'b>(
alloc.reflow(":"), alloc.reflow(":"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("Ability members must include a "), alloc.reflow("Ability members must include a "),
alloc.keyword("has"), alloc.keyword("has"),
alloc.reflow(" clause binding a type variable to an ability, like"), alloc.reflow(" clause binding a type variable to an ability, like"),
]), ]),
alloc.type_block(alloc.concat(vec![ alloc.type_block(alloc.concat([
alloc.type_variable("a".into()), alloc.type_variable("a".into()),
alloc.space(), alloc.space(),
alloc.keyword("has"), alloc.keyword("has"),
alloc.space(), alloc.space(),
alloc.symbol_unqualified(ability), alloc.symbol_unqualified(ability),
])), ])),
alloc.concat(vec![alloc.reflow( alloc.concat([alloc
"Otherwise, the function does not need to be part of the ability!", .reflow("Otherwise, the function does not need to be part of the ability!")]),
)]),
]); ]);
title = ABILITY_MEMBER_MISSING_HAS_CLAUSE.to_string(); title = ABILITY_MEMBER_MISSING_HAS_CLAUSE.to_string();
severity = Severity::RuntimeError; severity = Severity::RuntimeError;
@ -692,7 +691,7 @@ pub fn can_problem<'b>(
mut bound_var_names, mut bound_var_names,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The definition of the ability member "), alloc.reflow("The definition of the ability member "),
alloc.symbol_unqualified(member), alloc.symbol_unqualified(member),
alloc.reflow(" includes multiple variables bound to the "), alloc.reflow(" includes multiple variables bound to the "),
@ -701,7 +700,7 @@ pub fn can_problem<'b>(
]), ]),
alloc.region(lines.convert_region(span_has_clauses)), alloc.region(lines.convert_region(span_has_clauses)),
alloc.reflow("Ability members can only bind one type variable to their parent ability. Otherwise, I wouldn't know what type implements an ability by looking at specializations!"), alloc.reflow("Ability members can only bind one type variable to their parent ability. Otherwise, I wouldn't know what type implements an ability by looking at specializations!"),
alloc.concat(vec![ alloc.concat([
alloc.hint("Did you mean to only bind "), alloc.hint("Did you mean to only bind "),
alloc.type_variable(bound_var_names.swap_remove(0)), alloc.type_variable(bound_var_names.swap_remove(0)),
alloc.reflow(" to "), alloc.reflow(" to "),
@ -719,14 +718,14 @@ pub fn can_problem<'b>(
region, region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The definition of the ability member "), alloc.reflow("The definition of the ability member "),
alloc.symbol_unqualified(member), alloc.symbol_unqualified(member),
alloc.reflow(" includes a has clause binding an ability it is not a part of:"), alloc.reflow(" includes a has clause binding an ability it is not a part of:"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.reflow("Currently, ability members can only bind variables to the ability they are a part of."), alloc.reflow("Currently, ability members can only bind variables to the ability they are a part of."),
alloc.concat(vec![ alloc.concat([
alloc.hint(""), alloc.hint(""),
alloc.reflow("Did you mean to bind the "), alloc.reflow("Did you mean to bind the "),
alloc.symbol_unqualified(ability), alloc.symbol_unqualified(ability),
@ -778,7 +777,7 @@ fn to_invalid_optional_value_report_help<'b>(
record_region: Region, record_region: Region,
) -> RocDocBuilder<'b> { ) -> RocDocBuilder<'b> {
alloc.stack(vec![ alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This record uses an optional value for the "), alloc.reflow("This record uses an optional value for the "),
alloc.record_field(field_name), alloc.record_field(field_name),
alloc.reflow(" field in an incorrect context!"), alloc.reflow(" field in an incorrect context!"),
@ -812,7 +811,7 @@ fn to_bad_ident_expr_report<'b>(
alloc.stack(vec![ alloc.stack(vec![
alloc.reflow(r"I trying to parse a record field access here:"), alloc.reflow(r"I trying to parse a record field access here:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat([
alloc.reflow("So I expect to see a lowercase letter next, like "), alloc.reflow("So I expect to see a lowercase letter next, like "),
alloc.parser_suggestion(".name"), alloc.parser_suggestion(".name"),
alloc.reflow(" or "), alloc.reflow(" or "),
@ -825,7 +824,7 @@ fn to_bad_ident_expr_report<'b>(
WeirdAccessor(_pos) => alloc.stack(vec![ WeirdAccessor(_pos) => alloc.stack(vec![
alloc.reflow("I am very confused by this field access"), alloc.reflow("I am very confused by this field access"),
alloc.region(lines.convert_region(surroundings)), alloc.region(lines.convert_region(surroundings)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("It looks like a field access on an accessor. I parse"), alloc.reflow("It looks like a field access on an accessor. I parse"),
alloc.parser_suggestion(".client.name"), alloc.parser_suggestion(".client.name"),
alloc.reflow(" as "), alloc.reflow(" as "),
@ -843,7 +842,7 @@ fn to_bad_ident_expr_report<'b>(
alloc.stack(vec![ alloc.stack(vec![
alloc.reflow("I am trying to parse a qualified name here:"), alloc.reflow("I am trying to parse a qualified name here:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat([
alloc.reflow("I was expecting to see an identifier next, like "), alloc.reflow("I was expecting to see an identifier next, like "),
alloc.parser_suggestion("height"), alloc.parser_suggestion("height"),
alloc.reflow(". A complete qualified name looks something like "), alloc.reflow(". A complete qualified name looks something like "),
@ -858,7 +857,7 @@ fn to_bad_ident_expr_report<'b>(
alloc.stack(vec![ alloc.stack(vec![
alloc.reflow("I am trying to parse a qualified name here:"), alloc.reflow("I am trying to parse a qualified name here:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"This looks like a qualified tag name to me, "), alloc.reflow(r"This looks like a qualified tag name to me, "),
alloc.reflow(r"but tags cannot be qualified! "), alloc.reflow(r"but tags cannot be qualified! "),
alloc.reflow(r"Maybe you wanted a qualified name, something like "), alloc.reflow(r"Maybe you wanted a qualified name, something like "),
@ -876,7 +875,7 @@ fn to_bad_ident_expr_report<'b>(
lines.convert_region(surroundings), lines.convert_region(surroundings),
lines.convert_region(region), lines.convert_region(region),
), ),
alloc.concat(vec![alloc.reflow( alloc.concat([alloc.reflow(
r"I recommend using camelCase, it is the standard in the Roc ecosystem.", r"I recommend using camelCase, it is the standard in the Roc ecosystem.",
)]), )]),
]) ])
@ -898,7 +897,7 @@ fn to_bad_ident_expr_report<'b>(
lines.convert_region(surroundings), lines.convert_region(surroundings),
lines.convert_region(region), lines.convert_region(region),
), ),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"It looks like a record field access on "), alloc.reflow(r"It looks like a record field access on "),
alloc.reflow(kind), alloc.reflow(kind),
alloc.text("."), alloc.text("."),
@ -913,7 +912,7 @@ fn to_bad_ident_expr_report<'b>(
lines.convert_region(surroundings), lines.convert_region(surroundings),
lines.convert_region(region), lines.convert_region(region),
), ),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"Looks like "), alloc.reflow(r"Looks like "),
alloc.reflow(kind), alloc.reflow(kind),
alloc.reflow(" is treated like a module name. "), alloc.reflow(" is treated like a module name. "),
@ -927,7 +926,7 @@ fn to_bad_ident_expr_report<'b>(
let region = let region =
Region::new(surroundings.start().bump_column(1), pos.bump_column(1)); Region::new(surroundings.start().bump_column(1), pos.bump_column(1));
alloc.stack(vec![ alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("I am trying to parse "), alloc.reflow("I am trying to parse "),
alloc.reflow(kind), alloc.reflow(kind),
alloc.reflow(" here:"), alloc.reflow(" here:"),
@ -936,7 +935,7 @@ fn to_bad_ident_expr_report<'b>(
lines.convert_region(surroundings), lines.convert_region(surroundings),
lines.convert_region(region), lines.convert_region(region),
), ),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"But after the "), alloc.reflow(r"But after the "),
alloc.keyword("@"), alloc.keyword("@"),
alloc.reflow(r" symbol I found a lowercase letter. "), alloc.reflow(r" symbol I found a lowercase letter. "),
@ -971,7 +970,7 @@ fn to_bad_ident_pattern_report<'b>(
alloc.stack(vec![ alloc.stack(vec![
alloc.reflow(r"I trying to parse a record field accessor here:"), alloc.reflow(r"I trying to parse a record field accessor here:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat([
alloc.reflow("Something like "), alloc.reflow("Something like "),
alloc.parser_suggestion(".name"), alloc.parser_suggestion(".name"),
alloc.reflow(" or "), alloc.reflow(" or "),
@ -984,7 +983,7 @@ fn to_bad_ident_pattern_report<'b>(
WeirdAccessor(_pos) => alloc.stack(vec![ WeirdAccessor(_pos) => alloc.stack(vec![
alloc.reflow("I am very confused by this field access"), alloc.reflow("I am very confused by this field access"),
alloc.region(lines.convert_region(surroundings)), alloc.region(lines.convert_region(surroundings)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("It looks like a field access on an accessor. I parse"), alloc.reflow("It looks like a field access on an accessor. I parse"),
alloc.parser_suggestion(".client.name"), alloc.parser_suggestion(".client.name"),
alloc.reflow(" as "), alloc.reflow(" as "),
@ -1002,7 +1001,7 @@ fn to_bad_ident_pattern_report<'b>(
alloc.stack(vec![ alloc.stack(vec![
alloc.reflow("I am trying to parse a qualified name here:"), alloc.reflow("I am trying to parse a qualified name here:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat([
alloc.reflow("I was expecting to see an identifier next, like "), alloc.reflow("I was expecting to see an identifier next, like "),
alloc.parser_suggestion("height"), alloc.parser_suggestion("height"),
alloc.reflow(". A complete qualified name looks something like "), alloc.reflow(". A complete qualified name looks something like "),
@ -1017,7 +1016,7 @@ fn to_bad_ident_pattern_report<'b>(
alloc.stack(vec![ alloc.stack(vec![
alloc.reflow("I am trying to parse a qualified name here:"), alloc.reflow("I am trying to parse a qualified name here:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region), alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat(vec![ alloc.concat([
alloc.reflow(r"This looks like a qualified tag name to me, "), alloc.reflow(r"This looks like a qualified tag name to me, "),
alloc.reflow(r"but tags cannot be qualified! "), alloc.reflow(r"but tags cannot be qualified! "),
alloc.reflow(r"Maybe you wanted a qualified name, something like "), alloc.reflow(r"Maybe you wanted a qualified name, something like "),
@ -1036,7 +1035,7 @@ fn to_bad_ident_pattern_report<'b>(
lines.convert_region(surroundings), lines.convert_region(surroundings),
lines.convert_region(region), lines.convert_region(region),
), ),
alloc.concat(vec![alloc.reflow( alloc.concat([alloc.reflow(
r"Underscores are not allowed in identifiers. Use camelCase instead!", r"Underscores are not allowed in identifiers. Use camelCase instead!",
)]), )]),
]) ])
@ -1131,7 +1130,7 @@ fn report_shadowing<'b>(
alloc.region(lines.convert_region(original_region)), alloc.region(lines.convert_region(original_region)),
alloc.reflow("But then it's defined a second time here:"), alloc.reflow("But then it's defined a second time here:"),
alloc.region(lines.convert_region(shadow.region)), alloc.region(lines.convert_region(shadow.region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("Since these "), alloc.reflow("Since these "),
alloc.reflow(what), alloc.reflow(what),
alloc.reflow(" have the same name, it's easy to use the wrong one on accident. Give one of them a new name."), alloc.reflow(" have the same name, it's easy to use the wrong one on accident. Give one of them a new name."),
@ -1219,7 +1218,7 @@ fn pretty_runtime_error<'b>(
}; };
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This"), alloc.reflow("This"),
alloc.text(name), alloc.text(name),
alloc.reflow("pattern is malformed:"), alloc.reflow("pattern is malformed:"),
@ -1243,7 +1242,7 @@ fn pretty_runtime_error<'b>(
suggestions.truncate(4); suggestions.truncate(4);
let did_you_mean = if suggestions.is_empty() { let did_you_mean = if suggestions.is_empty() {
alloc.concat(vec![ alloc.concat([
alloc.reflow("In fact, it looks like "), alloc.reflow("In fact, it looks like "),
alloc.module_name(module_name.clone()), alloc.module_name(module_name.clone()),
alloc.reflow(" doesn't expose any values!"), alloc.reflow(" doesn't expose any values!"),
@ -1258,7 +1257,7 @@ fn pretty_runtime_error<'b>(
]) ])
}; };
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The "), alloc.reflow("The "),
alloc.module_name(module_name), alloc.module_name(module_name),
alloc.reflow(" module does not expose `"), alloc.reflow(" module does not expose `"),
@ -1302,7 +1301,7 @@ fn pretty_runtime_error<'b>(
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.reflow(r"I am confused by this type name:"), alloc.reflow(r"I am confused by this type name:"),
alloc.region(lines.convert_region(surroundings)), alloc.region(lines.convert_region(surroundings)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("Type names start with an uppercase letter, "), alloc.reflow("Type names start with an uppercase letter, "),
alloc.reflow("and can optionally be qualified by a module name, like "), alloc.reflow("and can optionally be qualified by a module name, like "),
alloc.parser_suggestion("Bool"), alloc.parser_suggestion("Bool"),
@ -1330,13 +1329,13 @@ fn pretty_runtime_error<'b>(
}; };
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This float literal is too "), alloc.reflow("This float literal is too "),
alloc.text(big_or_small), alloc.text(big_or_small),
alloc.reflow(":"), alloc.reflow(":"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc alloc
.reflow("Roc uses signed 64-bit floating points, allowing values between "), .reflow("Roc uses signed 64-bit floating points, allowing values between "),
alloc.text(format!("{:e}", f64::MIN)), alloc.text(format!("{:e}", f64::MIN)),
@ -1354,11 +1353,11 @@ fn pretty_runtime_error<'b>(
.append(alloc.reflow("Learn more about number literals at TODO")); .append(alloc.reflow("Learn more about number literals at TODO"));
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This float literal contains an invalid digit:"), alloc.reflow("This float literal contains an invalid digit:"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.reflow("Floating point literals can only contain the digits 0-9, or use scientific notation 10e4, or have a float suffix."), alloc.reflow("Floating point literals can only contain the digits 0-9, or use scientific notation 10e4, or have a float suffix."),
]), ]),
tip, tip,
@ -1368,9 +1367,9 @@ fn pretty_runtime_error<'b>(
} }
RuntimeError::InvalidFloat(FloatErrorKind::IntSuffix, region, _raw_str) => { RuntimeError::InvalidFloat(FloatErrorKind::IntSuffix, region, _raw_str) => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![alloc.reflow( alloc
"This number literal is a float, but it has an integer suffix:", .concat([alloc
)]), .reflow("This number literal is a float, but it has an integer suffix:")]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
]); ]);
@ -1418,7 +1417,7 @@ fn pretty_runtime_error<'b>(
.append(alloc.reflow("Learn more about number literals at TODO")); .append(alloc.reflow("Learn more about number literals at TODO"));
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This "), alloc.reflow("This "),
alloc.text(name), alloc.text(name),
alloc.reflow(" literal contains "), alloc.reflow(" literal contains "),
@ -1426,7 +1425,7 @@ fn pretty_runtime_error<'b>(
alloc.text(":"), alloc.text(":"),
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([
alloc.text(plurals), alloc.text(plurals),
contains, contains,
alloc.text(charset), alloc.text(charset),
@ -1442,7 +1441,7 @@ fn pretty_runtime_error<'b>(
let (big_or_small, info) = if let IntErrorKind::Underflow = error_kind { let (big_or_small, info) = if let IntErrorKind::Underflow = error_kind {
( (
"small", "small",
alloc.concat(vec![ alloc.concat([
alloc.reflow( alloc.reflow(
"The smallest number representable in Roc is the minimum I128 value, ", "The smallest number representable in Roc is the minimum I128 value, ",
), ),
@ -1453,7 +1452,7 @@ fn pretty_runtime_error<'b>(
} else { } else {
( (
"big", "big",
alloc.concat(vec![ alloc.concat([
alloc.reflow( alloc.reflow(
"The largest number representable in Roc is the maximum U128 value, ", "The largest number representable in Roc is the maximum U128 value, ",
), ),
@ -1468,7 +1467,7 @@ fn pretty_runtime_error<'b>(
.append(alloc.reflow("Learn more about number literals at TODO")); .append(alloc.reflow("Learn more about number literals at TODO"));
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This integer literal is too "), alloc.reflow("This integer literal is too "),
alloc.text(big_or_small), alloc.text(big_or_small),
alloc.reflow(":"), alloc.reflow(":"),
@ -1482,9 +1481,9 @@ fn pretty_runtime_error<'b>(
} }
RuntimeError::InvalidInt(IntErrorKind::FloatSuffix, _base, region, _raw_str) => { RuntimeError::InvalidInt(IntErrorKind::FloatSuffix, _base, region, _raw_str) => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![alloc.reflow( alloc
"This number literal is an integer, but it has a float suffix:", .concat([alloc
)]), .reflow("This number literal is an integer, but it has a float suffix:")]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
]); ]);
@ -1500,11 +1499,10 @@ fn pretty_runtime_error<'b>(
_raw_str, _raw_str,
) => { ) => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![alloc.reflow( alloc.concat([alloc
"This integer literal overflows the type indicated by its suffix:", .reflow("This integer literal overflows the type indicated by its suffix:")]),
)]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.tip().append(alloc.concat(vec![ alloc.tip().append(alloc.concat([
alloc.reflow("The suffix indicates this integer is a "), alloc.reflow("The suffix indicates this integer is a "),
alloc.type_str(suffix_type), alloc.type_str(suffix_type),
alloc.reflow(", whose maximum value is "), alloc.reflow(", whose maximum value is "),
@ -1525,11 +1523,10 @@ fn pretty_runtime_error<'b>(
_raw_str, _raw_str,
) => { ) => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![alloc.reflow( alloc.concat([alloc
"This integer literal underflows the type indicated by its suffix:", .reflow("This integer literal underflows the type indicated by its suffix:")]),
)]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.tip().append(alloc.concat(vec![ alloc.tip().append(alloc.concat([
alloc.reflow("The suffix indicates this integer is a "), alloc.reflow("The suffix indicates this integer is a "),
alloc.type_str(suffix_type), alloc.type_str(suffix_type),
alloc.reflow(", whose minimum value is "), alloc.reflow(", whose minimum value is "),
@ -1557,7 +1554,7 @@ fn pretty_runtime_error<'b>(
} }
RuntimeError::InvalidRecordUpdate { region } => { RuntimeError::InvalidRecordUpdate { region } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This expression cannot be updated"), alloc.reflow("This expression cannot be updated"),
alloc.reflow(":"), alloc.reflow(":"),
]), ]),
@ -1608,7 +1605,7 @@ fn pretty_runtime_error<'b>(
.append(alloc.reflow("Learn more about character literals at TODO")); .append(alloc.reflow("Learn more about character literals at TODO"));
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![alloc.reflow("This character literal is empty.")]), alloc.concat([alloc.reflow("This character literal is empty.")]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
tip, tip,
]); ]);
@ -1621,13 +1618,11 @@ fn pretty_runtime_error<'b>(
.append(alloc.reflow("Learn more about character literals at TODO")); .append(alloc.reflow("Learn more about character literals at TODO"));
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This character literal contains more than one code point.") alloc.reflow("This character literal contains more than one code point.")
]), ]),
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.concat(vec![ alloc.concat([alloc.reflow("Character literals can only contain one code point.")]),
alloc.reflow("Character literals can only contain one code point.")
]),
tip, tip,
]); ]);
@ -1662,7 +1657,7 @@ fn pretty_runtime_error<'b>(
}; };
let mut stack = vec![ let mut stack = vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The opaque type "), alloc.reflow("The opaque type "),
alloc.type_str(opaque.as_inline_str().as_str()), alloc.type_str(opaque.as_inline_str().as_str()),
alloc.reflow(" referenced here is not defined:"), alloc.reflow(" referenced here is not defined:"),
@ -1689,7 +1684,7 @@ fn pretty_runtime_error<'b>(
imported_region, imported_region,
} => { } => {
doc = alloc.stack(vec![ doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The unwrapped opaque type "), alloc.reflow("The unwrapped opaque type "),
alloc.type_str(opaque.as_inline_str().as_str()), alloc.type_str(opaque.as_inline_str().as_str()),
alloc.reflow(" referenced here:"), alloc.reflow(" referenced here:"),
@ -1784,7 +1779,7 @@ fn not_found<'b>(
); );
suggestions.truncate(4); suggestions.truncate(4);
let default_no = alloc.concat(vec![ let default_no = alloc.concat([
alloc.reflow("Is there an "), alloc.reflow("Is there an "),
alloc.keyword("import"), alloc.keyword("import"),
alloc.reflow(" or "), alloc.reflow(" or "),
@ -1808,7 +1803,7 @@ fn not_found<'b>(
}; };
alloc.stack(vec![ alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("I cannot find a `"), alloc.reflow("I cannot find a `"),
alloc.string(name.to_string()), alloc.string(name.to_string()),
alloc.reflow("` "), alloc.reflow("` "),
@ -1842,7 +1837,7 @@ fn module_not_found<'b>(
if suggestions.is_empty() { if suggestions.is_empty() {
// We don't have any recommended spelling corrections // We don't have any recommended spelling corrections
alloc.concat(vec![ alloc.concat([
alloc.reflow("Is there an "), alloc.reflow("Is there an "),
alloc.keyword("import"), alloc.keyword("import"),
alloc.reflow(" or "), alloc.reflow(" or "),
@ -1860,7 +1855,7 @@ fn module_not_found<'b>(
}; };
alloc.stack(vec![ alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The `"), alloc.reflow("The `"),
alloc.string(name.to_string()), alloc.string(name.to_string()),
alloc.reflow("` module is not imported:"), alloc.reflow("` module is not imported:"),

View file

@ -22,7 +22,7 @@ pub fn mono_problem<'b>(
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.reflow("Other possibilities include:"), alloc.reflow("Other possibilities include:"),
unhandled_patterns_to_doc_block(alloc, missing), unhandled_patterns_to_doc_block(alloc, missing),
alloc.concat(vec![ alloc.concat([
alloc.reflow( alloc.reflow(
"I would have to crash if I saw one of those! \ "I would have to crash if I saw one of those! \
So rather than pattern matching in function arguments, put a ", So rather than pattern matching in function arguments, put a ",
@ -45,7 +45,7 @@ pub fn mono_problem<'b>(
alloc.region(lines.convert_region(region)), alloc.region(lines.convert_region(region)),
alloc.reflow("Other possibilities include:"), alloc.reflow("Other possibilities include:"),
unhandled_patterns_to_doc_block(alloc, missing), unhandled_patterns_to_doc_block(alloc, missing),
alloc.concat(vec![ alloc.concat([
alloc.reflow( alloc.reflow(
"I would have to crash if I saw one of those! \ "I would have to crash if I saw one of those! \
You can use a binding to deconstruct a value if there is only ONE possibility. \ You can use a binding to deconstruct a value if there is only ONE possibility. \
@ -65,7 +65,7 @@ pub fn mono_problem<'b>(
} }
BadCase => { BadCase => {
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("This "), alloc.reflow("This "),
alloc.keyword("when"), alloc.keyword("when"),
alloc.reflow(" does not cover all the possibilities:"), alloc.reflow(" does not cover all the possibilities:"),
@ -94,7 +94,7 @@ pub fn mono_problem<'b>(
index, index,
}) => { }) => {
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The "), alloc.reflow("The "),
alloc.string(index.ordinal()), alloc.string(index.ordinal()),
alloc.reflow(" pattern is redundant:"), alloc.reflow(" pattern is redundant:"),
@ -169,7 +169,7 @@ fn pattern_to_doc_help<'b>(
); );
debug_assert!(args.len() == 2); debug_assert!(args.len() == 2);
let tag = pattern_to_doc_help(alloc, args[1].clone(), in_type_param); let tag = pattern_to_doc_help(alloc, args[1].clone(), in_type_param);
alloc.concat(vec![ alloc.concat([
tag, tag,
alloc.text(AFTER_TAG_INDENT), alloc.text(AFTER_TAG_INDENT),
alloc.text("(note the lack of an "), alloc.text("(note the lack of an "),

File diff suppressed because it is too large Load diff

View file

@ -81,7 +81,7 @@ pub fn type_problem<'b>(
let found_arguments = alloc.text(type_got.to_string()); let found_arguments = alloc.text(type_got.to_string());
let doc = alloc.stack(vec![ let doc = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.reflow("The "), alloc.reflow("The "),
alloc.symbol_unqualified(symbol), alloc.symbol_unqualified(symbol),
alloc.reflow(" alias expects "), alloc.reflow(" alias expects "),
@ -210,7 +210,7 @@ fn report_incomplete_ability<'a>(
debug_assert!(!missing_members.is_empty()); debug_assert!(!missing_members.is_empty());
let mut stack = vec![alloc.concat(vec![ let mut stack = vec![alloc.concat([
alloc.reflow("The type "), alloc.reflow("The type "),
alloc.symbol_unqualified(typ), alloc.symbol_unqualified(typ),
alloc.reflow(" does not fully implement the ability "), alloc.reflow(" does not fully implement the ability "),
@ -219,7 +219,7 @@ fn report_incomplete_ability<'a>(
])]; ])];
for member in missing_members.into_iter() { for member in missing_members.into_iter() {
stack.push(alloc.concat(vec![ stack.push(alloc.concat([
alloc.reflow("A specialization for "), alloc.reflow("A specialization for "),
alloc.symbol_unqualified(member.value), alloc.symbol_unqualified(member.value),
alloc.reflow(", which is defined here:"), alloc.reflow(", which is defined here:"),
@ -228,7 +228,7 @@ fn report_incomplete_ability<'a>(
} }
if !specialized_members.is_empty() { if !specialized_members.is_empty() {
stack.push(alloc.concat(vec![ stack.push(alloc.concat([
alloc.note(""), alloc.note(""),
alloc.symbol_unqualified(typ), alloc.symbol_unqualified(typ),
alloc.reflow(" specializes the following members of "), alloc.reflow(" specializes the following members of "),
@ -237,7 +237,7 @@ fn report_incomplete_ability<'a>(
])); ]));
for spec in specialized_members { for spec in specialized_members {
stack.push(alloc.concat(vec![ stack.push(alloc.concat([
alloc.symbol_unqualified(spec.value), alloc.symbol_unqualified(spec.value),
alloc.reflow(", specialized here:"), alloc.reflow(", specialized here:"),
])); ]));
@ -461,8 +461,8 @@ fn to_expr_report<'b>(
let (the_name_text, on_name_text) = match pattern_to_doc(alloc, &name.value) { let (the_name_text, on_name_text) = match pattern_to_doc(alloc, &name.value) {
Some(doc) => ( Some(doc) => (
alloc.concat(vec![alloc.reflow("the "), doc.clone()]), alloc.concat([alloc.reflow("the "), doc.clone()]),
alloc.concat(vec![alloc.reflow(" on "), doc]), alloc.concat([alloc.reflow(" on "), doc]),
), ),
None => (alloc.text("this"), alloc.nil()), None => (alloc.text("this"), alloc.nil()),
}; };
@ -474,7 +474,7 @@ fn to_expr_report<'b>(
index, index,
num_branches, num_branches,
.. ..
} if num_branches == 2 => alloc.concat(vec![ } if num_branches == 2 => alloc.concat([
alloc.keyword(if index == HumanIndex::FIRST { alloc.keyword(if index == HumanIndex::FIRST {
"then" "then"
} else { } else {
@ -484,19 +484,19 @@ fn to_expr_report<'b>(
alloc.keyword("if"), alloc.keyword("if"),
alloc.text(" expression:"), alloc.text(" expression:"),
]), ]),
TypedIfBranch { index, .. } => alloc.concat(vec![ TypedIfBranch { index, .. } => alloc.concat([
alloc.string(index.ordinal()), alloc.string(index.ordinal()),
alloc.reflow(" branch of this "), alloc.reflow(" branch of this "),
alloc.keyword("if"), alloc.keyword("if"),
alloc.text(" expression:"), alloc.text(" expression:"),
]), ]),
TypedWhenBranch { index, .. } => alloc.concat(vec![ TypedWhenBranch { index, .. } => alloc.concat([
alloc.string(index.ordinal()), alloc.string(index.ordinal()),
alloc.reflow(" branch of this "), alloc.reflow(" branch of this "),
alloc.keyword("when"), alloc.keyword("when"),
alloc.text(" expression:"), alloc.text(" expression:"),
]), ]),
TypedBody { .. } => alloc.concat(vec![ TypedBody { .. } => alloc.concat([
alloc.text("body of "), alloc.text("body of "),
the_name_text, the_name_text,
alloc.text(" definition:"), alloc.text(" definition:"),
@ -525,14 +525,14 @@ fn to_expr_report<'b>(
found, found,
expected_type, expected_type,
expectation_context, expectation_context,
alloc.concat(vec![ alloc.concat([
alloc.reflow("The type annotation"), alloc.reflow("The type annotation"),
on_name_text, on_name_text,
alloc.reflow(" says "), alloc.reflow(" says "),
it.clone(), it.clone(),
alloc.reflow(" should have the type:"), alloc.reflow(" should have the type:"),
]), ]),
alloc.concat(vec![ alloc.concat([
alloc.reflow("However, the type of "), alloc.reflow("However, the type of "),
it, it,
alloc.reflow(" is connected to another type in a way that isn't reflected in this annotation.") alloc.reflow(" is connected to another type in a way that isn't reflected in this annotation.")
@ -545,7 +545,7 @@ fn to_expr_report<'b>(
expected_type, expected_type,
expectation_context, expectation_context,
add_category(alloc, alloc.text(it_is), &category), add_category(alloc, alloc.text(it_is), &category),
alloc.concat(vec![ alloc.concat([
alloc.text("But the type annotation"), alloc.text("But the type annotation"),
on_name_text, on_name_text,
alloc.text(" says it should be:"), alloc.text(" says it should be:"),
@ -575,7 +575,7 @@ fn to_expr_report<'b>(
} }
Expected::ForReason(reason, expected_type, region) => match reason { Expected::ForReason(reason, expected_type, region) => match reason {
Reason::ExpectCondition => { Reason::ExpectCondition => {
let problem = alloc.concat(vec![ let problem = alloc.concat([
alloc.text("This "), alloc.text("This "),
alloc.keyword("expect"), alloc.keyword("expect"),
alloc.text(" condition needs to be a "), alloc.text(" condition needs to be a "),
@ -594,7 +594,7 @@ fn to_expr_report<'b>(
Some(expr_region), Some(expr_region),
problem, problem,
alloc.text("Right now its"), alloc.text("Right now its"),
alloc.concat(vec![ alloc.concat([
alloc.reflow("But I need every "), alloc.reflow("But I need every "),
alloc.keyword("expect"), alloc.keyword("expect"),
alloc.reflow(" condition to evaluate to a "), alloc.reflow(" condition to evaluate to a "),
@ -614,7 +614,7 @@ fn to_expr_report<'b>(
) )
} }
Reason::IfCondition => { Reason::IfCondition => {
let problem = alloc.concat(vec![ let problem = alloc.concat([
alloc.text("This "), alloc.text("This "),
alloc.keyword("if"), alloc.keyword("if"),
alloc.text(" condition needs to be a "), alloc.text(" condition needs to be a "),
@ -633,7 +633,7 @@ fn to_expr_report<'b>(
Some(expr_region), Some(expr_region),
problem, problem,
alloc.text("Right now its"), alloc.text("Right now its"),
alloc.concat(vec![ alloc.concat([
alloc.reflow("But I need every "), alloc.reflow("But I need every "),
alloc.keyword("if"), alloc.keyword("if"),
alloc.reflow(" condition to evaluate to a "), alloc.reflow(" condition to evaluate to a "),
@ -653,7 +653,7 @@ fn to_expr_report<'b>(
) )
} }
Reason::WhenGuard => { Reason::WhenGuard => {
let problem = alloc.concat(vec![ let problem = alloc.concat([
alloc.text("This "), alloc.text("This "),
alloc.keyword("if"), alloc.keyword("if"),
alloc.text(" guard condition needs to be a "), alloc.text(" guard condition needs to be a "),
@ -671,7 +671,7 @@ fn to_expr_report<'b>(
Some(expr_region), Some(expr_region),
problem, problem,
alloc.text("Right now its"), alloc.text("Right now its"),
alloc.concat(vec![ alloc.concat([
alloc.reflow("But I need every "), alloc.reflow("But I need every "),
alloc.keyword("if"), alloc.keyword("if"),
alloc.reflow(" guard condition to evaluate to a "), alloc.reflow(" guard condition to evaluate to a "),
@ -697,7 +697,7 @@ fn to_expr_report<'b>(
expected_type, expected_type,
region, region,
Some(expr_region), Some(expr_region),
alloc.concat(vec![ alloc.concat([
alloc.text("This "), alloc.text("This "),
alloc.keyword("if"), alloc.keyword("if"),
alloc.text(" has an "), alloc.text(" has an "),
@ -706,17 +706,17 @@ fn to_expr_report<'b>(
alloc.keyword("then"), alloc.keyword("then"),
alloc.text(" branch:"), alloc.text(" branch:"),
]), ]),
alloc.concat(vec![ alloc.concat([
alloc.text("The "), alloc.text("The "),
alloc.keyword("else"), alloc.keyword("else"),
alloc.text(" branch is"), alloc.text(" branch is"),
]), ]),
alloc.concat(vec![ alloc.concat([
alloc.text("but the "), alloc.text("but the "),
alloc.keyword("then"), alloc.keyword("then"),
alloc.text(" branch has the type:"), alloc.text(" branch has the type:"),
]), ]),
Some(alloc.concat(vec![ Some(alloc.concat([
alloc.text("I need all branches in an "), alloc.text("I need all branches in an "),
alloc.keyword("if"), alloc.keyword("if"),
alloc.text(" to have the same type!"), alloc.text(" to have the same type!"),
@ -731,7 +731,7 @@ fn to_expr_report<'b>(
expected_type, expected_type,
region, region,
Some(expr_region), Some(expr_region),
alloc.concat(vec![ alloc.concat([
alloc.reflow("The "), alloc.reflow("The "),
alloc.string(index.ordinal()), alloc.string(index.ordinal()),
alloc.reflow(" branch of this "), alloc.reflow(" branch of this "),
@ -740,7 +740,7 @@ fn to_expr_report<'b>(
]), ]),
alloc.string(format!("The {} branch is", index.ordinal())), alloc.string(format!("The {} branch is", index.ordinal())),
alloc.reflow("But all the previous branches have type:"), alloc.reflow("But all the previous branches have type:"),
Some(alloc.concat(vec![ Some(alloc.concat([
alloc.reflow("I need all branches in an "), alloc.reflow("I need all branches in an "),
alloc.keyword("if"), alloc.keyword("if"),
alloc.reflow(" to have the same type!"), alloc.reflow(" to have the same type!"),
@ -756,20 +756,20 @@ fn to_expr_report<'b>(
expected_type, expected_type,
region, region,
Some(expr_region), Some(expr_region),
alloc.concat(vec![ alloc.concat([
alloc.reflow("The "), alloc.reflow("The "),
alloc.string(index.ordinal()), alloc.string(index.ordinal()),
alloc.reflow(" branch of this "), alloc.reflow(" branch of this "),
alloc.keyword("when"), alloc.keyword("when"),
alloc.reflow(" does not match all the previous branches:"), alloc.reflow(" does not match all the previous branches:"),
]), ]),
alloc.concat(vec![ alloc.concat([
alloc.reflow("The "), alloc.reflow("The "),
alloc.string(index.ordinal()), alloc.string(index.ordinal()),
alloc.reflow(" branch is"), alloc.reflow(" branch is"),
]), ]),
alloc.reflow("But all the previous branches have type:"), alloc.reflow("But all the previous branches have type:"),
Some(alloc.concat(vec![ Some(alloc.concat([
alloc.reflow("I need all branches of a "), alloc.reflow("I need all branches of a "),
alloc.keyword("when"), alloc.keyword("when"),
alloc.reflow(" to have the same type!"), alloc.reflow(" to have the same type!"),
@ -810,12 +810,12 @@ fn to_expr_report<'b>(
expected_type, expected_type,
region, region,
Some(expr_region), Some(expr_region),
alloc.concat(vec![ alloc.concat([
alloc.text("I cannot update the "), alloc.text("I cannot update the "),
alloc.record_field(field.to_owned()), alloc.record_field(field.to_owned()),
alloc.text(" field like this:"), alloc.text(" field like this:"),
]), ]),
alloc.concat(vec![ alloc.concat([
alloc.text("You are trying to update "), alloc.text("You are trying to update "),
alloc.record_field(field), alloc.record_field(field),
alloc.text(" to be"), alloc.text(" to be"),
@ -846,7 +846,7 @@ fn to_expr_report<'b>(
region, region,
Some(expr_region), Some(expr_region),
alloc.reflow("Something is off with this record update:"), alloc.reflow("Something is off with this record update:"),
alloc.concat(vec![ alloc.concat([
alloc.reflow("The"), alloc.reflow("The"),
alloc.symbol_unqualified(symbol), alloc.symbol_unqualified(symbol),
alloc.reflow(" record is"), alloc.reflow(" record is"),
@ -939,7 +939,7 @@ fn to_expr_report<'b>(
0 => { 0 => {
let this_value = match name { let this_value = match name {
None => alloc.text("This value"), None => alloc.text("This value"),
Some(symbol) => alloc.concat(vec![ Some(symbol) => alloc.concat([
alloc.text("The "), alloc.text("The "),
alloc.symbol_unqualified(symbol), alloc.symbol_unqualified(symbol),
alloc.text(" value"), alloc.text(" value"),
@ -947,7 +947,7 @@ fn to_expr_report<'b>(
}; };
let lines = vec![ let lines = vec![
alloc.concat(vec![ alloc.concat([
this_value, this_value,
alloc.string(format!( alloc.string(format!(
" is not a function, but it was given {}:", " is not a function, but it was given {}:",
@ -972,7 +972,7 @@ fn to_expr_report<'b>(
n => { n => {
let this_function = match name { let this_function = match name {
None => alloc.text("This function"), None => alloc.text("This function"),
Some(symbol) => alloc.concat(vec![ Some(symbol) => alloc.concat([
alloc.text("The "), alloc.text("The "),
alloc.symbol_unqualified(symbol), alloc.symbol_unqualified(symbol),
alloc.text(" function"), alloc.text(" function"),
@ -981,7 +981,7 @@ fn to_expr_report<'b>(
if n < arity as usize { if n < arity as usize {
let lines = vec![ let lines = vec![
alloc.concat(vec![ alloc.concat([
this_function, this_function,
alloc.string(format!( alloc.string(format!(
" expects {}, but it got {} instead:", " expects {}, but it got {} instead:",
@ -1005,7 +1005,7 @@ fn to_expr_report<'b>(
} }
} else { } else {
let lines = vec![ let lines = vec![
alloc.concat(vec![ alloc.concat([
this_function, this_function,
alloc.string(format!( alloc.string(format!(
" expects {}, but it got only {}:", " expects {}, but it got only {}:",
@ -1050,13 +1050,13 @@ fn to_expr_report<'b>(
expected_type, expected_type,
region, region,
Some(expr_region), Some(expr_region),
alloc.concat(vec![ alloc.concat([
alloc.string(format!("The {} argument to ", ith)), alloc.string(format!("The {} argument to ", ith)),
this_function.clone(), this_function.clone(),
alloc.text(" is not what I expect:"), alloc.text(" is not what I expect:"),
]), ]),
alloc.text("This argument is"), alloc.text("This argument is"),
alloc.concat(vec![ alloc.concat([
alloc.text("But "), alloc.text("But "),
this_function, this_function,
alloc.string(format!(" needs the {} argument to be:", ith)), alloc.string(format!(" needs the {} argument to be:", ith)),
@ -1085,13 +1085,13 @@ fn to_expr_report<'b>(
def_region: _, def_region: _,
unimplemented_abilities, unimplemented_abilities,
} => { } => {
let problem = alloc.concat(vec![ let problem = alloc.concat([
alloc.reflow("Something is off with this specialization of "), alloc.reflow("Something is off with this specialization of "),
alloc.symbol_unqualified(member_name), alloc.symbol_unqualified(member_name),
alloc.reflow(":"), alloc.reflow(":"),
]); ]);
let this_is = alloc.reflow("This value is"); let this_is = alloc.reflow("This value is");
let instead_of = alloc.concat(vec![ let instead_of = alloc.concat([
alloc.reflow("But the type annotation on "), alloc.reflow("But the type annotation on "),
alloc.symbol_unqualified(member_name), alloc.symbol_unqualified(member_name),
alloc.reflow(" says it must match:"), alloc.reflow(" says it must match:"),
@ -1106,7 +1106,7 @@ fn to_expr_report<'b>(
} }
let hint = alloc.stack(vec![ let hint = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.note(""), alloc.note(""),
alloc.reflow("Some types in this specialization don't implement the abilities they are expected to. I found the following missing implementations:"), alloc.reflow("Some types in this specialization don't implement the abilities they are expected to. I found the following missing implementations:"),
]), ]),
@ -1136,20 +1136,20 @@ fn to_expr_report<'b>(
member_name, member_name,
def_region: _, def_region: _,
} => { } => {
let problem = alloc.concat(vec![ let problem = alloc.concat([
alloc.reflow("This specialization of "), alloc.reflow("This specialization of "),
alloc.symbol_unqualified(member_name), alloc.symbol_unqualified(member_name),
alloc.reflow(" is overly general:"), alloc.reflow(" is overly general:"),
]); ]);
let this_is = alloc.reflow("This value is"); let this_is = alloc.reflow("This value is");
let instead_of = alloc.concat(vec![ let instead_of = alloc.concat([
alloc.reflow("But the type annotation on "), alloc.reflow("But the type annotation on "),
alloc.symbol_unqualified(member_name), alloc.symbol_unqualified(member_name),
alloc.reflow(" says it must match:"), alloc.reflow(" says it must match:"),
]); ]);
let note = alloc.stack(vec![ let note = alloc.stack(vec![
alloc.concat(vec![ alloc.concat([
alloc.note(""), alloc.note(""),
alloc.reflow("The specialized type is too general, and does not provide a concrete type where a type variable is bound to an ability."), alloc.reflow("The specialized type is too general, and does not provide a concrete type where a type variable is bound to an ability."),
]), ]),
@ -1211,7 +1211,7 @@ fn does_not_implement<'a>(
err_type: ErrorType, err_type: ErrorType,
ability: Symbol, ability: Symbol,
) -> RocDocBuilder<'a> { ) -> RocDocBuilder<'a> {
alloc.concat(vec![ alloc.concat([
to_doc(alloc, Parens::Unnecessary, err_type).0, to_doc(alloc, Parens::Unnecessary, err_type).0,
alloc.reflow(" does not implement "), alloc.reflow(" does not implement "),
alloc.symbol_unqualified(ability), alloc.symbol_unqualified(ability),
@ -1223,7 +1223,7 @@ fn symbol_does_not_implement<'a>(
symbol: Symbol, symbol: Symbol,
ability: Symbol, ability: Symbol,
) -> RocDocBuilder<'a> { ) -> RocDocBuilder<'a> {
alloc.concat(vec![ alloc.concat([
alloc.symbol_unqualified(symbol), alloc.symbol_unqualified(symbol),
alloc.reflow(" does not implement "), alloc.reflow(" does not implement "),
alloc.symbol_unqualified(ability), alloc.symbol_unqualified(ability),
@ -1325,7 +1325,7 @@ fn format_category<'b>(
match category { match category {
Lookup(name) => ( Lookup(name) => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.symbol_foreign_qualified(*name), alloc.symbol_foreign_qualified(*name),
alloc.text(" value"), alloc.text(" value"),
@ -1334,7 +1334,7 @@ fn format_category<'b>(
), ),
If => ( If => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.keyword("if"), alloc.keyword("if"),
alloc.text(" expression"), alloc.text(" expression"),
@ -1342,7 +1342,7 @@ fn format_category<'b>(
alloc.text(" produces:"), alloc.text(" produces:"),
), ),
When => ( When => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.keyword("when"), alloc.keyword("when"),
alloc.text(" expression"), alloc.text(" expression"),
@ -1350,47 +1350,44 @@ fn format_category<'b>(
alloc.text(" produces:"), alloc.text(" produces:"),
), ),
List => ( List => (
alloc.concat(vec![this_is, alloc.text(" a list")]), alloc.concat([this_is, alloc.text(" a list")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
Num => ( Num => (
alloc.concat(vec![this_is, alloc.text(" a number")]), alloc.concat([this_is, alloc.text(" a number")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
Int => ( Int => (
alloc.concat(vec![this_is, alloc.text(" an integer")]), alloc.concat([this_is, alloc.text(" an integer")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
Float => ( Float => (
alloc.concat(vec![this_is, alloc.text(" a float")]), alloc.concat([this_is, alloc.text(" a float")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
Str => ( Str => (
alloc.concat(vec![this_is, alloc.text(" a string")]), alloc.concat([this_is, alloc.text(" a string")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
StrInterpolation => ( StrInterpolation => (
alloc.concat(vec![ alloc.concat([this_is, alloc.text(" a value in a string interpolation,")]),
this_is,
alloc.text(" a value in a string interpolation,"),
]),
alloc.text(" which was of type:"), alloc.text(" which was of type:"),
), ),
Character => ( Character => (
alloc.concat(vec![this_is, alloc.text(" a character")]), alloc.concat([this_is, alloc.text(" a character")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
Lambda => ( Lambda => (
alloc.concat(vec![this_is, alloc.text(" an anonymous function")]), alloc.concat([this_is, alloc.text(" an anonymous function")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
ClosureSize => ( ClosureSize => (
alloc.concat(vec![this_is, alloc.text(" the closure size of a function")]), alloc.concat([this_is, alloc.text(" the closure size of a function")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
OpaqueWrap(opaque) => ( OpaqueWrap(opaque) => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.opaque_name(*opaque), alloc.opaque_name(*opaque),
alloc.text(" opaque wrapping"), alloc.text(" opaque wrapping"),
@ -1399,9 +1396,7 @@ fn format_category<'b>(
), ),
OpaqueArg => ( OpaqueArg => (
alloc.concat(vec![ alloc.concat([alloc.text(format!("{}his argument to an opaque type", t))]),
alloc.text(format!("{}his argument to an opaque type", t))
]),
alloc.text(" has type:"), alloc.text(" has type:"),
), ),
@ -1409,7 +1404,7 @@ fn format_category<'b>(
tag_name: TagName::Global(name), tag_name: TagName::Global(name),
args_count: 0, args_count: 0,
} => ( } => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.global_tag_name(name.to_owned()), alloc.global_tag_name(name.to_owned()),
if name.as_str() == "True" || name.as_str() == "False" { if name.as_str() == "True" || name.as_str() == "False" {
@ -1424,7 +1419,7 @@ fn format_category<'b>(
tag_name: TagName::Private(name), tag_name: TagName::Private(name),
args_count: 0, args_count: 0,
} => ( } => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.private_tag_name(*name), alloc.private_tag_name(*name),
alloc.text(" private tag"), alloc.text(" private tag"),
@ -1436,7 +1431,7 @@ fn format_category<'b>(
tag_name: TagName::Global(name), tag_name: TagName::Global(name),
args_count: _, args_count: _,
} => ( } => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.global_tag_name(name.to_owned()), alloc.global_tag_name(name.to_owned()),
alloc.text(" global tag application"), alloc.text(" global tag application"),
@ -1447,7 +1442,7 @@ fn format_category<'b>(
tag_name: TagName::Private(name), tag_name: TagName::Private(name),
args_count: _, args_count: _,
} => ( } => (
alloc.concat(vec![ alloc.concat([
alloc.text("This "), alloc.text("This "),
alloc.private_tag_name(*name), alloc.private_tag_name(*name),
alloc.text(" private tag application"), alloc.text(" private tag application"),
@ -1460,12 +1455,12 @@ fn format_category<'b>(
} => unreachable!("closure tags are for internal use only"), } => unreachable!("closure tags are for internal use only"),
Record => ( Record => (
alloc.concat(vec![this_is, alloc.text(" a record")]), alloc.concat([this_is, alloc.text(" a record")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
Accessor(field) => ( Accessor(field) => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.record_field(field.to_owned()), alloc.record_field(field.to_owned()),
alloc.text(" value"), alloc.text(" value"),
@ -1473,7 +1468,7 @@ fn format_category<'b>(
alloc.text(" is a:"), alloc.text(" is a:"),
), ),
Access(field) => ( Access(field) => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}he value at ", t)), alloc.text(format!("{}he value at ", t)),
alloc.record_field(field.to_owned()), alloc.record_field(field.to_owned()),
]), ]),
@ -1494,11 +1489,11 @@ fn format_category<'b>(
alloc.text(" produces:"), alloc.text(" produces:"),
), ),
CallResult(Some(_), CalledVia::StringInterpolation) => ( CallResult(Some(_), CalledVia::StringInterpolation) => (
alloc.concat(vec![this_is, alloc.text(" a string")]), alloc.concat([this_is, alloc.text(" a string")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
CallResult(Some(symbol), _) => ( CallResult(Some(symbol), _) => (
alloc.concat(vec![ alloc.concat([
alloc.text(format!("{}his ", t)), alloc.text(format!("{}his ", t)),
alloc.symbol_foreign_qualified(*symbol), alloc.symbol_foreign_qualified(*symbol),
alloc.text(" call"), alloc.text(" call"),
@ -1517,19 +1512,19 @@ fn format_category<'b>(
} }
Uniqueness => ( Uniqueness => (
alloc.concat(vec![this_is, alloc.text(" an uniqueness attribute")]), alloc.concat([this_is, alloc.text(" an uniqueness attribute")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
Storage(_file, _line) => ( Storage(_file, _line) => (
alloc.concat(vec![this_is, alloc.text(" a value")]), alloc.concat([this_is, alloc.text(" a value")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
DefaultValue(_) => ( DefaultValue(_) => (
alloc.concat(vec![this_is, alloc.text(" a default field")]), alloc.concat([this_is, alloc.text(" a default field")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
AbilityMemberSpecialization(_ability_member) => ( AbilityMemberSpecialization(_ability_member) => (
alloc.concat(vec![this_is, alloc.text(" a declared specialization")]), alloc.concat([this_is, alloc.text(" a declared specialization")]),
alloc.text(" of type:"), alloc.text(" of type:"),
), ),
} }
@ -1541,7 +1536,7 @@ fn add_category<'b>(
category: &Category, category: &Category,
) -> RocDocBuilder<'b> { ) -> RocDocBuilder<'b> {
let (summary, suffix) = format_category(alloc, this_is, category, true); let (summary, suffix) = format_category(alloc, this_is, category, true);
alloc.concat(vec![summary, suffix]) alloc.concat([summary, suffix])
} }
fn to_pattern_report<'b>( fn to_pattern_report<'b>(
@ -1602,7 +1597,7 @@ fn to_pattern_report<'b>(
alloc.text("The argument is a pattern that matches"), alloc.text("The argument is a pattern that matches"),
&category, &category,
), ),
alloc.concat(vec![ alloc.concat([
alloc.text("But the annotation on "), alloc.text("But the annotation on "),
name, name,
alloc.text(" says the "), alloc.text(" says the "),
@ -1637,7 +1632,7 @@ fn to_pattern_report<'b>(
alloc.text("The first pattern is trying to match"), alloc.text("The first pattern is trying to match"),
&category, &category,
), ),
alloc.concat(vec![ alloc.concat([
alloc.text("But the expression between "), alloc.text("But the expression between "),
alloc.keyword("when"), alloc.keyword("when"),
alloc.text(" and "), alloc.text(" and "),
@ -1734,12 +1729,12 @@ fn add_pattern_category<'b>(
PatternDefault => alloc.reflow(" an optional field of type:"), PatternDefault => alloc.reflow(" an optional field of type:"),
Set => alloc.reflow(" sets of type:"), Set => alloc.reflow(" sets of type:"),
Map => alloc.reflow(" maps of type:"), Map => alloc.reflow(" maps of type:"),
Ctor(tag_name) => alloc.concat(vec![ Ctor(tag_name) => alloc.concat([
alloc.reflow(" a "), alloc.reflow(" a "),
alloc.tag_name(tag_name.clone()), alloc.tag_name(tag_name.clone()),
alloc.reflow(" tag of type:"), alloc.reflow(" tag of type:"),
]), ]),
Opaque(opaque) => alloc.concat(vec![ Opaque(opaque) => alloc.concat([
alloc.opaque_name(*opaque), alloc.opaque_name(*opaque),
alloc.reflow(" unwrappings of type:"), alloc.reflow(" unwrappings of type:"),
]), ]),
@ -1750,7 +1745,7 @@ fn add_pattern_category<'b>(
Character => alloc.reflow(" characters:"), Character => alloc.reflow(" characters:"),
}; };
alloc.concat(vec![i_am_trying_to_match, rest]) alloc.concat([i_am_trying_to_match, rest])
} }
fn to_circular_report<'b>( fn to_circular_report<'b>(
@ -2804,7 +2799,7 @@ mod report_text {
args: Vec<RocDocBuilder<'b>>, args: Vec<RocDocBuilder<'b>>,
ret: RocDocBuilder<'b>, ret: RocDocBuilder<'b>,
) -> RocDocBuilder<'b> { ) -> RocDocBuilder<'b> {
let function_doc = alloc.concat(vec![ let function_doc = alloc.concat([
alloc.intersperse(args, alloc.reflow(", ")), alloc.intersperse(args, alloc.reflow(", ")),
alloc.reflow(" -> "), alloc.reflow(" -> "),
ret, ret,
@ -2825,11 +2820,8 @@ mod report_text {
if args.is_empty() { if args.is_empty() {
name name
} else { } else {
let apply_doc = alloc.concat(vec![ let apply_doc =
name, alloc.concat([name, alloc.space(), alloc.intersperse(args, alloc.space())]);
alloc.space(),
alloc.intersperse(args, alloc.space()),
]);
match parens { match parens {
Parens::Unnecessary | Parens::InFn => apply_doc, Parens::Unnecessary | Parens::InFn => apply_doc,
@ -3209,7 +3201,7 @@ fn type_problem_to_pretty<'b>(
Infinite | Error | FlexVar(_) => alloc.nil(), Infinite | Error | FlexVar(_) => alloc.nil(),
FlexAbleVar(_, ability) => bad_rigid_var( FlexAbleVar(_, ability) => bad_rigid_var(
x, x,
alloc.concat(vec![ alloc.concat([
alloc.reflow("an instance of the ability "), alloc.reflow("an instance of the ability "),
alloc.symbol_unqualified(ability), alloc.symbol_unqualified(ability),
]), ]),
@ -3222,7 +3214,7 @@ fn type_problem_to_pretty<'b>(
} }
Alias(symbol, _, _, _) | Type(symbol, _) => bad_rigid_var( Alias(symbol, _, _, _) | Type(symbol, _) => bad_rigid_var(
x, x,
alloc.concat(vec![ alloc.concat([
alloc.reflow("a "), alloc.reflow("a "),
alloc.symbol_unqualified(symbol), alloc.symbol_unqualified(symbol),
alloc.reflow(" value"), alloc.reflow(" value"),
@ -3232,7 +3224,7 @@ fn type_problem_to_pretty<'b>(
} }
} }
(IntFloat, _) => alloc.tip().append(alloc.concat(vec![ (IntFloat, _) => alloc.tip().append(alloc.concat([
alloc.reflow("You can convert between "), alloc.reflow("You can convert between "),
alloc.type_str("Int"), alloc.type_str("Int"),
alloc.reflow(" and "), alloc.reflow(" and "),
@ -3285,7 +3277,7 @@ fn type_problem_to_pretty<'b>(
alloc.stack(vec![tip1, tip2]) alloc.stack(vec![tip1, tip2])
} }
}, },
(OptionalRequiredMismatch(field), _) => alloc.tip().append(alloc.concat(vec![ (OptionalRequiredMismatch(field), _) => alloc.tip().append(alloc.concat([
alloc.reflow("To extract the "), alloc.reflow("To extract the "),
alloc.record_field(field), alloc.record_field(field),
alloc.reflow( alloc.reflow(
@ -3294,7 +3286,7 @@ fn type_problem_to_pretty<'b>(
alloc.reflow("Learn more about optional fields at TODO."), alloc.reflow("Learn more about optional fields at TODO."),
])), ])),
(OpaqueComparedToNonOpaque, _) => alloc.tip().append(alloc.concat(vec![ (OpaqueComparedToNonOpaque, _) => alloc.tip().append(alloc.concat([
alloc.reflow( alloc.reflow(
"Type comparisons between an opaque type are only ever \ "Type comparisons between an opaque type are only ever \
equal if both types are the same opaque type. Did you mean \ equal if both types are the same opaque type. Did you mean \