diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+1.41.0
+
+* [Support standard version 22.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v22.0.0)
+  * [Allow `with` expressions to update `Optional` values using `?`](https://github.com/dhall-lang/dhall-haskell/pull/2386)
+  * [Add `showConstructor` keyword](https://github.com/dhall-lang/dhall-haskell/pull/2384)
+* [BUG FIX: Fix pretty-printing of time zones](https://github.com/dhall-lang/dhall-haskell/pull/2379)
+  * Timezones with a negative offset were previously being rendered with two
+    leading minus signs instead of one
+* [BUG FIX: `dhall freeze --cache` to work with standard version 21.0.0](https://github.com/dhall-lang/dhall-haskell/pull/2350)
+  * `dhall freeze` will now use `missing sha256:…` for the first import so that
+    the latter import will be tried if the import is not in cache
+  * The old behavior is incompatible with standard version 21.0.0 because the
+    new behavior of the `?` operator doesn't fall back on hash mismatches
+* [BUG FIX: Allow `with` expression to update a field named `Some`](https://github.com/dhall-lang/dhall-haskell/pull/2354)
+  * This fixes a discrepancy between the Haskell implementation and the standard
+    where the Haskell implementation would not permit
+    `{ Some = 0 } with Some = 1 `
+* [Fix `dhall {format,lint,freeze}` to preserve leading shebangs](https://github.com/dhall-lang/dhall-haskell/pull/2364)
+* [Add `FromDhall` instances for `Int{8,16,32,64}`](https://github.com/dhall-lang/dhall-haskell/pull/2349)
+
 1.40.2
 
 * [Supports standard version 21.1.0](https://github.com/dhall-lang/dhall-haskell/pull/2236)
diff --git a/dhall-lang/tests/import/data/cors/AllowedAll.dhall b/dhall-lang/tests/import/data/cors/AllowedAll.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/AllowedAll.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/AllowedAll.dhall
diff --git a/dhall-lang/tests/import/data/cors/Empty.dhall b/dhall-lang/tests/import/data/cors/Empty.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/Empty.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/Empty.dhall
diff --git a/dhall-lang/tests/import/data/cors/NoCORS.dhall b/dhall-lang/tests/import/data/cors/NoCORS.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/NoCORS.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/NoCORS.dhall
diff --git a/dhall-lang/tests/import/data/cors/Null.dhall b/dhall-lang/tests/import/data/cors/Null.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/Null.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/Null.dhall
diff --git a/dhall-lang/tests/import/data/cors/OnlyGithub.dhall b/dhall-lang/tests/import/data/cors/OnlyGithub.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/OnlyGithub.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/OnlyGithub.dhall
diff --git a/dhall-lang/tests/import/data/cors/OnlyOther.dhall b/dhall-lang/tests/import/data/cors/OnlyOther.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/OnlyOther.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/OnlyOther.dhall
diff --git a/dhall-lang/tests/import/data/cors/OnlySelf.dhall b/dhall-lang/tests/import/data/cors/OnlySelf.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/OnlySelf.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/OnlySelf.dhall
diff --git a/dhall-lang/tests/import/data/cors/Prelude.dhall b/dhall-lang/tests/import/data/cors/Prelude.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/Prelude.dhall
@@ -0,0 +1,1 @@
+https://prelude.dhall-lang.org/List/length
diff --git a/dhall-lang/tests/import/data/cors/SelfImportAbsolute.dhall b/dhall-lang/tests/import/data/cors/SelfImportAbsolute.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/SelfImportAbsolute.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/SelfImportAbsolute.dhall
diff --git a/dhall-lang/tests/import/data/cors/SelfImportRelative.dhall b/dhall-lang/tests/import/data/cors/SelfImportRelative.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/data/cors/SelfImportRelative.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/SelfImportRelative.dhall
diff --git a/dhall-lang/tests/import/failure/unit/cors/Empty.dhall b/dhall-lang/tests/import/failure/unit/cors/Empty.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/failure/unit/cors/Empty.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/Empty.dhall
diff --git a/dhall-lang/tests/import/failure/unit/cors/NoCORS.dhall b/dhall-lang/tests/import/failure/unit/cors/NoCORS.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/failure/unit/cors/NoCORS.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/NoCORS.dhall
diff --git a/dhall-lang/tests/import/failure/unit/cors/Null.dhall b/dhall-lang/tests/import/failure/unit/cors/Null.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/failure/unit/cors/Null.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/Null.dhall
diff --git a/dhall-lang/tests/import/failure/unit/cors/OnlyOther.dhall b/dhall-lang/tests/import/failure/unit/cors/OnlyOther.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/failure/unit/cors/OnlyOther.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyOther.dhall
diff --git a/dhall-lang/tests/import/failure/unit/cors/OnlySelf.dhall b/dhall-lang/tests/import/failure/unit/cors/OnlySelf.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/failure/unit/cors/OnlySelf.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlySelf.dhall
diff --git a/dhall-lang/tests/import/failure/unit/cors/TwoHops.dhall b/dhall-lang/tests/import/failure/unit/cors/TwoHops.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/failure/unit/cors/TwoHops.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/TwoHopsFail.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/AllowedAllA.dhall b/dhall-lang/tests/import/success/unit/cors/AllowedAllA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/AllowedAllA.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/AllowedAll.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/AllowedAllB.dhall b/dhall-lang/tests/import/success/unit/cors/AllowedAllB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/AllowedAllB.dhall
@@ -0,0 +1,1 @@
+42
diff --git a/dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalA.dhall b/dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalA.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/NoCORS.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalB.dhall b/dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalB.dhall
@@ -0,0 +1,1 @@
+42
diff --git a/dhall-lang/tests/import/success/unit/cors/OnlyGithubA.dhall b/dhall-lang/tests/import/success/unit/cors/OnlyGithubA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/OnlyGithubA.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyGithub.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/OnlyGithubB.dhall b/dhall-lang/tests/import/success/unit/cors/OnlyGithubB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/OnlyGithubB.dhall
@@ -0,0 +1,1 @@
+42
diff --git a/dhall-lang/tests/import/success/unit/cors/PreludeA.dhall b/dhall-lang/tests/import/success/unit/cors/PreludeA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/PreludeA.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/acee30866a179c9e9bb3fc02ec8be2883685eb14/tests/import/data/cors/Prelude.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/PreludeB.dhall b/dhall-lang/tests/import/success/unit/cors/PreludeB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/PreludeB.dhall
@@ -0,0 +1,1 @@
+List/length
diff --git a/dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2A.dhall b/dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2A.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2A.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/SelfImportAbsolute.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2B.dhall b/dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2B.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2B.dhall
@@ -0,0 +1,1 @@
+42
diff --git a/dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteA.dhall b/dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteA.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/SelfImportAbsolute.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteB.dhall b/dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteB.dhall
@@ -0,0 +1,1 @@
+42
diff --git a/dhall-lang/tests/import/success/unit/cors/SelfImportRelative2A.dhall b/dhall-lang/tests/import/success/unit/cors/SelfImportRelative2A.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/SelfImportRelative2A.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/SelfImportRelative.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/SelfImportRelative2B.dhall b/dhall-lang/tests/import/success/unit/cors/SelfImportRelative2B.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/SelfImportRelative2B.dhall
@@ -0,0 +1,1 @@
+42
diff --git a/dhall-lang/tests/import/success/unit/cors/SelfImportRelativeA.dhall b/dhall-lang/tests/import/success/unit/cors/SelfImportRelativeA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/SelfImportRelativeA.dhall
@@ -0,0 +1,1 @@
+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/SelfImportRelative.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/SelfImportRelativeB.dhall b/dhall-lang/tests/import/success/unit/cors/SelfImportRelativeB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/SelfImportRelativeB.dhall
@@ -0,0 +1,1 @@
+42
diff --git a/dhall-lang/tests/import/success/unit/cors/TwoHopsA.dhall b/dhall-lang/tests/import/success/unit/cors/TwoHopsA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/TwoHopsA.dhall
@@ -0,0 +1,1 @@
+https://test.dhall-lang.org/cors/TwoHopsSuccess.dhall
diff --git a/dhall-lang/tests/import/success/unit/cors/TwoHopsB.dhall b/dhall-lang/tests/import/success/unit/cors/TwoHopsB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/import/success/unit/cors/TwoHopsB.dhall
@@ -0,0 +1,1 @@
+42
diff --git a/dhall-lang/tests/parser/failure/time/DateTimeZone.dhall b/dhall-lang/tests/parser/failure/time/DateTimeZone.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/DateTimeZone.dhall
@@ -0,0 +1,2 @@
+-- A date and time zone is not valid (because the time is missing)
+2011-04-01+02:00
diff --git a/dhall-lang/tests/parser/failure/time/InvalidDayOfMonth.dhall b/dhall-lang/tests/parser/failure/time/InvalidDayOfMonth.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/InvalidDayOfMonth.dhall
@@ -0,0 +1,2 @@
+-- April only has 30 days
+2000-04-31
diff --git a/dhall-lang/tests/parser/failure/time/InvalidHour.dhall b/dhall-lang/tests/parser/failure/time/InvalidHour.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/InvalidHour.dhall
@@ -0,0 +1,2 @@
+-- Hours must range between 0-23
+24:00:00
diff --git a/dhall-lang/tests/parser/failure/time/InvalidLeapSecond.dhall b/dhall-lang/tests/parser/failure/time/InvalidLeapSecond.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/InvalidLeapSecond.dhall
@@ -0,0 +1,3 @@
+-- Leap seconds are not permitted by the Dhall standard, even though RFC 3339
+-- supports them
+2016-12-31T23:59:60
diff --git a/dhall-lang/tests/parser/failure/time/InvalidMinute.dhall b/dhall-lang/tests/parser/failure/time/InvalidMinute.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/InvalidMinute.dhall
@@ -0,0 +1,2 @@
+-- Minutes must range between 0-59
+00:60:00
diff --git a/dhall-lang/tests/parser/failure/time/InvalidMonth.dhall b/dhall-lang/tests/parser/failure/time/InvalidMonth.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/InvalidMonth.dhall
@@ -0,0 +1,2 @@
+-- Months must be between 1-12
+2000-13-01
diff --git a/dhall-lang/tests/parser/failure/time/InvalidSecond.dhall b/dhall-lang/tests/parser/failure/time/InvalidSecond.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/InvalidSecond.dhall
@@ -0,0 +1,2 @@
+-- Seconds must range between 0-59 (and leap seconds are not supported)
+00:00:60
diff --git a/dhall-lang/tests/parser/failure/time/NegativeYear.dhall b/dhall-lang/tests/parser/failure/time/NegativeYear.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/NegativeYear.dhall
@@ -0,0 +1,2 @@
+-- Negative years are not permitted
+-0001-01-01
diff --git a/dhall-lang/tests/parser/failure/time/YearTooLarge.dhall b/dhall-lang/tests/parser/failure/time/YearTooLarge.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/failure/time/YearTooLarge.dhall
@@ -0,0 +1,2 @@
+-- Only 4-digit years are permitted
+10000-01-01
diff --git a/dhall-lang/tests/parser/success/time/DateTimeA.dhall b/dhall-lang/tests/parser/success/time/DateTimeA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/success/time/DateTimeA.dhall
@@ -0,0 +1,1 @@
+1960-12-25T04:23:34
diff --git a/dhall-lang/tests/parser/success/time/DateTimeB.dhallb b/dhall-lang/tests/parser/success/time/DateTimeB.dhallb
new file mode 100644
Binary files /dev/null and b/dhall-lang/tests/parser/success/time/DateTimeB.dhallb differ
diff --git a/dhall-lang/tests/parser/success/time/DateTimeTimeZoneA.dhall b/dhall-lang/tests/parser/success/time/DateTimeTimeZoneA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/success/time/DateTimeTimeZoneA.dhall
@@ -0,0 +1,1 @@
+2020-01-01T12:00:00-08:00
diff --git a/dhall-lang/tests/parser/success/time/DateTimeTimeZoneB.dhallb b/dhall-lang/tests/parser/success/time/DateTimeTimeZoneB.dhallb
new file mode 100644
Binary files /dev/null and b/dhall-lang/tests/parser/success/time/DateTimeTimeZoneB.dhallb differ
diff --git a/dhall-lang/tests/parser/success/time/LowercaseTA.dhall b/dhall-lang/tests/parser/success/time/LowercaseTA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/success/time/LowercaseTA.dhall
@@ -0,0 +1,2 @@
+-- Check that lowercase `t` is supported
+2000-01-01t12:00:00
diff --git a/dhall-lang/tests/parser/success/time/LowercaseTB.dhallb b/dhall-lang/tests/parser/success/time/LowercaseTB.dhallb
new file mode 100644
Binary files /dev/null and b/dhall-lang/tests/parser/success/time/LowercaseTB.dhallb differ
diff --git a/dhall-lang/tests/parser/success/time/TimeTimeZoneA.dhall b/dhall-lang/tests/parser/success/time/TimeTimeZoneA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/success/time/TimeTimeZoneA.dhall
@@ -0,0 +1,1 @@
+00:00:00+00:00
diff --git a/dhall-lang/tests/parser/success/time/TimeTimeZoneB.dhallb b/dhall-lang/tests/parser/success/time/TimeTimeZoneB.dhallb
new file mode 100644
Binary files /dev/null and b/dhall-lang/tests/parser/success/time/TimeTimeZoneB.dhallb differ
diff --git a/dhall-lang/tests/parser/success/time/TimeTimeZoneZA.dhall b/dhall-lang/tests/parser/success/time/TimeTimeZoneZA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/parser/success/time/TimeTimeZoneZA.dhall
@@ -0,0 +1,5 @@
+-- Same as `./TimeTimeZoneA.dhall`, but with `Z` as the `TimeZone`
+--
+-- This ensures that implementation still parse `Z` in conjunction with a time,
+-- even if `Z` by itself is not permitted
+00:00:00Z
diff --git a/dhall-lang/tests/parser/success/time/TimeTimeZoneZB.dhallb b/dhall-lang/tests/parser/success/time/TimeTimeZoneZB.dhallb
new file mode 100644
Binary files /dev/null and b/dhall-lang/tests/parser/success/time/TimeTimeZoneZB.dhallb differ
diff --git a/dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldName.dhall b/dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldName.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldName.dhall
@@ -0,0 +1,1 @@
+{ x = 1 } : { y : Natural }
diff --git a/dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldType.dhall b/dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldType.dhall
@@ -0,0 +1,1 @@
+{ x = 1 } : { x : Text }
diff --git a/dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap.dhall b/dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap.dhall
@@ -0,0 +1,1 @@
+assert : (\(_: Bool) -> _) === (\(x: Bool) -> _)
diff --git a/dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap2.dhall b/dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap2.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap2.dhall
@@ -0,0 +1,1 @@
+\(_: Bool) -> assert : (\(_: Bool) -> _) === (\(x: Bool) -> _)
diff --git a/dhall-lang/tests/type-inference/failure/unit/AssertDoubleZeros.dhall b/dhall-lang/tests/type-inference/failure/unit/AssertDoubleZeros.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/AssertDoubleZeros.dhall
@@ -0,0 +1,1 @@
+assert : -0.0 ≡ +0.0
diff --git a/dhall-lang/tests/type-inference/failure/unit/AssertNotEquivalence.dhall b/dhall-lang/tests/type-inference/failure/unit/AssertNotEquivalence.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/AssertNotEquivalence.dhall
@@ -0,0 +1,1 @@
+assert : Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/AssertTriviallyFalse.dhall b/dhall-lang/tests/type-inference/failure/unit/AssertTriviallyFalse.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/AssertTriviallyFalse.dhall
@@ -0,0 +1,1 @@
+assert : 1 === 2
diff --git a/dhall-lang/tests/type-inference/failure/unit/CompletionMissingRequiredField.dhall b/dhall-lang/tests/type-inference/failure/unit/CompletionMissingRequiredField.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/CompletionMissingRequiredField.dhall
@@ -0,0 +1,6 @@
+let Example =
+      { Type = { name : Text, id : Optional Natural }
+      , default = { id = None Natural }
+      }
+
+in  Example::{=}
diff --git a/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongDefaultType.dhall b/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongDefaultType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongDefaultType.dhall
@@ -0,0 +1,6 @@
+let Example =
+      { Type = { name : Text, id : Optional Natural }
+      , default = { name = True, id = None Natural }
+      }
+
+in  Example::{=}
diff --git a/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongFieldName.dhall b/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongFieldName.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongFieldName.dhall
@@ -0,0 +1,6 @@
+let Example =
+      { Type = { name : Text, id : Optional Natural }
+      , default = { name = "", id = None Natural }
+      }
+
+in  Example::{ nam = "John Doe" }
diff --git a/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongOverridenType.dhall b/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongOverridenType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongOverridenType.dhall
@@ -0,0 +1,6 @@
+let Example =
+      { Type = { name : Text, id : Optional Natural }
+      , default = { name = "", id = None Natural }
+      }
+
+in  Example::{ name = True }
diff --git a/dhall-lang/tests/type-inference/failure/unit/EmptyToMap.dhall b/dhall-lang/tests/type-inference/failure/unit/EmptyToMap.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/EmptyToMap.dhall
@@ -0,0 +1,1 @@
+toMap {=}
diff --git a/dhall-lang/tests/type-inference/failure/unit/EquivalenceNotSameType.dhall b/dhall-lang/tests/type-inference/failure/unit/EquivalenceNotSameType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/EquivalenceNotSameType.dhall
@@ -0,0 +1,1 @@
+1 === False
diff --git a/dhall-lang/tests/type-inference/failure/unit/EquivalenceNotTerms.dhall b/dhall-lang/tests/type-inference/failure/unit/EquivalenceNotTerms.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/EquivalenceNotTerms.dhall
@@ -0,0 +1,1 @@
+Bool === Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/FunctionApplicationArgumentNotMatch.dhall b/dhall-lang/tests/type-inference/failure/unit/FunctionApplicationArgumentNotMatch.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/FunctionApplicationArgumentNotMatch.dhall
@@ -0,0 +1,1 @@
+(λ(_ : Natural) → _) True
diff --git a/dhall-lang/tests/type-inference/failure/unit/FunctionApplicationIsNotFunction.dhall b/dhall-lang/tests/type-inference/failure/unit/FunctionApplicationIsNotFunction.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/FunctionApplicationIsNotFunction.dhall
@@ -0,0 +1,1 @@
+True True
diff --git a/dhall-lang/tests/type-inference/failure/unit/FunctionArgumentTypeNotAType.dhall b/dhall-lang/tests/type-inference/failure/unit/FunctionArgumentTypeNotAType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/FunctionArgumentTypeNotAType.dhall
@@ -0,0 +1,1 @@
+λ(_ : 1) → _
diff --git a/dhall-lang/tests/type-inference/failure/unit/FunctionTypeArgumentTypeNotAType.dhall b/dhall-lang/tests/type-inference/failure/unit/FunctionTypeArgumentTypeNotAType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/FunctionTypeArgumentTypeNotAType.dhall
@@ -0,0 +1,1 @@
+2 → _
diff --git a/dhall-lang/tests/type-inference/failure/unit/FunctionTypeKindSort.dhall b/dhall-lang/tests/type-inference/failure/unit/FunctionTypeKindSort.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/FunctionTypeKindSort.dhall
@@ -0,0 +1,1 @@
+Kind → Sort
diff --git a/dhall-lang/tests/type-inference/failure/unit/FunctionTypeOutputTypeNotAType.dhall b/dhall-lang/tests/type-inference/failure/unit/FunctionTypeOutputTypeNotAType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/FunctionTypeOutputTypeNotAType.dhall
@@ -0,0 +1,1 @@
+Bool -> 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/FunctionTypeTypeSort.dhall b/dhall-lang/tests/type-inference/failure/unit/FunctionTypeTypeSort.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/FunctionTypeTypeSort.dhall
@@ -0,0 +1,1 @@
+Type → Sort
diff --git a/dhall-lang/tests/type-inference/failure/unit/HeterogenousToMap.dhall b/dhall-lang/tests/type-inference/failure/unit/HeterogenousToMap.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/HeterogenousToMap.dhall
@@ -0,0 +1,1 @@
+toMap { foo= 1, bar= "Bar" }
diff --git a/dhall-lang/tests/type-inference/failure/unit/IfBranchesNotMatch.dhall b/dhall-lang/tests/type-inference/failure/unit/IfBranchesNotMatch.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/IfBranchesNotMatch.dhall
@@ -0,0 +1,1 @@
+if True then 1 else ""
diff --git a/dhall-lang/tests/type-inference/failure/unit/IfBranchesNotTermTypeOrKind.dhall b/dhall-lang/tests/type-inference/failure/unit/IfBranchesNotTermTypeOrKind.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/IfBranchesNotTermTypeOrKind.dhall
@@ -0,0 +1,1 @@
+if True then Kind else Kind
diff --git a/dhall-lang/tests/type-inference/failure/unit/IfNotBool.dhall b/dhall-lang/tests/type-inference/failure/unit/IfNotBool.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/IfNotBool.dhall
@@ -0,0 +1,1 @@
+if 1 then 1 else 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/LetInSort.dhall b/dhall-lang/tests/type-inference/failure/unit/LetInSort.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/LetInSort.dhall
@@ -0,0 +1,1 @@
+\(x: let x = 0 in Sort) -> 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/LetWithNonterminatingAnnotation.dhall b/dhall-lang/tests/type-inference/failure/unit/LetWithNonterminatingAnnotation.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/LetWithNonterminatingAnnotation.dhall
@@ -0,0 +1,14 @@
+-- When you check if an inferred type is equivalent to an annotation,
+-- you must alpha-beta-normalize both sides first.  But it is not safe
+-- to beta-normalise an expression which hasn't first been
+-- typechecked.
+--
+-- This test contains an annotation which doesn't typecheck, and
+-- which, when beta-normalized, doesn't terminate.  It exists to
+-- verify that implementations typecheck the annotation before
+-- checking equivalence.
+let a
+    : (λ(x : Natural) → x x) (λ(x : Natural) → x x)
+    = 3
+
+in  5
diff --git a/dhall-lang/tests/type-inference/failure/unit/LetWithWrongAnnotation.dhall b/dhall-lang/tests/type-inference/failure/unit/LetWithWrongAnnotation.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/LetWithWrongAnnotation.dhall
@@ -0,0 +1,1 @@
+let x : Natural = True in True
diff --git a/dhall-lang/tests/type-inference/failure/unit/ListLiteralEmptyNotType.dhall b/dhall-lang/tests/type-inference/failure/unit/ListLiteralEmptyNotType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/ListLiteralEmptyNotType.dhall
@@ -0,0 +1,1 @@
+[] : List Type
diff --git a/dhall-lang/tests/type-inference/failure/unit/ListLiteralNotType.dhall b/dhall-lang/tests/type-inference/failure/unit/ListLiteralNotType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/ListLiteralNotType.dhall
@@ -0,0 +1,1 @@
+[ Bool ]
diff --git a/dhall-lang/tests/type-inference/failure/unit/ListLiteralTypesNotMatch.dhall b/dhall-lang/tests/type-inference/failure/unit/ListLiteralTypesNotMatch.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/ListLiteralTypesNotMatch.dhall
@@ -0,0 +1,1 @@
+[ True, 1 ]
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeAlternativeHasNoHandler.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeAlternativeHasNoHandler.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeAlternativeHasNoHandler.dhall
@@ -0,0 +1,1 @@
+merge {=} (< x : Bool >.x True)
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeAnnotationMismatch.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeAnnotationMismatch.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeAnnotationMismatch.dhall
@@ -0,0 +1,1 @@
+merge { x = 0 } < x >.x : Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeAnnotationNotType.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeAnnotationNotType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeAnnotationNotType.dhall
@@ -0,0 +1,1 @@
+merge {=} <> : Type
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeBool.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeBool.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeBool.dhall
@@ -0,0 +1,1 @@
+\(x: { True: Natural, False: Natural }) -> merge x True
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation1.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation1.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation1.dhall
@@ -0,0 +1,1 @@
+\(x: <>) -> (merge {=} x) : Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation2.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation2.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation2.dhall
@@ -0,0 +1,1 @@
+\(x: <>) -> let y: Bool = merge {=} x in 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeEmptyWithoutAnnotation.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeEmptyWithoutAnnotation.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeEmptyWithoutAnnotation.dhall
@@ -0,0 +1,1 @@
+merge {=} <>
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeHandlerFreeVar.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeHandlerFreeVar.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeHandlerFreeVar.dhall
@@ -0,0 +1,1 @@
+merge { x = None } (<x: Type>.x Bool)
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotFunction.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotFunction.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotFunction.dhall
@@ -0,0 +1,1 @@
+merge { x = True } (< x : Bool >.x True)
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotInUnion.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotInUnion.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotInUnion.dhall
@@ -0,0 +1,1 @@
+merge { x = λ(_ : Bool) → _ } <> : Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotMatchAlternativeType.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotMatchAlternativeType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotMatchAlternativeType.dhall
@@ -0,0 +1,1 @@
+merge { x = λ(_ : Bool) → _ } (< x : Natural >.x 1)
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeHandlersWithDifferentType.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeHandlersWithDifferentType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeHandlersWithDifferentType.dhall
@@ -0,0 +1,1 @@
+merge { x = λ(_ : Bool) → _, y = λ(_ : Natural) → _ } (< x : Bool | y : Natural >.x True)
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeLhsNotRecord.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeLhsNotRecord.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeLhsNotRecord.dhall
@@ -0,0 +1,1 @@
+merge True < x >.x
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler1.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler1.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler1.dhall
@@ -0,0 +1,1 @@
+merge {=} <x>.x
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler2.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler2.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler2.dhall
@@ -0,0 +1,1 @@
+merge { x = 0 } <x | y>.x
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeRhsNotUnion.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeRhsNotUnion.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeRhsNotUnion.dhall
@@ -0,0 +1,1 @@
+merge {=} True
diff --git a/dhall-lang/tests/type-inference/failure/unit/MergeUnusedHandler.dhall b/dhall-lang/tests/type-inference/failure/unit/MergeUnusedHandler.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MergeUnusedHandler.dhall
@@ -0,0 +1,1 @@
+merge { x = 1, y = 2 } < x >.x
diff --git a/dhall-lang/tests/type-inference/failure/unit/MistypedToMap1.dhall b/dhall-lang/tests/type-inference/failure/unit/MistypedToMap1.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MistypedToMap1.dhall
@@ -0,0 +1,1 @@
+toMap { foo= 1, bar= 4 } : Natural
diff --git a/dhall-lang/tests/type-inference/failure/unit/MistypedToMap2.dhall b/dhall-lang/tests/type-inference/failure/unit/MistypedToMap2.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MistypedToMap2.dhall
@@ -0,0 +1,1 @@
+toMap { foo= 1, bar= 4 } : List Natural
diff --git a/dhall-lang/tests/type-inference/failure/unit/MistypedToMap3.dhall b/dhall-lang/tests/type-inference/failure/unit/MistypedToMap3.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MistypedToMap3.dhall
@@ -0,0 +1,1 @@
+toMap { foo= 1, bar= 4 } : List { mapKey : Natural, mapValue : Natural }
diff --git a/dhall-lang/tests/type-inference/failure/unit/MistypedToMap4.dhall b/dhall-lang/tests/type-inference/failure/unit/MistypedToMap4.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/MistypedToMap4.dhall
@@ -0,0 +1,1 @@
+toMap { foo= 1, bar= 4 } : List { mapKey : Text, mapValue : Text }
diff --git a/dhall-lang/tests/type-inference/failure/unit/NaturalSubtractNotNatural.dhall b/dhall-lang/tests/type-inference/failure/unit/NaturalSubtractNotNatural.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/NaturalSubtractNotNatural.dhall
@@ -0,0 +1,1 @@
+Natural/subtract True True
diff --git a/dhall-lang/tests/type-inference/failure/unit/NestedAnnotInnerWrong.dhall b/dhall-lang/tests/type-inference/failure/unit/NestedAnnotInnerWrong.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/NestedAnnotInnerWrong.dhall
@@ -0,0 +1,1 @@
+(0 : Bool) : Natural
diff --git a/dhall-lang/tests/type-inference/failure/unit/NestedAnnotOuterWrong.dhall b/dhall-lang/tests/type-inference/failure/unit/NestedAnnotOuterWrong.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/NestedAnnotOuterWrong.dhall
@@ -0,0 +1,1 @@
+(0 : Natural) : Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/NonRecordToMap.dhall b/dhall-lang/tests/type-inference/failure/unit/NonRecordToMap.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/NonRecordToMap.dhall
@@ -0,0 +1,1 @@
+toMap "text"
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorAndNotBool.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorAndNotBool.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorAndNotBool.dhall
@@ -0,0 +1,1 @@
+1 && 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorEqualNotBool.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorEqualNotBool.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorEqualNotBool.dhall
@@ -0,0 +1,1 @@
+1 == 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateLhsNotList.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateLhsNotList.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateLhsNotList.dhall
@@ -0,0 +1,1 @@
+1 # [ True ]
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateListsNotMatch.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateListsNotMatch.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateListsNotMatch.dhall
@@ -0,0 +1,1 @@
+[ True ] # [ 1 ]
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateNotListsButMatch.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateNotListsButMatch.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateNotListsButMatch.dhall
@@ -0,0 +1,1 @@
+1 # 2
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateRhsNotList.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateRhsNotList.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateRhsNotList.dhall
@@ -0,0 +1,1 @@
+[ True ] # 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorNotEqualNotBool.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorNotEqualNotBool.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorNotEqualNotBool.dhall
@@ -0,0 +1,1 @@
+1 != 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorOrNotBool.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorOrNotBool.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorOrNotBool.dhall
@@ -0,0 +1,1 @@
+1 || 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorPlusNotNatural.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorPlusNotNatural.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorPlusNotNatural.dhall
@@ -0,0 +1,1 @@
+True + True
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateLhsNotText.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateLhsNotText.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateLhsNotText.dhall
@@ -0,0 +1,1 @@
+1 ++ ""
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateRhsNotText.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateRhsNotText.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateRhsNotText.dhall
@@ -0,0 +1,1 @@
+"" ++ 1
diff --git a/dhall-lang/tests/type-inference/failure/unit/OperatorTimesNotNatural.dhall b/dhall-lang/tests/type-inference/failure/unit/OperatorTimesNotNatural.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OperatorTimesNotNatural.dhall
@@ -0,0 +1,1 @@
+True * True
diff --git a/dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxAbsent.dhall b/dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxAbsent.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxAbsent.dhall
@@ -0,0 +1,1 @@
+[] : Optional Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxPresent.dhall b/dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxPresent.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxPresent.dhall
@@ -0,0 +1,1 @@
+[ 1 ] : Optional Natural
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsAbstract.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsAbstract.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsAbstract.dhall
@@ -0,0 +1,13 @@
+{-  This test illustrates that duplicate fields need not be literals in order
+    to be properly normalized.  One or both of the duplicate fields can be
+    abstract because field duplication delegates its behavior to the `∧`
+    operator
+
+    This particular example fails because it desugars to:
+
+        λ(r : { y : Natural }) → { x = { y = 1 } ∧ r }
+
+    ... and the `∧` operator can infer that the two records collide on the
+    field `y`
+-}
+λ(r : { y : Natural }) → { x = { y = 1 }, x = r }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsCollidingRecords.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsCollidingRecords.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsCollidingRecords.dhall
@@ -0,0 +1,8 @@
+{-  This fails because the expression desugars to:
+
+        { x = { y = 0 } ∧ { y = 0 } }
+
+    ... which is ill-typed due to `∧` forbidding collisions and the two `y`
+    fields collide.
+-}
+{ x = { y = 0 }, x = { y = 0 } }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsNotRecords.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsNotRecords.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsNotRecords.dhall
@@ -0,0 +1,7 @@
+{-  This fails because the expression desugars to:
+
+    { x = 0 ∧ 0 }
+
+    ... which is ill-typed due to ∧ only working on records
+-}
+{ x = 0, x = 0 }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeFieldTypeMismatch.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeFieldTypeMismatch.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeFieldTypeMismatch.dhall
@@ -0,0 +1,1 @@
+{ y = {=} }.( {y : Natural} )
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeNotPresent.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeNotPresent.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeNotPresent.dhall
@@ -0,0 +1,1 @@
+{ y = {=} }.( {x : Natural} )
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordProjectionDuplicateFields.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionDuplicateFields.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionDuplicateFields.dhall
@@ -0,0 +1,1 @@
+{ x = 1 }.{ x, x }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordProjectionEmpty.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionEmpty.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionEmpty.dhall
@@ -0,0 +1,1 @@
+{=}.{ x }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotPresent.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotPresent.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotPresent.dhall
@@ -0,0 +1,1 @@
+{ y = {=} }.{ x }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotRecord.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotRecord.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotRecord.dhall
@@ -0,0 +1,1 @@
+True.{ x }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordSelectionEmpty.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordSelectionEmpty.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordSelectionEmpty.dhall
@@ -0,0 +1,1 @@
+{=}.x
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotPresent.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotPresent.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotPresent.dhall
@@ -0,0 +1,1 @@
+{ y = {=} }.x
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotRecord.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotRecord.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotRecord.dhall
@@ -0,0 +1,1 @@
+True.x
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordSelectionTypeNotUnionType.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordSelectionTypeNotUnionType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordSelectionTypeNotUnionType.dhall
@@ -0,0 +1,1 @@
+Bool.x
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordTypeDuplicateFields.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordTypeDuplicateFields.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordTypeDuplicateFields.dhall
@@ -0,0 +1,1 @@
+{ x: Natural, x: Natural }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecordTypeValueMember.dhall b/dhall-lang/tests/type-inference/failure/unit/RecordTypeValueMember.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecordTypeValueMember.dhall
@@ -0,0 +1,1 @@
+{ x : True }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeLhsNotRecord.dhall b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeLhsNotRecord.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeLhsNotRecord.dhall
@@ -0,0 +1,1 @@
+True ∧ {=}
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeOverlapping.dhall b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeOverlapping.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeOverlapping.dhall
@@ -0,0 +1,1 @@
+{ x = True } ∧ { x = False }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeRhsNotRecord.dhall b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeRhsNotRecord.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeRhsNotRecord.dhall
@@ -0,0 +1,1 @@
+{=} ∧ True
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeLhsNotRecordType.dhall b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeLhsNotRecordType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeLhsNotRecordType.dhall
@@ -0,0 +1,1 @@
+Bool ⩓ {}
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeOverlapping.dhall b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeOverlapping.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeOverlapping.dhall
@@ -0,0 +1,1 @@
+{ x : Bool } ⩓ { x : Natural }
diff --git a/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeRhsNotRecordType.dhall b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeRhsNotRecordType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeRhsNotRecordType.dhall
@@ -0,0 +1,1 @@
+{} ⩓ Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalBuild.dhall b/dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalBuild.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalBuild.dhall
@@ -0,0 +1,1 @@
+Optional/build
diff --git a/dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalFold.dhall b/dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalFold.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalFold.dhall
@@ -0,0 +1,1 @@
+Optional/fold
diff --git a/dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeLhsNotRecord.dhall b/dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeLhsNotRecord.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeLhsNotRecord.dhall
@@ -0,0 +1,1 @@
+True ⫽ {=}
diff --git a/dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeRhsNotRecord.dhall b/dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeRhsNotRecord.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeRhsNotRecord.dhall
@@ -0,0 +1,1 @@
+{=} ⫽ True
diff --git a/dhall-lang/tests/type-inference/failure/unit/SomeNotType.dhall b/dhall-lang/tests/type-inference/failure/unit/SomeNotType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/SomeNotType.dhall
@@ -0,0 +1,1 @@
+Some Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/Sort.dhall b/dhall-lang/tests/type-inference/failure/unit/Sort.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/Sort.dhall
@@ -0,0 +1,1 @@
+Sort
diff --git a/dhall-lang/tests/type-inference/failure/unit/TextLiteralInterpolateNotText.dhall b/dhall-lang/tests/type-inference/failure/unit/TextLiteralInterpolateNotText.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/TextLiteralInterpolateNotText.dhall
@@ -0,0 +1,1 @@
+"${1}"
diff --git a/dhall-lang/tests/type-inference/failure/unit/ToMapEmptyInvalidAnnotation.dhall b/dhall-lang/tests/type-inference/failure/unit/ToMapEmptyInvalidAnnotation.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/ToMapEmptyInvalidAnnotation.dhall
@@ -0,0 +1,2 @@
+-- The mapKey must be Text
+toMap {=} : List { mapKey : Bool, mapValue : Text }
diff --git a/dhall-lang/tests/type-inference/failure/unit/ToMapWrongKind.dhall b/dhall-lang/tests/type-inference/failure/unit/ToMapWrongKind.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/ToMapWrongKind.dhall
@@ -0,0 +1,1 @@
+toMap { x = Bool }
diff --git a/dhall-lang/tests/type-inference/failure/unit/TypeAnnotationWrong.dhall b/dhall-lang/tests/type-inference/failure/unit/TypeAnnotationWrong.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/TypeAnnotationWrong.dhall
@@ -0,0 +1,1 @@
+1 : Bool
diff --git a/dhall-lang/tests/type-inference/failure/unit/UnionConstructorFieldNotPresent.dhall b/dhall-lang/tests/type-inference/failure/unit/UnionConstructorFieldNotPresent.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/UnionConstructorFieldNotPresent.dhall
@@ -0,0 +1,1 @@
+< x : Bool >.y
diff --git a/dhall-lang/tests/type-inference/failure/unit/UnionDeprecatedConstructorsKeyword.dhall b/dhall-lang/tests/type-inference/failure/unit/UnionDeprecatedConstructorsKeyword.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/UnionDeprecatedConstructorsKeyword.dhall
@@ -0,0 +1,1 @@
+constructors < Left : Natural | Right : Bool >
diff --git a/dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants1.dhall b/dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants1.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants1.dhall
@@ -0,0 +1,1 @@
+<x | x>
diff --git a/dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants2.dhall b/dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants2.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants2.dhall
@@ -0,0 +1,1 @@
+<x | x: Natural>
diff --git a/dhall-lang/tests/type-inference/failure/unit/UnionTypeNotType.dhall b/dhall-lang/tests/type-inference/failure/unit/UnionTypeNotType.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/UnionTypeNotType.dhall
@@ -0,0 +1,1 @@
+< x : True >
diff --git a/dhall-lang/tests/type-inference/failure/unit/VariableFree.dhall b/dhall-lang/tests/type-inference/failure/unit/VariableFree.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/VariableFree.dhall
@@ -0,0 +1,1 @@
+x
diff --git a/dhall-lang/tests/type-inference/failure/unit/WithInfersKind.dhall b/dhall-lang/tests/type-inference/failure/unit/WithInfersKind.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/WithInfersKind.dhall
@@ -0,0 +1,1 @@
+Some ({=} with x = Bool)
diff --git a/dhall-lang/tests/type-inference/failure/unit/WithInvalidOverrideA.dhall b/dhall-lang/tests/type-inference/failure/unit/WithInvalidOverrideA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/WithInvalidOverrideA.dhall
@@ -0,0 +1,6 @@
+{-  The `with` keyword cannot "descend" past a field that is not a record
+
+    In the following example, the `a` field is not a record, therefore there is
+    no possibility of adding or overriding `a` with an inner `b` field
+-}
+{ a = 1 } with a.b = 2
diff --git a/dhall-lang/tests/type-inference/failure/unit/WithNotRecord.dhall b/dhall-lang/tests/type-inference/failure/unit/WithNotRecord.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/WithNotRecord.dhall
@@ -0,0 +1,1 @@
+5 with a = 10
diff --git a/dhall-lang/tests/type-inference/failure/unit/Z.dhall b/dhall-lang/tests/type-inference/failure/unit/Z.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/failure/unit/Z.dhall
@@ -0,0 +1,4 @@
+-- The purpose of this test is to check that an implementation is not parsing a
+-- standalone `Z` as a `TimeOffset`.  Instead, this should be treated as an
+-- unbound variable named `Z`
+Z
diff --git a/dhall-lang/tests/type-inference/success/unit/time/DateA.dhall b/dhall-lang/tests/type-inference/success/unit/time/DateA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/DateA.dhall
@@ -0,0 +1,1 @@
+Date
diff --git a/dhall-lang/tests/type-inference/success/unit/time/DateB.dhall b/dhall-lang/tests/type-inference/success/unit/time/DateB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/DateB.dhall
@@ -0,0 +1,1 @@
+Type
diff --git a/dhall-lang/tests/type-inference/success/unit/time/DateLiteralA.dhall b/dhall-lang/tests/type-inference/success/unit/time/DateLiteralA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/DateLiteralA.dhall
@@ -0,0 +1,1 @@
+2000-01-01
diff --git a/dhall-lang/tests/type-inference/success/unit/time/DateLiteralB.dhall b/dhall-lang/tests/type-inference/success/unit/time/DateLiteralB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/DateLiteralB.dhall
@@ -0,0 +1,1 @@
+Date
diff --git a/dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralA.dhall b/dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralA.dhall
@@ -0,0 +1,1 @@
+2000-01-01T12:00:00
diff --git a/dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralB.dhall b/dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralB.dhall
@@ -0,0 +1,1 @@
+{ date : Date, time : Time }
diff --git a/dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralA.dhall b/dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralA.dhall
@@ -0,0 +1,1 @@
+2000-01-01T12:00:00+08:00
diff --git a/dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralB.dhall b/dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralB.dhall
@@ -0,0 +1,1 @@
+{ date : Date, time : Time, timeZone : TimeZone }
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeA.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeA.dhall
@@ -0,0 +1,1 @@
+Time
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeB.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeB.dhall
@@ -0,0 +1,1 @@
+Type
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeLiteralA.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeLiteralA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeLiteralA.dhall
@@ -0,0 +1,1 @@
+12:00:00
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeLiteralB.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeLiteralB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeLiteralB.dhall
@@ -0,0 +1,1 @@
+Time
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralA.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralA.dhall
@@ -0,0 +1,1 @@
+12:00:00+08:00
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralB.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralB.dhall
@@ -0,0 +1,1 @@
+{ time : Time, timeZone : TimeZone }
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeZoneA.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeZoneA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeZoneA.dhall
@@ -0,0 +1,1 @@
+TimeZone
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeZoneB.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeZoneB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeZoneB.dhall
@@ -0,0 +1,1 @@
+Type
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralA.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralA.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralA.dhall
@@ -0,0 +1,1 @@
++08:00
diff --git a/dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralB.dhall b/dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralB.dhall
new file mode 100644
--- /dev/null
+++ b/dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralB.dhall
@@ -0,0 +1,1 @@
+TimeZone
diff --git a/dhall.cabal b/dhall.cabal
--- a/dhall.cabal
+++ b/dhall.cabal
@@ -1,8 +1,8 @@
+Cabal-Version: 2.4
 Name: dhall
-Version: 1.40.2
-Cabal-Version: 2.0
+Version: 1.41.0
 Build-Type: Simple
-License: BSD3
+License: BSD-3-Clause
 License-File: LICENSE
 Copyright: 2017 Gabriel Gonzalez
 Author: Gabriel Gonzalez
@@ -24,10 +24,9 @@
 Data-Files:
     man/dhall.1
 Extra-Source-Files:
-    benchmark/deep-nested-large-record/*.dhall
-    benchmark/examples/*.dhall
-    benchmark/examples/normalize/*.dhall
     CHANGELOG.md
+    benchmark/**/*.dhall
+    dhall-lang/Prelude/**/*.dhall
     dhall-lang/Prelude/Bool/and
     dhall-lang/Prelude/Bool/build
     dhall-lang/Prelude/Bool/even
@@ -35,16 +34,10 @@
     dhall-lang/Prelude/Bool/not
     dhall-lang/Prelude/Bool/odd
     dhall-lang/Prelude/Bool/or
-    dhall-lang/Prelude/Bool/package.dhall
     dhall-lang/Prelude/Bool/show
-    dhall-lang/Prelude/Bool/*.dhall
-    dhall-lang/Prelude/Double/package.dhall
     dhall-lang/Prelude/Double/show
-    dhall-lang/Prelude/Double/*.dhall
     dhall-lang/Prelude/Function/compose
     dhall-lang/Prelude/Function/identity
-    dhall-lang/Prelude/Function/package.dhall
-    dhall-lang/Prelude/Function/*.dhall
     dhall-lang/Prelude/Integer/abs
     dhall-lang/Prelude/Integer/add
     dhall-lang/Prelude/Integer/clamp
@@ -58,20 +51,17 @@
     dhall-lang/Prelude/Integer/negative
     dhall-lang/Prelude/Integer/nonNegative
     dhall-lang/Prelude/Integer/nonPositive
-    dhall-lang/Prelude/Integer/package.dhall
     dhall-lang/Prelude/Integer/positive
     dhall-lang/Prelude/Integer/show
     dhall-lang/Prelude/Integer/subtract
     dhall-lang/Prelude/Integer/toDouble
     dhall-lang/Prelude/Integer/toNatural
-    dhall-lang/Prelude/Integer/*.dhall
     dhall-lang/Prelude/JSON/Format
     dhall-lang/Prelude/JSON/Nesting
     dhall-lang/Prelude/JSON/Tagged
     dhall-lang/Prelude/JSON/Type
     dhall-lang/Prelude/JSON/array
     dhall-lang/Prelude/JSON/bool
-    dhall-lang/Prelude/JSON/core.dhall
     dhall-lang/Prelude/JSON/double
     dhall-lang/Prelude/JSON/integer
     dhall-lang/Prelude/JSON/keyText
@@ -81,16 +71,12 @@
     dhall-lang/Prelude/JSON/number
     dhall-lang/Prelude/JSON/object
     dhall-lang/Prelude/JSON/omitNullFields
-    dhall-lang/Prelude/JSON/package.dhall
     dhall-lang/Prelude/JSON/render
     dhall-lang/Prelude/JSON/renderAs
-    dhall-lang/Prelude/JSON/renderCompact.dhall
-    dhall-lang/Prelude/JSON/renderInteger.dhall
     dhall-lang/Prelude/JSON/renderYAML
     dhall-lang/Prelude/JSON/string
     dhall-lang/Prelude/JSON/tagInline
     dhall-lang/Prelude/JSON/tagNested
-    dhall-lang/Prelude/JSON/*.dhall
     dhall-lang/Prelude/List/all
     dhall-lang/Prelude/List/any
     dhall-lang/Prelude/List/build
@@ -110,7 +96,6 @@
     dhall-lang/Prelude/List/length
     dhall-lang/Prelude/List/map
     dhall-lang/Prelude/List/null
-    dhall-lang/Prelude/List/package.dhall
     dhall-lang/Prelude/List/partition
     dhall-lang/Prelude/List/replicate
     dhall-lang/Prelude/List/reverse
@@ -119,10 +104,7 @@
     dhall-lang/Prelude/List/unpackOptionals
     dhall-lang/Prelude/List/unzip
     dhall-lang/Prelude/List/zip
-    dhall-lang/Prelude/List/*.dhall
     dhall-lang/Prelude/Location/Type
-    dhall-lang/Prelude/Location/package.dhall
-    dhall-lang/Prelude/Location/*.dhall
     dhall-lang/Prelude/Map/Entry
     dhall-lang/Prelude/Map/Type
     dhall-lang/Prelude/Map/empty
@@ -130,9 +112,7 @@
     dhall-lang/Prelude/Map/keyValue
     dhall-lang/Prelude/Map/keys
     dhall-lang/Prelude/Map/map
-    dhall-lang/Prelude/Map/package.dhall
     dhall-lang/Prelude/Map/values
-    dhall-lang/Prelude/Map/*.dhall
     dhall-lang/Prelude/Monoid
     dhall-lang/Prelude/Natural/build
     dhall-lang/Prelude/Natural/enumerate
@@ -149,7 +129,6 @@
     dhall-lang/Prelude/Natural/max
     dhall-lang/Prelude/Natural/min
     dhall-lang/Prelude/Natural/odd
-    dhall-lang/Prelude/Natural/package.dhall
     dhall-lang/Prelude/Natural/product
     dhall-lang/Prelude/Natural/show
     dhall-lang/Prelude/Natural/sort
@@ -157,9 +136,6 @@
     dhall-lang/Prelude/Natural/sum
     dhall-lang/Prelude/Natural/toDouble
     dhall-lang/Prelude/Natural/toInteger
-    dhall-lang/Prelude/Natural/*.dhall
-    dhall-lang/Prelude/NonEmpty/*.dhall
-    dhall-lang/Prelude/Operator/package.dhall
     dhall-lang/Prelude/Optional/all
     dhall-lang/Prelude/Optional/any
     dhall-lang/Prelude/Optional/build
@@ -172,282 +148,33 @@
     dhall-lang/Prelude/Optional/length
     dhall-lang/Prelude/Optional/map
     dhall-lang/Prelude/Optional/null
-    dhall-lang/Prelude/Optional/package.dhall
     dhall-lang/Prelude/Optional/toList
     dhall-lang/Prelude/Optional/unzip
-    dhall-lang/Prelude/Optional/*.dhall
     dhall-lang/Prelude/Text/concat
     dhall-lang/Prelude/Text/concatMap
     dhall-lang/Prelude/Text/concatMapSep
     dhall-lang/Prelude/Text/concatSep
     dhall-lang/Prelude/Text/default
     dhall-lang/Prelude/Text/defaultMap
-    dhall-lang/Prelude/Text/package.dhall
-    dhall-lang/Prelude/Text/replace.dhall
     dhall-lang/Prelude/Text/replicate
     dhall-lang/Prelude/Text/show
     dhall-lang/Prelude/Text/spaces
-    dhall-lang/Prelude/Text/*.dhall
     dhall-lang/Prelude/XML/Type
     dhall-lang/Prelude/XML/attribute
     dhall-lang/Prelude/XML/element
     dhall-lang/Prelude/XML/emptyAttributes
     dhall-lang/Prelude/XML/leaf
-    dhall-lang/Prelude/XML/package.dhall
     dhall-lang/Prelude/XML/render
     dhall-lang/Prelude/XML/text
-    dhall-lang/Prelude/XML/*.dhall
-    dhall-lang/Prelude/*.dhall
-    dhall-lang/Prelude/package.dhall
-    dhall-lang/tests/alpha-normalization/success/unit/*.dhall
-    dhall-lang/tests/alpha-normalization/success/regression/*.dhall
-    dhall-lang/tests/binary-decode/failure/unit/*.dhallb
-    dhall-lang/tests/binary-decode/success/unit/*.dhall
-    dhall-lang/tests/binary-decode/success/unit/*.dhallb
-    dhall-lang/tests/binary-decode/success/unit/imports/*.dhall
-    dhall-lang/tests/binary-decode/success/unit/imports/*.dhallb
+    dhall-lang/tests/**/*.dhall
+    dhall-lang/tests/**/*.dhallb
+    dhall-lang/tests/**/*.hash
+    dhall-lang/tests/**/*.txt
     dhall-lang/tests/import/cache/dhall/12203871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc
     dhall-lang/tests/import/cache/dhall/1220618f785ce8f3930a9144398f576f0a992544b51212bc9108c31b4e670dc6ed21
-    dhall-lang/tests/import/data/*.dhall
-    dhall-lang/tests/import/data/*.txt
-    dhall-lang/tests/import/failure/*.dhall
-    dhall-lang/tests/import/failure/unit/*.dhall
-    dhall-lang/tests/import/success/*.dhall
-    dhall-lang/tests/import/success/unit/*.dhall
-    dhall-lang/tests/import/success/unit/asLocation/*.dhall
-    dhall-lang/tests/normalization/success/*.dhall
-    dhall-lang/tests/normalization/success/haskell-tutorial/access/*.dhall
-    dhall-lang/tests/normalization/success/haskell-tutorial/combineTypes/*.dhall
-    dhall-lang/tests/normalization/success/haskell-tutorial/prefer/*.dhall
-    dhall-lang/tests/normalization/success/haskell-tutorial/projection/*.dhall
-    dhall-lang/tests/normalization/success/regression/*.dhall
-    dhall-lang/tests/normalization/success/simple/*.dhall
-    dhall-lang/tests/normalization/success/simplifications/*.dhall
-    dhall-lang/tests/normalization/success/unit/*.dhall
-    dhall-lang/tests/parser/failure/*.dhall
-    dhall-lang/tests/parser/failure/spacing/*.dhall
-    dhall-lang/tests/parser/failure/unit/*.dhall
-    dhall-lang/tests/parser/success/*.dhall
-    dhall-lang/tests/parser/success/*.dhallb
-    dhall-lang/tests/parser/success/text/*.dhall
-    dhall-lang/tests/parser/success/text/*.dhallb
-    dhall-lang/tests/parser/success/unit/*.dhall
-    dhall-lang/tests/parser/success/unit/*.dhallb
-    dhall-lang/tests/parser/success/unit/operators/*.dhall
-    dhall-lang/tests/parser/success/unit/operators/*.dhallb
-    dhall-lang/tests/parser/success/unit/import/*.dhall
-    dhall-lang/tests/parser/success/unit/import/*.dhallb
-    dhall-lang/tests/parser/success/unit/import/urls/*.dhall
-    dhall-lang/tests/parser/success/unit/import/urls/*.dhallb
-    dhall-lang/tests/semantic-hash/success/*.dhall
-    dhall-lang/tests/semantic-hash/success/*.hash
-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/*.dhall
-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/*.hash
-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/*.dhall
-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/*.hash
-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/*.dhall
-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/*.hash
-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/*.dhall
-    dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/and/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/and/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/build/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/build/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/even/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/even/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/not/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/not/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/or/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/or/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/show/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Bool/show/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Double/show/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Double/show/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Integer/show/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Integer/show/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/all/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/all/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/any/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/any/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/build/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/build/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/concat/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/concat/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/filter/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/filter/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/fold/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/fold/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/generate/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/generate/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/head/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/head/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/indexed/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/indexed/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/iterate/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/iterate/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/last/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/last/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/length/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/length/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/map/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/map/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/null/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/null/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/replicate/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/replicate/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/reverse/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/reverse/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/shifted/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/shifted/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/List/unzip/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/List/unzip/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/build/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/build/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/even/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/even/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/product/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/product/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/show/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/show/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/all/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/all/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/any/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/any/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/build/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/build/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/head/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/head/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/last/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/last/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/length/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/length/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/map/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/map/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/null/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/null/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Text/concat/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Text/concat/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/*.hash
-    dhall-lang/tests/semantic-hash/success/prelude/Text/show/*.dhall
-    dhall-lang/tests/semantic-hash/success/prelude/Text/show/*.hash
-    dhall-lang/tests/semantic-hash/success/simple/*.dhall
-    dhall-lang/tests/semantic-hash/success/simple/*.hash
-    dhall-lang/tests/semantic-hash/success/simplifications/*.dhall
-    dhall-lang/tests/semantic-hash/success/simplifications/*.hash
-    dhall-lang/tests/type-inference/failure/*.dhall
-    dhall-lang/tests/type-inference/success/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Bool/and/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Bool/build/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Bool/even/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Bool/fold/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Bool/not/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Bool/odd/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Bool/or/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Bool/show/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Double/show/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Integer/show/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/all/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/any/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/build/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/concat/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/concatMap/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/filter/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/fold/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/generate/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/head/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/indexed/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/iterate/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/last/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/length/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/map/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/null/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/replicate/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/reverse/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/shifted/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/List/unzip/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Monoid/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/build/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/even/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/fold/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/isZero/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/odd/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/product/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/show/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/sum/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/all/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/any/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/build/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/concat/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/filter/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/fold/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/head/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/last/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/length/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/map/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/null/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/toList/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Optional/unzip/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Text/concat/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Text/concatMap/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/*.dhall
-    dhall-lang/tests/type-inference/success/prelude/Text/concatSep/*.dhall
-    dhall-lang/tests/type-inference/success/regression/*.dhall
-    dhall-lang/tests/type-inference/success/simple/*.dhall
-    dhall-lang/tests/type-inference/success/simple/access/*.dhall
-    dhall-lang/tests/type-inference/success/unit/*.dhall
-    tests/diff/*.dhall
-    tests/diff/*.txt
-    tests/format/*.dhall
-    tests/freeze/*.dhall
-    tests/lint/success/*.dhall
-    tests/recursive/*.dhall
-    tests/regression/*.dhall
-    tests/schemas/*.dhall
-    tests/tags/*.dhall
-    tests/tags/*.tags
-    tests/th/*.dhall
-    tests/tutorial/*.dhall
+    tests/**/*.dhall
+    tests/**/*.tags
+    tests/**/*.txt
 
 Source-Repository head
     Type: git
@@ -469,8 +196,7 @@
   Default:     False
   Manual:      True
 
-Library
-    Hs-Source-Dirs: src
+Common common
     Build-Depends:
         base                        >= 4.11.0.0 && < 5   ,
         aeson                       >= 1.0.0.0  && < 2.1 ,
@@ -501,7 +227,7 @@
         mmorph                                     < 1.3 ,
         mtl                         >= 2.2.1    && < 2.3 ,
         network-uri                 >= 2.6      && < 2.7 ,
-        optparse-applicative        >= 0.14.0.0 && < 0.17,
+        optparse-applicative        >= 0.14.0.0 && < 0.18,
         parsers                     >= 0.12.4   && < 0.13,
         parser-combinators                               ,
         prettyprinter               >= 1.7.0    && < 1.8 ,
@@ -512,7 +238,7 @@
         serialise                   >= 0.2.0.0  && < 0.3 ,
         scientific                  >= 0.3.0.0  && < 0.4 ,
         template-haskell            >= 2.13.0.0 && < 2.19,
-        text                        >= 0.11.1.0 && < 1.3 ,
+        text                        >= 0.11.1.0 && < 2.1 ,
         text-manipulate             >= 0.2.0.1  && < 0.4 ,
         th-lift-instances           >= 0.1.13   && < 0.2 ,
         time                        >= 1.1.4    && < 1.13,
@@ -520,12 +246,19 @@
         unordered-containers        >= 0.1.3.0  && < 0.3 ,
         uri-encode                                 < 1.6 ,
         vector                      >= 0.11.0.0 && < 0.13
+
     if flag(with-http)
       CPP-Options:
         -DWITH_HTTP
       if flag(use-http-client-tls)
         CPP-Options:
           -DUSE_HTTP_CLIENT_TLS
+
+    GHC-Options: -Wall -Wcompat -Wincomplete-uni-patterns
+
+Library
+    Import: common
+    Hs-Source-Dirs: src
     if impl(ghcjs)
       Hs-Source-Dirs: ghcjs-src
       Build-Depends:
@@ -626,21 +359,21 @@
         Dhall.Import.HTTP
         Dhall.Import.Manager
 
-    GHC-Options: -Wall -fwarn-incomplete-uni-patterns
     Default-Language: Haskell2010
 
 Executable dhall
+    Import: common
     Hs-Source-Dirs: dhall
     Main-Is: Main.hs
-    Build-Depends: base, dhall
-    GHC-Options: -Wall -rtsopts
+    Build-Depends: dhall
+    GHC-Options: -rtsopts
     Default-Language: Haskell2010
 
 Test-Suite tasty
+    Import: common
     Type: exitcode-stdio-1.0
     Hs-Source-Dirs: tests
     Main-Is: Dhall/Test/Main.hs
-    GHC-Options: -Wall
     Other-Modules:
         Dhall.Test.Dhall
         Dhall.Test.Diff
@@ -661,27 +394,13 @@
         Dhall.Test.TypeInference
         Dhall.Test.Util
     Build-Depends:
-        base                      >= 4        && < 5   ,
-        bytestring                                     ,
-        cborg                     >= 0.2.0.0  && < 0.3 ,
-        containers                                     ,
-        data-fix                                       ,
-        deepseq                   >= 1.2.0.1  && < 1.5 ,
         dhall                                          ,
-        directory                                      ,
-        either                                         ,
-        filepath                                       ,
         foldl                                    < 1.5 ,
         generic-random            >= 1.3.0.0  && < 1.6 ,
         http-client                                    ,
         http-client-tls                                ,
-        lens-family-core                               ,
-        megaparsec                                     ,
-        prettyprinter                                  ,
         QuickCheck                >= 2.14     && < 2.15,
         quickcheck-instances      >= 0.3.12   && < 0.4 ,
-        scientific                                     ,
-        serialise                                      ,
         special-values                           < 0.2 ,
         spoon                                    < 0.4 ,
         system-filepath                                ,
@@ -690,28 +409,16 @@
         tasty-hunit               >= 0.10     && < 0.11,
         tasty-quickcheck          >= 0.9.2    && < 0.11,
         tasty-silver                             < 3.4 ,
-        template-haskell                               ,
         temporary                 >= 1.2.1    && < 1.4 ,
-        text                      >= 0.11.1.0 && < 1.3 ,
-        time                                           ,
-        transformers                                   ,
         turtle                                   < 1.6 ,
-        unordered-containers                           ,
-        vector                    >= 0.11.0.0 && < 0.13
-    if flag(with-http)
-      CPP-Options:
-        -DWITH_HTTP
     Default-Language: Haskell2010
 
 Test-Suite doctest
+    Import: common
     Type: exitcode-stdio-1.0
     Hs-Source-Dirs: doctest
     Main-Is: Main.hs
-    GHC-Options: -Wall
     Build-Depends:
-        base                          ,
-        directory                     ,
-        filepath                < 1.5 ,
         mockery                 < 0.4 ,
         doctest   >= 0.7.0
     if os(windows)
@@ -720,30 +427,24 @@
     Default-Language: Haskell2010
 
 Benchmark dhall-parser
+    Import: common
     Type: exitcode-stdio-1.0
     Hs-Source-Dirs: benchmark/parser
     Main-Is: Main.hs
     Build-Depends:
-        base                      >= 4        && < 5  ,
-        bytestring                                    ,
-        containers                >= 0.5.0.0  && < 0.7,
         dhall                                         ,
-        directory                                     ,
         gauge                     >= 0.2.3    && < 0.3,
-        text                      >= 0.11.1.0 && < 1.3
     Default-Language: Haskell2010
     Other-Extensions:
         TypeApplications
-    ghc-options: -rtsopts -Wall
+    Ghc-Options: -rtsopts
 
 Benchmark deep-nested-large-record
+    Import: common
     Type: exitcode-stdio-1.0
     Hs-Source-Dirs: benchmark/deep-nested-large-record
     Main-Is: Main.hs
     Build-Depends:
-        base                      >= 4        && < 5  ,
-        containers                >= 0.5.0.0  && < 0.7,
         dhall                                         ,
         gauge                     >= 0.2.3    && < 0.3
     Default-Language: Haskell2010
-    ghc-options: -Wall
diff --git a/src/Dhall.hs b/src/Dhall.hs
--- a/src/Dhall.hs
+++ b/src/Dhall.hs
@@ -1,23 +1,15 @@
 {-# LANGUAGE ApplicativeDo              #-}
 {-# LANGUAGE ConstraintKinds            #-}
-{-# LANGUAGE DefaultSignatures          #-}
-{-# LANGUAGE DeriveFunctor              #-}
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses      #-}
-{-# LANGUAGE MultiWayIf                 #-}
 {-# LANGUAGE OverloadedStrings          #-}
 {-# LANGUAGE PolyKinds                  #-}
 {-# LANGUAGE RankNTypes                 #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE ScopedTypeVariables        #-}
-{-# LANGUAGE TupleSections              #-}
-{-# LANGUAGE TypeApplications           #-}
 {-# LANGUAGE TypeFamilies               #-}
-{-# LANGUAGE TypeOperators              #-}
 {-# LANGUAGE UndecidableInstances       #-}
-{-# LANGUAGE ViewPatterns               #-}
 
 {-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining
     how to use the language, the compiler, and this library
diff --git a/src/Dhall/Binary.hs b/src/Dhall/Binary.hs
--- a/src/Dhall/Binary.hs
+++ b/src/Dhall/Binary.hs
@@ -47,6 +47,7 @@
     , Scheme (..)
     , URL (..)
     , Var (..)
+    , WithComponent (..)
     )
 
 import Data.Foldable (toList)
@@ -559,8 +560,19 @@
 
                                 n <- Decoding.decodeListLen
 
-                                ks₀ <- replicateDecoder n Decoding.decodeString
+                                let decodeWithComponent = do
+                                        tokenType₂ <- Decoding.peekTokenType
+                                        case tokenType₂ of
+                                            TypeString -> do
+                                                fmap WithLabel Decoding.decodeString
+                                            _ -> do
+                                                m <- Decoding.decodeInt
 
+                                                case m of
+                                                    0 -> return WithQuestion
+                                                    _ -> die ("Unexpected integer encoding a with expression: " <> show n)
+                                ks₀ <- replicateDecoder n decodeWithComponent
+
                                 ks₁ <- case NonEmpty.nonEmpty ks₀ of
                                     Nothing ->
                                         die "0 field labels in decoded with expression"
@@ -638,6 +650,9 @@
                                 let minutes = sign (_HH * 60 + _MM)
 
                                 return (TimeZoneLiteral (Time.TimeZone minutes False ""))
+                            34 -> do
+                                t <- go
+                                return (ShowConstructor t)
                             _ ->
                                 die ("Unexpected tag: " <> show tag)
 
@@ -1014,8 +1029,11 @@
             encodeList4
                 (Encoding.encodeInt 29)
                 (go l)
-                (encodeList (fmap Encoding.encodeString ks))
+                (encodeList (fmap encodeWithComponent ks))
                 (go r)
+          where
+            encodeWithComponent  WithQuestion  = Encoding.encodeInt 0
+            encodeWithComponent (WithLabel k ) = Encoding.encodeString k
 
         DateLiteral day ->
             encodeList4
@@ -1059,6 +1077,11 @@
             sign = 0 <= minutes
 
             (_HH, _MM) = abs minutes `divMod` 60
+
+        ShowConstructor t ->
+            encodeList2
+                (Encoding.encodeInt 34)
+                (go t)
 
         Note _ b ->
             go b
diff --git a/src/Dhall/Core.hs b/src/Dhall/Core.hs
--- a/src/Dhall/Core.hs
+++ b/src/Dhall/Core.hs
@@ -31,6 +31,7 @@
     , makeFunctionBinding
     , FieldSelection (..)
     , makeFieldSelection
+    , WithComponent (..)
     , Expr(..)
 
     -- * Normalization
@@ -76,7 +77,6 @@
     , Eval.textShow
     , censorExpression
     , censorText
-    , Syntax.desugarWith
     ) where
 
 import Control.Exception      (Exception)
@@ -92,8 +92,7 @@
 
 import qualified Control.Exception
 import qualified Data.Text
-import qualified Dhall.Eval        as Eval
-import qualified Dhall.Syntax      as Syntax
+import qualified Dhall.Eval         as Eval
 
 -- | Pretty-print a value
 pretty :: Pretty a => a -> Text
diff --git a/src/Dhall/Deriving.hs b/src/Dhall/Deriving.hs
--- a/src/Dhall/Deriving.hs
+++ b/src/Dhall/Deriving.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE AllowAmbiguousTypes  #-}
 {-# LANGUAGE DataKinds            #-}
 {-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE KindSignatures       #-}
 {-# LANGUAGE PolyKinds            #-}
 {-# LANGUAGE ScopedTypeVariables  #-}
 {-# LANGUAGE TypeApplications     #-}
diff --git a/src/Dhall/Diff.hs b/src/Dhall/Diff.hs
--- a/src/Dhall/Diff.hs
+++ b/src/Dhall/Diff.hs
@@ -35,6 +35,7 @@
     , FunctionBinding (..)
     , RecordField (..)
     , Var (..)
+    , WithComponent (..)
     )
 import Numeric.Natural       (Natural)
 import Prettyprinter         (Doc, Pretty)
@@ -636,6 +637,10 @@
         keyword "toMap"
     <>  " "
     <>  ignore
+skeleton (ShowConstructor {}) =
+        keyword "showConstructor"
+    <>  " "
+    <>  ignore
 skeleton (Field {}) =
         ignore
     <>  dot
@@ -783,6 +788,15 @@
     mismatch l r
 diffAnnotatedExpression l r@(ToMap {}) =
     mismatch l r
+diffAnnotatedExpression (ShowConstructor aL) (ShowConstructor aR) = align doc
+  where
+    doc =   keyword "showConstructor"
+        <>  " "
+        <>  format " " (diffWithExpression aL aR)
+diffAnnotatedExpression l@(ShowConstructor {}) r =
+    mismatch l r
+diffAnnotatedExpression l r@(ShowConstructor {}) =
+    mismatch l r
 diffAnnotatedExpression (ListLit aL@(Just _) bL) (ListLit aR bR) = align doc
   where
     doc =   format " " (diffList bL bR)
@@ -1054,12 +1068,15 @@
         (   format " " (diffImportExpression eL eR)
         <>  "with "
         <>  align
-            (   format " " (diffPath ksL ksR)
+            (   format " " (diffPath (fmap toText ksL) (fmap toText ksR))
             <>  "= "
             <>  diffOperatorExpression vL vR
             )
         )
   where
+    toText  WithQuestion  = "?"
+    toText (WithLabel k ) = k
+
     diffPath (kL :| []) (kR :| []) =
         diffLabel kL kR
     diffPath (kL₀ :| kL₁ : ksL') (kR₀ :| kR₁ : ksR') =
diff --git a/src/Dhall/Eval.hs b/src/Dhall/Eval.hs
--- a/src/Dhall/Eval.hs
+++ b/src/Dhall/Eval.hs
@@ -10,8 +10,6 @@
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE ViewPatterns         #-}
 
-{-# OPTIONS_GHC -O #-}
-
 {-| Eval-apply environment machine with conversion checking and quoting to
     normal forms. Fairly similar to GHCI's STG machine algorithmically, but much
     simpler, with no known call optimization or environment trimming.
@@ -71,6 +69,7 @@
     , PreferAnnotation (..)
     , RecordField (..)
     , Var (..)
+    , WithComponent (..)
     )
 
 import qualified Data.Char
@@ -230,12 +229,13 @@
     | VPrefer !(Val a) !(Val a)
     | VMerge !(Val a) !(Val a) !(Maybe (Val a))
     | VToMap !(Val a) !(Maybe (Val a))
+    | VShowConstructor !(Val a)
     | VField !(Val a) !Text
     | VInject !(Map Text (Maybe (Val a))) !Text !(Maybe (Val a))
     | VProject !(Val a) !(Either (Set Text) (Val a))
     | VAssert !(Val a)
     | VEquivalent !(Val a) !(Val a)
-    | VWith !(Val a) (NonEmpty Text) !(Val a)
+    | VWith !(Val a) (NonEmpty WithComponent) !(Val a)
     | VEmbed a
 
 -- | For use with "Text.Show.Functions".
@@ -418,9 +418,9 @@
             t' ->
                 VProject t' (Left ks)
 
-vWith :: Val a -> NonEmpty Text -> Val a -> Val a
-vWith (VRecordLit kvs) (k  :| []     ) v = VRecordLit (Map.insert k  v  kvs)
-vWith (VRecordLit kvs) (k₀ :| k₁ : ks) v = VRecordLit (Map.insert k₀ e₂ kvs)
+vWith :: Val a -> NonEmpty WithComponent -> Val a -> Val a
+vWith (VRecordLit kvs) (WithLabel k  :| []     ) v = VRecordLit (Map.insert k  v  kvs)
+vWith (VRecordLit kvs) (WithLabel k₀ :| k₁ : ks) v = VRecordLit (Map.insert k₀ e₂ kvs)
   where
     e₁ =
         case Map.lookup k₀ kvs of
@@ -428,6 +428,9 @@
             Just e₁' -> e₁'
 
     e₂ = vWith e₁ (k₁ :| ks) v
+vWith (VNone _T) (WithQuestion :| _      ) _ = VNone _T
+vWith (VSome  _) (WithQuestion :| []     ) v = VSome v
+vWith (VSome  t) (WithQuestion :| k₁ : ks) v = VSome (vWith t (k₁ :| ks) v)
 vWith e₀ ks v₀ = VWith e₀ ks v₀
 
 eval :: forall a. Eq a => Environment a -> Expr Void a -> Val a
@@ -809,6 +812,14 @@
                     in  VListLit Nothing s
                 (x', ma') ->
                     VToMap x' ma'
+        ShowConstructor x ->
+            case eval env x of
+                VInject m k _
+                    | Just _ <- Map.lookup k m -> VTextLit (VChunks [] k)
+                    | otherwise                -> error errorMsg
+                VSome _ -> VTextLit (VChunks [] "Some")
+                VNone _ -> VTextLit (VChunks [] "None")
+                x' -> VShowConstructor x'
         Field t (Syntax.fieldSelectionLabel -> k) ->
             vField (eval env t) k
         Project t (Left ks) ->
@@ -1035,6 +1046,8 @@
             conv env t t' && conv env u u'
         (VToMap t _, VToMap t' _) ->
             conv env t t'
+        (VShowConstructor t, VShowConstructor t') ->
+            conv env t t'
         (VField t k, VField t' k') ->
             conv env t t' && k == k'
         (VProject t (Left ks), VProject t' (Left ks')) ->
@@ -1245,6 +1258,8 @@
             Merge (quote env t) (quote env u) (fmap (quote env) ma)
         VToMap t ma ->
             ToMap (quote env t) (fmap (quote env) ma)
+        VShowConstructor t ->
+            ShowConstructor (quote env t)
         VField t k ->
             Field (quote env t) $ Syntax.makeFieldSelection k
         VProject t p ->
@@ -1444,6 +1459,8 @@
                 Merge (go x) (go y) (fmap go ma)
             ToMap x ma ->
                 ToMap (go x) (fmap go ma)
+            ShowConstructor x ->
+                ShowConstructor (go x)
             Field t k ->
                 Field (go t) k
             Project t ks ->
diff --git a/src/Dhall/Format.hs b/src/Dhall/Format.hs
--- a/src/Dhall/Format.hs
+++ b/src/Dhall/Format.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE LambdaCase        #-}
-{-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards   #-}
 
diff --git a/src/Dhall/Freeze.hs b/src/Dhall/Freeze.hs
--- a/src/Dhall/Freeze.hs
+++ b/src/Dhall/Freeze.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards   #-}
 {-# LANGUAGE ViewPatterns      #-}
@@ -253,6 +252,12 @@
     -> IO (Expr s Import)
 freezeExpression = freezeExpressionWithManager Dhall.Import.defaultNewManager
 
+-- https://github.com/dhall-lang/dhall-haskell/issues/2347
+toMissing :: Import -> Import
+toMissing import_ =
+    import_ { importHashed = (importHashed import_) { importType = Missing } }
+
+
 -- | See 'freezeExpression'.
 freezeExpressionWithManager
     :: IO Dhall.Import.Manager
@@ -315,17 +320,21 @@
             (Embed import_@(Import { importHashed = ImportHashed { hash = Nothing } })) = do
                 frozenImport <- freezeFunction import_
 
+                let frozenMissing = toMissing frozenImport
+
                 {- The two imports can be the same if the import is local and
                    `freezeFunction` only freezes remote imports by default
                 -}
                 if frozenImport /= import_
-                    then return (ImportAlt (Embed frozenImport) (Embed import_))
+                    then return (ImportAlt (Embed frozenMissing) (Embed import_))
                     else return (Embed import_)
         cache
             (Embed import_@(Import { importHashed = ImportHashed { hash = Just _ } })) = do
                 -- Regenerate the integrity check, just in case it's wrong
                 frozenImport <- freezeFunction import_
 
+                let frozenMissing = toMissing frozenImport
+
                 -- `dhall freeze --cache` also works the other way around, adding an
                 -- unprotected fallback import to imports that are already
                 -- protected
@@ -335,7 +344,7 @@
                             }
                         }
 
-                return (ImportAlt (Embed frozenImport) (Embed thawedImport))
+                return (ImportAlt (Embed frozenMissing) (Embed thawedImport))
         cache expression_ =
             return expression_
 
diff --git a/src/Dhall/Import.hs b/src/Dhall/Import.hs
--- a/src/Dhall/Import.hs
+++ b/src/Dhall/Import.hs
@@ -9,7 +9,6 @@
 {-# LANGUAGE RecordWildCards     #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
-{-# LANGUAGE ViewPatterns        #-}
 
 {-# OPTIONS_GHC -Wall #-}
 
diff --git a/src/Dhall/Import/Types.hs b/src/Dhall/Import/Types.hs
--- a/src/Dhall/Import/Types.hs
+++ b/src/Dhall/Import/Types.hs
@@ -50,7 +50,7 @@
     pretty (Chained import_) = pretty import_
 
 -- | An import that has been fully interpeted
-data ImportSemantics = ImportSemantics
+newtype ImportSemantics = ImportSemantics
     { importSemantics :: Expr Void Void
     -- ^ The fully resolved import, typechecked and beta-normal.
     }
diff --git a/src/Dhall/Main.hs b/src/Dhall/Main.hs
--- a/src/Dhall/Main.hs
+++ b/src/Dhall/Main.hs
@@ -361,7 +361,7 @@
       where
         -- Parse explicit stdin in the input filepaths
         parseStdin inputs
-            | any (== InputFile "-") inputs = StandardInput : filter (/= InputFile "-") inputs
+            | InputFile "-" `elem` inputs = StandardInput : filter (/= InputFile "-") inputs
             | otherwise = inputs
 
         f = fromMaybe (pure StandardInput) . nonEmpty . parseStdin . fmap InputFile
diff --git a/src/Dhall/Marshal/Decode.hs b/src/Dhall/Marshal/Decode.hs
--- a/src/Dhall/Marshal/Decode.hs
+++ b/src/Dhall/Marshal/Decode.hs
@@ -7,14 +7,12 @@
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses      #-}
-{-# LANGUAGE MultiWayIf                 #-}
 {-# LANGUAGE OverloadedStrings          #-}
 {-# LANGUAGE PolyKinds                  #-}
 {-# LANGUAGE RankNTypes                 #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE ScopedTypeVariables        #-}
 {-# LANGUAGE StandaloneDeriving         #-}
-{-# LANGUAGE TupleSections              #-}
 {-# LANGUAGE TypeApplications           #-}
 {-# LANGUAGE TypeFamilies               #-}
 {-# LANGUAGE TypeOperators              #-}
@@ -146,7 +144,6 @@
     , Predicate (..)
     )
 import Data.Hashable                    (Hashable)
-import Data.Int                         (Int16, Int32, Int64, Int8)
 import Data.List.NonEmpty               (NonEmpty (..))
 import Data.Typeable                    (Proxy (..), Typeable)
 import Dhall.Parser                     (Src (..))
diff --git a/src/Dhall/Marshal/Encode.hs b/src/Dhall/Marshal/Encode.hs
--- a/src/Dhall/Marshal/Encode.hs
+++ b/src/Dhall/Marshal/Encode.hs
@@ -206,6 +206,34 @@
 
         declared = Integer
 
+instance ToDhall Int8 where
+    injectWith _ = Encoder {..}
+      where
+        embed = IntegerLit . toInteger
+
+        declared = Integer
+
+instance ToDhall Int16 where
+    injectWith _ = Encoder {..}
+      where
+        embed = IntegerLit . toInteger
+
+        declared = Integer
+
+instance ToDhall Int32 where
+    injectWith _ = Encoder {..}
+      where
+        embed = IntegerLit . toInteger
+
+        declared = Integer
+
+instance ToDhall Int64 where
+    injectWith _ = Encoder {..}
+      where
+        embed = IntegerLit . toInteger
+
+        declared = Integer
+
 {-| Encode a 'Word' to a Dhall @Natural@.
 
 >>> embed inject (12 :: Word)
diff --git a/src/Dhall/Marshal/Internal.hs b/src/Dhall/Marshal/Internal.hs
--- a/src/Dhall/Marshal/Internal.hs
+++ b/src/Dhall/Marshal/Internal.hs
@@ -27,6 +27,10 @@
     -- * Re-exports
     , Fix(..)
     , HashMap
+    , Int8
+    , Int16
+    , Int32
+    , Int64
     , Map
     , Natural
     , Scientific
@@ -44,6 +48,7 @@
 import Control.Monad.Trans.State.Strict
 import Data.Fix                         (Fix (..))
 import Data.HashMap.Strict              (HashMap)
+import Data.Int                         (Int16, Int32, Int64, Int8)
 import Data.Map                         (Map)
 import Data.Scientific                  (Scientific)
 import Data.Sequence                    (Seq)
diff --git a/src/Dhall/Normalize.hs b/src/Dhall/Normalize.hs
--- a/src/Dhall/Normalize.hs
+++ b/src/Dhall/Normalize.hs
@@ -38,6 +38,7 @@
     , FunctionBinding (..)
     , PreferAnnotation (..)
     , RecordField (..)
+    , WithComponent (..)
     , Var (..)
     )
 
@@ -623,6 +624,18 @@
                 return (ListLit listType keyValues)
             _ ->
                 return (ToMap x' t')
+    ShowConstructor x -> do
+        x' <- loop x
+        return $ case x' of
+            Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY) ->
+                case Dhall.Map.lookup kY ktsY of
+                    Just _ -> TextLit (Chunks [] kY)
+                    _ -> ShowConstructor x'
+            Some _ ->
+                TextLit (Chunks [] "Some")
+            App None _ ->
+                TextLit (Chunks [] "None")
+            _ -> ShowConstructor x'
     Field r k@FieldSelection{fieldSelectionLabel = x}        -> do
         let singletonRecordLit v = RecordLit (Dhall.Map.singleton x v)
 
@@ -686,9 +699,9 @@
         case e' of
             RecordLit kvs ->
                 case ks of
-                    k :| [] ->
+                    WithLabel k :| [] ->
                         return (RecordLit (Dhall.Map.insert k (Syntax.makeRecordField v') kvs))
-                    k₀ :| k₁ : ks' -> do
+                    WithLabel k₀ :| k₁ : ks' -> do
                         let e₁ =
                                 case Dhall.Map.lookup k₀ kvs of
                                     Nothing -> RecordLit mempty
@@ -697,6 +710,23 @@
                         e₂ <- loop (With e₁ (k₁ :| ks') v')
 
                         return (RecordLit (Dhall.Map.insert k₀ (Syntax.makeRecordField e₂) kvs))
+                    WithQuestion :| _ -> do
+                        return (With e' ks v')
+            Some t ->
+                case ks of
+                    WithQuestion :| [] -> do
+                        return (Some v')
+                    WithQuestion :| k : ks' -> do
+                        w <- loop (With t (k :| ks') v)
+                        return (Some w)
+                    WithLabel _ :| _ ->
+                        return (With e' ks v')
+            App None _T ->
+                case ks of
+                    WithQuestion :| _ ->
+                        return (App None _T)
+                    WithLabel _ :| _ ->
+                        return (With e' ks v')
             _ ->
                 return (With e' ks v')
     Note _ e' -> loop e'
@@ -909,6 +939,11 @@
       ToMap x t -> case x of
           RecordLit _ -> False
           _ -> loop x && all loop t
+      ShowConstructor x -> loop x && case x of
+          Field (Union _) _ -> False
+          Some _ -> False
+          App None _ -> False
+          _ -> True
       Field r (FieldSelection Nothing k Nothing) -> case r of
           RecordLit _ -> False
           Project _ _ -> False
diff --git a/src/Dhall/Parser.hs b/src/Dhall/Parser.hs
--- a/src/Dhall/Parser.hs
+++ b/src/Dhall/Parser.hs
@@ -21,12 +21,13 @@
     , Parser(..)
     ) where
 
-import Control.Exception (Exception)
-import Data.Text         (Text)
-import Data.Void         (Void)
-import Dhall.Src         (Src (..))
+import Control.Applicative (many)
+import Control.Exception   (Exception)
+import Data.Text           (Text)
+import Data.Void           (Void)
+import Dhall.Src           (Src (..))
 import Dhall.Syntax
-import Text.Megaparsec   (ParseErrorBundle (..), PosState (..))
+import Text.Megaparsec     (ParseErrorBundle (..), PosState (..))
 
 import qualified Data.Text       as Text
 import qualified Dhall.Core      as Core
@@ -123,7 +124,7 @@
     Right (txt, r) -> Right (createHeader txt, r)
   where
     parser = do
-        (bytes, _) <- Text.Megaparsec.match whitespace
+        (bytes, _) <- Text.Megaparsec.match (many shebang *> whitespace)
         r <- expr
         Text.Megaparsec.eof
         return (bytes, r)
diff --git a/src/Dhall/Parser/Expression.hs b/src/Dhall/Parser/Expression.hs
--- a/src/Dhall/Parser/Expression.hs
+++ b/src/Dhall/Parser/Expression.hs
@@ -234,26 +234,29 @@
     <|> try partialTime
     <|> try timeNumOffset
 
+-- | Parse a \"shebang\" line (i.e. an initial line beginning with @#!@)
+shebang :: Parser ()
+shebang = do
+    _ <- text "#!"
+
+    let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'
+
+    _ <- Dhall.Parser.Combinators.takeWhile predicate
+
+    _ <- endOfLine
+
+    return ()
+
 -- | Given a parser for imports,
 parsers :: forall a. Parser a -> Parsers a
 parsers embedded = Parsers{..}
   where
     completeExpression_ =
-            many shebang
-        *>  whitespace
+            whitespace
         *>  expression
         <*  whitespace
         <*  optional lineCommentPrefix
 
-    shebang = do
-        _ <- text "#!"
-
-        let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'
-
-        _ <- Dhall.Parser.Combinators.takeWhile predicate
-
-        endOfLine
-
     letBinding = do
         src0 <- try (_let *> src nonemptyWhitespace)
 
@@ -385,8 +388,12 @@
                     bs <- some (do
                         try (nonemptyWhitespace *> _with *> nonemptyWhitespace)
 
-                        keys <- Combinators.NonEmpty.sepBy1 anyLabel (try (whitespace *> _dot) *> whitespace)
+                        let withComponent =
+                                    fmap WithLabel anyLabelOrSome
+                                <|> fmap (\_ -> WithQuestion) (text "?")
 
+                        keys <- Combinators.NonEmpty.sepBy1 withComponent (try (whitespace *> _dot) *> whitespace)
+
                         whitespace
 
                         _equal
@@ -517,10 +524,15 @@
 
                     return (\a -> ToMap a Nothing, Just "argument to ❰toMap❱")
 
-            let alternative3 =
+            let alternative3 = do
+                    try (_showConstructor *> nonemptyWhitespace)
+
+                    return (\a -> ShowConstructor a, Just "argument to ❰showConstructor❱")
+
+            let alternative4 =
                     return (id, Nothing)
 
-            (f, maybeMessage) <- alternative0 <|> alternative1 <|> alternative2 <|> alternative3
+            (f, maybeMessage) <- alternative0 <|> alternative1 <|> alternative2 <|> alternative3 <|> alternative4
 
             let adapt parser =
                     case maybeMessage of
diff --git a/src/Dhall/Parser/Token.hs b/src/Dhall/Parser/Token.hs
--- a/src/Dhall/Parser/Token.hs
+++ b/src/Dhall/Parser/Token.hs
@@ -47,6 +47,7 @@
     _using,
     _merge,
     _toMap,
+    _showConstructor,
     _assert,
     _Some,
     _None,
@@ -951,6 +952,13 @@
 -}
 _toMap :: Parser ()
 _toMap = keyword "toMap"
+
+{-| Parse the @showConstructor@ keyword
+
+    This corresponds to the @showConstructor@ rule from the official grammar
+-}
+_showConstructor :: Parser ()
+_showConstructor = keyword "showConstructor"
 
 {-| Parse the @assert@ keyword
 
diff --git a/src/Dhall/Pretty/Internal.hs b/src/Dhall/Pretty/Internal.hs
--- a/src/Dhall/Pretty/Internal.hs
+++ b/src/Dhall/Pretty/Internal.hs
@@ -513,7 +513,7 @@
 escapeLabel allowReserved l =
     case Text.uncons l of
         Just (h, t)
-            | headCharacter h && Text.all tailCharacter t && (notReservedIdentifier || (allowReserved && someOrNotLanguageKeyword))
+            | headCharacter h && Text.all tailCharacter t && (notReservedIdentifier || (allowReserved && someOrNotLanguageKeyword)) && l /= "?"
                 -> l
         _       -> "`" <> l <> "`"
     where
@@ -829,7 +829,11 @@
             <>  Pretty.align (keyword "with" <> " " <> update)
 
         (update, _) =
-            prettyKeyValue prettyOperatorExpression equals (makeKeyValue b c)
+            prettyKeyValue prettyOperatorExpression equals
+                (makeKeyValue (fmap toText b) c)
+
+        toText  WithQuestion  = "?"
+        toText (WithLabel k ) = k
     prettyExpression (Assert a) =
         Pretty.group (Pretty.flatAlt long short)
       where
@@ -1199,6 +1203,7 @@
             Some a            -> app (builtin "Some") (a : args)
             Merge a b Nothing -> app (keyword "merge") (a : b : args)
             ToMap a Nothing   -> app (keyword "toMap") (a : args)
+            ShowConstructor a -> app (keyword "showConstructor") (a : args)
             e | Note _ b <- e ->
                   go args b
               | null args ->
@@ -1354,7 +1359,7 @@
       where
         sign = if 0 <= minutes then "+" else "-"
 
-        (_HH, _MM) = minutes `divMod` 60
+        (_HH, _MM) = abs minutes `divMod` 60
     prettyPrimitiveExpression List =
         builtin "List"
     prettyPrimitiveExpression ListBuild =
@@ -1480,7 +1485,19 @@
                                 <>  keyword "toMap"
                                 <>  case shallowDenote val' of
                                         RecordCompletion _T r ->
-                                            completion _T r
+                                                " "
+                                            <>  completion _T r
+                                        _ ->    Pretty.hardline
+                                            <>  "    "
+                                            <>  prettyImportExpression_ val'
+
+                            ShowConstructor val' ->
+                                    " "
+                                <>  keyword "showConstructor"
+                                <>  case shallowDenote val' of
+                                        RecordCompletion _T r ->
+                                                " "
+                                            <>  completion _T r
                                         _ ->    Pretty.hardline
                                             <>  "    "
                                             <>  prettyImportExpression_ val'
diff --git a/src/Dhall/Schemas.hs b/src/Dhall/Schemas.hs
--- a/src/Dhall/Schemas.hs
+++ b/src/Dhall/Schemas.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE DeriveAnyClass    #-}
-{-# LANGUAGE OverloadedLists   #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards   #-}
 
diff --git a/src/Dhall/Syntax.hs b/src/Dhall/Syntax.hs
--- a/src/Dhall/Syntax.hs
+++ b/src/Dhall/Syntax.hs
@@ -4,7 +4,6 @@
 {-# LANGUAGE DeriveLift                 #-}
 {-# LANGUAGE DeriveTraversable          #-}
 {-# LANGUAGE DerivingStrategies         #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE LambdaCase                 #-}
 {-# LANGUAGE OverloadedLists            #-}
 {-# LANGUAGE OverloadedStrings          #-}
@@ -38,6 +37,7 @@
     , makeFunctionBinding
     , FieldSelection(..)
     , makeFieldSelection
+    , WithComponent(..)
 
     -- ** 'Let'-blocks
     , MultiLet(..)
@@ -80,9 +80,6 @@
     , linesLiteral
     , unlinesLiteral
 
-    -- * Desugaring
-    , desugarWith
-
     -- * Utilities
     , internalError
     -- `shift` should really be in `Dhall.Normalize`, but it's here to avoid a
@@ -119,7 +116,6 @@
 import qualified Data.Text
 import qualified Data.Time          as Time
 import qualified Dhall.Crypto
-import qualified Dhall.Optics       as Optics
 import qualified Lens.Family        as Lens
 import qualified Network.URI        as URI
 import qualified Prettyprinter      as Pretty
@@ -430,6 +426,10 @@
 makeFieldSelection :: Text -> FieldSelection s
 makeFieldSelection t = FieldSelection Nothing t Nothing
 
+-- | A path component for a @with@ expression
+data WithComponent = WithLabel Text | WithQuestion
+    deriving (Data, Eq, Generic, Lift, NFData, Ord, Show)
+
 {-| Syntax tree for expressions
 
     The @s@ type parameter is used to track the presence or absence of `Src`
@@ -633,6 +633,8 @@
     -- | > ToMap x (Just t)                         ~  toMap x : t
     --   > ToMap x  Nothing                         ~  toMap x
     | ToMap (Expr s a) (Maybe (Expr s a))
+    -- | > ShowConstructor x                        ~  showConstructor x
+    | ShowConstructor (Expr s a)
     -- | > Field e (FieldSelection _ x _)              ~  e.x
     | Field (Expr s a) (FieldSelection s)
     -- | > Project e (Left xs)                      ~  e.{ xs }
@@ -643,7 +645,7 @@
     -- | > Equivalent _ x y                           ~  x ≡ y
     | Equivalent (Maybe CharacterSet) (Expr s a) (Expr s a)
     -- | > With x y e                               ~  x with y = e
-    | With (Expr s a) (NonEmpty Text) (Expr s a)
+    | With (Expr s a) (NonEmpty WithComponent) (Expr s a)
     -- | > Note s x                                 ~  e
     | Note s (Expr s a)
     -- | > ImportAlt                                ~  e1 ? e2
@@ -880,6 +882,7 @@
 unsafeSubExpressions f (RecordCompletion a b) = RecordCompletion <$> f a <*> f b
 unsafeSubExpressions f (Merge a b t) = Merge <$> f a <*> f b <*> traverse f t
 unsafeSubExpressions f (ToMap a t) = ToMap <$> f a <*> traverse f t
+unsafeSubExpressions f (ShowConstructor a) = ShowConstructor <$> f a
 unsafeSubExpressions f (Project a b) = Project <$> f a <*> traverse f b
 unsafeSubExpressions f (Assert a) = Assert <$> f a
 unsafeSubExpressions f (Equivalent cs a b) = Equivalent cs <$> f a <*> f b
@@ -1461,30 +1464,6 @@
     mt' = fmap (fmap (shift d (V x n))) mt
     r'  =             shift d (V x n)  r
 shift d v expression = Lens.over subExpressions (shift d v) expression
-
--- | Desugar all @with@ expressions
-desugarWith :: Expr s a -> Expr s a
-desugarWith = Optics.rewriteOf subExpressions rewrite
-  where
-    rewrite e@(With record (key :| []) value) =
-        Just
-            (Prefer
-                mempty
-                (PreferFromWith e)
-                record
-                (RecordLit [ (key, makeRecordField value) ])
-            )
-    rewrite e@(With record (key0 :| key1 : keys) value) =
-        Just
-            (Let
-                (makeBinding "_" record)
-                (Prefer mempty (PreferFromWith e) "_"
-                    (RecordLit
-                        [ (key0, makeRecordField $ With (Field "_" (FieldSelection Nothing key0 Nothing)) (key1 :| keys) (shift 1 "_" value)) ]
-                    )
-                )
-            )
-    rewrite _ = Nothing
 
 _ERROR :: String
 _ERROR = "\ESC[1;31mError\ESC[0m"
diff --git a/src/Dhall/TypeCheck.hs b/src/Dhall/TypeCheck.hs
--- a/src/Dhall/TypeCheck.hs
+++ b/src/Dhall/TypeCheck.hs
@@ -61,6 +61,7 @@
     , PreferAnnotation (..)
     , RecordField (..)
     , Var (..)
+    , WithComponent (..)
     )
 
 import qualified Data.Foldable               as Foldable
@@ -1130,6 +1131,14 @@
 
                        die (MapTypeMismatch (quote names (mapType _T')) _T₁'')
 
+        ShowConstructor e -> do
+            _E' <- loop ctx e
+            case _E' of
+              VUnion _ -> pure VText
+              VOptional _ -> pure VText
+
+              _ -> die ShowConstructorNotOnUnion
+
         Field e (Syntax.fieldSelectionLabel -> x) -> do
             _E' <- loop ctx e
 
@@ -1275,26 +1284,42 @@
 
             -- The purpose of this inner loop is to ensure that we only need to
             -- typecheck the record once
-            let with tE' ks v = do
-                    kTs' <- case tE' of
-                        VRecord kTs' -> return kTs'
-                        _            -> die (NotWithARecord e₀ (quote names tE'))
 
+            let with tE' ks v = case tE' of
+                  VRecord kTs' ->
                     case ks of
-                        k :| [] -> do
-                            tV' <- loop ctx v
+                      WithLabel k :| [] -> do
+                          tV' <- loop ctx v
 
-                            return (VRecord (Dhall.Map.insert k tV' kTs'))
-                        k₀ :| k₁ : ks' -> do
-                            let _T =
-                                    case Dhall.Map.lookup k₀ kTs' of
-                                        Just _T' -> _T'
-                                        Nothing  -> VRecord mempty
+                          return (VRecord (Dhall.Map.insert k tV' kTs'))
+                      WithLabel k₀ :| k₁ : ks' -> do
+                          let _T =
+                                  case Dhall.Map.lookup k₀ kTs' of
+                                      Just _T' -> _T'
+                                      Nothing  -> VRecord mempty
 
-                            tV' <- with _T (k₁ :| ks') v
+                          tV' <- with _T (k₁ :| ks') v
 
-                            return (VRecord (Dhall.Map.insert k₀ tV' kTs'))
+                          return (VRecord (Dhall.Map.insert k₀ tV' kTs'))
+                      WithQuestion :| _ -> do
+                          die NotALabelPath
 
+                  VOptional _O' -> do
+                    case ks of
+                      WithQuestion  :| [] -> do
+                        tV' <- loop ctx v
+                        if Eval.conv values _O' tV'
+                          then return (VOptional _O')
+                          else die OptionalWithTypeMismatch
+
+                      WithQuestion :| k₁ : ks' -> do
+                        tV' <- with _O' (k₁ :| ks') v
+                        return (VOptional tV')
+
+                      WithLabel k :| _ -> die (NotAQuestionPath k)
+
+                  _ -> die (NotWithARecord e₀ (quote names tE')) -- TODO: NotWithARecordOrOptional
+
             with tE₀' ks₀ v₀
 
         Note s e ->
@@ -1396,6 +1421,10 @@
     | CantListAppend (Expr s a) (Expr s a)
     | CantAdd (Expr s a) (Expr s a)
     | CantMultiply (Expr s a) (Expr s a)
+    | OptionalWithTypeMismatch
+    | NotALabelPath
+    | NotAQuestionPath Text
+    | ShowConstructorNotOnUnion
     deriving (Show)
 
 formatHints :: [Doc Ann] -> Doc Ann
@@ -4550,6 +4579,126 @@
 prettyTypeMessage (CantMultiply expr0 expr1) =
         buildNaturalOperator "*" expr0 expr1
 
+prettyTypeMessage OptionalWithTypeMismatch = ErrorMessages {..}
+  where
+    short = "❰with❱ cannot change the type of an ❰Optional❱ value"
+    hints = []
+    long =
+        "Explanation: The ❰with❱ keyword cannot change the type of a value stored inside \n\
+        \of a ❰Some❱ constructor                                                         \n\
+        \                                                                                \n\
+        \For example, this is a valid use of ❰with❱:                                     \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \           The old value has type ❰Natural❱                                     \n\
+        \           ⇩                                                                    \n\
+        \    ┌───────────────────┐                                                       \n\
+        \    │ Some 1 with ? = 2 │                                                       \n\
+        \    └───────────────────┘                                                       \n\
+        \                      ⇧                                                         \n\
+        \                      ... which matches the type of the new value, which is also\n\
+        \                      ❰Natural❱                                                 \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \... but the following example is not valid:                                     \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \           The old value has type ❰Natural❱                                     \n\
+        \           ⇩                                                                    \n\
+        \    ┌──────────────────────┐                                                    \n\
+        \    │ Some 1 with ? = True │                                                    \n\
+        \    └──────────────────────┘                                                    \n\
+        \                      ⇧                                                         \n\
+        \                      ... but the new value has type ❰Bool❱, which does not     \n\
+        \                      match                                                     \n"
+
+prettyTypeMessage NotALabelPath = ErrorMessages {..}
+  where
+    short = "Use a label to update a record"
+    hints = []
+    long =
+        "Explanation: The ❰with❱ keyword supports updating records by naming the field(s)\n\
+        \to update, but you provided a path component of ❰?❱, which only works on        \n\
+        \❰Optional❱ values and not records.                                              \n\
+        \                                                                                \n\
+        \For example, these are valid uses of ❰with❱ to update a record:                 \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \    ┌──────────────────────┐                                                    \n\
+        \    │ { x = 1 } with x = 2 │                                                    \n\
+        \    └──────────────────────┘                                                    \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \    ┌────────────────────────────────┐                                          \n\
+        \    │ { x = { y = 1 } } with x.y = 2 │                                          \n\
+        \    └────────────────────────────────┘                                          \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \... but the following example is not valid:                                     \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \    ┌──────────────────────┐                                                    \n\
+        \    │ { x = 1 } with ? = 2 │                                                    \n\
+        \    └──────────────────────┘                                                    \n\
+        \                     ⇧                                                          \n\
+        \                     This path component is reserved for updating ❰Optional❱    \n\
+        \                     values and not records                                     \n\
+        \                                                                                \n\
+        \Note that you can update a field named ❰?❱ if you escape the path component,    \n\
+        \though:                                                                         \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \    ┌────────────────────────┐                                                  \n\
+        \    │ { ? = 1 } with `?` = 2 │                                                  \n\
+        \    └────────────────────────┘                                                  \n"
+
+prettyTypeMessage (NotAQuestionPath k) = ErrorMessages {..}
+  where
+    short = "Use ❰?❱ to update an ❰Optional❱ value"
+    hints = []
+    long =
+        "Explanation: The ❰with❱ keyword supports updating ❰Optional❱ values using a path\n\
+        \component of ❰?❱, but you provided a path component other than ❰?❱.             \n\
+        \                                                                                \n\
+        \For example, these are valid uses of ❰with❱ to update an ❰Optional❱ value:      \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \    ┌───────────────────┐                                                       \n\
+        \    │ Some 1 with ? = 2 │                                                       \n\
+        \    └───────────────────┘                                                       \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \    ┌─────────────────────────────┐                                             \n\
+        \    │ { x = Some 1 } with x.? = 2 │                                             \n\
+        \    └─────────────────────────────┘                                             \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \... but the following example is not valid:                                     \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \    ┌──────────────────────┐                                                    \n\
+        \    │ Some 1 with x = True │                                                    \n\
+        \    └──────────────────────┘                                                    \n\
+        \                  ⇧                                                             \n\
+        \                  This path component should have been ❰?❱                      \n\
+        \                                                                                \n\
+        \                                                                                \n\
+        \────────────────────────────────────────────────────────────────────────────────\n\
+        \                                                                                \n\
+        \You provided this path component:                                               \n\
+        \                                                                                \n\
+        \" <> txt0 <> "\n\
+        \                                                                                \n\
+        \... which perhaps should have been ❰?❱.                                         \n"
+      where
+        txt0 = insert k
+
+prettyTypeMessage ShowConstructorNotOnUnion = ErrorMessages {..}
+  where
+      short = "ShowConstructorNotOnUnion"
+      hints = []
+      long = ""
+
 buildBooleanOperator :: Pretty a => Text -> Expr s a -> Expr s a -> ErrorMessages
 buildBooleanOperator operator expr0 expr1 = ErrorMessages {..}
   where
@@ -4831,6 +4980,14 @@
         CantAdd <$> f a <*> f b
     CantMultiply a b ->
         CantMultiply <$> f a <*> f b
+    OptionalWithTypeMismatch ->
+        pure OptionalWithTypeMismatch
+    NotALabelPath ->
+        pure NotALabelPath
+    NotAQuestionPath k ->
+        pure (NotAQuestionPath k)
+    ShowConstructorNotOnUnion ->
+        pure ShowConstructorNotOnUnion
 
 {-| Newtype used to wrap error messages so that they render with a more
     detailed explanation of what went wrong
diff --git a/src/Dhall/Util.hs b/src/Dhall/Util.hs
--- a/src/Dhall/Util.hs
+++ b/src/Dhall/Util.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards   #-}
-{-# LANGUAGE TypeApplications  #-}
 
 -- | Shared utility functions
 
diff --git a/tests/Dhall/Test/Import.hs b/tests/Dhall/Test/Import.hs
--- a/tests/Dhall/Test/Import.hs
+++ b/tests/Dhall/Test/Import.hs
@@ -84,13 +84,7 @@
 
     let directoryString = FilePath.takeDirectory inputPath
 
-    let expectedFailures =
-            [ importDirectory </> "success/unit/cors/TwoHops"
-            , importDirectory </> "success/unit/cors/SelfImportAbsolute"
-            , importDirectory </> "success/unit/cors/AllowedAll"
-            , importDirectory </> "success/unit/cors/SelfImportRelative"
-            , importDirectory </> "success/unit/cors/OnlyGithub"
-            ]
+    let expectedFailures = [ ]
 
     Test.Util.testCase prefix expectedFailures (do
 
diff --git a/tests/Dhall/Test/QuickCheck.hs b/tests/Dhall/Test/QuickCheck.hs
--- a/tests/Dhall/Test/QuickCheck.hs
+++ b/tests/Dhall/Test/QuickCheck.hs
@@ -1,3 +1,5 @@
+-- TODO: update because we added ShowConstructor constructor to Expr in Dhall.Syntax
+
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE FlexibleInstances   #-}
@@ -50,6 +52,7 @@
     , Scheme (..)
     , URL (..)
     , Var (..)
+    , WithComponent (..)
     )
 import Dhall.Map              (Map)
 
@@ -296,6 +299,10 @@
     arbitrary = FieldSelection <$> pure Nothing <*> label <*> pure Nothing
     shrink = genericShrink
 
+instance Arbitrary WithComponent where
+    arbitrary =
+        Test.QuickCheck.oneof [ pure WithQuestion, WithLabel <$> arbitrary ]
+
 instance (Arbitrary s, Arbitrary a) => Arbitrary (Expr s a) where
     arbitrary =
         Test.QuickCheck.suchThat
@@ -405,6 +412,7 @@
             % (7 :: W "RecordCompletion")
             % (1 :: W "Merge")
             % (1 :: W "ToMap")
+            % (1 :: W "ShowConstructor")
             % (7 :: W "Field")
             % (7 :: W "Project")
             % (1 :: W "Assert")
diff --git a/tests/format/negativeTimeZoneA.dhall b/tests/format/negativeTimeZoneA.dhall
new file mode 100644
--- /dev/null
+++ b/tests/format/negativeTimeZoneA.dhall
@@ -0,0 +1,1 @@
+04:00:00-04:00
diff --git a/tests/format/negativeTimeZoneB.dhall b/tests/format/negativeTimeZoneB.dhall
new file mode 100644
--- /dev/null
+++ b/tests/format/negativeTimeZoneB.dhall
@@ -0,0 +1,1 @@
+04:00:00-04:00
diff --git a/tests/format/preserveShebangA.dhall b/tests/format/preserveShebangA.dhall
new file mode 100644
--- /dev/null
+++ b/tests/format/preserveShebangA.dhall
@@ -0,0 +1,2 @@
+#!/usr/bin/env -S dhall text --file
+"Hello, world!"
diff --git a/tests/format/preserveShebangB.dhall b/tests/format/preserveShebangB.dhall
new file mode 100644
--- /dev/null
+++ b/tests/format/preserveShebangB.dhall
@@ -0,0 +1,2 @@
+#!/usr/bin/env -S dhall text --file
+"Hello, world!"
diff --git a/tests/freeze/cachedB.dhall b/tests/freeze/cachedB.dhall
--- a/tests/freeze/cachedB.dhall
+++ b/tests/freeze/cachedB.dhall
@@ -1,3 +1,3 @@
-  ./True.dhall
+  missing
     sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
 ? ./True.dhall
diff --git a/tests/freeze/incorrectHashB.dhall b/tests/freeze/incorrectHashB.dhall
--- a/tests/freeze/incorrectHashB.dhall
+++ b/tests/freeze/incorrectHashB.dhall
@@ -1,3 +1,3 @@
-  ./True.dhall
+  missing
     sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
 ? ./True.dhall
diff --git a/tests/freeze/protectedB.dhall b/tests/freeze/protectedB.dhall
--- a/tests/freeze/protectedB.dhall
+++ b/tests/freeze/protectedB.dhall
@@ -1,3 +1,3 @@
-  ./True.dhall
+  missing
     sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
 ? ./True.dhall
diff --git a/tests/freeze/unprotectedB.dhall b/tests/freeze/unprotectedB.dhall
--- a/tests/freeze/unprotectedB.dhall
+++ b/tests/freeze/unprotectedB.dhall
@@ -1,3 +1,3 @@
-  ./True.dhall
+  missing
     sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
 ? ./True.dhall
