mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Refactor headers_from_annotation to match over TypeTag
This commit is contained in:
parent
c8de1e5a27
commit
7fa508b3c8
1 changed files with 108 additions and 91 deletions
|
@ -5,14 +5,15 @@ use roc_can::expected::{Expected, PExpected};
|
||||||
use roc_can::pattern::Pattern::{self, *};
|
use roc_can::pattern::Pattern::{self, *};
|
||||||
use roc_can::pattern::{DestructType, ListPatterns, RecordDestruct, TupleDestruct};
|
use roc_can::pattern::{DestructType, ListPatterns, RecordDestruct, TupleDestruct};
|
||||||
use roc_collections::all::{HumanIndex, SendMap};
|
use roc_collections::all::{HumanIndex, SendMap};
|
||||||
|
use roc_collections::soa::Index;
|
||||||
use roc_collections::VecMap;
|
use roc_collections::VecMap;
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use roc_types::subs::Variable;
|
use roc_types::subs::Variable;
|
||||||
use roc_types::types::{
|
use roc_types::types::{
|
||||||
AliasKind, Category, OptAbleType, PReason, PatternCategory, Reason, RecordField, Type,
|
AliasKind, AliasShared, Category, OptAbleType, PReason, PatternCategory, Reason, RecordField,
|
||||||
TypeExtension, TypeTag, Types,
|
Type, TypeExtension, TypeTag, Types,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
@ -31,10 +32,10 @@ pub struct PatternState {
|
||||||
/// Would add `x => <42>` to the headers (i.e., symbol points to a type variable). If the
|
/// Would add `x => <42>` to the headers (i.e., symbol points to a type variable). If the
|
||||||
/// definition has an annotation, we instead now add `x => Int`.
|
/// definition has an annotation, we instead now add `x => Int`.
|
||||||
pub fn headers_from_annotation(
|
pub fn headers_from_annotation(
|
||||||
types: &mut Types,
|
types: &Types,
|
||||||
constraints: &mut Constraints,
|
constraints: &mut Constraints,
|
||||||
pattern: &Pattern,
|
pattern: &Pattern,
|
||||||
annotation: &Loc<&Type>,
|
annotation: &Loc<Index<TypeTag>>,
|
||||||
) -> Option<VecMap<Symbol, Loc<TypeOrVar>>> {
|
) -> Option<VecMap<Symbol, Loc<TypeOrVar>>> {
|
||||||
let mut headers = VecMap::default();
|
let mut headers = VecMap::default();
|
||||||
// Check that the annotation structurally agrees with the pattern, preventing e.g. `{ x, y } : Int`
|
// Check that the annotation structurally agrees with the pattern, preventing e.g. `{ x, y } : Int`
|
||||||
|
@ -51,12 +52,13 @@ pub fn headers_from_annotation(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn headers_from_annotation_help(
|
fn headers_from_annotation_help(
|
||||||
types: &mut Types,
|
types: &Types,
|
||||||
constraints: &mut Constraints,
|
constraints: &mut Constraints,
|
||||||
pattern: &Pattern,
|
pattern: &Pattern,
|
||||||
annotation: &Loc<&Type>,
|
annotation: &Loc<Index<TypeTag>>,
|
||||||
headers: &mut VecMap<Symbol, Loc<TypeOrVar>>,
|
headers: &mut VecMap<Symbol, Loc<TypeOrVar>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let typ = annotation.value;
|
||||||
match pattern {
|
match pattern {
|
||||||
Identifier(symbol)
|
Identifier(symbol)
|
||||||
| Shadowed(_, _, symbol)
|
| Shadowed(_, _, symbol)
|
||||||
|
@ -64,20 +66,14 @@ fn headers_from_annotation_help(
|
||||||
ident: symbol,
|
ident: symbol,
|
||||||
specializes: _,
|
specializes: _,
|
||||||
} => {
|
} => {
|
||||||
let annotation_index = {
|
let annotation_index = constraints.push_type(types, typ);
|
||||||
let typ = types.from_old_type(annotation.value);
|
|
||||||
constraints.push_type(types, typ)
|
|
||||||
};
|
|
||||||
let typ = Loc::at(annotation.region, annotation_index);
|
let typ = Loc::at(annotation.region, annotation_index);
|
||||||
headers.insert(*symbol, typ);
|
headers.insert(*symbol, typ);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
As(subpattern, symbol) => {
|
As(subpattern, symbol) => {
|
||||||
let annotation_index = {
|
let annotation_index = constraints.push_type(types, typ);
|
||||||
let typ = types.from_old_type(annotation.value);
|
|
||||||
constraints.push_type(types, typ)
|
|
||||||
};
|
|
||||||
let typ = Loc::at(annotation.region, annotation_index);
|
let typ = Loc::at(annotation.region, annotation_index);
|
||||||
headers.insert(*symbol, typ);
|
headers.insert(*symbol, typ);
|
||||||
|
|
||||||
|
@ -94,8 +90,13 @@ fn headers_from_annotation_help(
|
||||||
| SingleQuote(..)
|
| SingleQuote(..)
|
||||||
| StrLiteral(_) => true,
|
| StrLiteral(_) => true,
|
||||||
|
|
||||||
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
|
RecordDestructure { destructs, .. } => {
|
||||||
Type::Record(fields, _) => {
|
let dealiased = types.shallow_dealias(annotation.value);
|
||||||
|
match types[dealiased] {
|
||||||
|
TypeTag::Record(fields) => {
|
||||||
|
let (field_names, _, field_types) = types.record_fields_slices(fields);
|
||||||
|
let field_names = &types[field_names];
|
||||||
|
|
||||||
for loc_destruct in destructs {
|
for loc_destruct in destructs {
|
||||||
let destruct = &loc_destruct.value;
|
let destruct = &loc_destruct.value;
|
||||||
|
|
||||||
|
@ -106,9 +107,12 @@ fn headers_from_annotation_help(
|
||||||
// For example, no matter whether it's `{ x } = rec` or
|
// For example, no matter whether it's `{ x } = rec` or
|
||||||
// `{ x ? 0 } = rec` or `{ x: 5 } -> ...` in all cases
|
// `{ x ? 0 } = rec` or `{ x: 5 } -> ...` in all cases
|
||||||
// the type of `x` within the binding itself is the same.
|
// the type of `x` within the binding itself is the same.
|
||||||
if let Some(field_type) = fields.get(&destruct.label) {
|
if let Some(i) = field_names
|
||||||
|
.iter()
|
||||||
|
.position(|field| field == &destruct.label)
|
||||||
|
{
|
||||||
let field_type_index = {
|
let field_type_index = {
|
||||||
let typ = types.from_old_type(&field_type.as_inner().clone());
|
let typ = field_types.at(i);
|
||||||
constraints.push_type(types, typ)
|
constraints.push_type(types, typ)
|
||||||
};
|
};
|
||||||
headers.insert(
|
headers.insert(
|
||||||
|
@ -121,9 +125,10 @@ fn headers_from_annotation_help(
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Type::EmptyRec => destructs.is_empty(),
|
TypeTag::EmptyRecord => destructs.is_empty(),
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TupleDestructure { destructs: _, .. } => {
|
TupleDestructure { destructs: _, .. } => {
|
||||||
todo!();
|
todo!();
|
||||||
|
@ -132,7 +137,7 @@ fn headers_from_annotation_help(
|
||||||
List { patterns, .. } => {
|
List { patterns, .. } => {
|
||||||
if let Some((_, Some(rest))) = patterns.opt_rest {
|
if let Some((_, Some(rest))) = patterns.opt_rest {
|
||||||
let annotation_index = {
|
let annotation_index = {
|
||||||
let typ = types.from_old_type(annotation.value);
|
let typ = annotation.value;
|
||||||
constraints.push_type(types, typ)
|
constraints.push_type(types, typ)
|
||||||
};
|
};
|
||||||
let typ = Loc::at(annotation.region, annotation_index);
|
let typ = Loc::at(annotation.region, annotation_index);
|
||||||
|
@ -152,17 +157,22 @@ fn headers_from_annotation_help(
|
||||||
tag_name,
|
tag_name,
|
||||||
arguments,
|
arguments,
|
||||||
..
|
..
|
||||||
} => match annotation.value.shallow_dealias() {
|
} => {
|
||||||
Type::TagUnion(tags, _) => {
|
let dealiased = types.shallow_dealias(annotation.value);
|
||||||
if let Some((_, arg_types)) = tags.iter().find(|(name, _)| name == tag_name) {
|
match types[dealiased] {
|
||||||
if !arguments.len() == arg_types.len() {
|
TypeTag::TagUnion(tags, _) => {
|
||||||
|
let (tags, payloads) = types.union_tag_slices(tags);
|
||||||
|
let tags = &types[tags];
|
||||||
|
|
||||||
|
if let Some(i) = tags.iter().position(|name| name == tag_name) {
|
||||||
|
let arg_types_slice = types[payloads.at(i)];
|
||||||
|
|
||||||
|
if !arguments.len() == arg_types_slice.len() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments
|
arguments.iter().zip(arg_types_slice.into_iter()).all(
|
||||||
.iter()
|
|(arg_pattern, arg_type)| {
|
||||||
.zip(arg_types.iter())
|
|
||||||
.all(|(arg_pattern, arg_type)| {
|
|
||||||
headers_from_annotation_help(
|
headers_from_annotation_help(
|
||||||
types,
|
types,
|
||||||
constraints,
|
constraints,
|
||||||
|
@ -170,13 +180,15 @@ fn headers_from_annotation_help(
|
||||||
&Loc::at(annotation.region, arg_type),
|
&Loc::at(annotation.region, arg_type),
|
||||||
headers,
|
headers,
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UnwrappedOpaque {
|
UnwrappedOpaque {
|
||||||
whole_var: _,
|
whole_var: _,
|
||||||
|
@ -185,22 +197,23 @@ fn headers_from_annotation_help(
|
||||||
specialized_def_type: _,
|
specialized_def_type: _,
|
||||||
type_arguments: pat_type_arguments,
|
type_arguments: pat_type_arguments,
|
||||||
lambda_set_variables: pat_lambda_set_variables,
|
lambda_set_variables: pat_lambda_set_variables,
|
||||||
} => match &annotation.value {
|
} => {
|
||||||
Type::Alias {
|
let typ = annotation.value;
|
||||||
|
|
||||||
|
match types[typ] {
|
||||||
|
TypeTag::OpaqueAlias { shared, actual } => {
|
||||||
|
let AliasShared {
|
||||||
symbol,
|
symbol,
|
||||||
kind: AliasKind::Opaque,
|
|
||||||
actual,
|
|
||||||
type_arguments,
|
|
||||||
lambda_set_variables,
|
lambda_set_variables,
|
||||||
infer_ext_in_output_types: _,
|
..
|
||||||
} if symbol == opaque
|
} = types[shared];
|
||||||
|
let type_arguments = types.get_type_arguments(typ);
|
||||||
|
|
||||||
|
if symbol == *opaque
|
||||||
&& type_arguments.len() == pat_type_arguments.len()
|
&& type_arguments.len() == pat_type_arguments.len()
|
||||||
&& lambda_set_variables.len() == pat_lambda_set_variables.len() =>
|
&& lambda_set_variables.len() == pat_lambda_set_variables.len()
|
||||||
{
|
{
|
||||||
let annotation_index = {
|
let annotation_index = constraints.push_type(types, typ);
|
||||||
let typ = types.from_old_type(annotation.value);
|
|
||||||
constraints.push_type(types, typ)
|
|
||||||
};
|
|
||||||
let typ = Loc::at(annotation.region, annotation_index);
|
let typ = Loc::at(annotation.region, annotation_index);
|
||||||
headers.insert(*opaque, typ);
|
headers.insert(*opaque, typ);
|
||||||
|
|
||||||
|
@ -212,9 +225,13 @@ fn headers_from_annotation_help(
|
||||||
&Loc::at(annotation.region, actual),
|
&Loc::at(annotation.region, actual),
|
||||||
headers,
|
headers,
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue