Skip to content

Commit 7a8a28f

Browse files
committed
Fix inference for empty ado blocks
This fixes inference by using `pure` for empty ado blocks; no other change is required for the non-empty case as inference can be done through `map` and `apply`
1 parent d4bd62d commit 7a8a28f

File tree

10 files changed

+29
-13
lines changed

10 files changed

+29
-13
lines changed

compiler-bin/src/lsp/event.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ fn lowered_error(context: &DiagnosticsContext<'_>, error: &LoweringError) -> Opt
128128
match kind {
129129
lowering::AdoFn::Map => Some("map"),
130130
lowering::AdoFn::Apply => Some("apply"),
131+
lowering::AdoFn::Pure => Some("pure"),
131132
},
132133
),
133134
lowering::NotInScope::TermOperator { id } => {

compiler-core/checking/src/algorithm/term.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,10 +382,11 @@ where
382382
infer_do(state, context, *bind, *discard, statements)
383383
}
384384

385-
lowering::ExpressionKind::Ado { map, apply, statements, expression } => {
385+
lowering::ExpressionKind::Ado { map, apply, pure, statements, expression } => {
386386
let Some(map) = map else { return Ok(unknown) };
387387
let Some(apply) = apply else { return Ok(unknown) };
388-
infer_ado(state, context, *map, *apply, statements, *expression)
388+
let Some(pure) = pure else { return Ok(unknown) };
389+
infer_ado(state, context, *map, *apply, *pure, statements, *expression)
389390
}
390391

391392
lowering::ExpressionKind::Constructor { resolution } => {
@@ -658,6 +659,7 @@ fn infer_ado<Q>(
658659
context: &CheckContext<Q>,
659660
map: lowering::TermVariableResolution,
660661
apply: lowering::TermVariableResolution,
662+
pure: lowering::TermVariableResolution,
661663
statements: &[lowering::DoStatement],
662664
expression: Option<lowering::ExpressionId>,
663665
) -> QueryResult<TypeId>
@@ -666,6 +668,7 @@ where
666668
{
667669
let map_type = lookup_term_variable(state, context, map)?;
668670
let apply_type = lookup_term_variable(state, context, apply)?;
671+
let pure_type = lookup_term_variable(state, context, pure)?;
669672

670673
// First, perform a forward pass where variable bindings are
671674
// bound to unification variables and let bindings are checked.
@@ -698,7 +701,7 @@ where
698701

699702
let [head_statement, tail_statements @ ..] = &ado_statements[..] else {
700703
return if let Some(expression) = expression {
701-
infer_expression(state, context, expression)
704+
check_function_term_application(state, context, pure_type, expression)
702705
} else {
703706
state.insert_error(ErrorKind::EmptyAdoBlock);
704707
Ok(context.prim.unknown)

compiler-core/lowering/src/algorithm/recursive.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ fn lower_expression_kind(
313313

314314
let map = state.resolve_term_full(context, qualifier.as_deref(), "map");
315315
let apply = state.resolve_term_full(context, qualifier.as_deref(), "apply");
316+
let pure = state.resolve_term_full(context, qualifier.as_deref(), "pure");
316317

317318
if map.is_none() {
318319
let id = context.stabilized.lookup_cst(cst).expect_id();
@@ -328,6 +329,13 @@ fn lower_expression_kind(
328329
.push(LoweringError::NotInScope(NotInScope::AdoFn { kind: AdoFn::Apply, id }));
329330
}
330331

332+
if pure.is_none() {
333+
let id = context.stabilized.lookup_cst(cst).expect_id();
334+
state
335+
.errors
336+
.push(LoweringError::NotInScope(NotInScope::AdoFn { kind: AdoFn::Pure, id }));
337+
}
338+
331339
let statements = recover! {
332340
cst.statements()?
333341
.children()
@@ -336,7 +344,7 @@ fn lower_expression_kind(
336344
};
337345
let expression = cst.expression().map(|cst| lower_expression(state, context, &cst));
338346

339-
ExpressionKind::Ado { map, apply, statements, expression }
347+
ExpressionKind::Ado { map, apply, pure, statements, expression }
340348
}),
341349
cst::Expression::ExpressionConstructor(cst) => {
342350
let resolution = cst.name().and_then(|cst| {

compiler-core/lowering/src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub enum DoFn {
3636
pub enum AdoFn {
3737
Map,
3838
Apply,
39+
Pure,
3940
}
4041

4142
#[derive(Debug, PartialEq, Eq)]

compiler-core/lowering/src/intermediate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ pub enum ExpressionKind {
118118
Ado {
119119
map: Option<TermVariableResolution>,
120120
apply: Option<TermVariableResolution>,
121+
pure: Option<TermVariableResolution>,
121122
statements: Arc<[DoStatement]>,
122123
expression: Option<ExpressionId>,
123124
},

tests-integration/fixtures/checking/051_ado_non_applicative/Main.purs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ module Main where
22

33
data Tuple a b = Tuple a b
44

5-
map :: forall a b. (a -> b) -> a -> b
6-
map f x = f x
5+
foreign import pure :: forall a b. a -> b
76

8-
apply :: forall a b. (a -> b) -> a -> b
9-
apply f x = f x
7+
foreign import map :: forall a b. (a -> b) -> a -> b
8+
9+
foreign import apply :: forall a b. (a -> b) -> a -> b
1010

1111
test :: Tuple Int String
1212
test = ado

tests-integration/fixtures/checking/051_ado_non_applicative/Main.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ expression: report
44
---
55
Terms
66
Tuple :: forall (a :: Type) (b :: Type). a -> b -> Tuple a b
7+
pure :: forall (a :: Type) (b :: Type). a -> b
78
map :: forall (a :: Type) (b :: Type). (a -> b) -> a -> b
89
apply :: forall (a :: Type) (b :: Type). (a -> b) -> a -> b
910
test :: Tuple Int String

tests-integration/fixtures/checking/052_ado_non_applicative_discard/Main.purs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
module Main where
22

3-
map :: forall a b. (a -> b) -> a -> b
4-
map f x = f x
3+
foreign import pure :: forall a b. a -> b
54

6-
apply :: forall a b. (a -> b) -> a -> b
7-
apply f x = f x
5+
foreign import map :: forall a b. (a -> b) -> a -> b
6+
7+
foreign import apply :: forall a b. (a -> b) -> a -> b
88

99
test :: Int
1010
test = ado

tests-integration/fixtures/checking/052_ado_non_applicative_discard/Main.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ source: tests-integration/tests/checking/generated.rs
33
expression: report
44
---
55
Terms
6+
pure :: forall (a :: Type) (b :: Type). a -> b
67
map :: forall (a :: Type) (b :: Type). (a -> b) -> a -> b
78
apply :: forall (a :: Type) (b :: Type). (a -> b) -> a -> b
89
test :: Int

tests-integration/fixtures/checking/116_empty_ado_block/Main.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pure :: forall (a :: Type). a -> Effect a
77
map :: forall (a :: Type) (b :: Type). (a -> b) -> Effect a -> Effect b
88
apply :: forall (a :: Type) (b :: Type). Effect (a -> b) -> Effect a -> Effect b
99
test1 :: ???
10-
test2 :: Int
10+
test2 :: Effect Int
1111

1212
Types
1313
Effect :: Type -> Type

0 commit comments

Comments
 (0)