Use inferred Fuzzer inner type for unify error when possible.
This commit is contained in:
parent
eb07365e73
commit
877d10ef22
|
@ -342,8 +342,39 @@ fn infer_definition(
|
||||||
let typed_via =
|
let typed_via =
|
||||||
ExprTyper::new(environment, lines, tracing).infer(arg.via.clone())?;
|
ExprTyper::new(environment, lines, tracing).infer(arg.via.clone())?;
|
||||||
|
|
||||||
let (inferred_annotation, inner_type) =
|
let hydrator: &mut Hydrator = hydrators.get_mut(&f.name).unwrap();
|
||||||
infer_fuzzer(environment, &typed_via.tipo(), &arg.via.location())?;
|
|
||||||
|
let provided_inner_type = arg
|
||||||
|
.annotation
|
||||||
|
.as_ref()
|
||||||
|
.map(|ann| hydrator.type_from_annotation(ann, environment))
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
let (inferred_annotation, inferred_inner_type) = infer_fuzzer(
|
||||||
|
environment,
|
||||||
|
provided_inner_type.clone(),
|
||||||
|
&typed_via.tipo(),
|
||||||
|
&arg.via.location(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Ensure that the annotation, if any, matches the type inferred from the
|
||||||
|
// Fuzzer.
|
||||||
|
if let Some(provided_inner_type) = provided_inner_type {
|
||||||
|
if !arg
|
||||||
|
.annotation
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.is_logically_equal(&inferred_annotation)
|
||||||
|
{
|
||||||
|
return Err(Error::CouldNotUnify {
|
||||||
|
location: arg.location,
|
||||||
|
expected: inferred_inner_type.clone(),
|
||||||
|
given: provided_inner_type.clone(),
|
||||||
|
situation: Some(UnifyErrorSituation::FuzzerAnnotationMismatch),
|
||||||
|
rigid_type_names: hydrator.rigid_names(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Replace the pre-registered type for the test function, to allow inferring
|
// Replace the pre-registered type for the test function, to allow inferring
|
||||||
// the function body with the right type arguments.
|
// the function body with the right type arguments.
|
||||||
|
@ -354,30 +385,14 @@ fn infer_definition(
|
||||||
if let Type::Fn { ref ret, .. } = scope.tipo.as_ref() {
|
if let Type::Fn { ref ret, .. } = scope.tipo.as_ref() {
|
||||||
scope.tipo = Rc::new(Type::Fn {
|
scope.tipo = Rc::new(Type::Fn {
|
||||||
ret: ret.clone(),
|
ret: ret.clone(),
|
||||||
args: vec![inner_type.clone()],
|
args: vec![inferred_inner_type.clone()],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the annotation, if any, matches the type inferred from the
|
Ok((
|
||||||
// Fuzzer.
|
Some((typed_via, inferred_inner_type)),
|
||||||
if let Some(ref provided_annotation) = arg.annotation {
|
Some(inferred_annotation),
|
||||||
let hydrator: &mut Hydrator = hydrators.get_mut(&f.name).unwrap();
|
))
|
||||||
|
|
||||||
let given =
|
|
||||||
hydrator.type_from_annotation(provided_annotation, environment)?;
|
|
||||||
|
|
||||||
if !provided_annotation.is_logically_equal(&inferred_annotation) {
|
|
||||||
return Err(Error::CouldNotUnify {
|
|
||||||
location: arg.location,
|
|
||||||
expected: inner_type.clone(),
|
|
||||||
given,
|
|
||||||
situation: Some(UnifyErrorSituation::FuzzerAnnotationMismatch),
|
|
||||||
rigid_type_names: hydrator.rigid_names(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((Some((typed_via, inner_type)), Some(inferred_annotation)))
|
|
||||||
}
|
}
|
||||||
None => Ok((None, None)),
|
None => Ok((None, None)),
|
||||||
}?;
|
}?;
|
||||||
|
@ -745,12 +760,17 @@ fn infer_function(
|
||||||
|
|
||||||
fn infer_fuzzer(
|
fn infer_fuzzer(
|
||||||
environment: &mut Environment<'_>,
|
environment: &mut Environment<'_>,
|
||||||
|
expected_inner_type: Option<Rc<Type>>,
|
||||||
tipo: &Rc<Type>,
|
tipo: &Rc<Type>,
|
||||||
location: &Span,
|
location: &Span,
|
||||||
) -> Result<(Annotation, Rc<Type>), Error> {
|
) -> Result<(Annotation, Rc<Type>), Error> {
|
||||||
let could_not_unify = || Error::CouldNotUnify {
|
let could_not_unify = || Error::CouldNotUnify {
|
||||||
location: *location,
|
location: *location,
|
||||||
expected: fuzzer(generic_var(0)),
|
expected: fuzzer(
|
||||||
|
expected_inner_type
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| generic_var(0)),
|
||||||
|
),
|
||||||
given: tipo.clone(),
|
given: tipo.clone(),
|
||||||
situation: None,
|
situation: None,
|
||||||
rigid_type_names: HashMap::new(),
|
rigid_type_names: HashMap::new(),
|
||||||
|
@ -789,8 +809,10 @@ fn infer_fuzzer(
|
||||||
_ => Err(could_not_unify()),
|
_ => Err(could_not_unify()),
|
||||||
},
|
},
|
||||||
|
|
||||||
Type::Var { tipo } => match &*tipo.deref().borrow() {
|
Type::Var { tipo, .. } => match &*tipo.deref().borrow() {
|
||||||
TypeVar::Link { tipo } => infer_fuzzer(environment, tipo, location),
|
TypeVar::Link { tipo } => {
|
||||||
|
infer_fuzzer(environment, expected_inner_type, tipo, location)
|
||||||
|
}
|
||||||
_ => Err(Error::GenericLeftAtBoundary {
|
_ => Err(Error::GenericLeftAtBoundary {
|
||||||
location: *location,
|
location: *location,
|
||||||
}),
|
}),
|
||||||
|
|
Loading…
Reference in New Issue