ResolveSubtypeIdent inspects the identifier used as the value of a `Subtype:` composite-literal field and reports the typed-scope verdict via the (resolved, ok) tuple: - (true, true): the identifier is a declared errs.Subtype constant. The AST pass may skip its nameset check for this site. - (false
(absPath string, sel *ast.Ident)
| 159 | // info, sel==nil, no type info for the identifier, or the resolved |
| 160 | // object is not a constant). Caller defers to AST-only resolution. |
| 161 | func (s *TypedScope) ResolveSubtypeIdent(absPath string, sel *ast.Ident) (resolved, ok bool) { |
| 162 | if !s.Enabled() { |
| 163 | return false, false |
| 164 | } |
| 165 | info, found := s.LookupFileInfo(absPath) |
| 166 | if !found || info == nil || sel == nil { |
| 167 | return false, false |
| 168 | } |
| 169 | obj, found := info.Uses[sel] |
| 170 | if !found || obj == nil { |
| 171 | // No type info for this identifier — caller falls back to AST. |
| 172 | return false, false |
| 173 | } |
| 174 | c, isConst := obj.(*types.Const) |
| 175 | if !isConst { |
| 176 | return false, false |
| 177 | } |
| 178 | if c.Pkg() == nil || c.Pkg().Path() != errsPkgPath { |
| 179 | // Foreign-package constant assigned to a Subtype: slot. Reject — |
| 180 | // the caller routes ALL selectors through this path regardless of |
| 181 | // name shape, so this branch fires for both `foreign.SubtypeFoo` |
| 182 | // and `foreign.MyKind`. |
| 183 | return false, true |
| 184 | } |
| 185 | if _, declared := s.errsSubtypeConsts[c.Name()]; !declared { |
| 186 | // In the errs package but not a Subtype const (defense-in-depth). |
| 187 | return false, true |
| 188 | } |
| 189 | return true, true |
| 190 | } |