Skip to content

0.49.0

Compare
Choose a tag to compare
@ponylang-main ponylang-main released this 26 Feb 12:42
· 660 commits to main since this release

Add workaround for compiler assertion failure in Promise.flatten_next

Under certain conditions a specific usage of Promise.flatten_next and Promise.next could trigger a compiler assertion, whose root-cause is still under investigation.

The workaround avoids the code-path that triggers the assertion. We still need a full solution.

Take exhaustive match into account when checking for field initialization

Previously, exhaustive matches were handled after we verified that an object's fields were initialized. This lead to the code such as the following not passing compiler checks:

primitive Foo
  fun apply() : (U32 | None) => 1

type Bar is (U32 | None)

actor Main
  let bar : Bar

  new create(env : Env) =>
      match Foo()
      | let result : U32 =>
          bar = result
      | None =>
          bar = 0
      end

Field initialization is now done in a later pass after exhaustiveness checking has been done.

Fix compiler crash related to using tuples as a generic constraint

Tuple types aren't legal constraints on generics in Pony and we have a check in an early compiler pass to detect and report that error. However, it was previously possible to "sneak" a tuple type as a generic constraint past the earlier check in the compiler by "smuggling" it in a type alias.

The type aliases aren't flattened into their various components until after the code that disallows tuples as generic constraints which would result in the following code causing ponyc to assert:

type Blocksize is (U8, U32)
class Block[T: Blocksize]

We've added an additional check to the compiler in a later pass to report an error on the "smuggled" tuple type as a constraint.

Add greatest common divisor to math package

Code to determine the greatest common divisor for two integers has been added to the standard library:

use "math"

actor Main
  new create(env: Env) =>
    try
      let gcd = GreatestCommonDivisor[I64](10, 20)?
      env.out.print(gcd.string())
    else
      env.out.print("No GCD")
    end

Add least common multiple to math package

Code to determine the least common multiple of two unsigned integers has been added to the standard library:

use "math"

actor Main
  new create(env: Env) =>
    try
      let lcm = LeastCommonMultiple[U64](10, 20)?
      env.out.print(lcm.string())
    else
      env.out.print("No LCM")
    end

Fix incorrect "field not initialized" error with while/else

Previously, due to a bug in the compiler's while/else handling code, the following code would be rejected as not initializing all object fields:

actor Main
  var _s: (String | None)

  new create(env: Env) =>
    var i: USize = 0
    while i < 5 do
       _s = i.string()
       i = i + 1
    else
      _s = ""
    end

Fix incorrect "field not initialized" error with try/else

Previously, due to a bug in the compiler's try/else handling code, the following code would be rejected as not initializing all object fields:

actor Main
  var _s: (String | None)

  new create(env: Env) =>
    try
      _s = "".usize()?.string()
    else
      _s = None
    end

Fix compiler crash related to using tuples in a union as a generic constraint

Tuple types aren't legal constraints on generics in Pony and we have a check in an early compiler pass to detect and report that error. However, it was previously possible to "sneak" a tuple type as a generic constraint past the earlier check in the compiler by "smuggling" it in a type union in a type alias.

The type aliases aren't flattened into their various components until after the code that disallows tuples as generic constraints which would result in the following code causing ponyc to assert:

type Blocksize is (U64 | (U8, U32))
class Block[T: Blocksize]

We've added an additional check to the compiler in a later pass to report an error on the "smuggled" tuple type as a constraint.

Fix incorrect code returned by ANSI.erase

erase was intended to erase all characters to the left of the cursor but was instead returning the code to erase all characters to the right.

Reimplement with

The with keyword has been little used in most Pony programs. with was implemented as "sugar" over the try/else/then construct. Over the course of time, this became problematic as changes were made to make try more friendly. However, these try changes negatively impacted with. Prior to this change, with had become barely usable. We've reimplemented with to address the usability problems that built up over time. with is no longer sugar over try and as such, shouldn't develop any unrelated problems going forward. However, the reimplemented with is a breaking change.

Because with was sugar over try, the full expression was with/else. Any error that occurred within a with block would be handled by provided else. The existence of with/else rather than pure with was not a principled choice. The else only existed because it was needed to satisfy error-handling in the try based implementation. Our new implementation of with does not have the optional else clause. All error handling is in the hands of the programmer like it would be with any other Pony construct.

Previously, you would have had:

with obj = SomeObjectThatNeedsDisposing() do
  // use obj
else
  // only run if an error has occurred
end

Now, you would do:

try
  with obj = SomeObjectThatNeedsDisposing() do
    // use obj
  end
else
  // only run if an error has occurred
end

Or perhaps:

with obj = SomeObjectThatNeedsDisposing() do
  try
    // use obj
  else
    // only run if an error has occurred
  end
end

The new with block guarantees that dispose will be called on all with condition variables before jumping away whether due to an error or a control flow structure such as return.

This first version of the "new with" maintains one weakness that the previous implementation suffered from; you can't use an iso variable as a with condition. The following code will not compile:

use @pony_exitcode[None](code: I32)

class Disposable
  var _exit_code: I32

  new iso create() =>
    _exit_code = 0

  fun ref set_exit(code: I32) =>
    _exit_code = code

  fun dispose() =>
    @pony_exitcode(_exit_code)

actor Main
  new create(env: Env) =>
    with d = Disposable do
      d.set_exit(10)
    end

A future improvement to the with implementation will allow the usage of iso variables as with conditions.

Fix the interfaces for Iter's map and map_stateful methods to be less strict

The map_stateful and map methods on an Iter (from the itertools package) were too strict in what they required, requiring a B^ in order to produce an Iter[B].

This change correctly makes them only require B.

Use symbol table from definition scope when looking up references from default method bodies

Previously, symbols from default method bodies were only looked up in the local scope of the file into which they were included. This resulted in compilation errors if said symbol wasn't available in the local scope.

Issues #3737 and #2150 were both examples of this problem.

We've updated definition lookup to check if the enclosing method is provided by a trait or interface and if it is, to also check to definition scope for any needed symbols.

Remove logger package from the standard library

The logger package is intentionally limited in its functionality and leans heavily into reducing messaging overhead between actors to the point of intentionally sacrificing functionality.

Our stated belief as a core team has been that the standard library isn't "batteries included". We have also stated that libraries were we believe it would be "relatively easy" for multiple competing standards to appear in the community shouldn't be included in the standard library unless other factors make inclusion important.

Some other factor we have discussed in the past include:

  • Not having a standard library version would make interop between different 3rd-party Pony libraries difficult.
  • The functionality is required or called for by an interface in one or more standard library classes.
  • We consider the having the functionality provided to be core to the "getting started with Pony experience".

We don't believe that any of above 3 points apply to the logger package. Therefore, we've removed logger from the standard library and turned it into it's own stand alone library.

If you were using the logger package, visit it's new home and follow the "How to Use" directions.

Fix call receiver type casting in LLVM IR

In some rare cases (such as in the PonyCheck library), ponyc was generating LLVM that did not use the correct pointer types for call site receiver arguments. This did not result in unsafe code at runtime, but it was still a violation of the LLVM type system, and it caused the "Verification" step of compilation to fail when enabled.

To fix this issue, we introduced an LLVM bitcast at such call sites to cast the receiver pointer to the correct LLVM type.

Rename ponybench package to match standard library naming conventions

We recently realized that when we renamed large portions of the standard library to conform with our naming standards, that we missed the ponybench package. To conform with the naming convention, the ponybench package as been renamed to pony_bench.

You'll need to update your test code from:

use "ponybench"

to

use "pony_bench"

Add PonyCheck to the standard library

PonyCheck, a property based testing library, has been added to the standard library. PonyCheck was previously its own project but has been merged into the standard library.

For the most part existing PonyCheck tests will continue to work once you make a few minor changes.

Remove PonyCheck from your corral.json

As PonyCheck is now part of the standard library, you don't need to use corral to fetch it.

Change the package name

Previously, the PonyCheck package was called ponycheck. To conform with standard library naming conventions, the package has been renamed to pony_check. So anywhere you previously had:

use "ponycheck"

You'll need to update to:

use "pony_check"

Update the PonyCheck primitive name

If you were using the Ponycheck primitive, you'll need to change it to its new name PonyCheck.

Fix failed initialization bug in Process Monitor

Previously, when a process failed to start up, it was possible to get a report
that the process had started up and exited with the error code 0 which
normally signals success.

Change standard library object capabilities pattern

We've changed standard library object capabilities pattern.

Object capabilities play an important role in Pony's security story. Developers can via a combination of disallowing the use of FFI within a given package and object capabilities be assured that 3rd-party libraries they use aren't doing unexpected things like opening network sockets.

