Improve CanDestroyType to handle remaining cases (#6943)

This is only fixing the decision about *whether* to produce a witness.
Implementation of the witness is still a TODO, though where a body is
generated, it should also precisely reflect where one _needs_ to be
generated.

Note the tests:

- toolchain/lower/testdata/function/generic/import_core_witness.carbon
- toolchain/lower/testdata/function/generic/import_unused_def.carbon

These tests can probably be produced _without_ Core.Destroy, but I found
the essence of them while trying to build //examples with Core.Destroy
and a simpler minimization wasn't striking me.

Assisted-by: Google Antigravity with Gemini

---------

Co-authored-by: jonmeow <jperkins@google.com>
This commit is contained in:
Jon Ross-Perkins
2026-04-02 22:54:58 +00:00
committed by GitHub
co-authored by jonmeow
parent 1fa7a64cd4
commit 9266ced4e3
212 changed files with 11376 additions and 4978 deletions
+100 -65
View File
@@ -93,67 +93,88 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) {
// CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr poison), !dbg !20
// CHECK:STDOUT: store ptr %Cpp.nullptr_t.as.Copy.impl.Op.call, ptr %.loc14_22.1.temp, align 8, !dbg !20
// CHECK:STDOUT: call void @_Z11TakeNullptrDn.carbon_thunk(ptr %.loc14_22.1.temp), !dbg !22
// CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %.loc14_22.1.temp), !dbg !20
// CHECK:STDOUT: call void @"_COp.dc33c1983710215f:core.Destroy.Core"(ptr %.loc12_18.2.temp), !dbg !19
// CHECK:STDOUT: ret void, !dbg !23
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: declare void @"_COp.1608e268d71809e4:core.Destroy.Core"(ptr)
// CHECK:STDOUT:
// CHECK:STDOUT: declare void @_Z7TakePtrPi(ptr noundef) #1
// CHECK:STDOUT:
// CHECK:STDOUT: declare ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr)
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define ptr @_CReturnNullptr.Main() #2 !dbg !24 {
// CHECK:STDOUT: define weak_odr void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %self) #2 !dbg !24 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr poison), !dbg !28
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.Copy.impl.Op.call, !dbg !29
// CHECK:STDOUT: ret void, !dbg !30
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define ptr @_CReturnNullptrCopy.Main() #2 !dbg !30 {
// CHECK:STDOUT: define weak_odr void @"_COp.ca2ce9262234b385:core.Destroy.Core"(ptr %self) #2 !dbg !31 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %a.var = alloca ptr, align 8, !dbg !31
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %a.var), !dbg !31
// CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call.loc22 = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr poison), !dbg !32
// CHECK:STDOUT: store ptr %Cpp.nullptr_t.as.Copy.impl.Op.call.loc22, ptr %a.var, align 8, !dbg !31
// CHECK:STDOUT: %.loc23 = load ptr, ptr %a.var, align 8, !dbg !33
// CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call.loc23 = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr %.loc23), !dbg !33
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.Copy.impl.Op.call.loc23, !dbg !34
// CHECK:STDOUT: ret void, !dbg !34
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define ptr @_CReturnConvertedNullptrIndirectly.Main() #2 !dbg !35 {
// CHECK:STDOUT: define weak_odr void @"_COp.dc33c1983710215f:core.Destroy.Core"(ptr %self) #2 !dbg !35 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %a.var = alloca ptr, align 8, !dbg !36
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %a.var), !dbg !36
// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk(ptr %a.var), !dbg !37
// CHECK:STDOUT: %.loc28_10 = load ptr, ptr %a.var, align 8, !dbg !38
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4"(ptr %.loc28_10), !dbg !39
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call, !dbg !39
// CHECK:STDOUT: ret void, !dbg !38
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define ptr @_CReturnConvertedNullptrDirectly.Main() #2 !dbg !40 {
// CHECK:STDOUT: define ptr @_CReturnNullptr.Main() #2 !dbg !39 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc32_28.1.temp = alloca ptr, align 8, !dbg !41
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc32_28.1.temp), !dbg !41
// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk(ptr %.loc32_28.1.temp), !dbg !41
// CHECK:STDOUT: %.loc32_28.4 = load ptr, ptr %.loc32_28.1.temp, align 8, !dbg !41
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4"(ptr %.loc32_28.4), !dbg !42
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call, !dbg !42
// CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr poison), !dbg !42
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.Copy.impl.Op.call, !dbg !43
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define ptr @_CConvertNullptrConstant.Main() #2 !dbg !43 {
// CHECK:STDOUT: define ptr @_CReturnNullptrCopy.Main() #2 !dbg !44 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4"(ptr poison), !dbg !44
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call, !dbg !44
// CHECK:STDOUT: %a.var = alloca ptr, align 8, !dbg !45
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %a.var), !dbg !45
// CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call.loc22 = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr poison), !dbg !46
// CHECK:STDOUT: store ptr %Cpp.nullptr_t.as.Copy.impl.Op.call.loc22, ptr %a.var, align 8, !dbg !45
// CHECK:STDOUT: %.loc23 = load ptr, ptr %a.var, align 8, !dbg !47
// CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call.loc23 = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr %.loc23), !dbg !47
// CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %a.var), !dbg !45
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.Copy.impl.Op.call.loc23, !dbg !48
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define linkonce_odr ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4"(ptr %self) #2 !dbg !45 {
// CHECK:STDOUT: %1 = call ptr @_CNone.Optional.Core.95809cda2a4fffc7(), !dbg !51
// CHECK:STDOUT: ret ptr %1, !dbg !52
// CHECK:STDOUT: define ptr @_CReturnConvertedNullptrIndirectly.Main() #2 !dbg !49 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %a.var = alloca ptr, align 8, !dbg !50
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %a.var), !dbg !50
// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk(ptr %a.var), !dbg !51
// CHECK:STDOUT: %.loc28_10 = load ptr, ptr %a.var, align 8, !dbg !52
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4"(ptr %.loc28_10), !dbg !53
// CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %a.var), !dbg !50
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call, !dbg !53
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define ptr @_CReturnConvertedNullptrDirectly.Main() #2 !dbg !54 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc32_28.1.temp = alloca ptr, align 8, !dbg !55
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc32_28.1.temp), !dbg !55
// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk(ptr %.loc32_28.1.temp), !dbg !55
// CHECK:STDOUT: %.loc32_28.4 = load ptr, ptr %.loc32_28.1.temp, align 8, !dbg !55
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4"(ptr %.loc32_28.4), !dbg !56
// CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %.loc32_28.1.temp), !dbg !55
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call, !dbg !56
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define ptr @_CConvertNullptrConstant.Main() #2 !dbg !57 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4"(ptr poison), !dbg !58
// CHECK:STDOUT: ret ptr %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call, !dbg !58
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define linkonce_odr ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4"(ptr %self) #2 !dbg !59 {
// CHECK:STDOUT: %1 = call ptr @_CNone.Optional.Core.95809cda2a4fffc7(), !dbg !65
// CHECK:STDOUT: ret ptr %1, !dbg !66
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
@@ -162,8 +183,8 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) {
// CHECK:STDOUT: declare ptr @_CMake.NullptrT.CppCompat.Core()
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define linkonce_odr ptr @_CNone.Optional.Core.95809cda2a4fffc7() #2 !dbg !53 {
// CHECK:STDOUT: ret ptr null, !dbg !55
// CHECK:STDOUT: define linkonce_odr ptr @_CNone.Optional.Core.95809cda2a4fffc7() #2 !dbg !67 {
// CHECK:STDOUT: ret ptr null, !dbg !69
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; uselistorder directives
@@ -203,35 +224,49 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) {
// CHECK:STDOUT: !21 = !DILocation(line: 12, column: 3, scope: !16)
// CHECK:STDOUT: !22 = !DILocation(line: 14, column: 3, scope: !16)
// CHECK:STDOUT: !23 = !DILocation(line: 11, column: 1, scope: !16)
// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "ReturnNullptr", linkageName: "_CReturnNullptr.Main", scope: null, file: !6, line: 17, type: !25, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "Op", linkageName: "_COp.705e422c84320121:core.Destroy.Core", scope: null, file: !6, line: 14, type: !25, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !28)
// CHECK:STDOUT: !25 = !DISubroutineType(types: !26)
// CHECK:STDOUT: !26 = !{!27}
// CHECK:STDOUT: !26 = !{null, !27}
// CHECK:STDOUT: !27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
// CHECK:STDOUT: !28 = !DILocation(line: 18, column: 10, scope: !24)
// CHECK:STDOUT: !29 = !DILocation(line: 18, column: 3, scope: !24)
// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "ReturnNullptrCopy", linkageName: "_CReturnNullptrCopy.Main", scope: null, file: !6, line: 21, type: !25, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !31 = !DILocation(line: 22, column: 3, scope: !30)
// CHECK:STDOUT: !32 = !DILocation(line: 22, column: 26, scope: !30)
// CHECK:STDOUT: !33 = !DILocation(line: 23, column: 10, scope: !30)
// CHECK:STDOUT: !34 = !DILocation(line: 23, column: 3, scope: !30)
// CHECK:STDOUT: !35 = distinct !DISubprogram(name: "ReturnConvertedNullptrIndirectly", linkageName: "_CReturnConvertedNullptrIndirectly.Main", scope: null, file: !6, line: 26, type: !25, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !36 = !DILocation(line: 27, column: 3, scope: !35)
// CHECK:STDOUT: !37 = !DILocation(line: 27, column: 26, scope: !35)
// CHECK:STDOUT: !38 = !DILocation(line: 28, column: 10, scope: !35)
// CHECK:STDOUT: !39 = !DILocation(line: 28, column: 3, scope: !35)
// CHECK:STDOUT: !40 = distinct !DISubprogram(name: "ReturnConvertedNullptrDirectly", linkageName: "_CReturnConvertedNullptrDirectly.Main", scope: null, file: !6, line: 31, type: !25, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !41 = !DILocation(line: 32, column: 10, scope: !40)
// CHECK:STDOUT: !42 = !DILocation(line: 32, column: 3, scope: !40)
// CHECK:STDOUT: !43 = distinct !DISubprogram(name: "ConvertNullptrConstant", linkageName: "_CConvertNullptrConstant.Main", scope: null, file: !6, line: 35, type: !25, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !44 = !DILocation(line: 36, column: 3, scope: !43)
// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4", scope: null, file: !46, line: 51, type: !47, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !49)
// CHECK:STDOUT: !46 = !DIFile(filename: "{{.*}}/prelude/types/cpp/nullptr.carbon", directory: "")
// CHECK:STDOUT: !47 = !DISubroutineType(types: !48)
// CHECK:STDOUT: !48 = !{!27, !27}
// CHECK:STDOUT: !49 = !{!50}
// CHECK:STDOUT: !50 = !DILocalVariable(arg: 1, scope: !45, type: !27)
// CHECK:STDOUT: !51 = !DILocation(line: 52, column: 14, scope: !45)
// CHECK:STDOUT: !52 = !DILocation(line: 52, column: 7, scope: !45)
// CHECK:STDOUT: !53 = distinct !DISubprogram(name: "None", linkageName: "_CNone.Optional.Core.95809cda2a4fffc7", scope: null, file: !54, line: 27, type: !25, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !54 = !DIFile(filename: "{{.*}}/prelude/types/optional.carbon", directory: "")
// CHECK:STDOUT: !55 = !DILocation(line: 28, column: 5, scope: !53)
// CHECK:STDOUT: !28 = !{!29}
// CHECK:STDOUT: !29 = !DILocalVariable(arg: 1, scope: !24, type: !27)
// CHECK:STDOUT: !30 = !DILocation(line: 14, column: 19, scope: !24)
// CHECK:STDOUT: !31 = distinct !DISubprogram(name: "Op", linkageName: "_COp.ca2ce9262234b385:core.Destroy.Core", scope: null, file: !6, line: 12, type: !25, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !32)
// CHECK:STDOUT: !32 = !{!33}
// CHECK:STDOUT: !33 = !DILocalVariable(arg: 1, scope: !31, type: !27)
// CHECK:STDOUT: !34 = !DILocation(line: 12, column: 15, scope: !31)
// CHECK:STDOUT: !35 = distinct !DISubprogram(name: "Op", linkageName: "_COp.dc33c1983710215f:core.Destroy.Core", scope: null, file: !6, line: 12, type: !25, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !36)
// CHECK:STDOUT: !36 = !{!37}
// CHECK:STDOUT: !37 = !DILocalVariable(arg: 1, scope: !35, type: !27)
// CHECK:STDOUT: !38 = !DILocation(line: 12, column: 15, scope: !35)
// CHECK:STDOUT: !39 = distinct !DISubprogram(name: "ReturnNullptr", linkageName: "_CReturnNullptr.Main", scope: null, file: !6, line: 17, type: !40, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !40 = !DISubroutineType(types: !41)
// CHECK:STDOUT: !41 = !{!27}
// CHECK:STDOUT: !42 = !DILocation(line: 18, column: 10, scope: !39)
// CHECK:STDOUT: !43 = !DILocation(line: 18, column: 3, scope: !39)
// CHECK:STDOUT: !44 = distinct !DISubprogram(name: "ReturnNullptrCopy", linkageName: "_CReturnNullptrCopy.Main", scope: null, file: !6, line: 21, type: !40, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !45 = !DILocation(line: 22, column: 3, scope: !44)
// CHECK:STDOUT: !46 = !DILocation(line: 22, column: 26, scope: !44)
// CHECK:STDOUT: !47 = !DILocation(line: 23, column: 10, scope: !44)
// CHECK:STDOUT: !48 = !DILocation(line: 23, column: 3, scope: !44)
// CHECK:STDOUT: !49 = distinct !DISubprogram(name: "ReturnConvertedNullptrIndirectly", linkageName: "_CReturnConvertedNullptrIndirectly.Main", scope: null, file: !6, line: 26, type: !40, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !50 = !DILocation(line: 27, column: 3, scope: !49)
// CHECK:STDOUT: !51 = !DILocation(line: 27, column: 26, scope: !49)
// CHECK:STDOUT: !52 = !DILocation(line: 28, column: 10, scope: !49)
// CHECK:STDOUT: !53 = !DILocation(line: 28, column: 3, scope: !49)
// CHECK:STDOUT: !54 = distinct !DISubprogram(name: "ReturnConvertedNullptrDirectly", linkageName: "_CReturnConvertedNullptrDirectly.Main", scope: null, file: !6, line: 31, type: !40, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !55 = !DILocation(line: 32, column: 10, scope: !54)
// CHECK:STDOUT: !56 = !DILocation(line: 32, column: 3, scope: !54)
// CHECK:STDOUT: !57 = distinct !DISubprogram(name: "ConvertNullptrConstant", linkageName: "_CConvertNullptrConstant.Main", scope: null, file: !6, line: 35, type: !40, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !58 = !DILocation(line: 36, column: 3, scope: !57)
// CHECK:STDOUT: !59 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.NullptrT.CppCompat.Core:ImplicitAs.83dbfcd16e56a769.Core.b88d1103f417c6d4", scope: null, file: !60, line: 51, type: !61, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !63)
// CHECK:STDOUT: !60 = !DIFile(filename: "{{.*}}/prelude/types/cpp/nullptr.carbon", directory: "")
// CHECK:STDOUT: !61 = !DISubroutineType(types: !62)
// CHECK:STDOUT: !62 = !{!27, !27}
// CHECK:STDOUT: !63 = !{!64}
// CHECK:STDOUT: !64 = !DILocalVariable(arg: 1, scope: !59, type: !27)
// CHECK:STDOUT: !65 = !DILocation(line: 52, column: 14, scope: !59)
// CHECK:STDOUT: !66 = !DILocation(line: 52, column: 7, scope: !59)
// CHECK:STDOUT: !67 = distinct !DISubprogram(name: "None", linkageName: "_CNone.Optional.Core.95809cda2a4fffc7", scope: null, file: !68, line: 27, type: !40, spFlags: DISPFlagDefinition, unit: !5)
// CHECK:STDOUT: !68 = !DIFile(filename: "{{.*}}/prelude/types/optional.carbon", directory: "")
// CHECK:STDOUT: !69 = !DILocation(line: 28, column: 5, scope: !67)