@@ -1567,17 +1567,7 @@ bool AssignmentFailure::diagnoseAsError() {
1567
1567
Type neededType = contextualType->getInOutObjectType ();
1568
1568
Type actualType = getType (immInfo.first )->getInOutObjectType ();
1569
1569
if (!neededType->isEqual (actualType)) {
1570
- if (DeclDiagnostic.ID == diag::cannot_pass_rvalue_inout_subelement.ID ) {
1571
- // We have a special diagnostic with tailored wording for this
1572
- // common case.
1573
- emitDiagnostic (Loc, diag::cannot_pass_rvalue_inout_converted,
1574
- actualType, neededType)
1575
- .highlight (immInfo.first ->getSourceRange ());
1576
-
1577
- if (auto inoutExpr = dyn_cast<InOutExpr>(immInfo.first ))
1578
- fixItChangeInoutArgType (inoutExpr->getSubExpr (), actualType,
1579
- neededType);
1580
- } else {
1570
+ if (DeclDiagnostic.ID != diag::cannot_pass_rvalue_inout_subelement.ID ) {
1581
1571
emitDiagnostic (Loc, DeclDiagnostic,
1582
1572
" implicit conversion from '" + actualType->getString () +
1583
1573
" ' to '" + neededType->getString () +
@@ -1601,68 +1591,6 @@ bool AssignmentFailure::diagnoseAsError() {
1601
1591
return true ;
1602
1592
}
1603
1593
1604
- void AssignmentFailure::fixItChangeInoutArgType (const Expr *arg,
1605
- Type actualType,
1606
- Type neededType) const {
1607
- auto *DC = getDC ();
1608
- auto *DRE = dyn_cast<DeclRefExpr>(arg);
1609
- if (!DRE)
1610
- return ;
1611
-
1612
- auto *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl ());
1613
- if (!VD)
1614
- return ;
1615
-
1616
- // Don't emit for non-local variables.
1617
- // (But in script-mode files, we consider module-scoped
1618
- // variables in the same file to be local variables.)
1619
- auto VDC = VD->getDeclContext ();
1620
- bool isLocalVar = VDC->isLocalContext ();
1621
- if (!isLocalVar && VDC->isModuleScopeContext ()) {
1622
- auto argFile = DC->getParentSourceFile ();
1623
- auto varFile = VDC->getParentSourceFile ();
1624
- isLocalVar = (argFile == varFile && argFile->isScriptMode ());
1625
- }
1626
- if (!isLocalVar)
1627
- return ;
1628
-
1629
- SmallString<32 > scratch;
1630
- SourceLoc endLoc; // Filled in if we decide to diagnose this
1631
- SourceLoc startLoc; // Left invalid if we're inserting
1632
-
1633
- auto isSimpleTypelessPattern = [](Pattern *P) -> bool {
1634
- if (auto VP = dyn_cast_or_null<VarPattern>(P))
1635
- P = VP->getSubPattern ();
1636
- return P && isa<NamedPattern>(P);
1637
- };
1638
-
1639
- auto typeRange = VD->getTypeSourceRangeForDiagnostics ();
1640
- if (typeRange.isValid ()) {
1641
- startLoc = typeRange.Start ;
1642
- endLoc = typeRange.End ;
1643
- } else if (isSimpleTypelessPattern (VD->getParentPattern ())) {
1644
- endLoc = VD->getNameLoc ();
1645
- scratch += " : " ;
1646
- }
1647
-
1648
- if (endLoc.isInvalid ())
1649
- return ;
1650
-
1651
- scratch += neededType.getString ();
1652
-
1653
- // Adjust into the location where we actually want to insert
1654
- endLoc = Lexer::getLocForEndOfToken (getASTContext ().SourceMgr , endLoc);
1655
-
1656
- // Since we already adjusted endLoc, this will turn an insertion
1657
- // into a zero-character replacement.
1658
- if (!startLoc.isValid ())
1659
- startLoc = endLoc;
1660
-
1661
- emitDiagnostic (VD->getLoc (), diag::inout_change_var_type_if_possible,
1662
- actualType, neededType)
1663
- .fixItReplaceChars (startLoc, endLoc, scratch);
1664
- }
1665
-
1666
1594
std::pair<Expr *, Optional<OverloadChoice>>
1667
1595
AssignmentFailure::resolveImmutableBase (Expr *expr) const {
1668
1596
auto &cs = getConstraintSystem ();
@@ -4348,3 +4276,79 @@ bool ThrowingFunctionConversionFailure::diagnoseAsError() {
4348
4276
getFromType (), getToType ());
4349
4277
return true ;
4350
4278
}
4279
+
4280
+ bool InOutConversionFailure::diagnoseAsError () {
4281
+ auto *anchor = getAnchor ();
4282
+ emitDiagnostic (anchor->getLoc (), diag::cannot_pass_rvalue_inout_converted,
4283
+ getFromType (), getToType ());
4284
+ fixItChangeArgumentType ();
4285
+ return true ;
4286
+ }
4287
+
4288
+ void InOutConversionFailure::fixItChangeArgumentType () const {
4289
+ auto *argExpr = getAnchor ();
4290
+ auto *DC = getDC ();
4291
+
4292
+ if (auto *IOE = dyn_cast<InOutExpr>(argExpr))
4293
+ argExpr = IOE->getSubExpr ();
4294
+
4295
+ auto *DRE = dyn_cast<DeclRefExpr>(argExpr);
4296
+ if (!DRE)
4297
+ return ;
4298
+
4299
+ auto *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl ());
4300
+ if (!VD)
4301
+ return ;
4302
+
4303
+ // Don't emit for non-local variables.
4304
+ // (But in script-mode files, we consider module-scoped
4305
+ // variables in the same file to be local variables.)
4306
+ auto VDC = VD->getDeclContext ();
4307
+ bool isLocalVar = VDC->isLocalContext ();
4308
+ if (!isLocalVar && VDC->isModuleScopeContext ()) {
4309
+ auto argFile = DC->getParentSourceFile ();
4310
+ auto varFile = VDC->getParentSourceFile ();
4311
+ isLocalVar = (argFile == varFile && argFile->isScriptMode ());
4312
+ }
4313
+ if (!isLocalVar)
4314
+ return ;
4315
+
4316
+ auto actualType = getFromType ();
4317
+ auto neededType = getToType ();
4318
+
4319
+ SmallString<32 > scratch;
4320
+ SourceLoc endLoc; // Filled in if we decide to diagnose this
4321
+ SourceLoc startLoc; // Left invalid if we're inserting
4322
+
4323
+ auto isSimpleTypelessPattern = [](Pattern *P) -> bool {
4324
+ if (auto VP = dyn_cast_or_null<VarPattern>(P))
4325
+ P = VP->getSubPattern ();
4326
+ return P && isa<NamedPattern>(P);
4327
+ };
4328
+
4329
+ auto typeRange = VD->getTypeSourceRangeForDiagnostics ();
4330
+ if (typeRange.isValid ()) {
4331
+ startLoc = typeRange.Start ;
4332
+ endLoc = typeRange.End ;
4333
+ } else if (isSimpleTypelessPattern (VD->getParentPattern ())) {
4334
+ endLoc = VD->getNameLoc ();
4335
+ scratch += " : " ;
4336
+ }
4337
+
4338
+ if (endLoc.isInvalid ())
4339
+ return ;
4340
+
4341
+ scratch += neededType.getString ();
4342
+
4343
+ // Adjust into the location where we actually want to insert
4344
+ endLoc = Lexer::getLocForEndOfToken (getASTContext ().SourceMgr , endLoc);
4345
+
4346
+ // Since we already adjusted endLoc, this will turn an insertion
4347
+ // into a zero-character replacement.
4348
+ if (!startLoc.isValid ())
4349
+ startLoc = endLoc;
4350
+
4351
+ emitDiagnostic (VD->getLoc (), diag::inout_change_var_type_if_possible,
4352
+ actualType, neededType)
4353
+ .fixItReplaceChars (startLoc, endLoc, scratch);
4354
+ }
0 commit comments