@@ -223,6 +223,64 @@ static bool isProjectedFromAggregate(SILValue value) {
223
223
return visitor.isMerge ;
224
224
}
225
225
226
+ // ===----------------------------------------------------------------------===//
227
+ // MARK: Expr/Type Inference for Diagnostics
228
+ // ===----------------------------------------------------------------------===//
229
+
230
+ namespace {
231
+
232
+ struct InferredCallerArgumentTypeInfo {
233
+ Type inferredType;
234
+ ApplyExpr *sourceApply;
235
+ ApplyIsolationCrossing isolationCrossing;
236
+ Expr *foundExpr;
237
+
238
+ InferredCallerArgumentTypeInfo (const Operand *op);
239
+ };
240
+
241
+ } // namespace
242
+
243
+ InferredCallerArgumentTypeInfo::InferredCallerArgumentTypeInfo (
244
+ const Operand *op)
245
+ : inferredType(op->get ()->getType().getASTType()), sourceApply(nullptr ),
246
+ isolationCrossing(), foundExpr(nullptr ) {
247
+ sourceApply = op->getUser ()->getLoc ().getAsASTNode <ApplyExpr>();
248
+ assert (sourceApply);
249
+ isolationCrossing = *sourceApply->getIsolationCrossing ();
250
+
251
+ // Grab out full apply site and see if we can find a better expr.
252
+ SILInstruction *i = const_cast <SILInstruction *>(op->getUser ());
253
+ auto fai = FullApplySite::isa (i);
254
+
255
+ // If we have self, then infer it.
256
+ if (fai.hasSelfArgument () && op == &fai.getSelfArgumentOperand ()) {
257
+ if (auto callExpr = dyn_cast<CallExpr>(sourceApply))
258
+ if (auto calledExpr =
259
+ dyn_cast<DotSyntaxCallExpr>(callExpr->getDirectCallee ()))
260
+ foundExpr = calledExpr->getBase ();
261
+ } else {
262
+ // Otherwise, try to infer using the operand of the ApplyExpr.
263
+ unsigned argNum = [&]() -> unsigned {
264
+ if (fai.isCalleeOperand (*op))
265
+ return op->getOperandNumber ();
266
+ return fai.getAppliedArgIndex (*op);
267
+ }();
268
+ if (argNum < sourceApply->getArgs ()->size ()) {
269
+ auto *expr = sourceApply->getArgs ()->getExpr (argNum);
270
+
271
+ // If we have an erasure expression, lets use the original type. We do
272
+ // this since we are not saying the specific parameter that is the
273
+ // issue and we are using the type to explain it to the user.
274
+ if (auto *erasureExpr = dyn_cast<ErasureExpr>(expr))
275
+ expr = erasureExpr->getSubExpr ();
276
+ foundExpr = expr;
277
+ }
278
+ }
279
+
280
+ if (foundExpr)
281
+ inferredType = foundExpr->findOriginalType ();
282
+ }
283
+
226
284
// ===----------------------------------------------------------------------===//
227
285
// MARK: Instruction Level Model
228
286
// ===----------------------------------------------------------------------===//
@@ -391,12 +449,12 @@ struct PartitionOpBuilder {
391
449
lookupValueID (tgt), lookupValueID (src), currentInst));
392
450
}
393
451
394
- void addTransfer (SILValue representative, Operand *op, Expr *expr ) {
452
+ void addTransfer (SILValue representative, Operand *op) {
395
453
assert (valueHasID (representative) &&
396
454
" transferred value should already have been encountered" );
397
455
398
456
currentInstPartitionOps.emplace_back (
399
- PartitionOp::Transfer (lookupValueID (representative), op, expr ));
457
+ PartitionOp::Transfer (lookupValueID (representative), op));
400
458
}
401
459
402
460
void addMerge (SILValue fst, SILValue snd) {
@@ -832,39 +890,23 @@ class PartitionOpTranslator {
832
890
if (auto value = tryToTrackValue (op))
833
891
builder.addRequire (value->getRepresentative ());
834
892
835
- auto getSourceArg = [&](unsigned i) {
836
- if (i < sourceApply->getArgs ()->size ())
837
- return sourceApply->getArgs ()->getExpr (i);
838
- return (Expr *)nullptr ;
839
- };
840
-
841
- auto getSourceSelf = [&]() {
842
- if (auto callExpr = dyn_cast<CallExpr>(sourceApply))
843
- if (auto calledExpr =
844
- dyn_cast<DotSyntaxCallExpr>(callExpr->getDirectCallee ()))
845
- return calledExpr->getBase ();
846
- return (Expr *)nullptr ;
847
- };
848
-
849
893
auto handleSILOperands = [&](MutableArrayRef<Operand> operands) {
850
- int argNum = 0 ;
851
- for (auto &operand : operands) {
852
- if (auto value = tryToTrackValue (operand.get ()))
853
- builder.addTransfer (value->getRepresentative (), &operand, getSourceArg (argNum));
854
- argNum++;
894
+ for (auto &op : operands) {
895
+ if (auto value = tryToTrackValue (op.get ()))
896
+ builder.addTransfer (value->getRepresentative (), &op);
855
897
}
856
898
};
857
899
858
- auto handleSILSelf = [&](Operand & self) {
859
- if (auto value = tryToTrackValue (self. get ()))
860
- builder.addTransfer (value->getRepresentative (), & self, getSourceSelf () );
900
+ auto handleSILSelf = [&](Operand * self) {
901
+ if (auto value = tryToTrackValue (self-> get ()))
902
+ builder.addTransfer (value->getRepresentative (), self);
861
903
};
862
904
863
905
if (applySite.hasSelfArgument ()) {
864
906
handleSILOperands (applySite.getOperandsWithoutSelf ());
865
- handleSILSelf (applySite.getSelfArgumentOperand ());
907
+ handleSILSelf (& applySite.getSelfArgumentOperand ());
866
908
} else {
867
- handleSILOperands (applySite. getArgumentOperands ());
909
+ handleSILOperands (applySite-> getAllOperands ());
868
910
}
869
911
870
912
// non-sendable results can't be returned from cross-isolation calls without
@@ -1660,8 +1702,8 @@ class TransferRequireAccumulator {
1660
1702
auto diag = fn->getASTContext ().Diags .diagnose (
1661
1703
loc.getSourceLoc (), diag::transfer_yields_race, numDisplayed,
1662
1704
numDisplayed != 1 , numHidden > 0 , numHidden);
1663
- if (auto sourceExpr = transferOp.getSourceExpr ())
1664
- diag.highlight (sourceExpr-> getSourceRange ());
1705
+ if (auto sourceExpr = transferOp.getSourceLoc ())
1706
+ diag.highlight (sourceExpr. getSourceRange ());
1665
1707
return ;
1666
1708
}
1667
1709
@@ -1671,7 +1713,7 @@ class TransferRequireAccumulator {
1671
1713
// transfer...
1672
1714
if (numRequiresToProcess-- == 0 )
1673
1715
break ;
1674
- auto loc = requireOp.getSourceLoc ();
1716
+ auto loc = requireOp.getSourceInst ()-> getLoc ();
1675
1717
fn->getASTContext ()
1676
1718
.Diags .diagnose (loc.getSourceLoc (), diag::possible_racy_access_site)
1677
1719
.highlight (loc.getSourceRange ());
@@ -1710,17 +1752,17 @@ class TransferRequireAccumulator {
1710
1752
assert (isolationCrossing && " ApplyExprs should be transferring only if "
1711
1753
" they are isolation crossing" );
1712
1754
1713
- auto argExpr = transferOp.getSourceExpr ();
1714
- assert (argExpr && " sourceExpr should be populated for ApplyExpr transfers" );
1755
+ InferredCallerArgumentTypeInfo argTypeInfo (transferOp.getSourceOp ());
1715
1756
1757
+ auto loc = transferOp.getSourceLoc ();
1716
1758
sourceInst->getFunction ()
1717
1759
->getASTContext ()
1718
1760
.Diags
1719
- .diagnose (argExpr-> getLoc (), diag::call_site_transfer_yields_race,
1720
- argExpr-> findOriginalType () ,
1721
- isolationCrossing. value () .getCallerIsolation (),
1722
- isolationCrossing. value () .getCalleeIsolation ())
1723
- .highlight (argExpr-> getSourceRange ());
1761
+ .diagnose (loc. getSourceLoc (), diag::call_site_transfer_yields_race,
1762
+ argTypeInfo. inferredType ,
1763
+ argTypeInfo. isolationCrossing .getCallerIsolation (),
1764
+ argTypeInfo. isolationCrossing .getCalleeIsolation ())
1765
+ .highlight (loc. getSourceRange ());
1724
1766
return true ;
1725
1767
}
1726
1768
};
@@ -2206,17 +2248,17 @@ class PartitionAnalysis {
2206
2248
" they are isolation crossing" );
2207
2249
return false ;
2208
2250
}
2209
- auto argExpr = transferOp.getSourceExpr ();
2251
+ auto argExpr = transferOp.getSourceLoc ();
2210
2252
if (!argExpr)
2211
2253
assert (false && " sourceExpr should be populated for ApplyExpr transfers" );
2212
2254
2213
2255
function->getASTContext ()
2214
2256
.Diags
2215
- .diagnose (argExpr-> getLoc (), diag::call_site_transfer_yields_race,
2216
- argExpr-> findOriginalType (),
2257
+ .diagnose (argExpr. getSourceLoc (), diag::call_site_transfer_yields_race,
2258
+ transferOp. getSourceOp ()-> get ()-> getType (). getASTType (),
2217
2259
isolationCrossing.value ().getCallerIsolation (),
2218
2260
isolationCrossing.value ().getCalleeIsolation ())
2219
- .highlight (argExpr-> getSourceRange ());
2261
+ .highlight (argExpr. getSourceRange ());
2220
2262
return true ;
2221
2263
}
2222
2264
0 commit comments