This is an archive of the discontinued LLVM Phabricator instance.

[lldb] Change dwim-print to default to disabled persistent results
ClosedPublic

Authored by kastiglione on Mar 8 2023, 1:27 PM.

Details

Summary

Change dwim-print to now disable persistent results by default, unless requested by
the user with the --persistent-result flag.

Ex:

(lldb) dwim-print 1 + 1
(int) 2
(lldb) dwim-print --persistent-result on -- 1 + 1
(int) $0 = 2

Users who wish to enable persistent results can make and use an alias that includes
--persistent-result on.

Diff Detail

Event Timeline

kastiglione created this revision.Mar 8 2023, 1:27 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 8 2023, 1:27 PM
kastiglione requested review of this revision.Mar 8 2023, 1:27 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 8 2023, 1:27 PM

Cleanup TestDWIMPrint

aprantl accepted this revision.Mar 14 2023, 2:11 PM
This revision is now accepted and ready to land.Mar 14 2023, 2:11 PM
jgorbe added a subscriber: jgorbe.Mar 23 2023, 10:01 AM

What was the rationale for this change? It changes the output format of a common command (given that print is now an alias for dwim-print) and it breaks basically anything that examines debugger output.

Also --persistent-result on can't be passed to print, it only works for me if I run specifically dwim-print. Is that intended?

Also --persistent-result on can't be passed to print, it only works for me if I run specifically dwim-print. Is that intended?

The intension is that for users who want persistent results enabled can do so by customizing their p or print alias, like so:

command unalias print
command alias print dwim-print --persistent-result on --

What was the rationale for this change? It changes the output format of a common command (given that print is now an alias for dwim-print) and it breaks basically anything that examines debugger output.

Are you using persistent results? If not, how much effort is it to either 1) change the tools/code that examine the output to not look for $\d+, or 2) use a custom print/p alias? Honest question.

The rationale is: dwim-print doesn't always use expression evaluation, it prefers to use frame variable where possible. In the future it could be expanded, for example to print register as well. Because dwim-print doesn't always use expression, there isn't always a persistent result. To make dwim-print output consistent, and because it's presumed most users don't use persistent results, we changed dwim-print to default to no persistent results. By consistent output, I mean that if a user runs print someVar and then follows that by running print someVar.dump(), it could be confusing if the first command doesn't have a persistent result, but the second one does.

breaks basically anything that examines debugger output

I'd be curious to learn about some example you have in mind here.

The rationale is: dwim-print doesn't always use expression evaluation, it prefers to use frame variable where possible. In the future it could be expanded, for example to print register as well. Because dwim-print doesn't always use expression, there isn't always a persistent result.

Oh, so in the cases where dwim-print delegates to frame variable you can't then refer to that result in another dwim-print command/other place where you'd like to reference a previously printed value?

That seems like a significant regression over existing print functionality and compared to gdb. At least for me that'd be annoying/inconvenient to have to think about which kind of printing I'm doing (& have to explicitly use the less stable full expression based printing) when I want to reuse a value.

To make dwim-print output consistent, and because it's presumed most users don't use persistent results

Got data on that? I'd /guess/ I use it maybe in single digit % of my prints, but probably at least 1%, though no idea if that's representative - even if it is, the inconsistency feels counter to the goals of dwim-print & the convenience provided by gdb's consistent value handling.

Oh, so in the cases where dwim-print delegates to frame variable you can't then refer to that result in another dwim-print command/other place where you'd like to reference a previously printed value?

If the variable is in scope, you can use the variable. If it's not in scope, can you tell me about the workflows that you'd use it in?

That seems like a significant regression over existing print functionality and compared to gdb. At least for me that'd be annoying/inconvenient to have to think about which kind of printing I'm doing (& have to explicitly use the less stable full expression based printing) when I want to reuse a value.

Our expectation is that for users such as yourself, the solution is to customize the p alias, or alternatively create a separate alias, like pr (print w/ result). Does that seem reasonable? My plan is to use e for the cases where I want persistent results, since expression still defaults to persisting result variables.

