mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
Merge pull request #1302 from rtfeldman/constrain_expr2_var
Constrain Expr2::Var
This commit is contained in:
commit
0ff7c98def
2 changed files with 76 additions and 71 deletions
|
@ -21,7 +21,7 @@ use roc_types::{
|
||||||
pub enum Constraint<'a> {
|
pub enum Constraint<'a> {
|
||||||
Eq(Type2, Expected<Type2>, Category, Region),
|
Eq(Type2, Expected<Type2>, Category, Region),
|
||||||
// Store(Type, Variable, &'static str, u32),
|
// Store(Type, Variable, &'static str, u32),
|
||||||
// Lookup(Symbol, Expected<Type>, Region),
|
Lookup(Symbol, Expected<Type2>, Region),
|
||||||
// Pattern(Region, PatternCategory, Type, PExpected<Type>),
|
// Pattern(Region, PatternCategory, Type, PExpected<Type>),
|
||||||
And(BumpVec<'a, Constraint<'a>>),
|
And(BumpVec<'a, Constraint<'a>>),
|
||||||
Let(&'a LetConstraint<'a>),
|
Let(&'a LetConstraint<'a>),
|
||||||
|
@ -52,6 +52,7 @@ pub fn constrain_expr<'a>(
|
||||||
Expr2::SmallStr(_) => Eq(str_type(env.pool), expected, Category::Str, region),
|
Expr2::SmallStr(_) => Eq(str_type(env.pool), expected, Category::Str, region),
|
||||||
Expr2::Blank => True,
|
Expr2::Blank => True,
|
||||||
Expr2::EmptyRecord => constrain_empty_record(expected, region),
|
Expr2::EmptyRecord => constrain_empty_record(expected, region),
|
||||||
|
Expr2::Var(symbol) => Lookup(*symbol, expected, region),
|
||||||
Expr2::SmallInt { var, .. } => {
|
Expr2::SmallInt { var, .. } => {
|
||||||
let mut flex_vars = BumpVec::with_capacity_in(1, arena);
|
let mut flex_vars = BumpVec::with_capacity_in(1, arena);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![allow(clippy::all)]
|
#![allow(clippy::all)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use crate::lang::constrain::Constraint::{self, *};
|
use crate::lang::constrain::Constraint::{self, *};
|
||||||
use crate::lang::pool::Pool;
|
use crate::lang::pool::{Pool, ShallowClone};
|
||||||
use crate::lang::types::Type2;
|
use crate::lang::types::Type2;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_can::expected::{Expected, PExpected};
|
use roc_can::expected::{Expected, PExpected};
|
||||||
|
@ -270,75 +270,79 @@ fn solve<'a>(
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// Lookup(symbol, expectation, region) => {
|
Lookup(symbol, expectation, region) => {
|
||||||
// match env.vars_by_symbol.get(&symbol) {
|
match env.vars_by_symbol.get(&symbol) {
|
||||||
// Some(var) => {
|
Some(var) => {
|
||||||
// // Deep copy the vars associated with this symbol before unifying them.
|
// Deep copy the vars associated with this symbol before unifying them.
|
||||||
// // Otherwise, suppose we have this:
|
// Otherwise, suppose we have this:
|
||||||
// //
|
|
||||||
// // identity = \a -> a
|
|
||||||
// //
|
|
||||||
// // x = identity 5
|
|
||||||
// //
|
|
||||||
// // When we call (identity 5), it's important that we not unify
|
|
||||||
// // on identity's original vars. If we do, the type of `identity` will be
|
|
||||||
// // mutated to be `Int -> Int` instead of `a -> `, which would be incorrect;
|
|
||||||
// // the type of `identity` is more general than that!
|
|
||||||
// //
|
|
||||||
// // Instead, we want to unify on a *copy* of its vars. If the copy unifies
|
|
||||||
// // successfully (in this case, to `Int -> Int`), we can use that to
|
|
||||||
// // infer the type of this lookup (in this case, `Int`) without ever
|
|
||||||
// // having mutated the original.
|
|
||||||
// //
|
|
||||||
// // If this Lookup is targeting a value in another module,
|
|
||||||
// // then we copy from that module's Subs into our own. If the value
|
|
||||||
// // is being looked up in this module, then we use our Subs as both
|
|
||||||
// // the source and destination.
|
|
||||||
// let actual = deep_copy_var(subs, rank, pools, *var);
|
|
||||||
// let expected = type_to_var(
|
|
||||||
// subs,
|
|
||||||
// rank,
|
|
||||||
// pools,
|
|
||||||
// cached_aliases,
|
|
||||||
// expectation.get_type_ref(),
|
|
||||||
// );
|
|
||||||
// match unify(subs, actual, expected) {
|
|
||||||
// Success(vars) => {
|
|
||||||
// introduce(subs, rank, pools, &vars);
|
|
||||||
//
|
//
|
||||||
// state
|
// identity = \a -> a
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// Failure(vars, actual_type, expected_type) => {
|
// x = identity 5
|
||||||
// introduce(subs, rank, pools, &vars);
|
|
||||||
//
|
//
|
||||||
// let problem = TypeError::BadExpr(
|
// When we call (identity 5), it's important that we not unify
|
||||||
// *region,
|
// on identity's original vars. If we do, the type of `identity` will be
|
||||||
// Category::Lookup(*symbol),
|
// mutated to be `Int -> Int` instead of `a -> `, which would be incorrect;
|
||||||
// actual_type,
|
// the type of `identity` is more general than that!
|
||||||
// expectation.clone().replace(expected_type),
|
|
||||||
// );
|
|
||||||
//
|
//
|
||||||
// problems.push(problem);
|
// Instead, we want to unify on a *copy* of its vars. If the copy unifies
|
||||||
|
// successfully (in this case, to `Int -> Int`), we can use that to
|
||||||
|
// infer the type of this lookup (in this case, `Int`) without ever
|
||||||
|
// having mutated the original.
|
||||||
//
|
//
|
||||||
// state
|
// If this Lookup is targeting a value in another module,
|
||||||
// }
|
// then we copy from that module's Subs into our own. If the value
|
||||||
// BadType(vars, problem) => {
|
// is being looked up in this module, then we use our Subs as both
|
||||||
// introduce(subs, rank, pools, &vars);
|
// the source and destination.
|
||||||
//
|
let actual = deep_copy_var(subs, rank, pools, *var);
|
||||||
// problems.push(TypeError::BadType(problem));
|
|
||||||
//
|
let expected = type_to_var(
|
||||||
// state
|
arena,
|
||||||
// }
|
mempool,
|
||||||
// }
|
subs,
|
||||||
// }
|
rank,
|
||||||
// None => {
|
pools,
|
||||||
// problems.push(TypeError::UnexposedLookup(*symbol));
|
cached_aliases,
|
||||||
//
|
expectation.get_type_ref(),
|
||||||
// state
|
);
|
||||||
// }
|
|
||||||
// }
|
match unify(subs, actual, expected) {
|
||||||
// }
|
Success(vars) => {
|
||||||
|
introduce(subs, rank, pools, &vars);
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
Failure(vars, actual_type, expected_type) => {
|
||||||
|
introduce(subs, rank, pools, &vars);
|
||||||
|
|
||||||
|
let problem = TypeError::BadExpr(
|
||||||
|
*region,
|
||||||
|
Category::Lookup(*symbol),
|
||||||
|
actual_type,
|
||||||
|
expectation.shallow_clone().replace(expected_type),
|
||||||
|
);
|
||||||
|
|
||||||
|
problems.push(problem);
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
BadType(vars, problem) => {
|
||||||
|
introduce(subs, rank, pools, &vars);
|
||||||
|
|
||||||
|
problems.push(TypeError::BadType(problem));
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
problems.push(TypeError::UnexposedLookup(*symbol));
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
And(sub_constraints) => {
|
And(sub_constraints) => {
|
||||||
let mut state = state;
|
let mut state = state;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue