Include annotation type signatures in Expected struct

To provide better error messages and suggestions related to changing
type annotations, we now pass annotation type signatures all the way
down through the constraint solver. At constraint generation we
associate the type signature with a unique variable, and during error
reporting, we pull out an `ErrorType` corresponding to the original type
signature, by looking up the unique variable. This gives us two nice
things:

1. It means we don't have to pass the original, AST-like type
   annotation, which can be quite large, to everyone who looks at an
   expectation.
2. It gives us a translation from a `Type` to an `ErrorType` for free
   using the existing translation procedure in `roc_types::subs`,
   without having to create a new translation function.
This commit is contained in:
ayazhafiz 2021-11-21 11:49:55 -05:00
parent 8726e38dad
commit ee34e79790
11 changed files with 152 additions and 42 deletions

View file

@ -11,8 +11,7 @@ use roc_types::subs::{
};
use roc_types::types::Type::{self, *};
use roc_types::types::{gather_fields_unsorted_iter, Alias, Category, ErrorType, PatternCategory};
use roc_unify::unify::unify;
use roc_unify::unify::Unified::*;
use roc_unify::unify::{unify, Unified::*};
use std::collections::hash_map::Entry;
// Type checking system adapted from Elm by Evan Czaplicki, BSD-3-Clause Licensed
@ -67,7 +66,7 @@ use std::collections::hash_map::Entry;
#[derive(PartialEq, Debug, Clone)]
pub enum TypeError {
BadExpr(Region, Category, ErrorType, Expected<ErrorType>),
BadExpr(Region, Category, ErrorType, Expected<ErrorType, ErrorType>),
BadPattern(Region, PatternCategory, ErrorType, PExpected<ErrorType>),
CircularType(Region, Symbol, ErrorType),
BadType(roc_types::types::Problem),
@ -206,7 +205,9 @@ fn solve(
expectation.get_type_ref(),
);
match unify(subs, actual, expected) {
// Don't transform bad types into errors in case we want to grab other types'
// original contents during a failure.
match unify_without_error_compaction(subs, actual, expected) {
Success(vars) => {
introduce(subs, rank, pools, &vars);
@ -219,7 +220,12 @@ fn solve(
*region,
category.clone(),
actual_type,
expectation.clone().replace(expected_type),
expectation
.clone()
.replace(expected_type)
.replace_annotation_with(|annot_var: Variable| {
subs.var_to_error_type(annot_var).0
}),
);
problems.push(problem);
@ -295,7 +301,9 @@ fn solve(
cached_aliases,
expectation.get_type_ref(),
);
match unify(subs, actual, expected) {
// Don't transform bad types into errors in case we want to grab other types'
// original contents during a failure.
match unify_without_error_compaction(subs, actual, expected) {
Success(vars) => {
introduce(subs, rank, pools, &vars);
@ -309,7 +317,12 @@ fn solve(
*region,
Category::Lookup(*symbol),
actual_type,
expectation.clone().replace(expected_type),
expectation
.clone()
.replace(expected_type)
.replace_annotation_with(|annot_var: Variable| {
subs.var_to_error_type(annot_var).0
}),
);
problems.push(problem);