Skip to content

[SILGen]Check if baseType is DynamicSelfType #80913

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 2 commits into from
Jun 7, 2025

Conversation

stzn
Copy link
Contributor

@stzn stzn commented Apr 18, 2025

Resolves #80669
I think the issue mentioned above has been resolved by this, but it’s unrelated. I will create a separate one for it.

The compiler crashed when compiling the following code:

func type<Root, Value>(at keyPath: KeyPath<Root, Value>) -> Value.Type {
    return Value.self
}

class Foo {
    var other = Foo()

    static func staticFunc() {
        type(at: \Self.other).bar()
    }

    static func bar() {
        print("Hello")
    }
}

The crash log was as follows:

SIL verification failed: can't upcast to same type: UI->getType() != UI->getOperand()->getType()
Verifying instruction:
     %4 = load [take] %2 : $*Foo                  // user: %5
->   %5 = upcast %4 : $Foo to $Foo                // users: %11, %6
     %6 = begin_borrow %5 : $Foo                  // users: %9, %8, %7
     destroy_value %5 : $Foo                      // id: %11
In function:
// key path getter for Foo.other : Self
sil shared [thunk] [ossa] @$s4main3FooC5otherACvpACXDTK : $@convention(keypath_accessor_getter) (@in_guaranteed Foo) -> @out Foo {
// %0                                             // user: %10
// %1                                             // user: %3
bb0(%0 : $*Foo, %1 : $*Foo):
  %2 = alloc_stack $Foo                           // users: %12, %4, %3
  copy_addr %1 to [init] %2                       // id: %3
  %4 = load [take] %2                             // user: %5
  %5 = upcast %4 to $Foo                          // users: %11, %6
  %6 = begin_borrow %5                            // users: %9, %8, %7
  %7 = class_method %6, #Foo.other!getter : (Foo) -> () -> Foo, $@convention(method) (@guaranteed Foo) -> @owned Foo // user: %8
  %8 = apply %7(%6) : $@convention(method) (@guaranteed Foo) -> @owned Foo // user: %10
  end_borrow %6                                   // id: %9
  store %8 to [init] %0                           // id: %10
  destroy_value %5                                // id: %11
  dealloc_stack %2                                // id: %12
  %13 = tuple ()                                  // user: %14
  return %13                                      // id: %14
} // end sil function '$s4main3FooC5otherACvpACXDTK'
Stack dump:
0.      Program arguments: /usr/bin/swift-frontend -frontend -interpret - -disable-objc-interop -color-diagnostics -enable-bare-slash-regex -empty-abi-descriptor -resource-dir /usr/lib/swift -no-auto-bridging-header-chaining -module-name main -in-process-plugin-server-path /usr/lib/swift/host/libSwiftInProcPluginServer.so -plugin-path /usr/lib/swift/host/plugins -plugin-path /usr/local/lib/swift/host/plugins
1.      Swift version 6.2-dev (LLVM a3e32cdaae72f3d, Swift fa8609703528715)
2.      Compiling with effective version 5.10
3.      While evaluating request ASTLoweringRequest(Lowering AST to SIL for module main)
4.      While verifying SIL function "@$s4main3FooC5otherACvpACXDTK".
 for <<debugloc at "<compiler-generated>":0:0>>
...

The cause appears to be that when using \Self in a key path, the baseType is DynamicSelfType. This prevents retrieving the baseClass using getClassOrBoundGenericClass, as seen here:
https://github.com/swiftlang/swift/blob/main/lib/SILGen/SILGenExpr.cpp#L3402

Therefore, a check was added to determine if baseType is DynamicSelfType.

@stzn stzn marked this pull request as ready for review April 18, 2025 17:41
@stzn stzn requested a review from jckarter as a code owner April 18, 2025 17:41
if (baseType->getClassOrBoundGenericClass() != propertyClass) {
auto baseClass = baseType->getClassOrBoundGenericClass();
if (auto dynamicSelfType = baseType->getAs<DynamicSelfType>()) {
baseClass = dynamicSelfType->getSelfType()->getClassOrBoundGenericClass();
Copy link
Contributor

@slavapestov slavapestov Apr 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of calling getClassOrBoundGenericClass() twice, how about we unwrap the DynamicSelfType first:

if (auto selfType = baseType->getAs<DynamicSelfType>()) {
  baseType = selfType->getSelfType();
baseClass = baseType->getClassOrBoundGenericClass();
ASSERT(baseClass != nullptr);

Copy link
Contributor Author

@stzn stzn Apr 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slavapestov

Thank you for checking. I tried the below code, but the assertion failed in subclass_generics.

if (auto selfType = baseType->getAs<DynamicSelfType>())
      baseType = selfType->getSelfType()->getCanonicalType();
auto baseClass = baseType->getClassOrBoundGenericClass();
ASSERT(baseClass != nullptr);

This assertion also fails with the current implementation.

Am I misunderstanding something? Should baseClass always be non-null here?

Copy link
Contributor Author

@stzn stzn Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slavapestov
As far as I confirmed, baseClass still could be nil when baseType is ArchetypeType. So, we can not add ASSERT(baseClass != nullptr);.

Please correct me if I'm wrong. Thank you.

@stzn stzn marked this pull request as draft April 24, 2025 23:07
@stzn stzn marked this pull request as ready for review April 25, 2025 11:29
@slavapestov
Copy link
Contributor

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor

Oops, dropped the ball on this one. Let's merge it if the tests pass.

@slavapestov slavapestov enabled auto-merge June 6, 2025 20:50
@slavapestov slavapestov merged commit 28af54a into swiftlang:main Jun 7, 2025
3 checks passed
@stzn stzn deleted the fix-crash-self-keypath-root branch June 7, 2025 02:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Crash when using Self in KeyPath expression
2 participants