func (c *Checker) processConversion(pkg *lint.Pkg, node ast.Node) {
	if node, ok := node.(*ast.CallExpr); ok {
		callTyp := pkg.TypesInfo.TypeOf(node.Fun)
		var typDst *types.Struct
		var ok bool
		switch typ := callTyp.(type) {
		case *types.Named:
			typDst, ok = typ.Underlying().(*types.Struct)
		case *types.Pointer:
			typDst, ok = typ.Elem().Underlying().(*types.Struct)
		default:
			return
		}
		if !ok {
			return
		}

		if typ, ok := pkg.TypesInfo.TypeOf(node.Args[0]).(*types.Basic); ok && typ.Kind() == types.UnsafePointer {
			// This is an unsafe conversion. Assume that all the
			// fields are relevant (they are, because of memory
			// layout)
			n := typDst.NumFields()
			for i := 0; i < n; i++ {
				c.graph.markUsedBy(typDst.Field(i), typDst)
			}
			return
		}

		typSrc, ok := dereferenceType(pkg.TypesInfo.TypeOf(node.Args[0])).Underlying().(*types.Struct)
		if !ok {
			return
		}

		// When we convert from type t1 to t2, were t1 and t2 are
		// structs, all fields are relevant, as otherwise the
		// conversion would fail.
		//
		// We mark t2's fields as used by t1's fields, and vice
		// versa. That way, if no code actually refers to a field
		// in either type, it's still correctly marked as unused.
		// If a field is used in either struct, it's implicitly
		// relevant in the other one, too.
		//
		// It works in a similar way for conversions between types
		// of two packages, only that the extra information in the
		// graph is redundant unless we're in whole program mode.
		n := typDst.NumFields()
		for i := 0; i < n; i++ {
			fDst := typDst.Field(i)
			fSrc := typSrc.Field(i)
			c.graph.markUsedBy(fDst, fSrc)
			c.graph.markUsedBy(fSrc, fDst)
		}
	}
}
func (c *Checker) processConversion(pkg *lint.Pkg, node ast.Node) {
	if node, ok := node.(*ast.CallExpr); ok {
		callTyp := pkg.TypesInfo.TypeOf(node.Fun)
		var typDst *types.Struct
		var ok bool
		switch typ := callTyp.(type) {
		case *types.Named:
			typDst, ok = typ.Underlying().(*types.Struct)
		case *types.Pointer:
			typDst, ok = typ.Elem().Underlying().(*types.Struct)
		default:
			return
		}
		if !ok {
			return
		}

		if typ, ok := pkg.TypesInfo.TypeOf(node.Args[0]).(*types.Basic); ok && typ.Kind() == types.UnsafePointer {
			
			
			
			n := typDst.NumFields()
			for i := 0; i < n; i++ {
				c.graph.markUsedBy(typDst.Field(i), typDst)
			}
			return
		}

		typSrc, ok := dereferenceType(pkg.TypesInfo.TypeOf(node.Args[0])).Underlying().(*types.Struct)
		if !ok {
			return
		}

		
		
		
		
		
		
		
		
		
		
		
		
		
		n := typDst.NumFields()
		for i := 0; i < n; i++ {
			fDst := typDst.Field(i)
			fSrc := typSrc.Field(i)
			c.graph.markUsedBy(fDst, fSrc)
			c.graph.markUsedBy(fSrc, fDst)
		}
	}
}
func ( c * Checker ) processConversion ( pkg * lint . Pkg , node ast . Node ) { if node , ok := node . ( * ast . CallExpr ) ; ok { callTyp := pkg . TypesInfo . TypeOf ( node . Fun ) var typDst * types . Struct var ok bool switch typ := callTyp . ( type ) { case * types . Named : typDst , ok = typ . Underlying ( ) . ( * types . Struct ) case * types . Pointer : typDst , ok = typ . Elem ( ) . Underlying ( ) . ( * types . Struct ) default : return } if ! ok { return } if typ , ok := pkg . TypesInfo . TypeOf ( node . Args [ 0 ] ) . ( * types . Basic ) ; ok && typ . Kind ( ) == types . UnsafePointer { // This is an unsafe conversion. Assume that all the // fields are relevant (they are, because of memory // layout) n := typDst . NumFields ( ) for i := 0 ; i < n ; i ++ { c . graph . markUsedBy ( typDst . Field ( i ) , typDst ) } return } typSrc , ok := dereferenceType ( pkg . TypesInfo . TypeOf ( node . Args [ 0 ] ) ) . Underlying ( ) . ( * types . Struct ) if ! ok { return } // When we convert from type t1 to t2, were t1 and t2 are // structs, all fields are relevant, as otherwise the // conversion would fail. // // We mark t2's fields as used by t1's fields, and vice // versa. That way, if no code actually refers to a field // in either type, it's still correctly marked as unused. // If a field is used in either struct, it's implicitly // relevant in the other one, too. // // It works in a similar way for conversions between types // of two packages, only that the extra information in the // graph is redundant unless we're in whole program mode. n := typDst . NumFields ( ) for i := 0 ; i < n ; i ++ { fDst := typDst . Field ( i ) fSrc := typSrc . Field ( i ) c . graph . markUsedBy ( fDst , fSrc ) c . graph . markUsedBy ( fSrc , fDst ) } } }
// processConversion marks fields as used if they're part of a type conversion.
processConversion marks fields as used if they re part of a type conversion .