Skip to content

Commit 56095cf

Browse files
committed
Sema: duplicate the note about which import limits access-level
Access-level on imports limit where decls from the target module can be referenced. This is reported by the typical error about and a note on the import. However, when using an IDE and editing a large file, the note on the import is easy to miss. Address this by duplicating the information on the error line as well so it's never out of the current viewport. rdar://119438201
1 parent f4d7327 commit 56095cf

5 files changed

+182
-44
lines changed

include/swift/AST/DiagnosticsSema.def

+5
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,11 @@ NOTE(decl_import_via_here,none,
25082508
"'%select{private|fileprivate|internal|package|%ERROR|%ERROR}1' "
25092509
"from %2 here",
25102510
(const Decl *, AccessLevel, const ModuleDecl*))
2511+
NOTE(decl_import_via_local,none,
2512+
"%kind0 is imported by this file as "
2513+
"'%select{private|fileprivate|internal|package|%ERROR|%ERROR}1' "
2514+
"from %2",
2515+
(const Decl *, AccessLevel, const ModuleDecl*))
25112516

25122517
// Opaque return types
25132518
ERROR(opaque_type_invalid_constraint,none,

lib/Sema/TypeCheckAccess.cpp

+55-43
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,8 @@ static void highlightOffendingType(InFlightDiagnostic &diag,
382382

383383
/// Emit a note on \p limitImport when it restricted the access level
384384
/// of a type.
385-
static void noteLimitingImport(ASTContext &ctx,
385+
static void noteLimitingImport(const Decl *userDecl,
386+
ASTContext &ctx,
386387
const ImportAccessLevel limitImport,
387388
const TypeRepr *complainRepr) {
388389
if (!limitImport.has_value())
@@ -393,6 +394,16 @@ static void noteLimitingImport(ASTContext &ctx,
393394

394395
if (auto *declRefTR = dyn_cast_or_null<DeclRefTypeRepr>(complainRepr)) {
395396
ValueDecl *VD = declRefTR->getBoundDecl();
397+
398+
// When using an IDE in a large file the decl_import_via_here note
399+
// may be easy to miss on the import. Duplicate the information on the
400+
// error line as well so it can't be missed.
401+
if (userDecl)
402+
userDecl->diagnose(diag::decl_import_via_local,
403+
VD,
404+
limitImport->accessLevel,
405+
limitImport->module.importedModule);
406+
396407
ctx.Diags.diagnose(limitImport->importLoc,
397408
diag::decl_import_via_here,
398409
VD,
@@ -405,6 +416,16 @@ static void noteLimitingImport(ASTContext &ctx,
405416
}
406417
}
407418

419+
static void noteLimitingImport(const Decl *userDecl,
420+
const ImportAccessLevel limitImport,
421+
const TypeRepr *complainRepr) {
422+
if (!limitImport.has_value())
423+
return;
424+
425+
ASTContext &ctx = userDecl->getASTContext();
426+
noteLimitingImport(userDecl, ctx, limitImport, complainRepr);
427+
}
428+
408429
void AccessControlCheckerBase::checkGenericParamAccess(
409430
const GenericContext *ownerCtx,
410431
const Decl *ownerDecl,
@@ -483,7 +504,7 @@ void AccessControlCheckerBase::checkGenericParamAccess(
483504
Context.Diags.diagnose(ownerDecl, diagID, ownerDecl->getDescriptiveKind(),
484505
accessControlErrorKind == ACEK::Requirement);
485506
highlightOffendingType(diag, complainRepr);
486-
noteLimitingImport(Context, minImportLimit, complainRepr);
507+
noteLimitingImport(/*userDecl*/nullptr, Context, minImportLimit, complainRepr);
487508
return;
488509
}
489510

@@ -500,7 +521,7 @@ void AccessControlCheckerBase::checkGenericParamAccess(
500521
contextAccess, minAccess, isa<FileUnit>(DC),
501522
accessControlErrorKind == ACEK::Requirement);
502523
highlightOffendingType(diag, complainRepr);
503-
noteLimitingImport(Context, minImportLimit, complainRepr);
524+
noteLimitingImport(/*userDecl*/nullptr, Context, minImportLimit, complainRepr);
504525
}
505526

506527
void AccessControlCheckerBase::checkGenericParamAccess(
@@ -532,7 +553,7 @@ void AccessControlCheckerBase::checkGlobalActorAccess(const Decl *D) {
532553
auto diag = D->diagnose(diag::global_actor_not_usable_from_inline,
533554
VD);
534555
highlightOffendingType(diag, complainRepr);
535-
noteLimitingImport(D->getASTContext(), importLimit, complainRepr);
556+
noteLimitingImport(D, importLimit, complainRepr);
536557
return;
537558
}
538559

@@ -544,7 +565,7 @@ void AccessControlCheckerBase::checkGlobalActorAccess(const Decl *D) {
544565
auto diag = D->diagnose(diag::global_actor_access, declAccess, VD,
545566
typeAccess, globalActorDecl->getName());
546567
highlightOffendingType(diag, complainRepr);
547-
noteLimitingImport(D->getASTContext(), importLimit, complainRepr);
568+
noteLimitingImport(D, importLimit, complainRepr);
548569
});
549570
}
550571

@@ -630,7 +651,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
630651
isTypeContext, isExplicit, theVarAccess,
631652
isa<FileUnit>(theVar->getDeclContext()),
632653
typeAccess, theVar->getInterfaceType());
633-
noteLimitingImport(theVar->getASTContext(), importLimit, complainRepr);
654+
noteLimitingImport(theVar, importLimit, complainRepr);
634655
});
635656
}
636657

@@ -664,7 +685,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
664685
TP->getLoc(), diagID, anyVar->isLet(), isTypeContext, isExplicit,
665686
anyVarAccess, isa<FileUnit>(anyVar->getDeclContext()), typeAccess);
666687
highlightOffendingType(diag, complainRepr);
667-
noteLimitingImport(anyVar->getASTContext(), importLimit, complainRepr);
688+
noteLimitingImport(anyVar, importLimit, complainRepr);
668689
});
669690

670691
// Check the property wrapper types.
@@ -691,7 +712,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
691712
isa<FileUnit>(anyVar->getDeclContext()),
692713
typeAccess);
693714
highlightOffendingType(diag, complainRepr);
694-
noteLimitingImport(anyVar->getASTContext(), importLimit, complainRepr);
715+
noteLimitingImport(anyVar, importLimit, complainRepr);
695716
});
696717
}
697718
}
@@ -740,7 +761,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
740761
auto diag = TAD->diagnose(diagID, isExplicit, aliasAccess, typeAccess,
741762
isa<FileUnit>(TAD->getDeclContext()));
742763
highlightOffendingType(diag, complainRepr);
743-
noteLimitingImport(TAD->getASTContext(), importLimit, complainRepr);
764+
noteLimitingImport(TAD, importLimit, complainRepr);
744765
});
745766
}
746767

@@ -826,8 +847,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
826847
auto diag = assocType->diagnose(diagID, assocType->getFormalAccess(),
827848
minAccess, accessControlErrorKind);
828849
highlightOffendingType(diag, complainRepr);
829-
noteLimitingImport(assocType->getASTContext(), minImportLimit,
830-
complainRepr);
850+
noteLimitingImport(assocType, minImportLimit, complainRepr);
831851
}
832852
}
833853

@@ -863,7 +883,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
863883
auto diag = ED->diagnose(diagID, isExplicit, enumDeclAccess, typeAccess,
864884
isa<FileUnit>(ED->getDeclContext()));
865885
highlightOffendingType(diag, complainRepr);
866-
noteLimitingImport(ED->getASTContext(), importLimit, complainRepr);
886+
noteLimitingImport(ED, importLimit, complainRepr);
867887
});
868888
}
869889
}
@@ -925,7 +945,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
925945
isa<FileUnit>(CD->getDeclContext()),
926946
superclassLocIter->getTypeRepr() != complainRepr);
927947
highlightOffendingType(diag, complainRepr);
928-
noteLimitingImport(CD->getASTContext(), importLimit, complainRepr);
948+
noteLimitingImport(CD, importLimit, complainRepr);
929949
});
930950
}
931951
}
@@ -1018,7 +1038,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
10181038
diagID, isExplicit, protoAccess, protocolControlErrorKind, minAccess,
10191039
isa<FileUnit>(proto->getDeclContext()), declKind);
10201040
highlightOffendingType(diag, complainRepr);
1021-
noteLimitingImport(proto->getASTContext(), minImportLimit, complainRepr);
1041+
noteLimitingImport(proto, minImportLimit, complainRepr);
10221042
}
10231043
}
10241044

@@ -1078,7 +1098,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
10781098
auto diag = SD->diagnose(diagID, isExplicit, subscriptDeclAccess,
10791099
minAccess, problemIsElement);
10801100
highlightOffendingType(diag, complainRepr);
1081-
noteLimitingImport(SD->getASTContext(), minImportLimit, complainRepr);
1101+
noteLimitingImport(SD, minImportLimit, complainRepr);
10821102
}
10831103
}
10841104

@@ -1205,7 +1225,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
12051225
functionKind, entityKind,
12061226
hasInaccessibleParameterWrapper);
12071227
highlightOffendingType(diag, complainRepr);
1208-
noteLimitingImport(fn->getASTContext(), minImportLimit, complainRepr);
1228+
noteLimitingImport(fn, minImportLimit, complainRepr);
12091229
}
12101230
}
12111231

@@ -1225,8 +1245,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
12251245
auto diag =
12261246
EED->diagnose(diagID, EED->getFormalAccess(), typeAccess);
12271247
highlightOffendingType(diag, complainRepr);
1228-
noteLimitingImport(EED->getASTContext(), importLimit,
1229-
complainRepr);
1248+
noteLimitingImport(EED, importLimit, complainRepr);
12301249
});
12311250
}
12321251
}
@@ -1289,7 +1308,7 @@ class AccessControlChecker : public AccessControlCheckerBase,
12891308
auto diag = MD->diagnose(diagID, isExplicit, macroDeclAccess,
12901309
minAccess, problemIsResult);
12911310
highlightOffendingType(diag, complainRepr);
1292-
noteLimitingImport(MD->getASTContext(), minImportLimit, complainRepr);
1311+
noteLimitingImport(MD, minImportLimit, complainRepr);
12931312
}
12941313
}
12951314

@@ -1412,8 +1431,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
14121431
}
14131432
Ctx.Diags.diagnose(NP->getLoc(), diagID, theVar->isLet(),
14141433
isTypeContext, theVar->getInterfaceType());
1415-
noteLimitingImport(theVar->getASTContext(), importLimit,
1416-
complainRepr);
1434+
noteLimitingImport(theVar, importLimit, complainRepr);
14171435
});
14181436
}
14191437

@@ -1452,8 +1470,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
14521470
auto diag = Ctx.Diags.diagnose(TP->getLoc(), diagID, anyVar->isLet(),
14531471
isTypeContext);
14541472
highlightOffendingType(diag, complainRepr);
1455-
noteLimitingImport(anyVar->getASTContext(), importLimit,
1456-
complainRepr);
1473+
noteLimitingImport(anyVar, importLimit, complainRepr);
14571474
});
14581475

14591476
for (auto attr : anyVar->getAttachedPropertyWrappers()) {
@@ -1469,7 +1486,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
14691486
diag::property_wrapper_type_not_usable_from_inline,
14701487
anyVar->isLet(), isTypeContext);
14711488
highlightOffendingType(diag, complainRepr);
1472-
noteLimitingImport(anyVar->getASTContext(), importLimit, complainRepr);
1489+
noteLimitingImport(anyVar, importLimit, complainRepr);
14731490
});
14741491
}
14751492
}
@@ -1508,7 +1525,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
15081525
diagID = diag::type_alias_underlying_type_not_usable_from_inline_warn;
15091526
auto diag = TAD->diagnose(diagID);
15101527
highlightOffendingType(diag, complainRepr);
1511-
noteLimitingImport(TAD->getASTContext(), importLimit, complainRepr);
1528+
noteLimitingImport(TAD, importLimit, complainRepr);
15121529
});
15131530
}
15141531

