Skip to content

[move-std] public(package) function aliases #24332

@admin-aftermath

Description

@admin-aftermath

Overview

Currently, function aliases only allow two visibility modifiers: public and private. public allows you to create cross-package aliases for the functions defined within your package whose input start with a type also defined within your package. Private function aliases allow localized function aliases for any function defined on any type; these aliases only exist within the module they are defined in.

Problem

Private function aliases are great when you are extending the functionality of an external type and want to normalize to method syntax when interacting with that type. There is one issue: due to the lack of a middle ground between public and private function aliases (i.e., public(package)), you must reimport the same set of private function aliases in all modules within your package that needs them. This can lead to a lot of boilerplate code in each module, especially when the same set of function aliases are needed across many modules.

I find that this is particulary true in two scenarios:

  1. When I split a single domain across many packages: a core package that defines the main type and many packages that extend the functionality of the main type. In the extension packages, each module contains many private function aliases for local-to-that-package functions that extend the core type.
  2. In tests, where I am often extending the functionality of third party types to better suit my testing needs. This extended functionality sometimes depends on the dependecies of my package, so extend module ... cannot be used as is to define public use fun aliases. This leads to most test files all starting with the same set of pivate function aliases.

Solution

The ability to define one set of public(package) function aliases for types defined outside the context of my package that are visible to all modules within a package would greatly reduce boilerplate code in both of the above scenarios.

Example

To give a concrete example of the above cases, consider a testing framework (package "A") that defines a Runner type:

module package_a::runner;

public struct Runner {
    scenario: TestScenario,
}

...

And now consider my local package (package "B") that depends on package "A" to add functionality to the Runner type to better interact with DeepBook:

module package_b::runner;

public fun place_limit_order(runner: &mut Runner, ...) {
    let pool = runner.scenario().borrow_shared<Pool>();

    ...
}

Package B also has a series of modules containing the tests for the package. Each module must begin with a set of private function aliases in order to use the place_limit_order function in a method syntax:

module package_b::test_place_limit_rder;

use fun package_b::runner::place_limit_order as Runner.place_limit_order;

...

For every function in package_b::runner that extends the functionality of Runner, I must repeat the same use fun alias in every test module. This leads to a lot of boilerplate code in each test module. Instead being able to define a single set of public(package) function aliases in package_b::runner that are visible to all modules within package B would greatly reduce this boilerplate:

module package_b::runner;

public(package) use fun package_b::runner::place_limit_order as Runnner.place_limit_order;

...

This example was for #[test_only] code since it is less domain-specific but the underlying problem is true outside of tests too. Also note that extend module package_a::runner cannot be used here as package A does not depend on DeepBookV3 and thus does not know the Pool type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions