dotnet / dotnet/msbuild

Consider type-based (correct-by-construction) modeling of partial evaluation stage instead of per-access runtime checks

Open
#14,321 0 comments 0 reactions 1 assignee Claimed by @ViktorHofer View on GitHub
triaged
Dominant language
C#
Stars
5.5k
Forks
1.5k
Avg merge
1d 8h
Merged PRs (30d)
141

Description

## Background

In [#14290](https://github.com/dotnet/msbuild/pull/14290) we added an opt-in partial (stop-after-pass) project evaluation mode via `ProjectEvaluationStage`. The current implementation stores the reached evaluation stage as runtime state on `Project`/`ProjectInstance` and validates member access against it on every call (e.g. `VerifyThrowEvaluationStageReached(...)`).

During review, @baronfel raised a design question ([review](https://github.com/dotnet/msbuild/pull/14290#pullrequestreview-4672482388)):

> Main question I have is one of design - today the 'state' of the Project/Instance is held and used to validate property access, which adds a small-but-nonzero amount of overhead to each access. A Type-based modeling of the evaluation state would allow disallowed members to be hardcoded to throw, which could sidestep this problem. I'm thinking of like private inner classes that all implement the same Project/Instance signature but can be swapped out so that the lifetimes of the various properties are correct-by-construction:

```csharp
private class PropertiesLifetimeProject(...) {
public override IDictionary ItemDefinitions =>
ErrorUtilities.ThrowInvalidOperation("OM_PartialEvaluationMemberUnavailable", memberName, _evaluationStage, ProjectEvaluationStage.ItemDefinitions);
}

private class ItemDefinitionsLifetimeProject(...) {
public override IDictionary ItemDefinitions => _data.ItemDefinitions;

public override ICollection Items =>
ErrorUtilities.ThrowInvalidOperation("OM_PartialEvaluationMemberUnavailable", memberName, _evaluationStage, ProjectEvaluationStage.Items);
}
```

...and so on.

## Proposal

Investigate replacing the per-access runtime stage checks with a type-based ("correct-by-construction") model, where each evaluation stage is represented by a distinct type/subclass exposing exactly the members valid at that stage and hard-coding later-stage members to throw. This would:

- Remove the small-but-nonzero per-access validation overhead on the hot object-model paths.
- Make the valid member surface for each stage correct by construction rather than enforced by scattered guards.

## Notes / open questions

- Feasibility depends on how much of the `Project`/`ProjectInstance` surface can be cleanly partitioned by stage, and how cache upgrade-in-place (partial -> Full) interacts with swapping the backing type.
- Should be weighed against the added type complexity vs. the current simpler runtime-check approach.

Tracking follow-up from PR #14290 review.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.