Repository navigation
TAIT defining scope options #107645
Description
during the stabilization of TAITs (type alias impl trait) in #63063 (comment) a concern was raised: it's not obvious for the compiler (and IDEs), which items' bodies are allowed to register hidden types for TAITs. For RPIT (return position impl trait) it was obvious: the body of the function in whose return type the impl Trait was in. For TAITs the status quo is point 1 in the list of options below. This may require some interesting module juggling to avoid cycle errors that can occur due to revealing the hidden type to prove Send or Sync bounds, and that revealing again looking at the item to look for things registering the hidden type (see example and passing example).
The possible schemes we know about currently are:
- any item that is (recursively) within the parent of the TAIT is allowed to register the hidden type
- any item that follows the rules of 1. and additionally has the TAIT in its signature or
wherebounds is allowed to register the hidden type. this change has a prospective impl at- Require TAITs to appear in the signature of items that register a hidden type #107073
- not much wiggle room for changing things after stabilization, as any change can quickly leed to then-stable code to have cycle errors
- same as 2. but not permitting
wherebounds to register hidden types - any item in the defining scope can register hidden types, but we error out if the TAIT is not mentioned in the signature or
wherebounds- Require TAITs to appear in the signature of items that register a hidden type #107809
- similar to 2., but since we still look at all functions in the defining scope, there's no change in cycle errors to 1.
- forward compatible with choosing 2. or 1. later
- same as 4. but not permitting
wherebounds to register hidden types- forward compatible with choosing 4. later
Ruled out schemes:
- any item that follows the rules of 1. and has a
#[defines(NameOfTheTypeAlias)]attribute is allowed to register the hidden type- probably undesirable due to the verbosity in "obvious" cases (like using a TAIT in function return position)
- only allow explicitly registering hidden types with a magic libcore function that syntactically mentions the TAIT by its path. This will still require looking at the body, but we don't need to typecheck the body, just do name resolution on it.
- this option is just listed for completeness, it's the worst option :)
I am nominating this issue for T-lang to discuss which options they prefer.
Activity
pnkfelix commentedon Feb 21, 2023
Discussing T-lang triage. We want/need to resolve choice between options provided asynchronously.
After we come to some conclusion, we'll FCP merge/close this to demarcate that conclusion.
pnkfelix commentedon Feb 21, 2023
Here's the zulip thread the T-lang team will use to align on this: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/align.20on.20TAIT.20defining.20scope.20options.20lang-team.23107645/near/329277776
nikomatsakis commentedon Mar 14, 2023
nikomatsakis commentedon Mar 14, 2023
@rfcbot fcp merge
I propose that we accept #107809. It implements a conservative path forward. Basically any function that constraints a TAIT but doesn't list the TAIT in its arguments/return type is a hard error, giving us room to change the behavior in the future.
Final behavior as I understand it
let(e.g.,let x: TAIT = 22_u32), a return (e.g.,return 22_u32in a function whose return type isTAIT), or in other ways.fn foo<T>() -> TAIT<T>and notfn foo() -> TAIT<u32>). This ensures inference is tractable and well-defined.Current bugs and limitations (forwards compatible to change)
TAITimplements an auto-trait will yield a cycle error unless the auto-trait is listed in the TAIT's bounds. This is suboptimal, but the ideal fix is unclear.<TAIT as SomeTrait>::SomeItem) ought to be considered a defining use. However, in the compiler today, if that associated type can be normalized, and the normalized form does not reference the TAIT, the function is not. This can only cause more errors.@rustbot labels -I-lang-nominated
rfcbot commentedon Mar 14, 2023
Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged team members:
Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.
tmandry commentedon Mar 14, 2023
@rfcbot concern why-not-just-the-return-type
Can we restrict to only the return type, instead of the return type and arguments? Are there major use cases that wouldn't be satisfied by this?
cc @oli-obk
oli-obk commentedon Mar 14, 2023
Not that I know of, though it may feel like a very artificial limitation to users
RalfJung commentedon Mar 14, 2023
We allow
impl Traitconsistently in argument and return position, so why should TAIT not work in both? Is the concern the polarity of quantification which is common between TAIT and return types but not argument types?116 remaining items
Dirbaio commentedon Nov 7, 2023
I've collected all my thoughts on TAIT defining scope design in a document. It goes through the possible designs and pros and cons of explicit (
defines-like) and implicit (like "parent mod + signature restriction") designs, and what data we have about their use cases.https://hackmd.io/i-xpzf-LR7q75pSRTDVSaA
zulip thread: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/TAIT.20defining.20scope.20implicit.20vs.20explicit
rfcbot commentedon Nov 11, 2023
The final comment period, with a disposition to merge, as per the review above, is now complete.
As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
This will be merged soon.
GoldsteinE commentedon Nov 20, 2023
I don’t think @Dirbaio points were properly addressed? Zulip threads seems dead and I don’t see a proper argument against points in Hackmd, only clarifying questions/answers.
Rollup merge of rust-lang#119766 - oli-obk:split_tait_and_atpit, r=co…
Rollup merge of rust-lang#119766 - oli-obk:split_tait_and_atpit, r=co…
Rollup merge of rust-lang#119766 - oli-obk:split_tait_and_atpit, r=co…
Unrolled build for rust-lang#119766
BatmanAoD commentedon Dec 19, 2024
The status of this issue is confusing -- what actually got approved & merged by the FCP ('m assuming this), and should this issue have been closed once the merge occurred?
traviscross commentedon Dec 19, 2024
The status is that we have a pending stabilization for ATPIT (#120700) that is waiting on implementation work, and that for TAIT more broadly, we're likely to do some kind of
#[defines(..)]-like scheme, with the details of that still to be decided.It's probably reasonable to leave this issue open until we close it in favor of another, e.g. perhaps one that settles those details.
oli-obk commentedon Mar 12, 2025
Resolved by #128440