Skip to content

IRGen: mangle conformance access paths with opaque result type as a root #24466

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
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
1 change: 1 addition & 0 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,7 @@ Property behaviors are implemented using private protocol conformances.
dependent-associated-conformance 'HA' DEPENDENT-CONFORMANCE-INDEX

dependent-associated-conformance ::= type protocol
dependent-protocol-conformance ::= dependent-protocol-conformance opaque-type 'HO'

A compact representation used to represent mangled protocol conformance witness
arguments at runtime. The ``module`` is only specified for conformances that
Expand Down
14 changes: 14 additions & 0 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2613,6 +2613,20 @@ void ASTMangler::appendConcreteProtocolConformance(
auto conformanceAccessPath =
CurGenericSignature->getConformanceAccessPath(type, proto);
appendDependentProtocolConformance(conformanceAccessPath);
} else if (auto opaqueType = canType->getAs<OpaqueTypeArchetypeType>()) {
GenericSignature *opaqueSignature = opaqueType->getBoundSignature();
GenericTypeParamType *opaqueTypeParam = opaqueSignature->getGenericParams().back();
ConformanceAccessPath conformanceAccessPath =
opaqueSignature->getConformanceAccessPath(opaqueTypeParam, proto);

// Append the conformance access path with the signature of the opaque type.
CanGenericSignature savedSignature = CurGenericSignature;
CurGenericSignature = opaqueSignature->getCanonicalSignature();
appendDependentProtocolConformance(conformanceAccessPath);
CurGenericSignature = savedSignature;

appendType(canType);
appendOperator("HO");
} else {
auto conditionalConf = module->lookupConformance(canType, proto);
appendConcreteProtocolConformance(conditionalConf->getConcrete());
Expand Down
44 changes: 44 additions & 0 deletions test/IRGen/opaque_result_type_access_path.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -module-name=test %s -o %t/a.out
// RUN: %target-run %t/a.out | %FileCheck %s
// REQUIRES: executable_test
// REQUIRES: CPU=arm64 || CPU=x86_64

// Check that the IRGenMangler does not crashq when mangling a conformance
// access path with an opaque result type as root.
// As a bonus, also do a runtime test to check that there is no miscompile.

protocol P {
func get() -> Int
}

extension Int : P {
func get() -> Int {
return self
}
}

struct X<T> {
let tt: T
init(_ t: T) {
tt = t
}
}

extension X : P where T : P {
func get() -> Int {
return tt.get()
}
}

func bar() -> some P {
return 27
}

func foo() -> some P {
return X(bar())
}

// CHECK: 27
print(foo().get())