Skip to content

Temporary lifetime testing strategy #159358

Description

@Mark-Simulacrum

I wanted to drop a thread here around our experience with making changes to dbg! and the difficulty (I think still unfinished) of getting a consistent experience on the temporary lifetimes. @dianne was already involved so has some additional context, but I thought it'd be a useful point to keep in mind more broadly for this group.

The collection of PRs:

(I may have missed one or two attempts there).

I think this is still pending in #157576 which uses super let to implement it, but as that PR says the result is not great in terms of saying "yes that's doing what I expect".

$(let $bound);+;
$(super let _ = ($bound = $processed));+;

However, the main goal in writing this up is that I think we're missing some good way for us to test this. Most of our temporary lifetimes are inherently implicit, and describing what happens at what scope in a way that can be guaranteed constant across refactoring is hard. Writing tests for language features (e.g., let-else, if-let, ...) takes a good deal of work to remember each case (e.g., see https://github.com/rust-lang/rust/blob/main/tests/ui/let-else/let-else-temporary-lifetime.rs, https://github.com/rust-lang/rust/blob/main/tests/ui/lifetimes/temporary-lifetime-extension.rs). Regardless of the syntax to express (super let, some macros, etc.), I think it would be very useful to have some way to exhaustively cover the cases a macro author (at least) or ideally language feature author needs to concern themselves with.

I'm not sure exactly what form that should take. Maybe the right answer is a collection of macros in core that you need to can use and then assert against a template -- e.g., something like this hypothetical:

temporary_tests!(dbg!($arg1, $arg2));

would expand into something that at least exhaustively enumerates cases and can be snapshot-tested across changes to the internals of the dbg! macro. In principle, that same strategy could be used for a language feature, e.g., something like this?

temporary_tests!(let $pat = $arg1 else { $arg2 });

I've not thought too deeply on the specific semantics, but I suspect the right shape is that each separate case would get its own test case produced from the template. It can then be compared (via execution / Drop prints / something else?) against canonical examples (e.g., "this language feature should behave exactly the same as this alternative feature) or the previous version of a library (snapshot testing) to prevent repeated regressions like the ones we worked through with dbg!.

Cutting an issue per some short discussion with @traviscross offline to keep track of this conversation.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-temporary-lifetime-extensionArea: temporary lifetime extensionC-discussionCategory: Discussion or questions that doesn't represent real issues.T-langRelevant to the language team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions