Skip to content

Let by-name implicit parameters have lazy semantics #1998

Closed
@odersky

Description

@odersky

Motivation

Generic programming often exhibits scenarios where an implicit expansion would diverge, were it not for a lazy implicit value that "ties the knot". Current Shapeless has the Lazy pseudo-type to handle this using some tricky macro machinery. Following an idea of @milessabin it seems cleaner to put this in the language and tie it to by-name implicit parameters.

Status Quo

By-name implicit parameters are disallowed in Scala-2. They have been introduced recently in dotty, but without attaching special meaning to them.

Proposal

Modify implicit search as follows:

When searching for an implicit value of type T to provide an argument for a by-name parameter of type => T:

  • Create a new implicit value with a fresh name lv, which has the signature of the following definition:

     implicit lazy val lv: T
    

    The current implementation uses the prefix $lazy_implicit$ followed by a unique integer for lv.

  • This lazy val is not immediately available as candidate for implicit search (making it immediately available would result in a looping implicit computation). But it becomes available in all nested contexts that look again for an implicit argument to a by-name parameter.

  • If this implicit search succeeds with expression E, and E contains references to the lazy implicit value lv, replace E by

     { implicit lazy val lv: T = E; lv }
    

    Otherwise, return E unchanged.

Implementation Status

This proposal has been implemented in #1993. The test cases in that PR starting with

lazy-implicits-... . scala

show where the feature is useful. All these test cases would have given a diverging implicit expansion before the change.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions