Don't treat dependent types as having a copy value representation. (#6055)

Add `Dependent` value and initializing representations for types whose
representations are unknown because they are dependent. When generating
SemIR in such cases, use a worst-case initializing representation that
both provides a destination address and also propagates a potential
result value.

Use this to fix incorrect lowering and lowering crashes for specific
functions involving generic types that don't use a copy value
representation.

In lowering, be careful to distinguish between whether the initializing
representation for the generic return type uses a return slot (which
affects whether the SemIR declaration and call have one) and whether the
initializing representation for the specific return type uses a return
slot (which affects whether the LLVM IR declaration and call have one).
This commit is contained in:
Richard Smith
2025-09-15 23:59:00 +00:00
committed by GitHub
parent ca40e9d693
commit b44ba47cf3
53 changed files with 1375 additions and 670 deletions
+7 -21
View File
@@ -67,10 +67,8 @@ fn F() {
// CHECK:STDOUT: %Cpp.ref.loc8_21: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Enum.ref.loc8_24: type = name_ref Enum, imports.%Enum.decl [concrete = constants.%Enum]
// CHECK:STDOUT: %a.ref.loc8: %Enum = name_ref a, imports.%int_0 [concrete = constants.%int_0]
// CHECK:STDOUT: %.loc8_29.1: ref %Enum = temporary_storage
// CHECK:STDOUT: %.loc8_29.2: ref %Enum = temporary %.loc8_29.1, %a.ref.loc8
// CHECK:STDOUT: assign %a.var, %.loc8_29.2
// CHECK:STDOUT: %.loc8_13: type = splice_block %Enum.ref.loc8_13 [concrete = constants.%Enum] {
// CHECK:STDOUT: assign %a.var, %a.ref.loc8
// CHECK:STDOUT: %.loc8: type = splice_block %Enum.ref.loc8_13 [concrete = constants.%Enum] {
// CHECK:STDOUT: %Cpp.ref.loc8_10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Enum.ref.loc8_13: type = name_ref Enum, imports.%Enum.decl [concrete = constants.%Enum]
// CHECK:STDOUT: }
@@ -79,24 +77,12 @@ fn F() {
// CHECK:STDOUT: %Cpp.ref.loc10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Enum.ref.loc10: type = name_ref Enum, imports.%Enum.decl [concrete = constants.%Enum]
// CHECK:STDOUT: %b.ref: %Enum = name_ref b, imports.%int_1 [concrete = constants.%int_1]
// CHECK:STDOUT: %.loc10_15.1: ref %Enum = temporary_storage
// CHECK:STDOUT: %.loc10_15.2: ref %Enum = temporary %.loc10_15.1, %b.ref
// CHECK:STDOUT: assign %a.ref.loc10, %.loc10_15.2
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound.loc10: <bound method> = bound_method %.loc10_15.2, constants.%T.as.Destroy.impl.Op.cd4
// CHECK:STDOUT: assign %a.ref.loc10, %b.ref
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %a.var, constants.%T.as.Destroy.impl.Op.cd4
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc10: <bound method> = bound_method %.loc10_15.2, %T.as.Destroy.impl.Op.specific_fn.1
// CHECK:STDOUT: %addr.loc10: %ptr.47b = addr_of %.loc10_15.2
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call.loc10: init %empty_tuple.type = call %bound_method.loc10(%addr.loc10)
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound.loc8_29: <bound method> = bound_method %.loc8_29.2, constants.%T.as.Destroy.impl.Op.cd4
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc8_29: <bound method> = bound_method %.loc8_29.2, %T.as.Destroy.impl.Op.specific_fn.2
// CHECK:STDOUT: %addr.loc8_29: %ptr.47b = addr_of %.loc8_29.2
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call.loc8_29: init %empty_tuple.type = call %bound_method.loc8_29(%addr.loc8_29)
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound.loc8_3: <bound method> = bound_method %a.var, constants.%T.as.Destroy.impl.Op.cd4
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc8_3: <bound method> = bound_method %a.var, %T.as.Destroy.impl.Op.specific_fn.3
// CHECK:STDOUT: %addr.loc8_3: %ptr.47b = addr_of %a.var
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call.loc8_3: init %empty_tuple.type = call %bound_method.loc8_3(%addr.loc8_3)
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %a.var, %T.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr: %ptr.47b = addr_of %a.var
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: