Skip to content

Fix a crash during lookup of an operator with package acl #66155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3973,10 +3973,12 @@ getAccessScopeForFormalAccess(const ValueDecl *VD,
auto pkg = resultDC->getPackageContext(/*lookupIfNotCurrent*/ true);
if (!pkg) {
auto srcFile = resultDC->getParentSourceFile();
// Check if the file containing package decls is an interface file; if a public
// interface contains package decls, they must be inlinable and do not need a
// package-name, so don't show diagnostics in that case.
if (srcFile && srcFile->Kind != SourceFileKind::Interface) {
// Check if the file containing package decls is an interface file; if an
// interface file contains package decls, they must be usableFromInline or
// inlinable and are accessed within the defining module, so package-name
// is not needed; do not show diagnostics in such case.
auto shouldSkipDiag = srcFile && srcFile->Kind == SourceFileKind::Interface;
if (!shouldSkipDiag) {
// No package context was found; show diagnostics
auto &d = VD->getASTContext().Diags;
d.diagnose(VD->getLoc(), diag::access_control_requires_package_name);
Expand Down Expand Up @@ -4175,15 +4177,16 @@ static bool checkAccess(const DeclContext *useDC, const ValueDecl *VD,
}
case AccessLevel::Package: {
auto srcFile = sourceDC->getParentSourceFile();
if (srcFile && srcFile->Kind != SourceFileKind::Interface) {
auto srcPkg = sourceDC->getPackageContext(/*lookupIfNotCurrent*/ true);
auto usePkg = useDC->getPackageContext(/*lookupIfNotCurrent*/ true);
return usePkg->isSamePackageAs(srcPkg);
} else {
// If source file is interface, package decls must be inlinable,
// essentially treated public so return true (see AccessLevel::Public)

// srcFile could be null if VD decl is from an imported .swiftmodule
if (srcFile && srcFile->Kind == SourceFileKind::Interface) {
// If source file is interface, package decls must be usableFromInline or
// inlinable, and are accessed only within the defining module so return true
return true;
}
auto srcPkg = sourceDC->getPackageContext(/*lookupIfNotCurrent*/ true);
auto usePkg = useDC->getPackageContext(/*lookupIfNotCurrent*/ true);
return srcPkg && usePkg && usePkg->isSamePackageAs(srcPkg);
}
case AccessLevel::Public:
case AccessLevel::Open:
Expand Down
35 changes: 35 additions & 0 deletions test/Sema/accessibility_package_in_extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t

// RUN: %target-swift-frontend -verify -module-name Lib %t/Lib.swift -emit-module -emit-module-path %t/Lib.swiftmodule -package-name myPkg

/// Type-checking an operator (L30 below) causes look up of all of its decls regardless of which access modifier is
/// used (decl in both Client and Lib in this case) before filtering. The decl in Lib is a package decl and has
/// package-name associated with it, but the use site (in Client) does not have package-name. The package decl
/// should be filtered out and the public == decl should be picked.
// RUN: %target-swift-frontend -typecheck -verify %t/Client.swift -I %t


//--- Lib.swift
public class Decl {
package static func == (lhs: Decl, rhs: Decl) -> Bool {
return true
}
}

//--- Client.swift
import Lib

extension Decl: Equatable {
public static func == (lhs: Decl, rhs: Decl) -> Bool {
return false
}
}

public protocol Proto {}
extension Proto {
func foo(first: Decl, second: Decl) -> Bool {
// Type-checking below causes a look up of == in both Client and Lib
return first == second
}
}