@@ -140,7 +140,6 @@ enum class Emitted {
140
140
// / so caches should generally directly or indirectly include a FileRef
141
141
// / as part of key (e.g. via core::Loc).
142
142
class SCIPState {
143
- string symbolScratchBuffer;
144
143
UnorderedMap<UntypedGenericSymbolRef, string> symbolStringCache;
145
144
146
145
// / Cache of occurrences for locals that have been emitted in this function.
@@ -202,7 +201,7 @@ class SCIPState {
202
201
203
202
public:
204
203
SCIPState (GemMetadata metadata)
205
- : symbolScratchBuffer (), symbolStringCache (), localOccurrenceCache (), symbolOccurrenceCache (),
204
+ : symbolStringCache (), localOccurrenceCache (), symbolOccurrenceCache (), potentialRefOnlySymbols (),
206
205
gemMetadata (metadata), occurrenceMap(), emittedSymbols(), symbolMap(), documents(), externalSymbols() {}
207
206
~SCIPState () = default ;
208
207
SCIPState (SCIPState &&) = default;
@@ -218,31 +217,35 @@ class SCIPState {
218
217
// / If the returned value is as success, the pointer is non-null.
219
218
// /
220
219
// / The argument symbol is used instead of recomputing from scratch if it is non-null.
221
- absl::StatusOr< const string *> saveSymbolString (const core::GlobalState &gs, UntypedGenericSymbolRef symRef,
222
- const scip::Symbol *symbol) {
220
+ absl::Status saveSymbolString (const core::GlobalState &gs, UntypedGenericSymbolRef symRef,
221
+ const scip::Symbol *symbol, std::string &output ) {
223
222
auto pair = this ->symbolStringCache .find (symRef);
224
223
if (pair != this ->symbolStringCache .end ()) {
225
- return &pair->second ;
224
+ // Yes, there is a "redundant" string copy here when we could "just"
225
+ // optimize it to return an interior pointer into the cache. However,
226
+ // that creates a footgun where this method cannot be safely called
227
+ // across invocations to non-const method calls on SCIPState.
228
+ output = pair->second ;
229
+ return absl::OkStatus ();
226
230
}
227
231
228
- this ->symbolScratchBuffer .clear ();
229
-
230
232
absl::Status status;
231
233
if (symbol) {
232
- status = scip::utils::emitSymbolString (*symbol, this -> symbolScratchBuffer );
234
+ status = scip::utils::emitSymbolString (*symbol, output );
233
235
} else {
234
236
scip::Symbol symbol;
235
237
status = symRef.symbolForExpr (gs, this ->gemMetadata , {}, symbol);
236
238
if (!status.ok ()) {
237
239
return status;
238
240
}
239
- status = scip::utils::emitSymbolString (symbol, this -> symbolScratchBuffer );
241
+ status = scip::utils::emitSymbolString (symbol, output );
240
242
}
241
243
if (!status.ok ()) {
242
244
return status;
243
245
}
244
- symbolStringCache.insert ({symRef, this ->symbolScratchBuffer });
245
- return &symbolStringCache[symRef];
246
+ symbolStringCache.insert ({symRef, output});
247
+
248
+ return absl::OkStatus ();
246
249
}
247
250
248
251
private:
@@ -361,9 +364,8 @@ class SCIPState {
361
364
SmallVec<scip::Relationship> &rels) {
362
365
untypedSymRef.saveRelationships (gs, this ->relationshipsMap [file], rels,
363
366
[this , &gs](UntypedGenericSymbolRef sym, std::string &out) {
364
- auto status = this ->saveSymbolString (gs, sym, nullptr );
367
+ auto status = this ->saveSymbolString (gs, sym, nullptr , out );
365
368
ENFORCE (status.ok ());
366
- out = *status.value ();
367
369
});
368
370
}
369
371
@@ -397,11 +399,11 @@ class SCIPState {
397
399
if (!status.ok ()) {
398
400
return status;
399
401
}
400
- absl::StatusOr<const string *> valueOrStatus (this ->saveSymbolString (gs, untypedSymRef, &symbol));
401
- if (!valueOrStatus.ok ()) {
402
- return valueOrStatus.status ();
402
+ std::string symbolString;
403
+ status = this ->saveSymbolString (gs, untypedSymRef, &symbol, symbolString);
404
+ if (!status.ok ()) {
405
+ return status;
403
406
}
404
- const string &symbolString = *valueOrStatus.value ();
405
407
406
408
SmallVec<string> docs;
407
409
symRef.saveDocStrings (gs, symRef.definitionType (), occLoc, docs);
@@ -444,11 +446,11 @@ class SCIPState {
444
446
}
445
447
auto &gs = ctx.state ;
446
448
auto file = ctx.file ;
447
- absl::StatusOr<const string *> valueOrStatus (this ->saveSymbolString (gs, symRef.withoutType (), nullptr ));
448
- if (!valueOrStatus.ok ()) {
449
- return valueOrStatus.status ();
449
+ std::string symbolString;
450
+ auto status = this ->saveSymbolString (gs, symRef.withoutType (), nullptr , symbolString);
451
+ if (!status.ok ()) {
452
+ return status;
450
453
}
451
- const string &symbolString = *valueOrStatus.value ();
452
454
453
455
SmallVec<string> overrideDocs{};
454
456
using Kind = GenericSymbolRef::Kind;
@@ -479,12 +481,11 @@ class SCIPState {
479
481
void finalizeRefOnlySymbolInfos (const core::GlobalState &gs, core::FileRef file) {
480
482
auto &potentialSyms = this ->potentialRefOnlySymbols [file];
481
483
484
+ std::string symbolString;
482
485
for (auto symRef : potentialSyms) {
483
- auto valueOrError = this ->saveSymbolString (gs, symRef, nullptr );
484
- if (!valueOrError.ok ()) {
486
+ if (!this ->saveSymbolString (gs, symRef, nullptr , symbolString).ok ()) {
485
487
continue ;
486
488
}
487
- auto &symbolString = *valueOrError.value ();
488
489
// Avoid calling saveRelationships if we already emitted this.
489
490
// saveSymbolInfo does this check too, so it isn't strictly needed.
490
491
if (this ->alreadyEmittedSymbolInfo (file, symbolString)) {
0 commit comments