Skip to content

fix: do not traverse struct fields if type has parser or implements TextUnmarshaler (#440) - #445

Open
webdevsamran wants to merge 2 commits into
caarlos0:mainfrom
webdevsamran:fix/440-use-field-name-struct-parser
Open

webdevsamran wants to merge 2 commits into
caarlos0:mainfrom
webdevsamran:fix/440-use-field-name-struct-parser

Conversation

@webdevsamran

Copy link
Copy Markdown

Summary

When UseFieldNameByDefault is enabled, struct fields that have a custom type parser or implement encoding.TextUnmarshaler (such as url.URL or time.Location) had their internal fields (Host, Path, etc.) traversed by doParse. This caused environment variables matching internal struct field names (such as PATH or HOST) to overwrite parsed values or fail validation if RequiredIfNoDef was set (#440).

  • Added hasCustomOrTextParserType helper to check if a struct type has a parser registered in opts.FuncMap (including defaultTypeParsers) or implements encoding.TextUnmarshaler.
  • Avoided recursing into struct internals in doParseField when hasCustomOrTextParserType is true.
  • Updated isSliceOfStructs to avoid treating slices of custom-parsed struct types (such as []url.URL) as index-prefixed struct collections.
  • Added unit regression tests in env_test.go verifying that url.URL retains its parsed values and does not get overwritten by HOST or PATH.

Closes #440


AI assistance disclosure: Authored with AI assistance (Google Antigravity); changes and tests independently reviewed and verified locally.

…extUnmarshaler (caarlos0#440)

Signed-off-by: Samran Asif <samranwebdev2000@gmail.com>

@SiluPanda SiluPanda left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for addressing the parser-versus-struct traversal boundary. go test ./... passed on this head.

I also ran an additional local case with UseFieldNameByDefault and RequiredIfNoDef enabled: preinitialized and nil *url.URL fields, []url.URL, and a custom pointer-receiver TextUnmarshaler used as a value, pointer, and slice element. With conflicting HOST/PATH variables present, all of those retained their parsed values.

A small, non-blocking coverage suggestion: could one custom TextUnmarshaler case be included in the committed tests? The new test name mentions that path, but its field is currently only url.URL. No blocker found in the behavior I checked.

AI-assisted review using Codex; the local checks above were executed.

…RLAndTextUnmarshaler

Signed-off-by: Samran Asif <samranwebdev2000@gmail.com>
@webdevsamran

Copy link
Copy Markdown
Author

Thanks @SiluPanda! Added a custom pointer-receiver TextUnmarshaler test case (covering both value and pointer fields) to TestUseFieldNameByDefault_URLAndTextUnmarshaler in commit 57149ea. All tests pass cleanly.

@codecov

codecov Bot commented Oct 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.85714% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 99.77%. Comparing base (fb64035) to head (57149ea).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
env.go 92.85% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##              main     #445      +/-   ##
===========================================
- Coverage   100.00%   99.77%   -0.23%     
===========================================
  Files            3        3              
  Lines          427      435       +8     
===========================================
+ Hits           427      434       +7     
- Misses           0        1       +1     

☔ View full report in Codecov by Harness.
📢 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.

@caarlos0 caarlos0 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Bot review by GitHub Copilot.

No findings. Reviewed the complete diff at 57149ea484a27d472e9593dc6cf8a545f3e8e7fe against merge base fb6403538040f91bb1d4e3fac6c55905ebd10b2d, with the relevant parsing logic, callers, documentation, and tests. Both independent checks completed: a read-only maintainer check and a verify-only adversarial check. The primary reviewer independently traced the relevant code paths.

All 29 focused tests passed, including the new regression tests and existing parser, error, pointer initialization, indexed slice, prefix, default, and field-parameter cases.

Verification limits: No standalone build, full suite, race run, or cross-platform validation was performed. The baseline overwrite behavior was inspected, not reproduced against the base commit. Preinitialized parser-backed pointers and parser-backed slices with conflicting indexed variables under UseFieldNameByDefault were inspected, but no targeted regressions were executed for those combinations.

@caarlos0

caarlos0 commented Oct 7, 2026

Copy link
Copy Markdown
Owner

lint is failing though

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

With UseFieldNameByDefault, a url.URL field's Host and Path are overwritten from HOST and PATH

3 participants