typelevel / typelevel/fs2

`Pull`'s public api is unsound

Open
#3,484 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Scala
Stars
2.5k
Forks
636
Avg merge
2d 4h
Merged PRs (30d)
7

Description

Because of Translate we may only G ~> F, not F ~> G. However GetScope and any operator that uses GetScope is subject to a soundness hole since:

  • Scope is allocated in the initial F.
  • Scope cannot have mapK since it must be invariant in F (acquisition of child resources).

Here is an example that throws a class cast exception.

I have been looking at it for a while and I can't see any other road to a sound structure than to require F ~> G if any interaction with the open resources in necessary.

The good news is that either more stream programs can be expressed with F ~> G or at least the current semantics can be retained explicitly.

new FunctionK[F, G] {
  def apply[A](fa: F[A]): G[A] = throw new ClassCastException("Oh no, couldn't go from F to G")
}

Assuming the api is used without throwing of exceptions, a bi-directional Translate allows Scope to be exposed (or at-least a subset of Scope's operators).

As of now, the only part of the api which is exposed and subject to this issue is lease. Fortunately lease doesn't invoke any other effects than ones in Scope, so any lossy F ~> G is completely fine, say EitherT[F, String, *] ~> F. Maybe a typeclass to represent non-structure preserving translations to make the G ~> F derivable for most cases?

Another direction could be to ensure that any Pull that is built on GetScope is non-translatable. Although this might require an extra type parameter to Pull and consequently Stream unfortunately.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the Pull API and the interactions among Translate, GetScope, lease, and Stream. Run the linked Scastie example to reproduce the ClassCastException, then trace the proposed translation directions and determine what API behavior or type constraints would make the resource interaction sound.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
api, stream-processing
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.