Add test for types of destructed recursive alias in issue

This commit is contained in:
Ayaz Hafiz 2022-06-22 11:16:42 -04:00
parent 69ab681f9c
commit fdba8b26d4
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 220 additions and 46 deletions

View file

@ -35,8 +35,18 @@ mod solve_expr {
fn parse_queries(src: &str) -> Vec<TypeQuery> {
let line_info = LineInfo::new(src);
let mut queries = vec![];
let mut consecutive_query_lines = 0;
for (i, line) in src.lines().enumerate() {
for capture in RE_TYPE_QUERY.captures_iter(line) {
let mut queries_on_line = RE_TYPE_QUERY.captures_iter(line).into_iter().peekable();
if queries_on_line.peek().is_none() {
consecutive_query_lines = 0;
continue;
} else {
consecutive_query_lines += 1;
}
for capture in queries_on_line {
let wher = capture.name("where").unwrap();
let subtract_col = capture
.name("sub")
@ -44,7 +54,7 @@ mod solve_expr {
.unwrap_or(0);
let (start, end) = (wher.start() as u32, wher.end() as u32);
let (start, end) = (start - subtract_col, end - subtract_col);
let last_line = i as u32 - 1;
let last_line = i as u32 - consecutive_query_lines;
let start_lc = LineColumn {
line: last_line,
column: start,
@ -277,6 +287,7 @@ mod solve_expr {
let var = find_type_at(region, &decls)
.unwrap_or_else(|| panic!("No type for {:?} ({:?})!", &text, region));
let snapshot = subs.snapshot();
let actual_str = name_and_print_var(
var,
subs,
@ -287,6 +298,7 @@ mod solve_expr {
print_only_under_alias,
},
);
subs.rollback_to(snapshot);
let elaborated =
match find_ability_member_and_owning_type_at(region, &decls, &abilities_store) {
@ -5480,7 +5492,7 @@ mod solve_expr {
Job lst s -> P lst s
"#
),
"[P (List [Job (List a) Str] as a) Str]*",
"[P (List ([Job (List a) Str] as a)) Str]*",
)
}
@ -6861,4 +6873,32 @@ mod solve_expr {
"Str -> Str",
)
}
#[test]
fn issue_3261() {
infer_queries!(
indoc!(
r#"
Named : [Named Str (List Named)]
foo : Named
foo = Named "outer" [Named "inner" []]
#^^^{-1}
Named name outerList = foo
#^^^^^^^^^^^^^^^^^^^^{-1}
# ^^^^ ^^^^^^^^^
{name, outerList}
"#
),
&[
"foo : [Named Str (List a)] as a",
"Named name outerList : [Named Str (List a)] as a",
"name : Str",
"outerList : List ([Named Str (List a)] as a)",
],
print_only_under_alias = true
)
}
}

View file

@ -90,6 +90,7 @@ fn find_names_needed(
roots: &mut Vec<Variable>,
root_appearances: &mut MutMap<Variable, Appearances>,
names_taken: &mut MutMap<Lowercase, Variable>,
find_under_alias: bool,
) {
use crate::subs::Content::*;
use crate::subs::FlatType::*;
@ -190,59 +191,151 @@ fn find_names_needed(
Structure(Apply(_, args)) => {
for index in args.into_iter() {
let var = subs[index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
find_names_needed(
var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
}
Structure(Func(arg_vars, _closure_var, ret_var)) => {
for index in arg_vars.into_iter() {
let var = subs[index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
find_names_needed(
var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
find_names_needed(*ret_var, subs, roots, root_appearances, names_taken);
find_names_needed(
*ret_var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
Structure(Record(sorted_fields, ext_var)) => {
for index in sorted_fields.iter_variables() {
let var = subs[index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
find_names_needed(
var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
find_names_needed(*ext_var, subs, roots, root_appearances, names_taken);
find_names_needed(
*ext_var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
Structure(TagUnion(tags, ext_var)) => {
for slice_index in tags.variables() {
let slice = subs[slice_index];
for var_index in slice {
let var = subs[var_index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
find_names_needed(
var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
}
find_names_needed(*ext_var, subs, roots, root_appearances, names_taken);
find_names_needed(
*ext_var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
Structure(FunctionOrTagUnion(_, _, ext_var)) => {
find_names_needed(*ext_var, subs, roots, root_appearances, names_taken);
find_names_needed(
*ext_var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
Structure(RecursiveTagUnion(rec_var, tags, ext_var)) => {
for slice_index in tags.variables() {
let slice = subs[slice_index];
for var_index in slice {
let var = subs[var_index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
find_names_needed(
var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
}
find_names_needed(*ext_var, subs, roots, root_appearances, names_taken);
find_names_needed(*rec_var, subs, roots, root_appearances, names_taken);
find_names_needed(
*ext_var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
find_names_needed(
*rec_var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
Alias(_symbol, args, _actual, _kind) => {
Alias(_symbol, args, actual, _kind) => {
// only find names for named parameters!
for var_index in args.into_iter().take(args.len()) {
let var = subs[var_index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
find_names_needed(
var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
if find_under_alias {
find_names_needed(
*actual,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
// TODO should we also look in the actual variable?
// find_names_needed(_actual, subs, roots, root_appearances, names_taken);
}
LambdaSet(subs::LambdaSet {
solved,
@ -253,21 +346,49 @@ fn find_names_needed(
let slice = subs[slice_index];
for var_index in slice {
let var = subs[var_index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
find_names_needed(
var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
}
for uls_index in unspecialized.into_iter() {
let Uls(var, _, _) = subs[uls_index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
find_names_needed(
var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
if let Some(rec_var) = recursion_var.into_variable() {
find_names_needed(rec_var, subs, roots, root_appearances, names_taken);
find_names_needed(
rec_var,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
}
&RangedNumber(typ, _) => {
find_names_needed(typ, subs, roots, root_appearances, names_taken);
find_names_needed(
typ,
subs,
roots,
root_appearances,
names_taken,
find_under_alias,
);
}
Error | Structure(Erroneous(_)) | Structure(EmptyRecord) | Structure(EmptyTagUnion) => {
// Errors and empty records don't need names.
@ -279,14 +400,25 @@ struct NamedResult {
recursion_structs_to_expand: Vec<Variable>,
}
fn name_all_type_vars(variable: Variable, subs: &mut Subs) -> NamedResult {
fn name_all_type_vars(
variable: Variable,
subs: &mut Subs,
find_names_under_alias: bool,
) -> NamedResult {
let mut roots = Vec::new();
let mut letters_used = 0;
let mut appearances = MutMap::default();
let mut taken = MutMap::default();
// Populate names_needed
find_names_needed(variable, subs, &mut roots, &mut appearances, &mut taken);
find_names_needed(
variable,
subs,
&mut roots,
&mut appearances,
&mut taken,
find_names_under_alias,
);
let mut recursion_structs_to_expand = vec![];
@ -417,7 +549,7 @@ pub fn name_and_print_var(
interns: &Interns,
debug_print: DebugPrint,
) -> String {
let named_result = name_all_type_vars(var, subs);
let named_result = name_all_type_vars(var, subs, debug_print.print_only_under_alias);
let content = subs.get_content_without_compacting(var);
content_to_string(content, subs, home, interns, named_result, debug_print)
}
@ -976,31 +1108,33 @@ fn write_flat_type<'a>(
}
RecursiveTagUnion(rec_var, tags, ext_var) => {
buf.push('[');
write_parens!(parens == Parens::InTypeParam, buf, {
buf.push('[');
let (tags, new_ext_var) = tags.unsorted_tags_and_ext(subs, *ext_var);
write_sorted_tags2(env, ctx, subs, buf, tags, |tag| tag.0.as_str().to_string());
let (tags, new_ext_var) = tags.unsorted_tags_and_ext(subs, *ext_var);
write_sorted_tags2(env, ctx, subs, buf, tags, |tag| tag.0.as_str().to_string());
buf.push(']');
buf.push(']');
write_ext_content(
env,
ctx,
subs,
buf,
ExtContent::from_var(subs, new_ext_var),
parens,
);
write_ext_content(
env,
ctx,
subs,
buf,
ExtContent::from_var(subs, new_ext_var),
parens,
);
buf.push_str(" as ");
write_content(
env,
ctx,
subs.get_content_without_compacting(*rec_var),
subs,
buf,
parens,
)
buf.push_str(" as ");
write_content(
env,
ctx,
subs.get_content_without_compacting(*rec_var),
subs,
buf,
parens,
)
})
}
Erroneous(problem) => {
buf.push_str(&format!("<Type Mismatch: {:?}>", problem));