Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TAIT defining scope options #206

Closed
tmandry opened this issue Apr 25, 2023 · 2 comments
Closed

TAIT defining scope options #206

tmandry opened this issue Apr 25, 2023 · 2 comments
Labels
meeting-proposal Proposal for a lang team design meeting T-lang

Comments

@tmandry
Copy link
Member

tmandry commented Apr 25, 2023

Summary

Please describe your meeting topic here. It doesn't have to be very long, but
it's always good to try and identify a concrete question to be answered or
narrow topic for discussion. Nobody likes a rambly meeting.

There are several options around what the defining scope of a TAIT is allowed to be and whether to require an explicit #[defines] or #[defined_by] attribute. From a recent discussion in the lang team meeting (linked below), the primary tradeoffs involved are:

  • Explicitness
  • Ease of use
  • How it affects IDE performance (resolving auto traits)
  • How it affects compiler complexity (resolving cycles wrt to auto traits)

We have several possible paths forward with various amounts of conservatism involved for a "TAIT MVP". The decision takes place along two axes:

  1. Where defining uses are allowed. More allowable defining uses means supporting more use cases. Some options:
    • Restrict to "obvious" cases where the TAIT appears in the type signature in return position
    • Restrict to cases where TAIT appears anywhere in the type signature
    • Allow defining uses anywhere in the parent item/module
  2. Whether to require an explicit attribute.
    • Always require an attribute
    • Require an attribute on the "non-obvious" cases
    • Do not require an attribute

Some of these options are forward-compatible with others from a lang perspective (some through an edition), but it is possible they would require considerable complexity or performance pessimization to continue supporting in the compiler and IDE tooling.

Background reading

Include any links to material that folks ought to try to read before-hand.

There probably needs to be a doc summarizing the discussion so far, but I don't know who is prepared to write that doc.

About this issue

This issue corresponds to a lang-team design meeting proposal. It corresponds to a possible topic of discussion that may be scheduled for deeper discussion during one of our design meetings.

cc @oli-obk @cramertj @matklad

@traviscross
Copy link
Contributor

traviscross commented Apr 25, 2023

Here's a summary of the discussion so far, insofar as that is possible, with links to resources:

  • The IDE issue is focused around detecting leaked auto traits. @cramertj has pointed this out and suggested that the IDE could show all possibilities and defer errors until a defining use has been found.

  • Leaked auto traits can have surprisingly arbitrary effects on type inference on stable Rust due to stable autoderef-based specialization (one example case of this was pointed out by @matklad). Basically, the way that Rust picks which method to call when the call is not fully-qualified is subtle enough to sneak in a kind of specialization. This is not particular to impl Trait or to auto traits and has been true of Rust for a long time, though code using this is probably somewhat rare outside of complex macros.

  • RA handles this incorrectly today for RPIT. The concern is that for RA to fix this, TAIT (without making the conditional trait bounds explicit or requiring the hidden type to appear in the signature or requiring an explicit annotation) could require the IDE to check more places than RPIT.

  • This IDE problem goes beyond TAIT. Stable Rust today already requires the IDE to check all function bodies to correctly infer all types due to nested impls for outside types. There is a WIP proposal that if accepted would fix this in a new edition.

  • There was a feeling on the call today that we had decided that some extra complexity was OK when we allowed auto traits to leak. Supporting this view, RFC 1522 did explicitly consider and accept the additional tooling complexity introduced by auto trait leakage requiring non-local type checking.

  • TAIT with the hidden type in the signature (or some other kind of annotation) is equivalent in complexity to RPIT for the IDE. (According to @matklad: "If it is possible to tell, just looking at the signature of a function, whether it can define TAIT, than TAIT = RPIT in terms of problem for IDE.")

  • @oli-obk implemented the signature-requiring variant (return or argument position) in Require TAITs to appear in the signature of items that register a hidden type rust#107809 in such a way that it "is forward compatible to all other designs" (according to @oli-obk).

  • Regarding cycle errors and compiler complexity, @oli-obk has stated about the signature-requiring variant, "we discovered that this may resolve various issues we have with cycle errors, incremental performance and generally simplify the hidden type checking logic". We would all like to hear more from @oli-obk about this.

  • Regarding a restriction of the hidden type to only return position, that would exclude common async use cases where a function's output is sent to a channel whose handle is accepted as an argument. @joshtriplett (here) and @jplatte (here) have expressed support for TAIT in argument position. @oli-obk (here) and @RalfJung (here) have questioned the need for preventing TAIT use in argument position.

  • Regarding an explicit defines syntax or attribute, there's a potential conceptual problem that, unlike in earlier RFCs with the named existential type syntax, RFC 2515 TAIT makes the inferred hidden type anonymous, so it is awkward to have to name or point to it in some way for the explicit syntax to work.

  • The lang team has ruled out accepting an explicit #[defines] attribute or syntax without an RFC. @cramertj stated, "There was discussion of whether definitions should be specifically annotated, but this was rejected as unnecessary. Stabilizing the #[defines(...)]-based implementation would require an RFC to reexamine these tradeoffs." There seems to be a common feeling that requiring explicit annotation would be too onerous, at least for the common cases.

  • @nikomatsakis has proposed to stabilize ATPIT ahead of TAIT. @nikomatsakis stated a preference for allowing the defining use to appear anywhere in the impl, saying, "Myself, I favor the lenient option. My reasoning is that it continues with the idea that the TAIT can be constrained within its defining scope, and the defining scope here is the enclosing item, which is the impl (not particular methods within the impl)." @oli-obk implemented this separate feature gate and it was merged. There's also a feeling that impl Trait for const and static items could be stabilized without controversy.

  • The relationship between the leakage of auto traits in TAIT/RPIT and conditional trait bounds is discussed here. Basically, if we explicitly annotated the leakage of auto traits somehow (or did not leak them at all), that would also address the issue. Conceivably, a sufficiently-smart IDE could lazily infer (when examining a function body) and cache similar internal annotations to improve the speed and correctness of its suggestions and type inferences.

  • The 9-year history of impl Trait is surveyed in this post. It has links to most everything that's been written about impl Trait and TAIT.

  • The specific history of how auto traits relate to impl Trait is surveyed in this post.

@tmandry tmandry moved this from Needs triage to Scheduled in T-lang design meeting schedule May 3, 2023
@tmandry tmandry moved this from Scheduled to Needs minutes in T-lang design meeting schedule Jun 7, 2023
@nikomatsakis
Copy link
Contributor

@github-project-automation github-project-automation bot moved this from Needs minutes to Done in T-lang design meeting schedule Jun 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
meeting-proposal Proposal for a lang team design meeting T-lang
Projects
Development

No branches or pull requests

3 participants