Skip to content

Precision gap: self-owned-source exemption too narrow (AssociatedObject, app-scoped instance, owned-collection element) #221

Description

@PhysShell

Found by: the issue #201 oracle sweep, docs/notes/oracle-sweep-2026-07-10.md; catalogued as docs/notes/field-notes-patterns.md entry 15 (plus the App-scoped-source case discussed in the sweep note under MaterialDesignInXamlToolkit).

The patterns

The shipped self-owned-source exemption (a class subscribing to something it owns is a collectable cycle, not a leak) keys off a directly constructed/assigned field. Three sibling shapes reach the same co-lifetime guarantee through a different path and aren't covered:

(a) Behavior<T>.AssociatedObject — a base-class accessor for the element the behavior is attached to (necessarily co-lifetimed; a Behavior cannot outlive being attached):

protectedoverridevoidOnAttached(){this.attachedElement=this.AssociatedObject;if(this.attachedElementisPanelpanel)panel.Loaded+=(sl,el)=>{ ...};// <- flagged; panel IS this.AssociatedObject}

MahApps.Metro src/MahApps.Metro/Behaviors/TiltBehavior.cs:62-70.

(b) An Application-derived subscriber whose source is an app-scoped (not literal static) instance. The existing clsIsApp exemption gates on source == "static"; here the source is PaletteHelper().GetThemeManager() → an app-scoped IThemeManager bound to the app's own merged ResourceDictionary (PaletteHelper.cs:22-26, verified) — genuinely process-lifetime, just not a literal static field:

publicpartialclassApp:Application{protectedoverridevoidOnStartup(StartupEventArgse){if(helper.GetThemeManager()is{}themeManager)themeManager.ThemeChanged+=ThemeManager_ThemeChanged;// <- flagged}}

MaterialDesignInXamlToolkit src/MahMaterialDragablzMashUp/App.xaml.cs:10,22.

(c) Subscribing to an element of the class's own constructed collection:

publicListsAndGridsViewModel(){Items1=CreateData();// own factoryforeach(varmodelinItems1)model.PropertyChanged+=(s,a)=>OnPropertyChanged(...);// <- flagged}

MaterialDesignInXamlToolkit src/MainDemo.Wpf/Domain/ListsAndGridsViewModel.cs:16-17 (both demo app variants).

Note: (b) is deliberately narrower than the clsIsStatic broadening rejected in oracle-known-fps.md ("Rejected approaches" — a static-class subscriber exemption was reverted as unsound because it says nothing about a lambda capturing a shorter-lived local). (b) only fires when the subscriber class itself derives from Application, exactly matching the existing clsIsApp precedent — it only loosens the source check, not the subscriber check.

Suggested direction (not prescriptive)

Extend the self-owned-source classifier to recognise: this.AssociatedObject (or equivalent well-known base-class accessors) as a self-owned reference; a clsIsApp subscriber whose source resolves from Application-scoped state (not just a literal static field); and a += on a loop variable drawn from a collection field the constructor/factory itself populated.

Scope

No analyzer code changed as part of the sweep — this issue tracks the fix as its own unit of work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions