summaryrefslogtreecommitdiff
path: root/dhall
diff options
context:
space:
mode:
Diffstat (limited to 'dhall')
-rw-r--r--dhall/src/error/mod.rs2
-rw-r--r--dhall/src/phase/typecheck.rs51
2 files changed, 48 insertions, 5 deletions
diff --git a/dhall/src/error/mod.rs b/dhall/src/error/mod.rs
index 125d013..20b8636 100644
--- a/dhall/src/error/mod.rs
+++ b/dhall/src/error/mod.rs
@@ -76,9 +76,11 @@ pub(crate) enum TypeMessage {
MergeAnnotMismatch,
MergeHandlerTypeMismatch,
MergeHandlerReturnTypeMustNotBeDependent,
+ MustCombineRecord(Typed),
ProjectionMustBeRecord,
ProjectionMissingEntry,
Sort,
+ RecordMismatch(Typed, Typed),
RecordTypeDuplicateField,
UnionTypeDuplicateField,
Unimplemented,
diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs
index 419b2e2..2315edb 100644
--- a/dhall/src/phase/typecheck.rs
+++ b/dhall/src/phase/typecheck.rs
@@ -598,6 +598,47 @@ fn type_last_layer(
}
Ok(RetTypeOnly(text_type))
}
+ BinOp(RightBiasedRecordMerge, l, r) => {
+ let l_type = l.get_type()?;
+ let l_kind = l_type.get_type()?;
+ let r_type = r.get_type()?;
+ let r_kind = r_type.get_type()?;
+
+ // Check the equality of kinds.
+ // This is to disallow expression such as:
+ // "{ x = Text } // { y = 1 }"
+ ensure_equal!(
+ l_kind,
+ r_kind,
+ mkerr(RecordMismatch(l.clone(), r.clone())),
+ );
+
+ // Extract the LHS record type
+ let mut kts_x = match l_type.to_value() {
+ Value::RecordType(kts) => kts,
+ _ => return Err(mkerr(MustCombineRecord(l.clone()))),
+ };
+
+ // Extract the RHS record type
+ let kts_y = match r_type.to_value() {
+ Value::RecordType(kts) => kts,
+ _ => return Err(mkerr(MustCombineRecord(r.clone()))),
+ };
+
+ // Union the two records, prefering
+ // the values found in the RHS.
+ for (label, value) in kts_y {
+ kts_x.insert(label, value);
+ }
+
+ // Construct the final record type from the union
+ Ok(RetTypeOnly(tck_record_type(
+ ctx,
+ kts_x.iter()
+ .map(|(x, v)| Ok((x.clone(), v.to_type()))),
+ )?
+ .into_type()))
+ }
BinOp(o @ ListAppend, l, r) => {
match l.get_type()?.to_value() {
Value::AppliedBuiltin(List, _) => {}
@@ -1135,11 +1176,11 @@ mod spec_tests {
// ti_success!(ti_success_unit_RecursiveRecordTypeMergeTwo, "unit/RecursiveRecordTypeMergeTwo");
// ti_success!(ti_success_unit_RecursiveRecordTypeMergeTwoKinds, "unit/RecursiveRecordTypeMergeTwoKinds");
// ti_success!(ti_success_unit_RecursiveRecordTypeMergeTwoTypes, "unit/RecursiveRecordTypeMergeTwoTypes");
- // ti_success!(ti_success_unit_RightBiasedRecordMergeRhsEmpty, "unit/RightBiasedRecordMergeRhsEmpty");
- // ti_success!(ti_success_unit_RightBiasedRecordMergeTwo, "unit/RightBiasedRecordMergeTwo");
- // ti_success!(ti_success_unit_RightBiasedRecordMergeTwoDifferent, "unit/RightBiasedRecordMergeTwoDifferent");
- // ti_success!(ti_success_unit_RightBiasedRecordMergeTwoKinds, "unit/RightBiasedRecordMergeTwoKinds");
- // ti_success!(ti_success_unit_RightBiasedRecordMergeTwoTypes, "unit/RightBiasedRecordMergeTwoTypes");
+ ti_success!(ti_success_unit_RightBiasedRecordMergeRhsEmpty, "unit/RightBiasedRecordMergeRhsEmpty");
+ ti_success!(ti_success_unit_RightBiasedRecordMergeTwo, "unit/RightBiasedRecordMergeTwo");
+ ti_success!(ti_success_unit_RightBiasedRecordMergeTwoDifferent, "unit/RightBiasedRecordMergeTwoDifferent");
+ ti_success!(ti_success_unit_RightBiasedRecordMergeTwoKinds, "unit/RightBiasedRecordMergeTwoKinds");
+ ti_success!(ti_success_unit_RightBiasedRecordMergeTwoTypes, "unit/RightBiasedRecordMergeTwoTypes");
ti_success!(ti_success_unit_SomeTrue, "unit/SomeTrue");
ti_success!(ti_success_unit_Text, "unit/Text");
ti_success!(ti_success_unit_TextLiteral, "unit/TextLiteral");