Got data on that? I'd /guess/ I use it maybe in single digit % of my prints, but probably at least 1%, though no idea if that's representative - even if it is, the inconsistency feels counter to the goals of dwim-print & the convenience provided by gdb's consistent value handling.

Re data: only anecdotal. I expect that those of us who work on lldb represent the biggest users of persistent results, but how much is that? You estimate 1%. I use it less than that, maybe one out of a thousand (0.01%), but probably less. @aprantl has mentioned he's more likely to hit the up arrow and edit a previous command than use persistent results, which I can see being true for most users.

It's not that the ability is taken away, only that the default is being set to match the majority of cases – the 99+% of prints don't need a persistent result.

Are you using persistent results? If not, how much effort is it to either 1) change the tools/code that examine the output to not look for $\d+, or 2) use a custom print/p alias? Honest question.

I'm not using them myself, and it's not much effort to fix the problems I've seen because of this. It just seemed weird to have a user-facing behavior change like this being committed without a rationale given.

I assumed switching to dwim-print would be transparent for users, and I'm not sure how a user that relies on these convenience variables is supposed to discover what happened when print stops producing them.

I'd be curious to learn about some example you have in mind here.

We have a python test harness that drives a debugger session that we mainly use for prettyprinter tests. Then we have tests that look like:

self.ContinueTo('StopHereForDebugger')
self.TestPrintOutputMatches('my_variable', 'Cord of length 4: "foo\\n"')

when I ported this from gdb I couldn't find an equivalent to gdb's output command (that prints just the value), so I reached for print which printed (Type) $0 = value instead, and kept everything after the ' = '. It wasn't even using the persistent values, but the change in the output format broke it.

I also found a failure in a one-off test that worked as a minimal sanity check for debug builds: build a debug binary, then run the debugger on it and try to print some variables in order to verify that debug builds do have debug info that the debugger can use (i.e. debug info is not completely missing, or corrupted). This is a shell script that basically does:

OUTPUT=$("$LLDB" -b -s "$SCRIPT_FILE" "$TEST_PROGRAM")

and then used the conveniently sequentially-numbered persistent results to grep the output:

# Check that `argc` is 1 and has type `int`.
(echo "$OUTPUT" | grep "(int).*[$]0 = 1") || die

I know they're not the most robust tests in the world, and as I said, it was not much effort to fix (they're already fixed!). But it still feels like a user-facing regression, and the consistency argument can go both ways: you could similarly argue that dwim-print should put the result of frame variable into a convenience variable to keep it consistent with the cases where the expression evaluator is used. So the real argument is that most users don't need it and it shouldn't be enabled by default. Which is a fine argument to make (although it's sad that we don't have data to support it one way or the other), but I had to ask to know because the commit description didn't mention any reasons at all.

By the way, I just bisected another problem to this commit: I'm seeing in some cases that prettyprinted values with synthetic children don't show child names when using dwim-print. So print used to show:

(lldb) p c
(MyClass) $0 = MyClass object with children: {
  [0] = 0x0000555555556004 "hello"
}
(lldb) p m
(MyMap) $1 = MyMap object with children: {
  ["my_key"] = 0x0000555555556011 "my_value"
}

but now it shows

(lldb) p c
(MyClass)  MyClass object with children: {
  0x0000555555556004 "hello"
}
(lldb) p m
(MyMap)  MyMap object with children: {
  0x0000555555556011 "my_value"
}

I don't have a repro test case to share right away but I though I'd give you a heads-up in case the problem is easy to find from the description. Or maybe it's the intended behavior? I get the same behavior with expr --persistent-result off -- m so I can't tell if it's a bug or if it's just the expected behavior when disabling persistent results. If it's the latter, that's a strong argument for me to unalias print and restore the old behavior in the lldbinit file we ship to our internal users.

I'll work on a small shareable test case tomorrow anyway.

@jgorbe thank you for letting me know! It's not intended that the names of child values are not printed. I have a fix ready for review here D146783.