@@ -1530,8 +1547,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
15301547
diagID = diag::associated_type_not_usable_from_inline_warn;
15311548
auto diag = assocType->diagnose(diagID, ACEK_Requirement);
15321549
highlightOffendingType(diag, complainRepr);
1533-
noteLimitingImport(assocType->getASTContext(), importLimit,
1534-
complainRepr);
1550+
noteLimitingImport(assocType, importLimit, complainRepr);
15351551
});
15361552
}
15371553
checkTypeAccess(assocType->getDefaultDefinitionType(),
@@ -1546,8 +1562,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
15461562
diagID = diag::associated_type_not_usable_from_inline_warn;
15471563
auto diag = assocType->diagnose(diagID, ACEK_DefaultDefinition);
15481564
highlightOffendingType(diag, complainRepr);
1549-
noteLimitingImport(assocType->getASTContext(), importLimit,
1550-
complainRepr);
1565+
noteLimitingImport(assocType, importLimit, complainRepr);
15511566
});
15521567

15531568
if (assocType->getTrailingWhereClause()) {
@@ -1565,8 +1580,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
15651580
diagID = diag::associated_type_not_usable_from_inline_warn;
15661581
auto diag = assocType->diagnose(diagID, ACEK_Requirement);
15671582
highlightOffendingType(diag, complainRepr);
1568-
noteLimitingImport(assocType->getASTContext(), importLimit,
1569-
complainRepr);
1583+
noteLimitingImport(assocType, importLimit, complainRepr);
15701584
});
15711585
}
15721586
}
@@ -1597,7 +1611,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
15971611
diagID = diag::enum_raw_type_not_usable_from_inline_warn;
15981612
auto diag = ED->diagnose(diagID);
15991613
highlightOffendingType(diag, complainRepr);
1600-
noteLimitingImport(ED->getASTContext(), importLimit, complainRepr);
1614+
noteLimitingImport(ED, importLimit, complainRepr);
16011615
});
16021616
}
16031617
}
@@ -1643,7 +1657,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
16431657
auto diag = CD->diagnose(diagID, superclassLocIter->getTypeRepr() !=
16441658
complainRepr);
16451659
highlightOffendingType(diag, complainRepr);
1646-
noteLimitingImport(CD->getASTContext(), importLimit, complainRepr);
1660+
noteLimitingImport(CD, importLimit, complainRepr);
16471661
});
16481662
}
16491663
}
@@ -1666,7 +1680,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
16661680
diagID = diag::protocol_usable_from_inline_warn;
16671681
auto diag = proto->diagnose(diagID, PCEK_Refine);
16681682
highlightOffendingType(diag, complainRepr);
1669-
noteLimitingImport(proto->getASTContext(), importLimit, complainRepr);
1683+
noteLimitingImport(proto, importLimit, complainRepr);
16701684
});
16711685
}
16721686

@@ -1685,7 +1699,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
16851699
diagID = diag::protocol_usable_from_inline_warn;
16861700
auto diag = proto->diagnose(diagID, PCEK_Requirement);
16871701
highlightOffendingType(diag, complainRepr);
1688-
noteLimitingImport(proto->getASTContext(), importLimit, complainRepr);
1702+
noteLimitingImport(proto, importLimit, complainRepr);
16891703
});
16901704
}
16911705
}
@@ -1704,7 +1718,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
17041718
diagID = diag::subscript_type_usable_from_inline_warn;
17051719
auto diag = SD->diagnose(diagID, /*problemIsElement=*/false);
17061720
highlightOffendingType(diag, complainRepr);
1707-
noteLimitingImport(SD->getASTContext(), importLimit, complainRepr);
1721+
noteLimitingImport(SD, importLimit, complainRepr);
17081722
});
17091723
}
17101724

@@ -1719,7 +1733,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
17191733
diagID = diag::subscript_type_usable_from_inline_warn;
17201734
auto diag = SD->diagnose(diagID, /*problemIsElement=*/true);
17211735
highlightOffendingType(diag, complainRepr);
1722-
noteLimitingImport(SD->getASTContext(), importLimit, complainRepr);
1736+
noteLimitingImport(SD, importLimit, complainRepr);
17231737
});
17241738
}
17251739

@@ -1757,8 +1771,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
17571771
/*problemIsResult=*/false,
17581772
/*inaccessibleWrapper=*/true);
17591773
highlightOffendingType(diag, complainRepr);
1760-
noteLimitingImport(fn->getASTContext(), importLimit,
1761-
complainRepr);
1774+
noteLimitingImport(fn, importLimit, complainRepr);
17621775
});
17631776
}
17641777
}
@@ -1775,7 +1788,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
17751788
/*problemIsResult=*/false,
17761789
/*inaccessibleWrapper=*/false);
17771790
highlightOffendingType(diag, complainRepr);
1778-
noteLimitingImport(fn->getASTContext(), importLimit, complainRepr);
1791+
noteLimitingImport(fn, importLimit, complainRepr);
17791792
});
17801793
}
17811794

@@ -1793,7 +1806,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
17931806
/*problemIsResult=*/true,
17941807
/*inaccessibleWrapper=*/false);
17951808
highlightOffendingType(diag, complainRepr);
1796-
noteLimitingImport(fn->getASTContext(), importLimit, complainRepr);
1809+
noteLimitingImport(fn, importLimit, complainRepr);
17971810
});
17981811
}
17991812
}
@@ -1816,8 +1829,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
18161829
diagID = diag::enum_case_usable_from_inline_warn;
18171830
auto diag = EED->diagnose(diagID);
18181831
highlightOffendingType(diag, complainRepr);
1819-
noteLimitingImport(EED->getASTContext(), importLimit,
1820-
complainRepr);
1832+
noteLimitingImport(EED, importLimit, complainRepr);
18211833
});
18221834
}
18231835
}

test/Sema/access-level-import-diag-priority.swift

+7
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,29 @@ private import PrivateLib // expected-note 1 {{struct 'PrivateImportType' import
4646

4747
/// Simple ordering
4848
public func publicFuncUsesPrivate(_ a: PublicImportType, b: PackageImportType, c: InternalImportType, d: FileprivateImportType, e: PrivateImportType) { // expected-error {{function cannot be declared public because its parameter uses a fileprivate type}}
49+
// expected-note @-1 {{struct 'FileprivateImportType' is imported by this file as 'fileprivate' from 'FileprivateLib'}}
4950
var _: PrivateImportType
5051
}
5152
public func publicFuncUsesFileprivate(_ a: PublicImportType, b: PackageImportType, c: InternalImportType, d: FileprivateImportType) { // expected-error {{function cannot be declared public because its parameter uses a fileprivate type}}
53+
// expected-note @-1 {{struct 'FileprivateImportType' is imported by this file as 'fileprivate' from 'FileprivateLib'}}
5254
var _: PrivateImportType
5355
}
5456
public func publicFuncUsesInternal(_ a: PublicImportType, b: PackageImportType, c: InternalImportType) { // expected-error {{function cannot be declared public because its parameter uses an internal type}}
57+
// expected-note @-1 {{struct 'InternalImportType' is imported by this file as 'internal' from 'InternalLib'}}
5558
var _: PrivateImportType
5659
}
5760
public func publicFuncUsesPackage(_ a: PublicImportType, b: PackageImportType) { // expected-error {{function cannot be declared public because its parameter uses a package type}}
61+
// expected-note @-1 {{struct 'PackageImportType' is imported by this file as 'package' from 'PackageLib'}}
5862
var _: PrivateImportType
5963
}
6064

6165
/// Disordered
6266
public func publicFuncUsesPrivateScambled(_ a: PublicImportType, b: PackageImportType, e: PrivateImportType, c: InternalImportType, d: FileprivateImportType) { // expected-error {{function cannot be declared public because its parameter uses a private type}}
67+
// expected-note @-1 {{struct 'PrivateImportType' is imported by this file as 'private' from 'PrivateLib'}}
6368
var _: PrivateImportType
6469
}
6570
public func publicFuncUsesPrivateScambled(_ a: PublicImportType, d: FileprivateImportType, b: PackageImportType, c: InternalImportType) { // expected-error {{function cannot be declared public because its parameter uses a fileprivate type}}
71+
// expected-note @-1 {{struct 'FileprivateImportType' is imported by this file as 'fileprivate' from 'FileprivateLib'}}
6672
var _: PrivateImportType
6773
}
6874

@@ -98,3 +104,4 @@ public func localVsImportedType3(a: LocalType, b: FileprivateImportType) {} // e
98104

99105
/// Only this one points to the imported type.
100106
public func localVsImportedType4(a: FileprivateImportType, b: LocalType) {} // expected-error {{function cannot be declared public because its parameter uses a fileprivate type}}
107+
// expected-note @-1 {{struct 'FileprivateImportType' is imported by this file as 'fileprivate' from 'FileprivateLib'}}

0 commit comments

Comments
 (0)