Skip to content
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

[SR-7022] [SIL] Autogenerated enum/struct equals functions access level mismatch #49570

Open
swift-ci opened this issue Feb 17, 2018 · 8 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-7022
Radar None
Original Reporter polac24 (JIRA User)
Type Bug
Status In Progress
Resolution
Environment

swift-DEVELOPMENT-SNAPSHOT-2018-02-14-a

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 52499d2b8e0c4f6f3b72a164fc1cca85

Issue Description:

_derived_enum_equals/_derived_struct_equals/hashValue lack access level of an enum in a type declaration so compiling from a sil file fails.

 echo 'public enum P{case a}'  | /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2018-02-14-a.xctoolchain/usr/bin/swiftc - -emit-sil

generates internal static func

sil_stage canonical

import Builtin
import Swift
import SwiftShims

public enum P {
  case a
  @_implements(Equatable, ==(_:_:)) static func __derived_enum_equals(_ a: P, _ b: P) -> Bool
  var hashValue: Int { get }
}

am I right that it should generate public static func __derived_struct_equals

public struct P : Equatable {
  @sil_stored var a: String { get set }
  init(a: String)
  @_implements(Equatable, ==(_:_:)) public static func __derived_struct_equals(_ a: P, _ b: P) -> Bool
}

Here is an error for compiling from a .sil

<stdin>:9:49: error: method '__derived_enum_equals' must be declared public because it matches a requirement in public protocol 'Equatable'
  @_implements(Equatable, ==(_:_:)) static func __derived_enum_equals(_ a: P, _ b: P) -> Bool
                                                ^
                                    public 
<stdin>:10:7: error: property 'hashValue' must be declared public because it matches a requirement in public protocol 'Hashable'
  var hashValue: Int { get }
      ^
  public 
Assertion failed: ((Qualifier != StoreOwnershipQualifier::Unqualified) || !getFunction().hasQualifiedOwnership() && "Unqualified inst in qualified function"), function createStore, file /Users/buildnode/jenkins/workspace/oss-swift-package-osx/swift/include/swift/SIL/SILBuilder.h, line 630.
0  swift                    0x000000010ed28058 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1  swift                    0x000000010ed28766 SignalHandler(int) + 694
2  libsystem_platform.dylib 0x00007fff6f941f5a _sigtramp + 26
3  swift                    0x000000010c7e5a62 swift::Parser::parseType(swift::Diag<>, bool, bool) + 2898
4  libsystem_c.dylib        0x00007fff6f76c312 abort + 127
5  libsystem_c.dylib        0x00007fff6f734368 basename_r + 0
6  swift                    0x000000010c3bac1d swift::SILBuilder::createStore(swift::SILLocation, swift::SILValue, swift::SILValue, swift::StoreOwnershipQualifier) + 461
7  swift                    0x000000010c31a181 (anonymous namespace)::SILParser::parseSILInstruction(swift::SILBuilder&) + 73569
8  swift                    0x000000010c3059a5 swift::SILParserTUState::parseDeclSIL(swift::Parser&) + 5541
9  swift                    0x000000010c788554 swift::Parser::parseTopLevel() + 148
10 swift                    0x000000010c30439b swift::parseIntoSourceFile(swift::SourceFile&, unsigned int, bool*, swift::SILParserState*, swift::PersistentParserState*, swift::DelayedParsingCallbacks*) + 299
11 swift                    0x000000010c292313 swift::CompilerInstance::parseAndTypeCheckMainFile(swift::PersistentParserState&, swift::DelayedParsingCallbacks*, swift::OptionSet<swift::TypeCheckingFlags, unsigned int>) + 483
12 swift                    0x000000010c291026 swift::CompilerInstance::parseAndCheckTypes(swift::CompilerInstance::ImplicitImports const&) + 758
13 swift                    0x000000010c290877 swift::CompilerInstance::performSema() + 567
14 swift                    0x000000010b772f53 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 1843
15 swift                    0x000000010b771890 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3376
16 swift                    0x000000010b72e192 main + 3042
17 libdyld.dylib            0x00007fff6f6c0115 start + 1
Stack dump:
0.  Program arguments: /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2018-02-14-a.xctoolchain/usr/bin/swift -frontend -c -primary-file - -target x86_64-apple-darwin17.4.0 -enable-objc-interop -color-diagnostics -parse-sil -module-name main -o /var/folders/3v/2ymlw0cd53q9k8qsr1vg45gh0000gn/T/--c118a5.o 
1.  With parser at source location: <stdin>:38:3
<unknown>:0: error: unable to execute command: Abort trap: 6
<unknown>:0: error: compile command failed due to signal 6 (use -v to see invocation)
@belkadan
Copy link
Contributor

Hm, it looks like we set the access at the Decl level, but don't copy over an attribute for it. Maybe SIL printing should set PrintAccess in PrintOptions?

@swift-ci
Copy link
Collaborator Author

