feat: allow assignments to be cast to other types
This commit is contained in:
parent
34d7a28351
commit
c07b9a1a81
|
@ -771,20 +771,36 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
location: Span,
|
location: Span,
|
||||||
) -> Result<TypedExpr, Error> {
|
) -> Result<TypedExpr, Error> {
|
||||||
let value = self.in_new_scope(|value_typer| value_typer.infer(value))?;
|
let value = self.in_new_scope(|value_typer| value_typer.infer(value))?;
|
||||||
let value_typ = value.tipo();
|
let mut value_typ = value.tipo();
|
||||||
|
|
||||||
// Ensure the pattern matches the type of the value
|
|
||||||
let pattern = PatternTyper::new(self.environment, &self.hydrator)
|
|
||||||
.unify(pattern, value_typ.clone())?;
|
|
||||||
|
|
||||||
// Check that any type annotation is accurate.
|
// Check that any type annotation is accurate.
|
||||||
if let Some(ann) = annotation {
|
let pattern = if let Some(ann) = annotation {
|
||||||
let ann_typ = self
|
let ann_typ = self
|
||||||
.type_from_annotation(ann)
|
.type_from_annotation(ann)
|
||||||
.map(|t| self.instantiate(t, &mut HashMap::new()))?;
|
.map(|t| self.instantiate(t, &mut HashMap::new()))?;
|
||||||
|
|
||||||
self.unify(ann_typ, value_typ.clone(), value.type_defining_location())?;
|
self.unify(
|
||||||
}
|
ann_typ.clone(),
|
||||||
|
value_typ.clone(),
|
||||||
|
value.type_defining_location(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
value_typ = ann_typ.clone();
|
||||||
|
|
||||||
|
// Ensure the pattern matches the type of the value
|
||||||
|
PatternTyper::new(self.environment, &self.hydrator).unify(
|
||||||
|
pattern,
|
||||||
|
value_typ.clone(),
|
||||||
|
Some(ann_typ),
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
// Ensure the pattern matches the type of the value
|
||||||
|
PatternTyper::new(self.environment, &self.hydrator).unify(
|
||||||
|
pattern,
|
||||||
|
value_typ.clone(),
|
||||||
|
None,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
// We currently only do limited exhaustiveness checking of custom types
|
// We currently only do limited exhaustiveness checking of custom types
|
||||||
// at the top level of patterns.
|
// at the top level of patterns.
|
||||||
|
@ -1688,8 +1704,11 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure the pattern matches the type of the value
|
// Ensure the pattern matches the type of the value
|
||||||
let pattern = PatternTyper::new(self.environment, &self.hydrator)
|
let pattern = PatternTyper::new(self.environment, &self.hydrator).unify(
|
||||||
.unify(pattern, value_type.clone())?;
|
pattern,
|
||||||
|
value_type.clone(),
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Check the type of the following code
|
// Check the type of the following code
|
||||||
let then = self.infer(then)?;
|
let then = self.infer(then)?;
|
||||||
|
|
|
@ -144,7 +144,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
// Unify each pattern in the multi-pattern with the corresponding subject
|
// Unify each pattern in the multi-pattern with the corresponding subject
|
||||||
let mut typed_multi = Vec::with_capacity(multi_pattern.len());
|
let mut typed_multi = Vec::with_capacity(multi_pattern.len());
|
||||||
for (pattern, subject_type) in multi_pattern.into_iter().zip(subjects) {
|
for (pattern, subject_type) in multi_pattern.into_iter().zip(subjects) {
|
||||||
let pattern = self.unify(pattern, subject_type.clone())?;
|
let pattern = self.unify(pattern, subject_type.clone(), None)?;
|
||||||
typed_multi.push(pattern);
|
typed_multi.push(pattern);
|
||||||
}
|
}
|
||||||
Ok(typed_multi)
|
Ok(typed_multi)
|
||||||
|
@ -224,12 +224,13 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
&mut self,
|
&mut self,
|
||||||
pattern: UntypedPattern,
|
pattern: UntypedPattern,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
|
ann_type: Option<Arc<Type>>,
|
||||||
) -> Result<TypedPattern, Error> {
|
) -> Result<TypedPattern, Error> {
|
||||||
match pattern {
|
match pattern {
|
||||||
Pattern::Discard { name, location } => Ok(Pattern::Discard { name, location }),
|
Pattern::Discard { name, location } => Ok(Pattern::Discard { name, location }),
|
||||||
|
|
||||||
Pattern::Var { name, location, .. } => {
|
Pattern::Var { name, location } => {
|
||||||
self.insert_variable(&name, tipo, location, location)?;
|
self.insert_variable(&name, ann_type.unwrap_or(tipo), location, location)?;
|
||||||
|
|
||||||
Ok(Pattern::Var { name, location })
|
Ok(Pattern::Var { name, location })
|
||||||
}
|
}
|
||||||
|
@ -288,9 +289,14 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
pattern,
|
pattern,
|
||||||
location,
|
location,
|
||||||
} => {
|
} => {
|
||||||
self.insert_variable(&name, tipo.clone(), location, pattern.location())?;
|
self.insert_variable(
|
||||||
|
&name,
|
||||||
|
ann_type.clone().unwrap_or_else(|| tipo.clone()),
|
||||||
|
location,
|
||||||
|
pattern.location(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let pattern = self.unify(*pattern, tipo)?;
|
let pattern = self.unify(*pattern, tipo, ann_type)?;
|
||||||
|
|
||||||
Ok(Pattern::Assign {
|
Ok(Pattern::Assign {
|
||||||
name,
|
name,
|
||||||
|
@ -324,11 +330,11 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
|
|
||||||
let elements = elements
|
let elements = elements
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|element| self.unify(element, tipo.clone()))
|
.map(|element| self.unify(element, tipo.clone(), None))
|
||||||
.try_collect()?;
|
.try_collect()?;
|
||||||
|
|
||||||
let tail = match tail {
|
let tail = match tail {
|
||||||
Some(tail) => Some(Box::new(self.unify(*tail, list(tipo))?)),
|
Some(tail) => Some(Box::new(self.unify(*tail, list(tipo), None)?)),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -397,12 +403,6 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
// Pattern::BitString { location, segments } => {
|
|
||||||
// self.environment
|
|
||||||
// .unify(type_, bit_string())
|
|
||||||
// .map_err(|e| convert_unify_error(e, location))?;
|
|
||||||
// self.infer_pattern_bit_string(segments, location)
|
|
||||||
// }
|
|
||||||
Pattern::Constructor {
|
Pattern::Constructor {
|
||||||
location,
|
location,
|
||||||
module,
|
module,
|
||||||
|
@ -506,7 +506,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
|
||||||
label,
|
label,
|
||||||
} = arg;
|
} = arg;
|
||||||
|
|
||||||
let value = self.unify(value, typ.clone())?;
|
let value = self.unify(value, typ.clone(), None)?;
|
||||||
|
|
||||||
Ok(CallArg {
|
Ok(CallArg {
|
||||||
value,
|
value,
|
||||||
|
|
Loading…
Reference in New Issue