@@ -3430,19 +3430,19 @@ static void validateTypealiasType(TypeChecker &tc, TypeAliasDecl *typeAlias) {
3430
3430
}
3431
3431
3432
3432
3433
- // / Bind the given function declaration, which declares an operator, to
3434
- // / the corresponding operator declaration.
3435
- void bindFuncDeclToOperator (TypeChecker &TC, FuncDecl *FD) {
3436
- OperatorDecl *op = nullptr ;
3433
+ // / Bind the given function declaration, which declares an operator, to the corresponding operator declaration.
3434
+ llvm::Expected<OperatorDecl *>
3435
+ FunctionOperatorRequest::evaluate (Evaluator &evaluator, FuncDecl *FD) const {
3436
+ auto &C = FD->getASTContext ();
3437
+ auto &diags = C.Diags ;
3437
3438
auto operatorName = FD->getFullName ().getBaseIdentifier ();
3438
3439
3439
3440
// Check for static/final/class when we're in a type.
3440
3441
auto dc = FD->getDeclContext ();
3441
3442
if (dc->isTypeContext ()) {
3442
3443
if (!FD->isStatic ()) {
3443
- TC.diagnose (FD->getLoc (), diag::nonstatic_operator_in_type,
3444
- operatorName,
3445
- dc->getDeclaredInterfaceType ())
3444
+ FD->diagnose (diag::nonstatic_operator_in_type,
3445
+ operatorName, dc->getDeclaredInterfaceType ())
3446
3446
.fixItInsert (FD->getAttributeInsertionLoc (/* forModifier=*/ true ),
3447
3447
" static " );
3448
3448
@@ -3451,17 +3451,18 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) {
3451
3451
// For a class, we also need the function or class to be 'final'.
3452
3452
if (!classDecl->isFinal () && !FD->isFinal () &&
3453
3453
FD->getStaticSpelling () != StaticSpellingKind::KeywordStatic) {
3454
- TC. diagnose ( FD->getLoc (), diag::nonfinal_operator_in_class,
3455
- operatorName, dc->getDeclaredInterfaceType ())
3454
+ FD->diagnose ( diag::nonfinal_operator_in_class,
3455
+ operatorName, dc->getDeclaredInterfaceType ())
3456
3456
.fixItInsert (FD->getAttributeInsertionLoc (/* forModifier=*/ true ),
3457
3457
" final " );
3458
- FD->getAttrs ().add (new (TC. Context ) FinalAttr (/* IsImplicit=*/ true ));
3458
+ FD->getAttrs ().add (new (C ) FinalAttr (/* IsImplicit=*/ true ));
3459
3459
}
3460
3460
}
3461
3461
} else if (!dc->isModuleScopeContext ()) {
3462
- TC. diagnose (FD, diag::operator_in_local_scope);
3462
+ FD-> diagnose (diag::operator_in_local_scope);
3463
3463
}
3464
3464
3465
+ OperatorDecl *op = nullptr ;
3465
3466
SourceFile &SF = *FD->getDeclContext ()->getParentSourceFile ();
3466
3467
if (FD->isUnaryOperator ()) {
3467
3468
if (FD->getAttrs ().hasAttribute <PrefixAttr>()) {
@@ -3485,21 +3486,21 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) {
3485
3486
// If we found both prefix and postfix, or neither prefix nor postfix,
3486
3487
// complain. We can't fix this situation.
3487
3488
if (static_cast <bool >(prefixOp) == static_cast <bool >(postfixOp)) {
3488
- TC .diagnose (FD, diag::declared_unary_op_without_attribute);
3489
+ diags .diagnose (FD, diag::declared_unary_op_without_attribute);
3489
3490
3490
3491
// If we found both, point at them.
3491
3492
if (prefixOp) {
3492
- TC .diagnose (prefixOp, diag::unary_operator_declaration_here, false )
3493
+ diags .diagnose (prefixOp, diag::unary_operator_declaration_here, false )
3493
3494
.fixItInsert (FD->getLoc (), " prefix " );
3494
- TC .diagnose (postfixOp, diag::unary_operator_declaration_here, true )
3495
+ diags .diagnose (postfixOp, diag::unary_operator_declaration_here, true )
3495
3496
.fixItInsert (FD->getLoc (), " postfix " );
3496
3497
} else {
3497
3498
// FIXME: Introduce a Fix-It that adds the operator declaration?
3498
3499
}
3499
3500
3500
3501
// FIXME: Errors could cascade here, because name lookup for this
3501
3502
// operator won't find this declaration.
3502
- return ;
3503
+ return nullptr ;
3503
3504
}
3504
3505
3505
3506
// We found only one operator declaration, so we know whether this
@@ -3519,29 +3520,33 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) {
3519
3520
}
3520
3521
3521
3522
// Emit diagnostic with the Fix-It.
3522
- TC .diagnose (FD->getFuncLoc (), diag::unary_op_missing_prepos_attribute,
3523
+ diags .diagnose (FD->getFuncLoc (), diag::unary_op_missing_prepos_attribute,
3523
3524
static_cast <bool >(postfixOp))
3524
3525
.fixItInsert (FD->getFuncLoc (), insertionText);
3525
- TC .diagnose (op, diag::unary_operator_declaration_here,
3526
+ diags .diagnose (op, diag::unary_operator_declaration_here,
3526
3527
static_cast <bool >(postfixOp));
3527
3528
}
3528
3529
} else if (FD->isBinaryOperator ()) {
3529
3530
op = SF.lookupInfixOperator (operatorName,
3530
3531
FD->isCascadingContextForLookup (false ),
3531
3532
FD->getLoc ());
3532
3533
} else {
3533
- TC .diagnose (FD, diag::invalid_arg_count_for_operator);
3534
- return ;
3534
+ diags .diagnose (FD, diag::invalid_arg_count_for_operator);
3535
+ return nullptr ;
3535
3536
}
3536
3537
3537
3538
if (!op) {
3538
3539
SourceLoc insertionLoc;
3539
3540
if (isa<SourceFile>(FD->getParent ())) {
3540
- // Parent context is SourceFile, insertion location is start of func declaration
3541
- // or unary operator
3542
- insertionLoc = FD->isUnaryOperator () ? FD->getAttrs ().getStartLoc () : FD->getStartLoc ();
3541
+ // Parent context is SourceFile, insertion location is start of func
3542
+ // declaration or unary operator
3543
+ if (FD->isUnaryOperator ()) {
3544
+ insertionLoc = FD->getAttrs ().getStartLoc ();
3545
+ } else {
3546
+ insertionLoc = FD->getStartLoc ();
3547
+ }
3543
3548
} else {
3544
- // Finding top-level decl context before SourceFile and inserting before it
3549
+ // Find the topmost non-file decl context and insert there.
3545
3550
for (DeclContext *CurContext = FD->getLocalContext ();
3546
3551
!isa<SourceFile>(CurContext);
3547
3552
CurContext = CurContext->getParent ()) {
@@ -3552,25 +3557,28 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) {
3552
3557
}
3553
3558
3554
3559
SmallString<128 > insertion;
3555
- auto numOfParams = FD->getParameters ()->size ();
3556
- if (numOfParams == 1 ) {
3557
- if (FD->getAttrs ().hasAttribute <PrefixAttr>())
3558
- insertion += " prefix operator " ;
3559
- else
3560
- insertion += " postfix operator " ;
3561
- } else if (numOfParams == 2 ) {
3562
- insertion += " infix operator " ;
3563
- }
3560
+ {
3561
+ llvm::raw_svector_ostream str (insertion);
3562
+ assert (FD->isUnaryOperator () || FD->isBinaryOperator ());
3563
+ if (FD->isUnaryOperator ()) {
3564
+ if (FD->getAttrs ().hasAttribute <PrefixAttr>())
3565
+ str << " prefix operator " ;
3566
+ else
3567
+ str << " postfix operator " ;
3568
+ } else {
3569
+ str << " infix operator " ;
3570
+ }
3564
3571
3565
- insertion += operatorName.str ();
3566
- insertion += " : <# Precedence Group #>\n " ;
3567
- InFlightDiagnostic opDiagnostic = TC.diagnose (FD, diag::declared_operator_without_operator_decl);
3572
+ str << operatorName.str () << " : <# Precedence Group #>\n " ;
3573
+ }
3574
+ InFlightDiagnostic opDiagnostic =
3575
+ diags.diagnose (FD, diag::declared_operator_without_operator_decl);
3568
3576
if (insertionLoc.isValid ())
3569
3577
opDiagnostic.fixItInsert (insertionLoc, insertion);
3570
- return ;
3578
+ return nullptr ;
3571
3579
}
3572
3580
3573
- FD-> setOperatorDecl (op) ;
3581
+ return op ;
3574
3582
}
3575
3583
3576
3584
bool swift::isMemberOperator (FuncDecl *decl, Type type) {
@@ -3868,10 +3876,9 @@ void TypeChecker::validateDecl(ValueDecl *D) {
3868
3876
3869
3877
DeclValidationRAII IBV (FD);
3870
3878
3871
- // Bind operator functions to the corresponding operator declaration.
3872
- if (FD->isOperator ())
3873
- bindFuncDeclToOperator (*this , FD);
3874
-
3879
+ // Force computing the operator decl in case it emits diagnostics.
3880
+ (void ) FD->getOperatorDecl ();
3881
+
3875
3882
// Validate 'static'/'class' on functions in extensions.
3876
3883
auto StaticSpelling = FD->getStaticSpelling ();
3877
3884
if (StaticSpelling != StaticSpellingKind::None &&
0 commit comments