Source file src/go/types/errsupport.go

     1  // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
     2  // Source: ../../cmd/compile/internal/types2/errsupport.go
     3  
     4  // Copyright 2024 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  
     8  // This file implements support functions for error messages.
     9  
    10  package types
    11  
    12  // lookupError returns a case-specific error when a lookup of selector sel in the
    13  // given type fails but an object with alternative spelling (case folding) is found.
    14  // If structLit is set, the error message is specifically for struct literal fields.
    15  func (check *Checker) lookupError(typ Type, sel string, obj Object, structLit bool) string {
    16  	// Provide more detail if there is an unexported object, or one with different capitalization.
    17  	// If selector and object are in the same package (==), export doesn't matter, otherwise (!=) it does.
    18  	// Messages depend on whether it's a general lookup or a field lookup in a struct literal.
    19  	//
    20  	// case           sel     pkg   have   message (examples for general lookup)
    21  	// ---------------------------------------------------------------------------------------------------------
    22  	// ok             x.Foo   ==    Foo
    23  	// misspelled     x.Foo   ==    FoO    type X has no field or method Foo, but does have field FoO
    24  	// misspelled     x.Foo   ==    foo    type X has no field or method Foo, but does have field foo
    25  	// misspelled     x.Foo   ==    foO    type X has no field or method Foo, but does have field foO
    26  	//
    27  	// misspelled     x.foo   ==    Foo    type X has no field or method foo, but does have field Foo
    28  	// misspelled     x.foo   ==    FoO    type X has no field or method foo, but does have field FoO
    29  	// ok             x.foo   ==    foo
    30  	// misspelled     x.foo   ==    foO    type X has no field or method foo, but does have field foO
    31  	//
    32  	// ok             x.Foo   !=    Foo
    33  	// misspelled     x.Foo   !=    FoO    type X has no field or method Foo, but does have field FoO
    34  	// unexported     x.Foo   !=    foo    type X has no field or method Foo, but does have unexported field foo
    35  	// missing        x.Foo   !=    foO    type X has no field or method Foo
    36  	//
    37  	// misspelled     x.foo   !=    Foo    type X has no field or method foo, but does have field Foo
    38  	// missing        x.foo   !=    FoO    type X has no field or method foo
    39  	// inaccessible   x.foo   !=    foo    cannot refer to unexported field foo
    40  	// missing        x.foo   !=    foO    type X has no field or method foo
    41  
    42  	const (
    43  		ok           = iota
    44  		missing      // no object found
    45  		misspelled   // found object with different spelling
    46  		unexported   // found object with name differing only in first letter
    47  		inaccessible // found object with matching name but inaccessible from the current package
    48  	)
    49  
    50  	// determine case
    51  	e := missing
    52  	var alt string // alternative spelling of selector; if any
    53  	if obj != nil {
    54  		alt = obj.Name()
    55  		if obj.Pkg() == check.pkg {
    56  			assert(alt != sel) // otherwise there is no lookup error
    57  			e = misspelled
    58  		} else if isExported(sel) {
    59  			if isExported(alt) {
    60  				e = misspelled
    61  			} else if tail(sel) == tail(alt) {
    62  				e = unexported
    63  			}
    64  		} else if isExported(alt) {
    65  			if tail(sel) == tail(alt) {
    66  				e = misspelled
    67  			}
    68  		} else if sel == alt {
    69  			e = inaccessible
    70  		}
    71  	}
    72  
    73  	if structLit {
    74  		switch e {
    75  		case missing:
    76  			return check.sprintf("unknown field %s in struct literal of type %s", sel, typ)
    77  		case misspelled:
    78  			return check.sprintf("unknown field %s in struct literal of type %s, but does have %s", sel, typ, alt)
    79  		case unexported:
    80  			return check.sprintf("unknown field %s in struct literal of type %s, but does have unexported %s", sel, typ, alt)
    81  		case inaccessible:
    82  			return check.sprintf("cannot refer to unexported field %s in struct literal of type %s", alt, typ)
    83  		}
    84  	} else {
    85  		what := "object"
    86  		switch obj.(type) {
    87  		case *Var:
    88  			what = "field"
    89  		case *Func:
    90  			what = "method"
    91  		}
    92  		switch e {
    93  		case missing:
    94  			return check.sprintf("type %s has no field or method %s", typ, sel)
    95  		case misspelled:
    96  			return check.sprintf("type %s has no field or method %s, but does have %s %s", typ, sel, what, alt)
    97  		case unexported:
    98  			return check.sprintf("type %s has no field or method %s, but does have unexported %s %s", typ, sel, what, alt)
    99  		case inaccessible:
   100  			return check.sprintf("cannot refer to unexported %s %s", what, alt)
   101  		}
   102  	}
   103  
   104  	panic("unreachable")
   105  }
   106  
   107  // tail returns the string s without its first (UTF-8) character.
   108  // If len(s) == 0, the result is s.
   109  func tail(s string) string {
   110  	for i, _ := range s {
   111  		if i > 0 {
   112  			return s[i:]
   113  		}
   114  	}
   115  	return s
   116  }
   117  

View as plain text