Rework 'is_opaque' to also check for inner types.
Also removed the duplication in infer_assignment and moved the check down.
This commit is contained in:
parent
22b618116e
commit
f10cf73905
|
@ -195,10 +195,14 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_opaque(&self) -> bool {
|
||||
pub fn is_or_holds_opaque(&self) -> bool {
|
||||
match self {
|
||||
Type::App { opaque, .. } => *opaque,
|
||||
_ => false,
|
||||
Type::Var { tipo, .. } => tipo.borrow().is_or_holds_opaque(),
|
||||
Type::App { opaque, args, .. } => {
|
||||
*opaque || args.iter().any(|arg| arg.is_or_holds_opaque())
|
||||
}
|
||||
Type::Tuple { elems, .. } => elems.iter().any(|elem| elem.is_or_holds_opaque()),
|
||||
Type::Fn { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -845,6 +849,13 @@ impl TypeVar {
|
|||
matches!(self, Self::Unbound { .. })
|
||||
}
|
||||
|
||||
pub fn is_or_holds_opaque(&self) -> bool {
|
||||
match self {
|
||||
Self::Link { tipo } => tipo.is_or_holds_opaque(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_void(&self) -> bool {
|
||||
match self {
|
||||
Self::Link { tipo } => tipo.is_void(),
|
||||
|
|
|
@ -928,18 +928,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
let mut value_typ = typed_value.tipo();
|
||||
|
||||
let value_is_data = value_typ.is_data();
|
||||
let value_is_opaque = value_typ.is_opaque();
|
||||
|
||||
// Check that any type annotation is accurate.
|
||||
let pattern = if let Some(ann) = annotation {
|
||||
let ann_typ = if let Some(ann) = annotation {
|
||||
let ann_typ = self
|
||||
.type_from_annotation(ann)
|
||||
.map(|t| self.instantiate(t, &mut HashMap::new()))?;
|
||||
|
||||
if kind.is_expect() && (ann_typ.is_opaque() || value_is_opaque) {
|
||||
return Err(Error::ExpectOnOpaqueType { location });
|
||||
}
|
||||
|
||||
self.unify(
|
||||
ann_typ.clone(),
|
||||
value_typ.clone(),
|
||||
|
@ -949,13 +944,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
|
||||
value_typ = ann_typ.clone();
|
||||
|
||||
// Ensure the pattern matches the type of the value
|
||||
PatternTyper::new(self.environment, &self.hydrator).unify(
|
||||
untyped_pattern.clone(),
|
||||
value_typ.clone(),
|
||||
Some(ann_typ),
|
||||
kind.is_let(),
|
||||
)?
|
||||
Some(ann_typ)
|
||||
} else {
|
||||
if value_is_data && !untyped_pattern.is_var() && !untyped_pattern.is_discard() {
|
||||
let ann = Annotation::Constructor {
|
||||
|
@ -976,19 +965,21 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
});
|
||||
}
|
||||
|
||||
if kind.is_expect() && value_is_opaque {
|
||||
return Err(Error::ExpectOnOpaqueType { location });
|
||||
}
|
||||
|
||||
// Ensure the pattern matches the type of the value
|
||||
PatternTyper::new(self.environment, &self.hydrator).unify(
|
||||
untyped_pattern.clone(),
|
||||
value_typ.clone(),
|
||||
None,
|
||||
kind.is_let(),
|
||||
)?
|
||||
None
|
||||
};
|
||||
|
||||
if kind.is_expect() && value_typ.is_or_holds_opaque() {
|
||||
return Err(Error::ExpectOnOpaqueType { location });
|
||||
}
|
||||
|
||||
// Ensure the pattern matches the type of the value
|
||||
let pattern = PatternTyper::new(self.environment, &self.hydrator).unify(
|
||||
untyped_pattern.clone(),
|
||||
value_typ.clone(),
|
||||
ann_typ,
|
||||
kind.is_let(),
|
||||
)?;
|
||||
|
||||
// If `expect` is explicitly used, we still check exhaustiveness but instead of returning an
|
||||
// error we emit a warning which explains that using `expect` is unnecessary.
|
||||
match kind {
|
||||
|
|
Loading…
Reference in New Issue