...

Source file src/cmd/compile/internal/types2/predicates.go

Documentation: cmd/compile/internal/types2

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file implements commonly used type predicates.
     6  
     7  package types2
     8  
     9  // isValid reports whether t is a valid type.
    10  func isValid(t Type) bool { return Unalias(t) != Typ[Invalid] }
    11  
    12  // The isX predicates below report whether t is an X.
    13  // If t is a type parameter the result is false; i.e.,
    14  // these predicates don't look inside a type parameter.
    15  
    16  func isBoolean(t Type) bool        { return isBasic(t, IsBoolean) }
    17  func isInteger(t Type) bool        { return isBasic(t, IsInteger) }
    18  func isUnsigned(t Type) bool       { return isBasic(t, IsUnsigned) }
    19  func isFloat(t Type) bool          { return isBasic(t, IsFloat) }
    20  func isComplex(t Type) bool        { return isBasic(t, IsComplex) }
    21  func isNumeric(t Type) bool        { return isBasic(t, IsNumeric) }
    22  func isString(t Type) bool         { return isBasic(t, IsString) }
    23  func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) }
    24  func isConstType(t Type) bool      { return isBasic(t, IsConstType) }
    25  
    26  // isBasic reports whether under(t) is a basic type with the specified info.
    27  // If t is a type parameter the result is false; i.e.,
    28  // isBasic does not look inside a type parameter.
    29  func isBasic(t Type, info BasicInfo) bool {
    30  	u, _ := under(t).(*Basic)
    31  	return u != nil && u.info&info != 0
    32  }
    33  
    34  // The allX predicates below report whether t is an X.
    35  // If t is a type parameter the result is true if isX is true
    36  // for all specified types of the type parameter's type set.
    37  // allX is an optimized version of isX(coreType(t)) (which
    38  // is the same as underIs(t, isX)).
    39  
    40  func allBoolean(t Type) bool         { return allBasic(t, IsBoolean) }
    41  func allInteger(t Type) bool         { return allBasic(t, IsInteger) }
    42  func allUnsigned(t Type) bool        { return allBasic(t, IsUnsigned) }
    43  func allNumeric(t Type) bool         { return allBasic(t, IsNumeric) }
    44  func allString(t Type) bool          { return allBasic(t, IsString) }
    45  func allOrdered(t Type) bool         { return allBasic(t, IsOrdered) }
    46  func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) }
    47  
    48  // allBasic reports whether under(t) is a basic type with the specified info.
    49  // If t is a type parameter, the result is true if isBasic(t, info) is true
    50  // for all specific types of the type parameter's type set.
    51  // allBasic(t, info) is an optimized version of isBasic(coreType(t), info).
    52  func allBasic(t Type, info BasicInfo) bool {
    53  	if tpar, _ := Unalias(t).(*TypeParam); tpar != nil {
    54  		return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })
    55  	}
    56  	return isBasic(t, info)
    57  }
    58  
    59  // hasName reports whether t has a name. This includes
    60  // predeclared types, defined types, and type parameters.
    61  // hasName may be called with types that are not fully set up.
    62  func hasName(t Type) bool {
    63  	switch Unalias(t).(type) {
    64  	case *Basic, *Named, *TypeParam:
    65  		return true
    66  	}
    67  	return false
    68  }
    69  
    70  // isTypeLit reports whether t is a type literal.
    71  // This includes all non-defined types, but also basic types.
    72  // isTypeLit may be called with types that are not fully set up.
    73  func isTypeLit(t Type) bool {
    74  	switch Unalias(t).(type) {
    75  	case *Named, *TypeParam:
    76  		return false
    77  	}
    78  	return true
    79  }
    80  
    81  // isTyped reports whether t is typed; i.e., not an untyped
    82  // constant or boolean.
    83  // Safe to call from types that are not fully set up.
    84  func isTyped(t Type) bool {
    85  	// Alias and named types cannot denote untyped types
    86  	// so there's no need to call Unalias or under, below.
    87  	b, _ := t.(*Basic)
    88  	return b == nil || b.info&IsUntyped == 0
    89  }
    90  
    91  // isUntyped(t) is the same as !isTyped(t).
    92  // Safe to call from types that are not fully set up.
    93  func isUntyped(t Type) bool {
    94  	return !isTyped(t)
    95  }
    96  
    97  // isUntypedNumeric reports whether t is an untyped numeric type.
    98  // Safe to call from types that are not fully set up.
    99  func isUntypedNumeric(t Type) bool {
   100  	// Alias and named types cannot denote untyped types
   101  	// so there's no need to call Unalias or under, below.
   102  	b, _ := t.(*Basic)
   103  	return b != nil && b.info&IsUntyped != 0 && b.info&IsNumeric != 0
   104  }
   105  
   106  // IsInterface reports whether t is an interface type.
   107  func IsInterface(t Type) bool {
   108  	_, ok := under(t).(*Interface)
   109  	return ok
   110  }
   111  
   112  // isNonTypeParamInterface reports whether t is an interface type but not a type parameter.
   113  func isNonTypeParamInterface(t Type) bool {
   114  	return !isTypeParam(t) && IsInterface(t)
   115  }
   116  
   117  // isTypeParam reports whether t is a type parameter.
   118  func isTypeParam(t Type) bool {
   119  	_, ok := Unalias(t).(*TypeParam)
   120  	return ok
   121  }
   122  
   123  // hasEmptyTypeset reports whether t is a type parameter with an empty type set.
   124  // The function does not force the computation of the type set and so is safe to
   125  // use anywhere, but it may report a false negative if the type set has not been
   126  // computed yet.
   127  func hasEmptyTypeset(t Type) bool {
   128  	if tpar, _ := Unalias(t).(*TypeParam); tpar != nil && tpar.bound != nil {
   129  		iface, _ := safeUnderlying(tpar.bound).(*Interface)
   130  		return iface != nil && iface.tset != nil && iface.tset.IsEmpty()
   131  	}
   132  	return false
   133  }
   134  
   135  // isGeneric reports whether a type is a generic, uninstantiated type
   136  // (generic signatures are not included).
   137  // TODO(gri) should we include signatures or assert that they are not present?
   138  func isGeneric(t Type) bool {
   139  	// A parameterized type is only generic if it doesn't have an instantiation already.
   140  	if alias, _ := t.(*Alias); alias != nil && alias.tparams != nil && alias.targs == nil {
   141  		return true
   142  	}
   143  	named := asNamed(t)
   144  	return named != nil && named.obj != nil && named.inst == nil && named.TypeParams().Len() > 0
   145  }
   146  
   147  // Comparable reports whether values of type T are comparable.
   148  func Comparable(T Type) bool {
   149  	return comparable(T, true, nil, nil)
   150  }
   151  
   152  // If dynamic is set, non-type parameter interfaces are always comparable.
   153  // If reportf != nil, it may be used to report why T is not comparable.
   154  func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool {
   155  	if seen[T] {
   156  		return true
   157  	}
   158  	if seen == nil {
   159  		seen = make(map[Type]bool)
   160  	}
   161  	seen[T] = true
   162  
   163  	switch t := under(T).(type) {
   164  	case *Basic:
   165  		// assume invalid types to be comparable
   166  		// to avoid follow-up errors
   167  		return t.kind != UntypedNil
   168  	case *Pointer, *Chan:
   169  		return true
   170  	case *Struct:
   171  		for _, f := range t.fields {
   172  			if !comparable(f.typ, dynamic, seen, nil) {
   173  				if reportf != nil {
   174  					reportf("struct containing %s cannot be compared", f.typ)
   175  				}
   176  				return false
   177  			}
   178  		}
   179  		return true
   180  	case *Array:
   181  		if !comparable(t.elem, dynamic, seen, nil) {
   182  			if reportf != nil {
   183  				reportf("%s cannot be compared", t)
   184  			}
   185  			return false
   186  		}
   187  		return true
   188  	case *Interface:
   189  		if dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) {
   190  			return true
   191  		}
   192  		if reportf != nil {
   193  			if t.typeSet().IsEmpty() {
   194  				reportf("empty type set")
   195  			} else {
   196  				reportf("incomparable types in type set")
   197  			}
   198  		}
   199  		// fallthrough
   200  	}
   201  	return false
   202  }
   203  
   204  // hasNil reports whether type t includes the nil value.
   205  func hasNil(t Type) bool {
   206  	switch u := under(t).(type) {
   207  	case *Basic:
   208  		return u.kind == UnsafePointer
   209  	case *Slice, *Pointer, *Signature, *Map, *Chan:
   210  		return true
   211  	case *Interface:
   212  		return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool {
   213  			return u != nil && hasNil(u)
   214  		})
   215  	}
   216  	return false
   217  }
   218  
   219  // samePkg reports whether packages a and b are the same.
   220  func samePkg(a, b *Package) bool {
   221  	// package is nil for objects in universe scope
   222  	if a == nil || b == nil {
   223  		return a == b
   224  	}
   225  	// a != nil && b != nil
   226  	return a.path == b.path
   227  }
   228  
   229  // An ifacePair is a node in a stack of interface type pairs compared for identity.
   230  type ifacePair struct {
   231  	x, y *Interface
   232  	prev *ifacePair
   233  }
   234  
   235  func (p *ifacePair) identical(q *ifacePair) bool {
   236  	return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
   237  }
   238  
   239  // A comparer is used to compare types.
   240  type comparer struct {
   241  	ignoreTags     bool // if set, identical ignores struct tags
   242  	ignoreInvalids bool // if set, identical treats an invalid type as identical to any type
   243  }
   244  
   245  // For changes to this code the corresponding changes should be made to unifier.nify.
   246  func (c *comparer) identical(x, y Type, p *ifacePair) bool {
   247  	x = Unalias(x)
   248  	y = Unalias(y)
   249  
   250  	if x == y {
   251  		return true
   252  	}
   253  
   254  	if c.ignoreInvalids && (!isValid(x) || !isValid(y)) {
   255  		return true
   256  	}
   257  
   258  	switch x := x.(type) {
   259  	case *Basic:
   260  		// Basic types are singletons except for the rune and byte
   261  		// aliases, thus we cannot solely rely on the x == y check
   262  		// above. See also comment in TypeName.IsAlias.
   263  		if y, ok := y.(*Basic); ok {
   264  			return x.kind == y.kind
   265  		}
   266  
   267  	case *Array:
   268  		// Two array types are identical if they have identical element types
   269  		// and the same array length.
   270  		if y, ok := y.(*Array); ok {
   271  			// If one or both array lengths are unknown (< 0) due to some error,
   272  			// assume they are the same to avoid spurious follow-on errors.
   273  			return (x.len < 0 || y.len < 0 || x.len == y.len) && c.identical(x.elem, y.elem, p)
   274  		}
   275  
   276  	case *Slice:
   277  		// Two slice types are identical if they have identical element types.
   278  		if y, ok := y.(*Slice); ok {
   279  			return c.identical(x.elem, y.elem, p)
   280  		}
   281  
   282  	case *Struct:
   283  		// Two struct types are identical if they have the same sequence of fields,
   284  		// and if corresponding fields have the same names, and identical types,
   285  		// and identical tags. Two embedded fields are considered to have the same
   286  		// name. Lower-case field names from different packages are always different.
   287  		if y, ok := y.(*Struct); ok {
   288  			if x.NumFields() == y.NumFields() {
   289  				for i, f := range x.fields {
   290  					g := y.fields[i]
   291  					if f.embedded != g.embedded ||
   292  						!c.ignoreTags && x.Tag(i) != y.Tag(i) ||
   293  						!f.sameId(g.pkg, g.name, false) ||
   294  						!c.identical(f.typ, g.typ, p) {
   295  						return false
   296  					}
   297  				}
   298  				return true
   299  			}
   300  		}
   301  
   302  	case *Pointer:
   303  		// Two pointer types are identical if they have identical base types.
   304  		if y, ok := y.(*Pointer); ok {
   305  			return c.identical(x.base, y.base, p)
   306  		}
   307  
   308  	case *Tuple:
   309  		// Two tuples types are identical if they have the same number of elements
   310  		// and corresponding elements have identical types.
   311  		if y, ok := y.(*Tuple); ok {
   312  			if x.Len() == y.Len() {
   313  				if x != nil {
   314  					for i, v := range x.vars {
   315  						w := y.vars[i]
   316  						if !c.identical(v.typ, w.typ, p) {
   317  							return false
   318  						}
   319  					}
   320  				}
   321  				return true
   322  			}
   323  		}
   324  
   325  	case *Signature:
   326  		y, _ := y.(*Signature)
   327  		if y == nil {
   328  			return false
   329  		}
   330  
   331  		// Two function types are identical if they have the same number of
   332  		// parameters and result values, corresponding parameter and result types
   333  		// are identical, and either both functions are variadic or neither is.
   334  		// Parameter and result names are not required to match, and type
   335  		// parameters are considered identical modulo renaming.
   336  
   337  		if x.TypeParams().Len() != y.TypeParams().Len() {
   338  			return false
   339  		}
   340  
   341  		// In the case of generic signatures, we will substitute in yparams and
   342  		// yresults.
   343  		yparams := y.params
   344  		yresults := y.results
   345  
   346  		if x.TypeParams().Len() > 0 {
   347  			// We must ignore type parameter names when comparing x and y. The
   348  			// easiest way to do this is to substitute x's type parameters for y's.
   349  			xtparams := x.TypeParams().list()
   350  			ytparams := y.TypeParams().list()
   351  
   352  			var targs []Type
   353  			for i := range xtparams {
   354  				targs = append(targs, x.TypeParams().At(i))
   355  			}
   356  			smap := makeSubstMap(ytparams, targs)
   357  
   358  			var check *Checker   // ok to call subst on a nil *Checker
   359  			ctxt := NewContext() // need a non-nil Context for the substitution below
   360  
   361  			// Constraints must be pair-wise identical, after substitution.
   362  			for i, xtparam := range xtparams {
   363  				ybound := check.subst(nopos, ytparams[i].bound, smap, nil, ctxt)
   364  				if !c.identical(xtparam.bound, ybound, p) {
   365  					return false
   366  				}
   367  			}
   368  
   369  			yparams = check.subst(nopos, y.params, smap, nil, ctxt).(*Tuple)
   370  			yresults = check.subst(nopos, y.results, smap, nil, ctxt).(*Tuple)
   371  		}
   372  
   373  		return x.variadic == y.variadic &&
   374  			c.identical(x.params, yparams, p) &&
   375  			c.identical(x.results, yresults, p)
   376  
   377  	case *Union:
   378  		if y, _ := y.(*Union); y != nil {
   379  			// TODO(rfindley): can this be reached during type checking? If so,
   380  			// consider passing a type set map.
   381  			unionSets := make(map[*Union]*_TypeSet)
   382  			xset := computeUnionTypeSet(nil, unionSets, nopos, x)
   383  			yset := computeUnionTypeSet(nil, unionSets, nopos, y)
   384  			return xset.terms.equal(yset.terms)
   385  		}
   386  
   387  	case *Interface:
   388  		// Two interface types are identical if they describe the same type sets.
   389  		// With the existing implementation restriction, this simplifies to:
   390  		//
   391  		// Two interface types are identical if they have the same set of methods with
   392  		// the same names and identical function types, and if any type restrictions
   393  		// are the same. Lower-case method names from different packages are always
   394  		// different. The order of the methods is irrelevant.
   395  		if y, ok := y.(*Interface); ok {
   396  			xset := x.typeSet()
   397  			yset := y.typeSet()
   398  			if xset.comparable != yset.comparable {
   399  				return false
   400  			}
   401  			if !xset.terms.equal(yset.terms) {
   402  				return false
   403  			}
   404  			a := xset.methods
   405  			b := yset.methods
   406  			if len(a) == len(b) {
   407  				// Interface types are the only types where cycles can occur
   408  				// that are not "terminated" via named types; and such cycles
   409  				// can only be created via method parameter types that are
   410  				// anonymous interfaces (directly or indirectly) embedding
   411  				// the current interface. Example:
   412  				//
   413  				//    type T interface {
   414  				//        m() interface{T}
   415  				//    }
   416  				//
   417  				// If two such (differently named) interfaces are compared,
   418  				// endless recursion occurs if the cycle is not detected.
   419  				//
   420  				// If x and y were compared before, they must be equal
   421  				// (if they were not, the recursion would have stopped);
   422  				// search the ifacePair stack for the same pair.
   423  				//
   424  				// This is a quadratic algorithm, but in practice these stacks
   425  				// are extremely short (bounded by the nesting depth of interface
   426  				// type declarations that recur via parameter types, an extremely
   427  				// rare occurrence). An alternative implementation might use a
   428  				// "visited" map, but that is probably less efficient overall.
   429  				q := &ifacePair{x, y, p}
   430  				for p != nil {
   431  					if p.identical(q) {
   432  						return true // same pair was compared before
   433  					}
   434  					p = p.prev
   435  				}
   436  				if debug {
   437  					assertSortedMethods(a)
   438  					assertSortedMethods(b)
   439  				}
   440  				for i, f := range a {
   441  					g := b[i]
   442  					if f.Id() != g.Id() || !c.identical(f.typ, g.typ, q) {
   443  						return false
   444  					}
   445  				}
   446  				return true
   447  			}
   448  		}
   449  
   450  	case *Map:
   451  		// Two map types are identical if they have identical key and value types.
   452  		if y, ok := y.(*Map); ok {
   453  			return c.identical(x.key, y.key, p) && c.identical(x.elem, y.elem, p)
   454  		}
   455  
   456  	case *Chan:
   457  		// Two channel types are identical if they have identical value types
   458  		// and the same direction.
   459  		if y, ok := y.(*Chan); ok {
   460  			return x.dir == y.dir && c.identical(x.elem, y.elem, p)
   461  		}
   462  
   463  	case *Named:
   464  		// Two named types are identical if their type names originate
   465  		// in the same type declaration; if they are instantiated they
   466  		// must have identical type argument lists.
   467  		if y := asNamed(y); y != nil {
   468  			// check type arguments before origins to match unifier
   469  			// (for correct source code we need to do all checks so
   470  			// order doesn't matter)
   471  			xargs := x.TypeArgs().list()
   472  			yargs := y.TypeArgs().list()
   473  			if len(xargs) != len(yargs) {
   474  				return false
   475  			}
   476  			for i, xarg := range xargs {
   477  				if !Identical(xarg, yargs[i]) {
   478  					return false
   479  				}
   480  			}
   481  			return identicalOrigin(x, y)
   482  		}
   483  
   484  	case *TypeParam:
   485  		// nothing to do (x and y being equal is caught in the very beginning of this function)
   486  
   487  	case nil:
   488  		// avoid a crash in case of nil type
   489  
   490  	default:
   491  		panic("unreachable")
   492  	}
   493  
   494  	return false
   495  }
   496  
   497  // identicalOrigin reports whether x and y originated in the same declaration.
   498  func identicalOrigin(x, y *Named) bool {
   499  	// TODO(gri) is this correct?
   500  	return x.Origin().obj == y.Origin().obj
   501  }
   502  
   503  // identicalInstance reports if two type instantiations are identical.
   504  // Instantiations are identical if their origin and type arguments are
   505  // identical.
   506  func identicalInstance(xorig Type, xargs []Type, yorig Type, yargs []Type) bool {
   507  	if len(xargs) != len(yargs) {
   508  		return false
   509  	}
   510  
   511  	for i, xa := range xargs {
   512  		if !Identical(xa, yargs[i]) {
   513  			return false
   514  		}
   515  	}
   516  
   517  	return Identical(xorig, yorig)
   518  }
   519  
   520  // Default returns the default "typed" type for an "untyped" type;
   521  // it returns the incoming type for all other types. The default type
   522  // for untyped nil is untyped nil.
   523  func Default(t Type) Type {
   524  	// Alias and named types cannot denote untyped types
   525  	// so there's no need to call Unalias or under, below.
   526  	if t, _ := t.(*Basic); t != nil {
   527  		switch t.kind {
   528  		case UntypedBool:
   529  			return Typ[Bool]
   530  		case UntypedInt:
   531  			return Typ[Int]
   532  		case UntypedRune:
   533  			return universeRune // use 'rune' name
   534  		case UntypedFloat:
   535  			return Typ[Float64]
   536  		case UntypedComplex:
   537  			return Typ[Complex128]
   538  		case UntypedString:
   539  			return Typ[String]
   540  		}
   541  	}
   542  	return t
   543  }
   544  
   545  // maxType returns the "largest" type that encompasses both x and y.
   546  // If x and y are different untyped numeric types, the result is the type of x or y
   547  // that appears later in this list: integer, rune, floating-point, complex.
   548  // Otherwise, if x != y, the result is nil.
   549  func maxType(x, y Type) Type {
   550  	// We only care about untyped types (for now), so == is good enough.
   551  	// TODO(gri) investigate generalizing this function to simplify code elsewhere
   552  	if x == y {
   553  		return x
   554  	}
   555  	if isUntypedNumeric(x) && isUntypedNumeric(y) {
   556  		// untyped types are basic types
   557  		if x.(*Basic).kind > y.(*Basic).kind {
   558  			return x
   559  		}
   560  		return y
   561  	}
   562  	return nil
   563  }
   564  
   565  // clone makes a "flat copy" of *p and returns a pointer to the copy.
   566  func clone[P *T, T any](p P) P {
   567  	c := *p
   568  	return &c
   569  }
   570  

View as plain text