mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
Parse "as" aliases into tag/args rather than arbitrary annotations
This commit is contained in:
parent
4ddb8e10fb
commit
2cd5bf8c03
8 changed files with 276 additions and 253 deletions
|
@ -374,124 +374,109 @@ fn can_annotation_help(
|
|||
}
|
||||
}
|
||||
}
|
||||
As(loc_inner, _spaces, loc_as) => match loc_as.value {
|
||||
TypeAnnotation::Apply(module_name, ident, loc_vars) if module_name.is_empty() => {
|
||||
let symbol = match scope.introduce(
|
||||
ident.into(),
|
||||
&env.exposed_ident_ids,
|
||||
&mut env.ident_ids,
|
||||
region,
|
||||
) {
|
||||
Ok(symbol) => symbol,
|
||||
As(loc_inner, _spaces, (ident, loc_vars)) => {
|
||||
let symbol = match scope.introduce(
|
||||
(*ident).into(),
|
||||
&env.exposed_ident_ids,
|
||||
&mut env.ident_ids,
|
||||
region,
|
||||
) {
|
||||
Ok(symbol) => symbol,
|
||||
|
||||
Err((original_region, shadow)) => {
|
||||
let problem = Problem::Shadowed(original_region, shadow.clone());
|
||||
Err((original_region, shadow)) => {
|
||||
let problem = Problem::Shadowed(original_region, shadow.clone());
|
||||
|
||||
env.problem(roc_problem::can::Problem::ShadowingInAnnotation {
|
||||
original_region,
|
||||
shadow,
|
||||
});
|
||||
env.problem(roc_problem::can::Problem::ShadowingInAnnotation {
|
||||
original_region,
|
||||
shadow,
|
||||
});
|
||||
|
||||
return Type::Erroneous(problem);
|
||||
}
|
||||
};
|
||||
|
||||
let inner_type = can_annotation_help(
|
||||
env,
|
||||
&loc_inner.value,
|
||||
region,
|
||||
scope,
|
||||
var_store,
|
||||
introduced_variables,
|
||||
local_aliases,
|
||||
references,
|
||||
);
|
||||
let mut vars = Vec::with_capacity(loc_vars.len());
|
||||
let mut lowercase_vars = Vec::with_capacity(loc_vars.len());
|
||||
|
||||
references.insert(symbol);
|
||||
|
||||
for loc_var in loc_vars {
|
||||
match loc_var.value {
|
||||
BoundVariable(ident) => {
|
||||
let var_name = Lowercase::from(ident);
|
||||
|
||||
if let Some(var) = introduced_variables.var_by_name(&var_name) {
|
||||
vars.push((var_name.clone(), Type::Variable(*var)));
|
||||
lowercase_vars.push(Loc::at(loc_var.region, (var_name, *var)));
|
||||
} else {
|
||||
let var = var_store.fresh();
|
||||
|
||||
introduced_variables.insert_named(var_name.clone(), var);
|
||||
vars.push((var_name.clone(), Type::Variable(var)));
|
||||
|
||||
lowercase_vars.push(Loc::at(loc_var.region, (var_name, var)));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// If anything other than a lowercase identifier
|
||||
// appears here, the whole annotation is invalid.
|
||||
return Type::Erroneous(Problem::CanonicalizationProblem);
|
||||
}
|
||||
}
|
||||
return Type::Erroneous(problem);
|
||||
}
|
||||
};
|
||||
|
||||
let alias_actual = if let Type::TagUnion(tags, ext) = inner_type {
|
||||
let rec_var = var_store.fresh();
|
||||
let inner_type = can_annotation_help(
|
||||
env,
|
||||
&loc_inner.value,
|
||||
region,
|
||||
scope,
|
||||
var_store,
|
||||
introduced_variables,
|
||||
local_aliases,
|
||||
references,
|
||||
);
|
||||
let mut vars = Vec::with_capacity(loc_vars.len());
|
||||
let mut lowercase_vars = Vec::with_capacity(loc_vars.len());
|
||||
|
||||
let mut new_tags = Vec::with_capacity(tags.len());
|
||||
for (tag_name, args) in tags {
|
||||
let mut new_args = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
let mut new_arg = arg.clone();
|
||||
new_arg.substitute_alias(symbol, &Type::Variable(rec_var));
|
||||
new_args.push(new_arg);
|
||||
}
|
||||
new_tags.push((tag_name.clone(), new_args));
|
||||
}
|
||||
Type::RecursiveTagUnion(rec_var, new_tags, ext)
|
||||
references.insert(symbol);
|
||||
|
||||
for loc_var in *loc_vars {
|
||||
let var_name = Lowercase::from(loc_var.value);
|
||||
|
||||
if let Some(var) = introduced_variables.var_by_name(&var_name) {
|
||||
vars.push((var_name.clone(), Type::Variable(*var)));
|
||||
lowercase_vars.push(Loc::at(loc_var.region, (var_name, *var)));
|
||||
} else {
|
||||
inner_type
|
||||
};
|
||||
let var = var_store.fresh();
|
||||
|
||||
let mut hidden_variables = MutSet::default();
|
||||
hidden_variables.extend(alias_actual.variables());
|
||||
introduced_variables.insert_named(var_name.clone(), var);
|
||||
vars.push((var_name.clone(), Type::Variable(var)));
|
||||
|
||||
for loc_var in lowercase_vars.iter() {
|
||||
hidden_variables.remove(&loc_var.value.1);
|
||||
}
|
||||
|
||||
scope.add_alias(symbol, region, lowercase_vars, alias_actual);
|
||||
|
||||
let alias = scope.lookup_alias(symbol).unwrap();
|
||||
local_aliases.insert(symbol, alias.clone());
|
||||
|
||||
// Type::Alias(symbol, vars, Box::new(alias.typ.clone()))
|
||||
|
||||
if vars.is_empty() && env.home == symbol.module_id() {
|
||||
let actual_var = var_store.fresh();
|
||||
introduced_variables.insert_host_exposed_alias(symbol, actual_var);
|
||||
Type::HostExposedAlias {
|
||||
name: symbol,
|
||||
type_arguments: vars,
|
||||
lambda_set_variables: alias.lambda_set_variables.clone(),
|
||||
actual: Box::new(alias.typ.clone()),
|
||||
actual_var,
|
||||
}
|
||||
} else {
|
||||
Type::Alias {
|
||||
symbol,
|
||||
type_arguments: vars,
|
||||
lambda_set_variables: alias.lambda_set_variables.clone(),
|
||||
actual: Box::new(alias.typ.clone()),
|
||||
}
|
||||
lowercase_vars.push(Loc::at(loc_var.region, (var_name, var)));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// This is a syntactically invalid type alias.
|
||||
Type::Erroneous(Problem::CanonicalizationProblem)
|
||||
|
||||
let alias_actual = if let Type::TagUnion(tags, ext) = inner_type {
|
||||
let rec_var = var_store.fresh();
|
||||
|
||||
let mut new_tags = Vec::with_capacity(tags.len());
|
||||
for (tag_name, args) in tags {
|
||||
let mut new_args = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
let mut new_arg = arg.clone();
|
||||
new_arg.substitute_alias(symbol, &Type::Variable(rec_var));
|
||||
new_args.push(new_arg);
|
||||
}
|
||||
new_tags.push((tag_name.clone(), new_args));
|
||||
}
|
||||
Type::RecursiveTagUnion(rec_var, new_tags, ext)
|
||||
} else {
|
||||
inner_type
|
||||
};
|
||||
|
||||
let mut hidden_variables = MutSet::default();
|
||||
hidden_variables.extend(alias_actual.variables());
|
||||
|
||||
for loc_var in lowercase_vars.iter() {
|
||||
hidden_variables.remove(&loc_var.value.1);
|
||||
}
|
||||
},
|
||||
|
||||
scope.add_alias(symbol, region, lowercase_vars, alias_actual);
|
||||
|
||||
let alias = scope.lookup_alias(symbol).unwrap();
|
||||
local_aliases.insert(symbol, alias.clone());
|
||||
|
||||
// Type::Alias(symbol, vars, Box::new(alias.typ.clone()))
|
||||
|
||||
if vars.is_empty() && env.home == symbol.module_id() {
|
||||
let actual_var = var_store.fresh();
|
||||
introduced_variables.insert_host_exposed_alias(symbol, actual_var);
|
||||
Type::HostExposedAlias {
|
||||
name: symbol,
|
||||
type_arguments: vars,
|
||||
lambda_set_variables: alias.lambda_set_variables.clone(),
|
||||
actual: Box::new(alias.typ.clone()),
|
||||
actual_var,
|
||||
}
|
||||
} else {
|
||||
Type::Alias {
|
||||
symbol,
|
||||
type_arguments: vars,
|
||||
lambda_set_variables: alias.lambda_set_variables.clone(),
|
||||
actual: Box::new(alias.typ.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Record { fields, ext } => {
|
||||
let ext_type = match ext {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue