Skip to content

Conversation

@BhautikChudasama
Copy link

Issue

  • getFieldProducersForFuncReturns fn would exit too early if it encountered even a single non-nilable field.
  • Upgraded golang to 1.24.0.
  • I simplified below code, Because i don't get if strings.HasPrefix(pass.Pkg.Path(), config.NilAwayPkgPathPrefix) {
	// Construct experimental features. By default, enable all features on NilAway itself.
	functionConfig := assertiontree.FunctionConfig{}
	if strings.HasPrefix(pass.Pkg.Path(), config.NilAwayPkgPathPrefix) { //nolint:revive
		// TODO: enable struct initialization flag (tracked in Issue #23).
		// TODO: enable anonymous function flag.
	} else {
		functionConfig.EnableStructInitCheck = conf.ExperimentalStructInitEnable
		functionConfig.EnableAnonymousFunc = conf.ExperimentalAnonymousFuncEnable
	}

I tried with below code

package main

import (
	"fmt"
	"math/rand"
)

type A struct {
	Name string
	Age  *int
}

func getAge() *int {
	// randomly return nil or value based on rand
	a := rand.Intn(2)
	if a == 0 {
		return nil
	}
	return &a
}

func GetA() A {
	return A{
		Name: "John",
		Age:  getAge(),
	}
}

func main() {
	fmt.Println("Hello, World!")
	var t *string = nil
	fmt.Println(*t)

	a := GetA()
	fmt.Println(*a.Age)
}

It works well.

➜ ./bin/nilaway -include-pkgs=go.uber.org/nilaway/a -experimental-struct-init=true ./a
/Users/bhautik/workspace/src/experiments/nilaway/a/a.go:32:15: error: Potential nil panic detected. Observed nil flow from source to dereference point: 
        - a/a.go:32:15: literal `nil` dereferenced via the assignment(s):
                - `nil` to `t` at a/a.go:31:6

/Users/bhautik/workspace/src/experiments/nilaway/a/a.go:35:15: error: Potential nil panic detected. Observed nil flow from source to dereference point: 
        - a/a.go:17:10: literal `nil` returned from `getAge()` in position 0
        - a/a.go:23:9: result 0 of `getAge()` field `Age` returned by result 0 of `GetA()`
        - a/a.go:35:15: field `Age` of result 0 of `GetA()` dereferenced

Issue: #359

@CLAassistant
Copy link

CLAassistant commented Aug 8, 2025

CLA assistant check
All committers have signed the CLA.

Comment on lines -92 to +95
// Construct experimental features. By default, enable all features on NilAway itself.
functionConfig := assertiontree.FunctionConfig{}
if strings.HasPrefix(pass.Pkg.Path(), config.NilAwayPkgPathPrefix) { //nolint:revive
// TODO: enable struct initialization flag (tracked in Issue #23).
// TODO: enable anonymous function flag.
} else {
functionConfig.EnableStructInitCheck = conf.ExperimentalStructInitEnable
functionConfig.EnableAnonymousFunc = conf.ExperimentalAnonymousFuncEnable
}
// Respect driver flags for experimental features for all packages.
functionConfig := assertiontree.FunctionConfig{
EnableStructInitCheck: conf.ExperimentalStructInitEnable,
EnableAnonymousFunc: conf.ExperimentalAnonymousFuncEnable,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was there such that we can enable these experimental features on NilAway itself (to dogfood), but now that we have exposed these as proper flags we can do that at CLI level instead of hard coding it.

Thanks!

@@ -0,0 +1 @@
golang 1.24.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove these changes? Usually minimum Go version upgrades should be put in separate PRs where we also update CI configs, use new language features etc.

go 1.23.0

toolchain go1.23.4
go 1.24.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

@yuxincs
Copy link
Contributor

yuxincs commented Aug 20, 2025

@BhautikChudasama Thanks for the contributions! I have left some comments here :)

Also, please run make lint (or make lint-fix to directly apply fixes) to lint and format the codebase such that CI can pass

@codecov
Copy link

codecov bot commented Aug 20, 2025

Codecov Report

❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 87.63%. Comparing base (8ad05f0) to head (e3b5190).

Files with missing lines Patch % Lines
...ssertion/function/assertiontree/structinit_util.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #360      +/-   ##
==========================================
+ Coverage   87.59%   87.63%   +0.04%     
==========================================
  Files          73       73              
  Lines       10848    10844       -4     
==========================================
+ Hits         9502     9503       +1     
+ Misses       1156     1153       -3     
+ Partials      190      188       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link

Golden Test

Note

✅ NilAway errors reported on standard libraries are identical.

2527 errors on base branch (main, 8ad05f0)
2527 errors on test branch (56c3911)

@BhautikChudasama
Copy link
Author

Hey @yuxincs sorry for late reply, I will update my PR. Thanks :)

@BhautikChudasama
Copy link
Author

BhautikChudasama commented Aug 30, 2025

hey @yuxincs i was experimenting with some files but it is still flaky. I tried to put my head but i couldn’t really get into. If you can help here.

here is the example

// a.go
package a

import (
	"fmt"

	"go.uber.org/nilaway/database"
	"go.uber.org/nilaway/models"
)

func main() {
	db, err := database.GetPostgresqlConnection("your_connection_string_here")
	if err != nil {
		fmt.Println("Error connecting to database:", err)
		return
	}

	deploymentItem, err := models.GetDeploymentItem(db, "aa")
	fmt.Println(deploymentItem.Id)
	fmt.Println(*deploymentItem.Col1)
	fmt.Println(string(*deploymentItem.Col2))
	fmt.Println(string(*deploymentItem.Col3))
	fmt.Println(string(*deploymentItem.Col4))
	fmt.Println(deploymentItem.Col5)
	fmt.Println(*deploymentItem.Col6)
	fmt.Println(string(*deploymentItem.Col7))
}
// models/deployment.go

package models

import (
	"context"
	"encoding/json"
	"errors"

	"go.uber.org/nilaway/database"
)

type DeploymentItem struct {
	Id   string           `json:"id" db:"id"`
	Col1 *string          `json:"col1" db:"col1"`
	Col2 *json.RawMessage `json:"col2" db:"col2"`
	Col3 *json.RawMessage `json:"col3" db:"col3"`
	Col4 *json.RawMessage `json:"col4" db:"col4"`
	Col5 string           `json:"col5" db:"col5"`
	Col6 *int             `json:"col6" db:"col6"`
	Col7 *json.RawMessage `json:"col7" db:"col7"`
}

func GetDeploymentItem(con *database.Db, id string) (DeploymentItem, error) {
	var deploymentItem DeploymentItem
	q, ok := con.GetQuery("getDeploymentItem")
	if !ok {
		return deploymentItem, errors.New("query not found: getDeploymentItem")
	}

	err := con.Con.QueryRow(context.Background(), q, id).Scan(&deploymentItem.Id, &deploymentItem.Col1, &deploymentItem.Col2, &deploymentItem.Col3, &deploymentItem.Col4, &deploymentItem.Col5, &deploymentItem.Col6)
	return deploymentItem, err
}

When i am trying to run this

nilaway on  main [!?] via 🐹 v1.23.5
➜ ./bin/nilaway -include-pkgs=go.uber.org/nilaway -experimental-struct-init=true -experimental-struct-init=true ./a
/Users/bhautik/workspace/src/experiments/nilaway/a/a.go:33:15: error: Potential nil panic detected. Observed nil flow from source to dereference point:
	- models/deployment.go:44:9: uninitialized field `Col1` returned by result 0 of `GetDeploymentItem()`
	- a/a.go:33:15: field `Col1` of result 0 of `GetDeploymentItem()` dereferenced

/Users/bhautik/workspace/src/experiments/nilaway/a/a.go:35:22: error: Potential nil panic detected. Observed nil flow from source to dereference point:
	- models/deployment.go:44:9: uninitialized field `Col3` returned by result 0 of `GetDeploymentItem()`
	- a/a.go:35:22: field `Col3` of result 0 of `GetDeploymentItem()` dereferenced

/Users/bhautik/workspace/src/experiments/nilaway/a/a.go:38:15: error: Potential nil panic detected. Observed nil flow from source to dereference point:
	- models/deployment.go:44:9: uninitialized field `Col6` returned by result 0 of `GetDeploymentItem()`
	- a/a.go:38:15: field `Col6` of result 0 of `GetDeploymentItem()` dereferenced

/Users/bhautik/workspace/src/experiments/nilaway/a/a.go:39:22: error: Potential nil panic detected. Observed nil flow from source to dereference point:
	- models/deployment.go:44:9: uninitialized field `Col7` returned by result 0 of `GetDeploymentItem()`
	- a/a.go:39:22: field `Col7` of result 0 of `GetDeploymentItem()` dereferenced

Expected it should return Col2 as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants