| ... | @@ -2127,6 +2127,50 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError | ... | @@ -2127,6 +2127,50 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError |
| 2127 | return sema.failWithOwnedErrorMsg(msg); | 2127 | return sema.failWithOwnedErrorMsg(msg); |
| 2128 | } | 2128 | } |
| 2129 | | 2129 | |
| | 2130 | fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, object_ty: Type, field_name: []const u8) CompileError { |
| | 2131 | const inner_ty = if (object_ty.isSinglePointer()) object_ty.childType() else object_ty; |
| | 2132 | |
| | 2133 | if (inner_ty.zigTypeTag() == .Optional) opt: { |
| | 2134 | var buf: Type.Payload.ElemType = undefined; |
| | 2135 | const child_ty = inner_ty.optionalChild(&buf); |
| | 2136 | if (!typeSupportsFieldAccess(child_ty, field_name)) break :opt; |
| | 2137 | const msg = msg: { |
| | 2138 | const msg = try sema.errMsg(block, src, "optional type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); |
| | 2139 | errdefer msg.destroy(sema.gpa); |
| | 2140 | try sema.errNote(block, src, msg, "consider using '.?', 'orelse', or 'if'", .{}); |
| | 2141 | break :msg msg; |
| | 2142 | }; |
| | 2143 | return sema.failWithOwnedErrorMsg(msg); |
| | 2144 | } else if (inner_ty.zigTypeTag() == .ErrorUnion) err: { |
| | 2145 | const child_ty = inner_ty.errorUnionPayload(); |
| | 2146 | if (!typeSupportsFieldAccess(child_ty, field_name)) break :err; |
| | 2147 | const msg = msg: { |
| | 2148 | const msg = try sema.errMsg(block, src, "error union type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); |
| | 2149 | errdefer msg.destroy(sema.gpa); |
| | 2150 | try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{}); |
| | 2151 | break :msg msg; |
| | 2152 | }; |
| | 2153 | return sema.failWithOwnedErrorMsg(msg); |
| | 2154 | } |
| | 2155 | return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); |
| | 2156 | } |
| | 2157 | |
| | 2158 | fn typeSupportsFieldAccess(ty: Type, field_name: []const u8) bool { |
| | 2159 | switch (ty.zigTypeTag()) { |
| | 2160 | .Array => return mem.eql(u8, field_name, "len"), |
| | 2161 | .Pointer => { |
| | 2162 | const ptr_info = ty.ptrInfo().data; |
| | 2163 | if (ptr_info.size == .Slice) { |
| | 2164 | return mem.eql(u8, field_name, "ptr") or mem.eql(u8, field_name, "len"); |
| | 2165 | } else if (ptr_info.pointee_type.zigTypeTag() == .Array) { |
| | 2166 | return mem.eql(u8, field_name, "len"); |
| | 2167 | } else return false; |
| | 2168 | }, |
| | 2169 | .Type, .Struct, .Union => return true, |
| | 2170 | else => return false, |
| | 2171 | } |
| | 2172 | } |
| | 2173 | |
| 2130 | /// We don't return a pointer to the new error note because the pointer | 2174 | /// We don't return a pointer to the new error note because the pointer |
| 2131 | /// becomes invalid when you add another one. | 2175 | /// becomes invalid when you add another one. |
| 2132 | fn errNote( | 2176 | fn errNote( |
| ... | @@ -23321,7 +23365,7 @@ fn fieldVal( | ... | @@ -23321,7 +23365,7 @@ fn fieldVal( |
| 23321 | }, | 23365 | }, |
| 23322 | else => {}, | 23366 | else => {}, |
| 23323 | } | 23367 | } |
| 23324 | return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); | 23368 | return sema.failWithInvalidFieldAccess(block, src, object_ty, field_name); |
| 23325 | } | 23369 | } |
| 23326 | | 23370 | |
| 23327 | fn fieldPtr( | 23371 | fn fieldPtr( |
| ... | @@ -23535,7 +23579,7 @@ fn fieldPtr( | ... | @@ -23535,7 +23579,7 @@ fn fieldPtr( |
| 23535 | }, | 23579 | }, |
| 23536 | else => {}, | 23580 | else => {}, |
| 23537 | } | 23581 | } |
| 23538 | return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); | 23582 | return sema.failWithInvalidFieldAccess(block, src, object_ty, field_name); |
| 23539 | } | 23583 | } |
| 23540 | | 23584 | |
| 23541 | fn fieldCallBind( | 23585 | fn fieldCallBind( |