Comment by Bartosz Polaczyk (JIRA)

Indeed! Enabling PrintAccess defines __derived_struct_equals as public, but assertion still fails:

((Qualifier != StoreOwnershipQualifier::Unqualified) || !getFunction().hasQualifiedOwnership() && "Unqualified inst in qualified function"), function createStore, file /Users/buildnode/jenkins/workspace/oss-swift-package-osx/swift/include/swift/SIL/SILBuilder.h, line 630.

Maybe I will try to dive into this issue...

@swift-ci
Copy link
Collaborator Author

Comment by Bartosz Polaczyk (JIRA)

Mentioned assertion failed because I missed -assume-parsing-unqualified-ownership-sil. My mistake.

Problem statement:
Equatable declaration is created in DerivedConformanceEquatableHashable::deriveEquatable_eq, which copies formal access from a type (together with a versioned attribute) to the `==` function.
As @belkadan pointed out, current implementation of a SILPrinter does not explicitly ask to print access types of AST declarations (Options.PrintAccess is false by default), so for declarations without access control attribute, their access is not printed in a SIL. Technically we could copy access attributes while derived-conforming to a protocol, rather than copy formal access and version only, but copying formal access only is almost as old as DerivedConformanceRawRepresentable so maybe it is better to not modify it...

Fix suggestion
Change suggested by @belkadan - .PrintAccess = true - emits formalAccesses to the SIL and SILGen, so it could solve all kinds of problems related with missing accesses modifier (like non-public var hashValue in the example above) but this seems to not be enough. For some reason SIL generated by

 private enum P {case a}

expects fileprivate access of __derived_enum_equals and hashValue (contrary to generated private attribute):

private enum P {
  case a
  @_implements(Equatable, ==(_:_:)) private static func __derived_enum_equals(_ a: P, _ b: P) -> Bool
  private var hashValue: Int { get }
}
bin/swift -frontend -c -primary-file /Users/bartosz.polaczyk/Desktop/si.sil -target x86_64-apple-darwin17.4.0 -enable-objc-interop -color-diagnostics -module-name si -o /var/folders/3v/2ymlw0cd53q9k8qsr1vg45gh0000gn/T/si-49e136.o -assume-parsing-unqualified-ownership-sil
/Users/bartosz.polaczyk/Desktop/si.sil:9:57: error: method '__derived_enum_equals' must be as accessible as its enclosing type because it matches a requirement in protocol 'Equatable'
  @_implements(Equatable, ==(_:_:)) private static func __derived_enum_equals(_ a: P, _ b: P) -> Bool
                                    ~~~~~~~             ^
                                    fileprivate
/Users/bartosz.polaczyk/Desktop/si.sil:10:15: error: property 'hashValue' must be as accessible as its enclosing type because it matches a requirement in protocol 'Hashable'
  private var hashValue: Int { get }
  ~~~~~~~     ^
  fileprivate

  

Now I am wondering if we really need to emit implicit AST types and declarations in a SILPrinter? I observed that even for .sil enum missing __derived_enum_equals, we still visit MultiConformanceChecker to derive Equatable.

BTW
@_versioned attribute is still quite misty for me as a "public-hidden" declaration, but shouldn't DerivedConformanceCodable also copy versioned attribute together with formal access? In other words, shouldn't 10bd85c also include Codable/CodingKey conformance?

@belkadan
Copy link
Contributor

@_versioned attribute is still quite misty for me as a "public-hidden" declaration, but shouldn't DerivedConformanceCodable also copy versioned attribute together with formal access? In other words, shouldn't 10bd85c also include Codable/CodingKey conformance?

Hm, probably yes. It's certainly possible for an inlinable function to rely on an internal-but-exposed-in-ABI type being Codable, and that would lead to it mentioning those methods directly.

graydon (JIRA User), @xwu, this also seems like a problem for __derived_enum_equals. Now we've put the wrong name in the ABI.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Mar 2, 2018

Comment by Graydon Hoare (JIRA)

@belkadan I .. am afraid I don't really get what you're saying here (nor do I understand much of the thread leading here). Is there a bug in copyFormalAccess?

@belkadan
Copy link
Contributor

belkadan commented Mar 2, 2018

No, I'm worried about __derived_enum_equals being a public symbol. What if someone devirtualizes the == call? You'd never be able to replace it with a custom == function.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Mar 2, 2018

Comment by Graydon Hoare (JIRA)

Hm, is this only a module-boundary thing? I.e. would it be fixed by keeping the symbol internal? It's only there to help with incremental mode (and I think some stdlib uses I don't quite understand).

@swift-ci
Copy link
Collaborator Author

Comment by Bartosz Polaczyk (JIRA)

I cannot proceed to fix that bug. I can only confirm that build swift-5.0-DEVELOPMENT-SNAPSHOT-2019-02-20-a still include the same SIL signature of __derived_enum_equals

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

2 participants