Joe Eli McIlvain and Sean T. Allen spent some time reviewing the previous usage of object capabilities and came away concerned. We believed the old standard library pattern was:

  • Error prone for beginning Pony programmers
  • Encouraged passing around AmbientAuth everywhere in a way that negated the advantages of using object capabilities and only left the disadvantages

To learn more about the reasoning for the change, see the RFC that this change implements.

Note, this is a breaking changes and might require you to change your code that involves object capability authorization usage. Only a single "most specific" authorization is now allowed at call sites so previously where you could have been using AmbientAuth directly to authorization an action like creating a TCPListener:

TCPListener(env.root, Listener(env.out))

You'll now have to use the most specific authorization for the object:

TCPListener(TCPListenAuth(env.root), Listener(env.out))

Updating authorization for Backpressure

Previously accepted:

  • AmbientAuth
  • ApplyReleaseBackpressureAuth
  • the BackpressureAuth type union.

Now accepted:

  • ApplyReleaseBackpressureAuth

Updating authorization for DNS

Previously accepted:

  • AmbientAuth
  • NetAuth
  • DNSAuth
  • the DNSLookupAuth type union

Now accepted:

  • DNSAuth

Updating authorization for FilePath

Previously accepted:

  • AmbientAuth
  • FileAuth
  • an existing FilePath instance

Now accepted:

  • FileAuth
  • an existing FilePath instance

Updating authorization for ProcessMonitor

Previously accepted:

  • AmbientAuth

  • StartProcessAuth

  • the ProcessMonitorAuth type union
    Now accepted:

  • StartProcessAuth

Updating authorization for RuntimeInfo

Previously accepted:

  • AmbientAuth
  • SchedulerInfoAuth
  • the RuntimeInfoAuth type union

Now accepted:

  • SchedulerInfoAuth

Updating authorization for Serialised

No changes are needed.

Updating authorization for TCPConnection

Previously accepted:

  • AmbientAuth
  • NetAuth
  • TCPAuth
  • TCPConnectAuth
  • the TCPConnectionAuth type union

Now accepted:

  • TCPConnectAuth

Updating authorization for TCPListener

Previously accepted:

  • AmbientAuth
  • NetAuth
  • TCPAuth
  • TCPListenAuth
  • the TCPListenerAuth type union

Now accepted:

  • TCPListenAuth

Updating authorization for UDPSocket

Previously accepted:

  • AmbientAuth
  • NetAuth
  • UDPAuth
  • the UDPSocketAuth type union

Now accepted:

  • UDPAuth

Update Windows version for Windows Docker Images

We've moved the base from Windows server 2019 to 2022. The version has to
match the underlying operating system and GitHub recently updated.

Rename ponytest package to match standard library naming conventions

We recently realized that when we renamed large portions of the standard library to conform with our naming standards, that we missed the ponytest package. To conform with the naming convention, the ponytest package as been renamed to pony_test.

You'll need to update your test code from:

use "ponytest"

to

use "pony_test"

[0.49.0] - 2022-02-26

Fixed

  • Add workaround for compiler assertion failure in Promise.flatten_next (PR #3991)
  • Take exhaustive match into account when checking for field initialization (PR #4006)
  • Fix compiler crash related to using tuples as a generic constraint (PR #4005)
  • Fix incorrect "field not initialized" error with while/else (PR #4009)
  • Fix incorrect "field not initialized" error with try/else (PR #4011)
  • Fix compiler crash related to using tuples in a union as a generic constraint (PR #4017)
  • Fix incorrect code returned by ANSI.erase (PR #4022)
  • Fix the signature of Iter's map_stateful/map to not require ephemerals (PR #4026)
  • Use symbol table from definition scope when looking up references from default method bodies (PR #4027)
  • Fix LLVM IR verification error found via PonyCheck (PR #4039)
  • Fix failed initialization bug in Process Monitor (PR #4043)

Added

  • Add LeastCommonMultiple and GreatestCommonDivisor to math package (PR #4001)
  • Add PonyCheck to standard library (PR #4034)

Changed

  • Reimplement with (PR #4024)
  • Remove logger package from the standard library (PR #4035)
  • Rename ponybench to match standard naming conventions. (PR #4033)
  • Change the standard library pattern for object capabilities (PR #4031)
  • Update Windows version used as the base for Windows images (PR #4044)
  • Rename ponytest package to conform to naming standards (PR #4032)