This is an archive of the discontinued LLVM Phabricator instance.

[ADT] Add `at` method (assertive lookup) to DenseMap and StringMap
ClosedPublic

Authored by StrongerXi on Feb 13 2023, 8:37 PM.

Details

Summary

This patch makes it easier for users when they want to use validated
lookup on DenseMap/StringMap as a composable C++ expression. For
instance:

// instead of
if (auto val = map.lookup(key))
   return val;
assert("...");

// we can write
return map.at(key);

Diff Detail

Event Timeline

StrongerXi created this revision.Feb 13 2023, 8:37 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 13 2023, 8:37 PM
StrongerXi requested review of this revision.Feb 13 2023, 8:37 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 13 2023, 8:37 PM

Very cool, I'm excited to get this. This will simplify a lot of code! Could you also add this to StringMap? It has a similar lookup method but it can't be used for non-default-constructible values, and has the same usage pattern as this container.

llvm/include/llvm/ADT/DenseMap.h
211

Unfortunately, I don't think we can afford to include this level of debug tracing in here. This adds a bunch of #include dependencies, and (more problematically) includes a bunch of code in the non assert build.

The standard LLVM way to do this (see in things like ArrayRef's subscript) is to just assert with a fixed message "lookupOrTrap failed due to a missing key", using the standard assert macro.

  1. Use assert and fixed error message
  2. Add the same method and unittests to StringMap
StrongerXi retitled this revision from [ADT] Add lookupOrTrap method to DenseMap to [ADT] Add lookupOrTrap method to DenseMap and StringMap.Feb 13 2023, 9:50 PM
StrongerXi edited the summary of this revision. (Show Details)
StrongerXi added inline comments.
llvm/include/llvm/ADT/DenseMap.h
211

Ah good points, updated.

llvm/include/llvm/ADT/StringMap.h
234–237

Updated because I noticed they didn't follow the convention of capitalized variable names.

foad added a subscriber: foad.Feb 14 2023, 3:55 AM

With apologies for bikeshedding:

I don't love the "OrTrap" name. It might trap in a Debug build, but it surely won't in a Release build. Anyway I don't think the name needs to say what the consequences might be if the key does not exist.

How about calling it just "lookup", and using a longer name like "lookupOrDefaultConstruct" for the less-obvious behaviour of the current lookup method? (Is there really much code that relies on its "or default construct" behaviour? And anyway aren't there more STL-like ways of getting that behaviour, like using operator[]?)

Or why not call it "at"?

Bikeshedding is good @foad, these are important core data structures :)

I agree with you that at seems like the right name for this, given the STL precedent. I wasn't aware of that existing for maps.

Renaming lookup -> lookupOrDefaultConstruct() or getValueIfPresent() or something like that would make sense as well, but seems like a separate issue.

I agree that at has the advantage of being similar (in spelling & semantics) to std::map::at. Possible counterarguments:

  1. at too implicit about the "assertive/validated" semantics.
  2. having something similar to lookup is a easier to adapt for existing users, also makes the API more consistent/intuitive.

I can't seem to think of many alternatives though, lookupChecked? What do you all think?

I also agree that renaming the old lookup should be a separate issue, and I think it has backward compatibility concerns too.

We generally don't worry to much about compatibility issues. It is good to deprecate the old name for a few weeks before removing it, but we don't do long cycles here.

I also don't like the 'at' name particularly, but it is highly precedented by the STL. I think any alternate name would have to be really good to overcome that.

StrongerXi edited the summary of this revision. (Show Details)

Rename lookupOrTrap to at

We generally don't worry to much about compatibility issues. It is good to deprecate the old name for a few weeks before removing it, but we don't do long cycles here.

I also don't like the 'at' name particularly, but it is highly precedented by the STL. I think any alternate name would have to be really good to overcome that.

Sounds good; renaming to at:).

StrongerXi retitled this revision from [ADT] Add lookupOrTrap method to DenseMap and StringMap to [ADT] Add `at` method (assertive lookup) to DenseMap and StringMap.Feb 14 2023, 9:51 PM
StrongerXi edited the summary of this revision. (Show Details)
foad added a comment.Feb 15 2023, 2:18 AM

Could you also add this to StringMap?

Maybe IntervalMap and MapVector too?

I agree with you that at seems like the right name for this, given the STL precedent. I wasn't aware of that existing for maps.

Agreed.

Renaming lookup -> lookupOrDefaultConstruct() or getValueIfPresent() or something like that would make sense as well, but seems like a separate issue.

I only suggested that to free up the name "lookup". I don't see any pressing need to change it if we are going with "at" for the new function.

llvm/include/llvm/ADT/DenseMap.h
206

Just a question: would it be better to return const ValueT & like std::map::at would? Do we also want a non-const version of this?

Could you also add this to StringMap?

Maybe IntervalMap and MapVector too?

I was thinking about this, didn't want to go too aggressive. But it should be easy to add once we reach consensus on the API here:).

llvm/include/llvm/ADT/DenseMap.h
206

Good question, I'm following the signature of existing lookup methods, I _guess_ the reason is more flexible API?

lattner accepted this revision.Feb 15 2023, 9:27 PM

Awesome, thank you for driving this!

llvm/include/llvm/ADT/DenseMap.h
206

+1, no need to copy non-trivial values.

llvm/include/llvm/ADT/StringMap.h
242

Similarly should return const&

This revision is now accepted and ready to land.Feb 15 2023, 9:27 PM

Address all feedbacks:

  1. Return const reference
StrongerXi marked 4 inline comments as done.Feb 15 2023, 11:41 PM

git clang-format