@@ -1394,28 +1394,38 @@ func (g *graph) stmt(stmt ast.Stmt, by types.Object) {
1394
1394
// embeddedField sees the field declared by the embedded field node, and marks the type as used by the field.
1395
1395
//
1396
1396
// Embedded fields are special in two ways: they don't have names, so we don't have immediate access to an ast.Ident to
1397
- // resolve to the field's types.Var, and we cannot use g.read on the type because eventually we do get to an ast.Ident,
1398
- // and ObjectOf resolves embedded fields to the field they declare, not the type. That's why we have code specially for
1399
- // handling embedded fields.
1397
+ // resolve to the field's types.Var and need to instead walk the AST , and we cannot use g.read on the type because
1398
+ // eventually we do get to an ast.Ident, and ObjectOf resolves embedded fields to the field they declare, not the type.
1399
+ // That's why we have code specially for handling embedded fields.
1400
1400
func (g * graph ) embeddedField (node ast.Node , by types.Object ) * types.Var {
1401
1401
// We need to traverse the tree to find the ast.Ident, but all the nodes we traverse should be used by the object we
1402
1402
// get once we resolve the ident. Collect the nodes and process them once we've found the ident.
1403
1403
nodes := make ([]ast.Node , 0 , 4 )
1404
1404
for {
1405
1405
switch node_ := node .(type ) {
1406
1406
case * ast.Ident :
1407
+ // obj is the field
1407
1408
obj := g .info .ObjectOf (node_ ).(* types.Var )
1409
+ // the field is declared by the enclosing type
1408
1410
g .see (obj , by )
1409
1411
for _ , n := range nodes {
1410
1412
g .read (n , obj )
1411
1413
}
1412
- switch typ := typeutil .Dereference (g .info .TypeOf (node_ )).(type ) {
1413
- case * types.Named :
1414
- g .use (typ .Obj (), obj )
1415
- case * types.Basic :
1416
- // Nothing to do
1417
- default :
1418
- lint .ExhaustiveTypeSwitch (typ )
1414
+
1415
+ if tname , ok := g .info .Uses [node_ ].(* types.TypeName ); ok && tname .IsAlias () {
1416
+ // When embedding an alias we want to use the alias, not what the alias points to.
1417
+ g .use (tname , obj )
1418
+ } else {
1419
+ switch typ := typeutil .Dereference (g .info .TypeOf (node_ )).(type ) {
1420
+ case * types.Named :
1421
+ // (7.2) fields use their types
1422
+ g .use (typ .Obj (), obj )
1423
+ case * types.Basic :
1424
+ // Nothing to do
1425
+ default :
1426
+ // Other types are only possible for aliases, which we've already handled
1427
+ lint .ExhaustiveTypeSwitch (typ )
1428
+ }
1419
1429
}
1420
1430
return obj
1421
1431
case * ast.StarExpr :
@@ -1518,6 +1528,9 @@ func (g *graph) namedType(typ *types.TypeName, spec ast.Expr) {
1518
1528
obj := g .info .ObjectOf (name )
1519
1529
g .see (obj , typ )
1520
1530
// (7.2) fields use their types
1531
+ //
1532
+ // This handles aliases correctly because ObjectOf(alias) returns the TypeName of the alias, not
1533
+ // what the alias points to.
1521
1534
g .read (field .Type , obj )
1522
1535
if name .Name == "_" {
1523
1536
// (9.9) objects named the blank identifier are used
0 commit comments