Materialize extension variable polarity in error type reporting

This commit is contained in:
Ayaz Hafiz 2022-10-25 15:30:19 -05:00
parent 3c15ff4694
commit 4d48ea7c2f
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
12 changed files with 277 additions and 126 deletions

View file

@ -13,7 +13,7 @@ use roc_types::subs::{
instantiate_rigids, Content, FlatType, GetSubsSlice, Rank, RecordFields, Subs, SubsSlice,
Variable,
};
use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory};
use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory, Polarity};
use roc_unify::unify::{Env, MustImplementConstraints};
use roc_unify::unify::{MustImplementAbility, Obligated};
@ -191,7 +191,8 @@ impl ObligationCache {
// Demote the bad variable that exposed this problem to an error, both so
// that we have an ErrorType to report and so that codegen knows to deal
// with the error later.
let (error_type, _moar_ghosts_n_stuff) = subs.var_to_error_type(var);
let (error_type, _moar_ghosts_n_stuff) =
subs.var_to_error_type(var, Polarity::OF_VALUE);
problems.push(TypeError::BadExprMissingAbility(
region,
category,
@ -208,7 +209,8 @@ impl ObligationCache {
// Demote the bad variable that exposed this problem to an error, both so
// that we have an ErrorType to report and so that codegen knows to deal
// with the error later.
let (error_type, _moar_ghosts_n_stuff) = subs.var_to_error_type(var);
let (error_type, _moar_ghosts_n_stuff) =
subs.var_to_error_type(var, Polarity::OF_PATTERN);
problems.push(TypeError::BadPatternMissingAbility(
region,
category,
@ -309,14 +311,15 @@ impl ObligationCache {
})) => Some(if failure_var == var {
UnderivableReason::SurfaceNotDerivable(context)
} else {
let (error_type, _skeletons) = subs.var_to_error_type(failure_var);
let (error_type, _skeletons) =
subs.var_to_error_type(failure_var, Polarity::OF_VALUE);
UnderivableReason::NestedNotDerivable(error_type, context)
}),
None => Some(UnderivableReason::NotABuiltin),
};
if let Some(underivable_reason) = opt_underivable {
let (error_type, _skeletons) = subs.var_to_error_type(var);
let (error_type, _skeletons) = subs.var_to_error_type(var, Polarity::OF_VALUE);
Err(Unfulfilled::AdhocUnderivable {
typ: error_type,
@ -1222,6 +1225,7 @@ pub fn resolve_ability_specialization<R: AbilityResolver>(
specialization_var,
signature_var,
Mode::EQ,
Polarity::Pos,
)
.expect_success(
"If resolving a specialization, the specialization must be known to typecheck.",

View file

@ -33,8 +33,8 @@ use roc_types::subs::{
};
use roc_types::types::Type::{self, *};
use roc_types::types::{
gather_fields_unsorted_iter, AliasCommon, AliasKind, Category, OptAbleType, OptAbleVar, Reason,
RecordField, TypeExtension, Uls,
gather_fields_unsorted_iter, AliasCommon, AliasKind, Category, OptAbleType, OptAbleVar,
Polarity, Reason, RecordField, TypeExtension, Uls,
};
use roc_unify::unify::{
unify, unify_introduced_ability_specialization, Env as UEnv, Mode, Obligated,
@ -922,7 +922,13 @@ fn solve(
expectation.get_type_ref(),
);
match unify(&mut UEnv::new(subs), actual, expected, Mode::EQ) {
match unify(
&mut UEnv::new(subs),
actual,
expected,
Mode::EQ,
Polarity::OF_VALUE,
) {
Success {
vars,
must_implement_ability,
@ -1034,7 +1040,13 @@ fn solve(
expectation.get_type_ref(),
);
match unify(&mut UEnv::new(subs), actual, expected, Mode::EQ) {
match unify(
&mut UEnv::new(subs),
actual,
expected,
Mode::EQ,
Polarity::OF_VALUE,
) {
Success {
vars,
must_implement_ability,
@ -1146,7 +1158,13 @@ fn solve(
_ => Mode::EQ,
};
match unify(&mut UEnv::new(subs), actual, expected, mode) {
match unify(
&mut UEnv::new(subs),
actual,
expected,
mode,
Polarity::OF_PATTERN,
) {
Success {
vars,
must_implement_ability,
@ -1357,7 +1375,13 @@ fn solve(
&tag_ty,
);
match unify(&mut UEnv::new(subs), actual, includes, Mode::PRESENT) {
match unify(
&mut UEnv::new(subs),
actual,
includes,
Mode::PRESENT,
Polarity::OF_PATTERN,
) {
Success {
vars,
must_implement_ability,
@ -1493,8 +1517,13 @@ fn solve(
);
let snapshot = subs.snapshot();
let unify_cond_and_patterns_outcome =
unify(&mut UEnv::new(subs), branches_var, real_var, Mode::EQ);
let unify_cond_and_patterns_outcome = unify(
&mut UEnv::new(subs),
branches_var,
real_var,
Mode::EQ,
Polarity::OF_PATTERN,
);
let should_check_exhaustiveness;
match unify_cond_and_patterns_outcome {
@ -1539,7 +1568,13 @@ fn solve(
// open_tag_union(subs, real_var);
open_tag_union(subs, branches_var);
let almost_eq = matches!(
unify(&mut UEnv::new(subs), real_var, branches_var, Mode::EQ),
unify(
&mut UEnv::new(subs),
real_var,
branches_var,
Mode::EQ,
Polarity::OF_PATTERN
),
Success { .. }
);
@ -1551,7 +1586,13 @@ fn solve(
} else {
// Case 4: incompatible types, report type error.
// Re-run first failed unification to get the type diff.
match unify(&mut UEnv::new(subs), real_var, branches_var, Mode::EQ) {
match unify(
&mut UEnv::new(subs),
real_var,
branches_var,
Mode::EQ,
Polarity::OF_PATTERN,
) {
Failure(vars, actual_type, expected_type, _bad_impls) => {
introduce(subs, rank, pools, &vars);
@ -1868,7 +1909,8 @@ fn check_ability_specialization(
// Commit so that the bad signature and its error persists in subs.
subs.commit_snapshot(snapshot);
let (_typ, _problems) = subs.var_to_error_type(symbol_loc_var.value);
let (_typ, _problems) =
subs.var_to_error_type(symbol_loc_var.value, Polarity::OF_VALUE);
let problem = TypeError::WrongSpecialization {
region: symbol_loc_var.region,
@ -1888,7 +1930,7 @@ fn check_ability_specialization(
// Commit so that `var` persists in subs.
subs.commit_snapshot(snapshot);
let (typ, _problems) = subs.var_to_error_type(var);
let (typ, _problems) = subs.var_to_error_type(var, Polarity::OF_VALUE);
let problem = TypeError::StructuralSpecialization {
region: symbol_loc_var.region,
@ -1910,8 +1952,10 @@ fn check_ability_specialization(
// so we can have two separate error types.
subs.rollback_to(snapshot);
let (expected_type, _problems) = subs.var_to_error_type(root_signature_var);
let (actual_type, _problems) = subs.var_to_error_type(symbol_loc_var.value);
let (expected_type, _problems) =
subs.var_to_error_type(root_signature_var, Polarity::OF_VALUE);
let (actual_type, _problems) =
subs.var_to_error_type(symbol_loc_var.value, Polarity::OF_VALUE);
let reason = Reason::GeneralizedAbilityMemberSpecialization {
member_name: ability_member,
@ -2772,7 +2816,13 @@ fn type_to_variable<'a>(
});
let category = Category::OpaqueArg;
match unify(&mut UEnv::new(subs), var, flex_ability, Mode::EQ) {
match unify(
&mut UEnv::new(subs),
var,
flex_ability,
Mode::EQ,
Polarity::OF_VALUE,
) {
Success {
vars: _,
must_implement_ability,
@ -3212,7 +3262,7 @@ fn circular_error(
loc_var: &Loc<Variable>,
) {
let var = loc_var.value;
let (error_type, _) = subs.var_to_error_type(var);
let (error_type, _) = subs.var_to_error_type(var, Polarity::OF_VALUE);
let problem = TypeError::CircularType(loc_var.region, symbol, error_type);
subs.set_content(var, Content::Error);

View file

@ -20,7 +20,7 @@ use roc_types::{
get_member_lambda_sets_at_region, Content, Descriptor, GetSubsSlice, LambdaSet, Mark,
OptVariable, Rank, Subs, SubsSlice, UlsOfVar, Variable,
},
types::{AliasKind, MemberImpl, Uls},
types::{AliasKind, MemberImpl, Polarity, Uls},
};
use roc_unify::unify::{unify, Env as UEnv, Mode, MustImplementConstraints};
@ -584,6 +584,7 @@ fn compact_lambda_set<P: Phase>(
t_f1,
t_f2,
Mode::LAMBDA_SET_SPECIALIZATION,
Polarity::Pos,
)
.expect_success("ambient functions don't unify");
trace_compact!(3iter_end. subs, t_f1);