Skip to content

Improve send return types#15644

Merged
josevalim merged 1 commit into
elixir-lang:mainfrom
lukaszsamson:lukaszsamson-send-return-type
Jul 21, 2026
Merged

Improve send return types#15644
josevalim merged 1 commit into
elixir-lang:mainfrom
lukaszsamson:lukaszsamson-send-return-type

Conversation

@lukaszsamson

Copy link
Copy Markdown
Contributor

Teach the type checker that Kernel.send/2 returns the message operand and add a typed signature for :erlang.send/3 status returns.

AssistedBy: GPT 5.5

@lukaszsamson
lukaszsamson force-pushed the lukaszsamson-send-return-type branch 2 times, most recently from cd06baa to 91c4ec8 Compare July 21, 2026 11:35
Comment thread lib/elixir/lib/module/types/apply.ex Outdated
end

defp remote_apply(:erlang, :send, _info, [_dest, message] = args_types, stack) do
{:ok, return(message, args_types, stack)}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am almost sure you still need to call remote_apply/3 to validate the argument types. In particular the first arg. See Map.from_struct typing as an example.

https://github.com/lukaszsamson/elixir/blob/91c4ec83b60b8679587776c2754d9c459e5fb9aa/lib/elixir/lib/module/types/apply.ex#L1144

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I now call the generic remote_apply/3 first and only replace the validated return type with the message type on success.

test "send returns the message" do
assert typecheck!(send(self(), {:msg, 1})) == tuple([atom([:msg]), integer()])

assert typeerror!(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This test is redundant. Instead we should test that we validate the first argument and emit an error otherwise.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated. I removed the redundant direct return assertion and added coverage that send/2 rejects an invalid destination.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You changed the wrong one. You should change the line commented, the previous positive assertion was good and should be kept.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correction: I had misread which assertion the comment referred to. The positive return-type assertion is restored, and only the redundant never-match diagnostic assertion was replaced with invalid-destination coverage.

@lukaszsamson
lukaszsamson force-pushed the lukaszsamson-send-return-type branch from 91c4ec8 to 42b7508 Compare July 21, 2026 17:08
Teach the type checker that Kernel.send/2 returns the message operand.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@lukaszsamson
lukaszsamson force-pushed the lukaszsamson-send-return-type branch from 42b7508 to 019e691 Compare July 21, 2026 17:26
@josevalim
josevalim merged commit fa7db38 into elixir-lang:main Jul 21, 2026
15 checks passed
@josevalim

Copy link
Copy Markdown
Member

💚 💙 💜 💛 ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants