Explorar o código

Allow conversions between all pointer types with `unsafe as`. (#6635)

Previously we only allowed conversions from `void*` to `U*` this way,
requiring casting via `void*` to get from `T*` to `U*`. That seems like
an unnecessary circumlocution.
Richard Smith hai 3 meses
pai
achega
8353965ca3

+ 10 - 0
core/prelude/operators/as.carbon

@@ -20,18 +20,22 @@ interface ImplicitAs(Dest:! type) {
   fn Convert[self: Self]() -> Dest;
 }
 
+// Workaround: ImplicitAs extends As.
 impl forall [U:! type, T:! ImplicitAs(U)] T as As(U) {
   fn Convert[self: Self]() -> U { return self.Convert(); }
 }
 
+// Workaround: As extends UnsafeAs.
 impl forall [U:! type, T:! As(U)] T as UnsafeAs(U) {
   fn Convert[self: Self]() -> U { return self.Convert(); }
 }
 
+// Copyable types have an identity conversion that performs a copy.
 impl forall [T:! Copy] T as ImplicitAs(T) {
   fn Convert[self: Self]() -> Self { return self.(Copy.Op)(); }
 }
 
+// `const` can be added and removed when converting a value.
 impl forall [T:! type, U:! ImplicitAs(T)] U as ImplicitAs(const T) {
   fn Convert[self: U]() -> const T { return self.Convert(); }
 }
@@ -39,3 +43,9 @@ impl forall [T:! type, U:! ImplicitAs(T)] U as ImplicitAs(const T) {
 impl forall [T:! type, U:! ImplicitAs(T)] const U as ImplicitAs(T) {
   fn Convert[self: const U]() -> T { return (self as U).Convert(); }
 }
+
+// Pointer types can be unsafely cast to other pointer types.
+// TODO: Should `unsafe as` be able to remove `const`?
+impl forall [T:! type, U:! type] T* as UnsafeAs(U*) {
+  fn Convert[self: T*]() -> U* = "pointer.unsafe_convert";
+}

+ 0 - 5
core/prelude/types/cpp/void.carbon

@@ -43,8 +43,3 @@ impl forall [T:! type] T* as ImplicitAs(const CppCompat.VoidBase*) {
 impl forall [T:! type] CppCompat.VoidBase* as UnsafeAs(T*) {
   fn Convert[self: CppCompat.VoidBase*]() -> T* = "pointer.unsafe_convert";
 }
-
-// TODO: Should `unsafe as` be able to remove `const`?
-impl forall [T:! type] const CppCompat.VoidBase* as UnsafeAs(const T*) {
-  fn Convert[self: const CppCompat.VoidBase*]() -> const T* = "pointer.unsafe_convert";
-}

+ 2 - 2
toolchain/driver/testdata/compile/optimize/optimize_none.carbon

@@ -155,10 +155,10 @@ fn VectorizedWithOptSpeed(a: array(i32, 65536)*) {
 // CHECK:STDOUT: !41 = !DILocalVariable(arg: 2, scope: !36, type: !7)
 // CHECK:STDOUT: !42 = !DILocation(line: 4294967295, scope: !36)
 // CHECK:STDOUT: !43 = !DILocation(line: 277, column: 3, scope: !36)
-// CHECK:STDOUT: !44 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.64ccbb8e5d9a0b8e", scope: null, file: !45, line: 32, type: !46, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !48)
+// CHECK:STDOUT: !44 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.64ccbb8e5d9a0b8e", scope: null, file: !45, line: 35, type: !46, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !48)
 // CHECK:STDOUT: !45 = !DIFile(filename: "{{.*}}/prelude/operators/as.carbon", directory: "")
 // CHECK:STDOUT: !46 = !DISubroutineType(types: !47)
 // CHECK:STDOUT: !47 = !{!7, !7}
 // CHECK:STDOUT: !48 = !{!49}
 // CHECK:STDOUT: !49 = !DILocalVariable(arg: 1, scope: !44, type: !7)
-// CHECK:STDOUT: !50 = !DILocation(line: 32, column: 38, scope: !44)
+// CHECK:STDOUT: !50 = !DILocation(line: 35, column: 38, scope: !44)

+ 2 - 2
toolchain/driver/testdata/compile/optimize/optimize_size.carbon

@@ -155,10 +155,10 @@ fn VectorizedWithOptSpeed(a: array(i32, 65536)*) {
 // CHECK:STDOUT: !41 = !DILocalVariable(arg: 2, scope: !36, type: !7)
 // CHECK:STDOUT: !42 = !DILocation(line: 4294967295, scope: !36)
 // CHECK:STDOUT: !43 = !DILocation(line: 277, column: 3, scope: !36)
-// CHECK:STDOUT: !44 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.64ccbb8e5d9a0b8e", scope: null, file: !45, line: 32, type: !46, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !48)
+// CHECK:STDOUT: !44 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.64ccbb8e5d9a0b8e", scope: null, file: !45, line: 35, type: !46, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !48)
 // CHECK:STDOUT: !45 = !DIFile(filename: "{{.*}}/prelude/operators/as.carbon", directory: "")
 // CHECK:STDOUT: !46 = !DISubroutineType(types: !47)
 // CHECK:STDOUT: !47 = !{!7, !7}
 // CHECK:STDOUT: !48 = !{!49}
 // CHECK:STDOUT: !49 = !DILocalVariable(arg: 1, scope: !44, type: !7)
-// CHECK:STDOUT: !50 = !DILocation(line: 32, column: 38, scope: !44)
+// CHECK:STDOUT: !50 = !DILocation(line: 35, column: 38, scope: !44)

+ 2 - 2
toolchain/lower/testdata/array/iterate.carbon

@@ -273,10 +273,10 @@ fn F() {
 // CHECK:STDOUT: !93 = distinct !DISubprogram(name: "None", linkageName: "_CNone.3e8267224c5dc9c2:OptionalStorage.Core.329e9a7481f16207", scope: null, file: !37, line: 110, type: !65, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !94 = !DILocation(line: 112, column: 5, scope: !93)
 // CHECK:STDOUT: !95 = !DILocation(line: 113, column: 5, scope: !93)
-// CHECK:STDOUT: !96 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.1e58d10da180d7d9:ImplicitAs.39e2e54f50ee65cc.Core.255ef555a3d2f793", scope: null, file: !97, line: 32, type: !98, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !100)
+// CHECK:STDOUT: !96 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.1e58d10da180d7d9:ImplicitAs.39e2e54f50ee65cc.Core.255ef555a3d2f793", scope: null, file: !97, line: 35, type: !98, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !100)
 // CHECK:STDOUT: !97 = !DIFile(filename: "{{.*}}/prelude/operators/as.carbon", directory: "")
 // CHECK:STDOUT: !98 = !DISubroutineType(types: !99)
 // CHECK:STDOUT: !99 = !{!16, !16}
 // CHECK:STDOUT: !100 = !{!101}
 // CHECK:STDOUT: !101 = !DILocalVariable(arg: 1, scope: !96, type: !16)
-// CHECK:STDOUT: !102 = !DILocation(line: 32, column: 38, scope: !96)
+// CHECK:STDOUT: !102 = !DILocation(line: 35, column: 38, scope: !96)

+ 2 - 2
toolchain/lower/testdata/for/break_continue.carbon

@@ -302,10 +302,10 @@ fn For() {
 // CHECK:STDOUT: !102 = distinct !DISubprogram(name: "None", linkageName: "_CNone.3e8267224c5dc9c2:OptionalStorage.Core.32fa7206ac42c9b7", scope: null, file: !46, line: 110, type: !74, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !103 = !DILocation(line: 112, column: 5, scope: !102)
 // CHECK:STDOUT: !104 = !DILocation(line: 113, column: 5, scope: !102)
-// CHECK:STDOUT: !105 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.beca8a3ca33a86fb", scope: null, file: !106, line: 32, type: !107, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !109)
+// CHECK:STDOUT: !105 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.beca8a3ca33a86fb", scope: null, file: !106, line: 35, type: !107, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !109)
 // CHECK:STDOUT: !106 = !DIFile(filename: "{{.*}}/prelude/operators/as.carbon", directory: "")
 // CHECK:STDOUT: !107 = !DISubroutineType(types: !108)
 // CHECK:STDOUT: !108 = !{!22, !22}
 // CHECK:STDOUT: !109 = !{!110}
 // CHECK:STDOUT: !110 = !DILocalVariable(arg: 1, scope: !105, type: !22)
-// CHECK:STDOUT: !111 = !DILocation(line: 32, column: 38, scope: !105)
+// CHECK:STDOUT: !111 = !DILocation(line: 35, column: 38, scope: !105)

+ 2 - 2
toolchain/lower/testdata/for/for.carbon

@@ -286,10 +286,10 @@ fn For() {
 // CHECK:STDOUT: !98 = distinct !DISubprogram(name: "None", linkageName: "_CNone.3e8267224c5dc9c2:OptionalStorage.Core.32fa7206ac42c9b7", scope: null, file: !42, line: 110, type: !70, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !99 = !DILocation(line: 112, column: 5, scope: !98)
 // CHECK:STDOUT: !100 = !DILocation(line: 113, column: 5, scope: !98)
-// CHECK:STDOUT: !101 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.beca8a3ca33a86fb", scope: null, file: !102, line: 32, type: !103, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !105)
+// CHECK:STDOUT: !101 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.beca8a3ca33a86fb", scope: null, file: !102, line: 35, type: !103, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !105)
 // CHECK:STDOUT: !102 = !DIFile(filename: "{{.*}}/prelude/operators/as.carbon", directory: "")
 // CHECK:STDOUT: !103 = !DISubroutineType(types: !104)
 // CHECK:STDOUT: !104 = !{!18, !18}
 // CHECK:STDOUT: !105 = !{!106}
 // CHECK:STDOUT: !106 = !DILocalVariable(arg: 1, scope: !101, type: !18)
-// CHECK:STDOUT: !107 = !DILocation(line: 32, column: 38, scope: !101)
+// CHECK:STDOUT: !107 = !DILocation(line: 35, column: 38, scope: !101)

+ 2 - 2
toolchain/lower/testdata/operators/increment.carbon

@@ -89,10 +89,10 @@ fn IncrSigned() {
 // CHECK:STDOUT: !24 = !DILocalVariable(arg: 2, scope: !19, type: !14)
 // CHECK:STDOUT: !25 = !DILocation(line: 4294967295, scope: !19)
 // CHECK:STDOUT: !26 = !DILocation(line: 277, column: 3, scope: !19)
-// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.64ccbb8e5d9a0b8e", scope: null, file: !28, line: 32, type: !29, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !31)
+// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.64ccbb8e5d9a0b8e", scope: null, file: !28, line: 35, type: !29, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !31)
 // CHECK:STDOUT: !28 = !DIFile(filename: "{{.*}}/prelude/operators/as.carbon", directory: "")
 // CHECK:STDOUT: !29 = !DISubroutineType(types: !30)
 // CHECK:STDOUT: !30 = !{!14, !14}
 // CHECK:STDOUT: !31 = !{!32}
 // CHECK:STDOUT: !32 = !DILocalVariable(arg: 1, scope: !27, type: !14)
-// CHECK:STDOUT: !33 = !DILocation(line: 32, column: 38, scope: !27)
+// CHECK:STDOUT: !33 = !DILocation(line: 35, column: 38, scope: !27)

+ 41 - 0
toolchain/lower/testdata/pointer/convert.carbon

@@ -0,0 +1,41 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lower/testdata/pointer/convert.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/pointer/convert.carbon
+
+fn UnsafeAs(p: i32*) -> i64* {
+  return p unsafe as i64*;
+}
+
+// CHECK:STDOUT: ; ModuleID = 'convert.carbon'
+// CHECK:STDOUT: source_filename = "convert.carbon"
+// CHECK:STDOUT:
+// CHECK:STDOUT: ; Function Attrs: nounwind
+// CHECK:STDOUT: define ptr @_CUnsafeAs.Main(ptr %p) #0 !dbg !4 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   ret ptr %p, !dbg !10
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: attributes #0 = { nounwind }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
+// CHECK:STDOUT: !llvm.dbg.cu = !{!2}
+// CHECK:STDOUT:
+// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
+// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
+// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+// CHECK:STDOUT: !3 = !DIFile(filename: "convert.carbon", directory: "")
+// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "UnsafeAs", linkageName: "_CUnsafeAs.Main", scope: null, file: !3, line: 13, type: !5, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
+// CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
+// CHECK:STDOUT: !6 = !{!7, !7}
+// CHECK:STDOUT: !7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 8)
+// CHECK:STDOUT: !8 = !{!9}
+// CHECK:STDOUT: !9 = !DILocalVariable(arg: 1, scope: !4, type: !7)
+// CHECK:STDOUT: !10 = !DILocation(line: 14, column: 3, scope: !4)

+ 23 - 23
toolchain/lower/testdata/primitives/optional.carbon

@@ -305,42 +305,42 @@ fn AddOrRemoveConst(a: i32, b: const i32) {
 // CHECK:STDOUT: !53 = !{!7}
 // CHECK:STDOUT: !54 = !DILocation(line: 27, column: 12, scope: !51)
 // CHECK:STDOUT: !55 = !DILocation(line: 27, column: 5, scope: !51)
-// CHECK:STDOUT: !56 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.a44fce96e16342e7:ImplicitAs.ad22d1bbc0605210.Core.bd3a79eb4ffd3025", scope: null, file: !57, line: 36, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !58)
+// CHECK:STDOUT: !56 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.a44fce96e16342e7:ImplicitAs.ad22d1bbc0605210.Core.bd3a79eb4ffd3025", scope: null, file: !57, line: 40, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !58)
 // CHECK:STDOUT: !57 = !DIFile(filename: "{{.*}}/prelude/operators/as.carbon", directory: "")
 // CHECK:STDOUT: !58 = !{!59}
 // CHECK:STDOUT: !59 = !DILocalVariable(arg: 1, scope: !56, type: !20)
-// CHECK:STDOUT: !60 = !DILocation(line: 36, column: 45, scope: !56)
-// CHECK:STDOUT: !61 = !DILocation(line: 36, column: 38, scope: !56)
+// CHECK:STDOUT: !60 = !DILocation(line: 40, column: 45, scope: !56)
+// CHECK:STDOUT: !61 = !DILocation(line: 40, column: 38, scope: !56)
 // CHECK:STDOUT: !62 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.e5cf8fcbb4feaae2:ImplicitAs.0f95c9e18c91e00a.Core.a7b795aef3d7a0e5", scope: null, file: !34, line: 93, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !63)
 // CHECK:STDOUT: !63 = !{!64}
 // CHECK:STDOUT: !64 = !DILocalVariable(arg: 1, scope: !62, type: !20)
 // CHECK:STDOUT: !65 = !DILocation(line: 94, column: 12, scope: !62)
 // CHECK:STDOUT: !66 = !DILocation(line: 94, column: 5, scope: !62)
-// CHECK:STDOUT: !67 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.a44fce96e16342e7:ImplicitAs.ad22d1bbc0605210.Core.b37806f50d6ac6f2", scope: null, file: !57, line: 36, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !68)
+// CHECK:STDOUT: !67 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.a44fce96e16342e7:ImplicitAs.ad22d1bbc0605210.Core.b37806f50d6ac6f2", scope: null, file: !57, line: 40, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !68)
 // CHECK:STDOUT: !68 = !{!69}
 // CHECK:STDOUT: !69 = !DILocalVariable(arg: 1, scope: !67, type: !20)
-// CHECK:STDOUT: !70 = !DILocation(line: 36, column: 45, scope: !67)
-// CHECK:STDOUT: !71 = !DILocation(line: 36, column: 38, scope: !67)
-// CHECK:STDOUT: !72 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.17f42c13d842b71d:ImplicitAs.eb057aa32837c84e.Core.bd3a79eb4ffd3025", scope: null, file: !57, line: 40, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !73)
+// CHECK:STDOUT: !70 = !DILocation(line: 40, column: 45, scope: !67)
+// CHECK:STDOUT: !71 = !DILocation(line: 40, column: 38, scope: !67)
+// CHECK:STDOUT: !72 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.17f42c13d842b71d:ImplicitAs.eb057aa32837c84e.Core.bd3a79eb4ffd3025", scope: null, file: !57, line: 44, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !73)
 // CHECK:STDOUT: !73 = !{!74}
 // CHECK:STDOUT: !74 = !DILocalVariable(arg: 1, scope: !72, type: !20)
-// CHECK:STDOUT: !75 = !DILocation(line: 40, column: 45, scope: !72)
-// CHECK:STDOUT: !76 = !DILocation(line: 40, column: 38, scope: !72)
-// CHECK:STDOUT: !77 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.17f42c13d842b71d:ImplicitAs.eb057aa32837c84e.Core.fdb5566b9a89e24d", scope: null, file: !57, line: 40, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !78)
+// CHECK:STDOUT: !75 = !DILocation(line: 44, column: 45, scope: !72)
+// CHECK:STDOUT: !76 = !DILocation(line: 44, column: 38, scope: !72)
+// CHECK:STDOUT: !77 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.17f42c13d842b71d:ImplicitAs.eb057aa32837c84e.Core.fdb5566b9a89e24d", scope: null, file: !57, line: 44, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !78)
 // CHECK:STDOUT: !78 = !{!79}
 // CHECK:STDOUT: !79 = !DILocalVariable(arg: 1, scope: !77, type: !20)
-// CHECK:STDOUT: !80 = !DILocation(line: 40, column: 45, scope: !77)
-// CHECK:STDOUT: !81 = !DILocation(line: 40, column: 38, scope: !77)
-// CHECK:STDOUT: !82 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.17f42c13d842b71d:ImplicitAs.eb057aa32837c84e.Core.b37806f50d6ac6f2", scope: null, file: !57, line: 40, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !83)
+// CHECK:STDOUT: !80 = !DILocation(line: 44, column: 45, scope: !77)
+// CHECK:STDOUT: !81 = !DILocation(line: 44, column: 38, scope: !77)
+// CHECK:STDOUT: !82 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.17f42c13d842b71d:ImplicitAs.eb057aa32837c84e.Core.b37806f50d6ac6f2", scope: null, file: !57, line: 44, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !83)
 // CHECK:STDOUT: !83 = !{!84}
 // CHECK:STDOUT: !84 = !DILocalVariable(arg: 1, scope: !82, type: !20)
-// CHECK:STDOUT: !85 = !DILocation(line: 40, column: 45, scope: !82)
-// CHECK:STDOUT: !86 = !DILocation(line: 40, column: 38, scope: !82)
-// CHECK:STDOUT: !87 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.17f42c13d842b71d:ImplicitAs.eb057aa32837c84e.Core.5fb98646c26c8976", scope: null, file: !57, line: 40, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !88)
+// CHECK:STDOUT: !85 = !DILocation(line: 44, column: 45, scope: !82)
+// CHECK:STDOUT: !86 = !DILocation(line: 44, column: 38, scope: !82)
+// CHECK:STDOUT: !87 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.17f42c13d842b71d:ImplicitAs.eb057aa32837c84e.Core.5fb98646c26c8976", scope: null, file: !57, line: 44, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !88)
 // CHECK:STDOUT: !88 = !{!89}
 // CHECK:STDOUT: !89 = !DILocalVariable(arg: 1, scope: !87, type: !20)
-// CHECK:STDOUT: !90 = !DILocation(line: 40, column: 45, scope: !87)
-// CHECK:STDOUT: !91 = !DILocation(line: 40, column: 38, scope: !87)
+// CHECK:STDOUT: !90 = !DILocation(line: 44, column: 45, scope: !87)
+// CHECK:STDOUT: !91 = !DILocation(line: 44, column: 38, scope: !87)
 // CHECK:STDOUT: !92 = distinct !DISubprogram(name: "Has", linkageName: "_CHas.e8f8f92d3d08d149:OptionalStorage.Core.b88d1103f417c6d4", scope: null, file: !34, line: 143, type: !5, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !93)
 // CHECK:STDOUT: !93 = !{!94}
 // CHECK:STDOUT: !94 = !DILocalVariable(arg: 1, scope: !92, type: !7)
@@ -370,11 +370,11 @@ fn AddOrRemoveConst(a: i32, b: const i32) {
 // CHECK:STDOUT: !118 = !DILocalVariable(arg: 1, scope: !116, type: !20)
 // CHECK:STDOUT: !119 = !DILocation(line: 30, column: 12, scope: !116)
 // CHECK:STDOUT: !120 = !DILocation(line: 30, column: 5, scope: !116)
-// CHECK:STDOUT: !121 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.a44fce96e16342e7:ImplicitAs.ad22d1bbc0605210.Core.b930bfdac0979466", scope: null, file: !57, line: 36, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !122)
+// CHECK:STDOUT: !121 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.a44fce96e16342e7:ImplicitAs.ad22d1bbc0605210.Core.b930bfdac0979466", scope: null, file: !57, line: 40, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !122)
 // CHECK:STDOUT: !122 = !{!123}
 // CHECK:STDOUT: !123 = !DILocalVariable(arg: 1, scope: !121, type: !20)
-// CHECK:STDOUT: !124 = !DILocation(line: 36, column: 45, scope: !121)
-// CHECK:STDOUT: !125 = !DILocation(line: 36, column: 38, scope: !121)
+// CHECK:STDOUT: !124 = !DILocation(line: 40, column: 45, scope: !121)
+// CHECK:STDOUT: !125 = !DILocation(line: 40, column: 38, scope: !121)
 // CHECK:STDOUT: !126 = distinct !DISubprogram(name: "Some", linkageName: "_CSome.Optional.Core.2a814810f68c37ba", scope: null, file: !34, line: 29, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !127)
 // CHECK:STDOUT: !127 = !{!128}
 // CHECK:STDOUT: !128 = !DILocalVariable(arg: 1, scope: !126, type: !20)
@@ -386,12 +386,12 @@ fn AddOrRemoveConst(a: i32, b: const i32) {
 // CHECK:STDOUT: !134 = !DILocation(line: 119, column: 5, scope: !131)
 // CHECK:STDOUT: !135 = !DILocation(line: 120, column: 5, scope: !131)
 // CHECK:STDOUT: !136 = !DILocation(line: 121, column: 5, scope: !131)
-// CHECK:STDOUT: !137 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.64ccbb8e5d9a0b8e", scope: null, file: !57, line: 32, type: !138, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !140)
+// CHECK:STDOUT: !137 = distinct !DISubprogram(name: "Convert", linkageName: "_CConvert.14b8745117b2bc54:ImplicitAs.a9271c1e04015f9c.Core.64ccbb8e5d9a0b8e", scope: null, file: !57, line: 35, type: !138, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !140)
 // CHECK:STDOUT: !138 = !DISubroutineType(types: !139)
 // CHECK:STDOUT: !139 = !{!20, !20}
 // CHECK:STDOUT: !140 = !{!141}
 // CHECK:STDOUT: !141 = !DILocalVariable(arg: 1, scope: !137, type: !20)
-// CHECK:STDOUT: !142 = !DILocation(line: 32, column: 38, scope: !137)
+// CHECK:STDOUT: !142 = !DILocation(line: 35, column: 38, scope: !137)
 // CHECK:STDOUT: !143 = distinct !DISubprogram(name: "Some", linkageName: "_CSome.3e8267224c5dc9c2:OptionalStorage.Core.d9fa83018d7f62e1", scope: null, file: !34, line: 115, type: !45, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !144)
 // CHECK:STDOUT: !144 = !{!145}
 // CHECK:STDOUT: !145 = !DILocalVariable(arg: 1, scope: !143, type: !20)