Skip to content

Propagate expected dict and async value type#8359

Merged
zth merged 4 commits into
masterfrom
improve-dict-type-propagation
Apr 19, 2026
Merged

Propagate expected dict and async value type#8359
zth merged 4 commits into
masterfrom
improve-dict-type-propagation

Conversation

@zth

@zth zth commented Apr 18, 2026

Copy link
Copy Markdown
Member

Currently, this fails:

module Hidden = {
  type routeHandlerObject = {get: int}
}

let dictValueInference: Dict.t<Hidden.routeHandlerObject> = dict{
  "health": {get: 200},
}

let primitiveMakeValueInference: Dict.t<Hidden.routeHandlerObject> = dict{"health": {get: 200}}

It fails because dict{} expression is emitted as Primitive_dict.make(["health", {get: 200}]), and that makes it loose type info. This PR propagates the expected dict type info further, which means the above code will work.

As a nice side effect, this PR also improves type error messages for dict. This:

let x: dict<JSON.t> = dict{"1": 1.}

Will currently fail on the whole dict{} (although it's just 1. that's wrong). After this fix it'll fail on 1. instead (Expected JSON.t, got float).

@cristianoc can you think of a better cleaner way to do this?

Also, Codex is saying these cases are also broken and could be fixed the same way:

  1. async
  2. spread arrays/lists
  3. tagged templates

These fail today:

module M = { type t = {get: int} }

// Fails
let f: unit => promise<M.t> = async () => {get: 1}
// Works (no async)
let f: unit => M.t = () => {get: 1}

// Fails
let xs: array<M.t> = [...[], {get: 1}]
let xs: list<M.t> = list{...list{}, {get: 1}}

// Fails
let tag = (_strings, values) => values[0]->Option.getOrThrow
let x: M.t = tag`a${{get: 1}}`

EDIT: I updated the PR to fix async as well.

@zth zth requested a review from cristianoc April 18, 2026 15:01
@pkg-pr-new

pkg-pr-new Bot commented Apr 18, 2026

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@8359

@rescript/darwin-arm64

npm i https://pkg.pr.new/@rescript/darwin-arm64@8359

@rescript/darwin-x64

npm i https://pkg.pr.new/@rescript/darwin-x64@8359

@rescript/linux-arm64

npm i https://pkg.pr.new/@rescript/linux-arm64@8359

@rescript/linux-x64

npm i https://pkg.pr.new/@rescript/linux-x64@8359

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@8359

@rescript/win32-x64

npm i https://pkg.pr.new/@rescript/win32-x64@8359

commit: 09b91a0

@cristianoc cristianoc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legit.
I guess a first class support for dict would avoid the issue, but might be more invasive.
(And async etc).

@zth zth changed the title Propagate expected dict value type into dict literal typing Apr 19, 2026
@zth zth force-pushed the improve-dict-type-propagation branch from 0fc2c8d to 09b91a0 Compare April 19, 2026 08:09
@zth zth enabled auto-merge (squash) April 19, 2026 08:19
@zth zth merged commit c8d05be into master Apr 19, 2026
32 checks passed
@zth zth deleted the improve-dict-type-propagation branch April 19, 2026 08:28
cknitt pushed a commit that referenced this pull request May 3, 2026
* propagate expected dict value type into dict literal typing

* cleaner impl

* change approach back to structural, and fix async as well

* changelog
# Conflicts:
#	CHANGELOG.md
cknitt pushed a commit that referenced this pull request May 4, 2026
* propagate expected dict value type into dict literal typing

* cleaner impl

* change approach back to structural, and fix async as well

* changelog
# Conflicts:
#	CHANGELOG.md
cknitt pushed a commit that referenced this pull request May 16, 2026
* propagate expected dict value type into dict literal typing

* cleaner impl

* change approach back to structural, and fix async as well

* changelog
# Conflicts:
#	CHANGELOG.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants