Skip to content

Conversation

@dcreager
Copy link
Member

@dcreager dcreager commented Sep 11, 2025

This PR removes the Constraints trait. We removed the bool implementation several weeks back, and are using ConstraintSet everywhere. There have been discussions about trying to include the reason for an assignability failure as part of the result, but that there are no concrete plans to do so soon, and it's not clear that we'll need the Constraints trait to do that. (We can ideally just update the ConstraintSet type directly.)

In the meantime, this just complicates the code for no good reason.

This PR is a pure refactoring, and contains no behavioral changes.

@dcreager dcreager added internal An internal refactor or improvement ty Multi-file analysis & type inference labels Sep 11, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Sep 11, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@github-actions
Copy link
Contributor

github-actions bot commented Sep 11, 2025

mypy_primer results

No ecosystem changes detected ✅
No memory usage changes detected ✅

Comment on lines -115 to -119
/// Returns a constraint set that never holds
fn unsatisfiable(db: &'db dyn Db) -> Self;

/// Returns a constraint set that always holds
fn always_satisfiable(db: &'db dyn Db) -> Self;
Copy link
Member Author

Choose a reason for hiding this comment

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

These methods (and by extension, from_bool) didn't actually use their db parameter, so I've simplified the API a bit. from_bool is now replaced with a From<bool> impl, and these two constructors are replaced with ConstraintSet::from(true) and from(false).

Copy link
Member

Choose a reason for hiding this comment

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

In terms of readability, I think I weakly prefer the old spelling, actually! ConstraintSet::unsatisfiable() seems clearer to me about what it means than ConstraintSet::from(false), even if the constructor is strictly-speaking redundant with the new From<bool> implementation. Same for ConstraintSet::always_satisfiable.

Copy link
Contributor

Choose a reason for hiding this comment

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

If it's a weak preference, I'll put in a vote in favor of the new spelling (or at least, in favor of not taking time to reintroduce the old methods and updating the PR to use them everywhere.)

Copy link
Member Author

Choose a reason for hiding this comment

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

or at least, in favor of not taking time to reintroduce the old methods and updating the PR to use them everywhere

I did that change in a separate commit, so the cost of reverting it would be ~zero if that sways your vote

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't feel strongly either, but I think the new spelling is pretty clear, and I like that it generalizes well to cases where we already have a boolean value, not literal true or false (e.g. ConstraintSet::from_bool(relation.is_assignability)). So it seems like we will need to have (and be able to read and understand the concept of) ConstraintSet::from_bool anyway, which makes me dis-inclined to pad the API with special-case methods for literal true and false.

Comment on lines +239 to +249
/// Updates this constraint set to hold the union of itself and another constraint set.
pub(crate) fn union(&mut self, db: &'db dyn Db, other: Self) -> &Self {
self.union_set(db, other);
self
}

/// Updates this constraint set to hold the intersection of itself and another constraint set.
pub(crate) fn intersect(&mut self, db: &'db dyn Db, other: &Self) -> &Self {
self.intersect_set(db, other);
self
}
Copy link
Member Author

@dcreager dcreager Sep 11, 2025

Choose a reason for hiding this comment

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

There's now an annoying difference here, where union takes in an owned other, while intersect takes in a reference. This is purely due to internal details about when we can/cannot reuse the existing storage. This didn't exist before, because clippy couldn't see through the trait to trip the "you can pass this by reference" lint. I decided to go ahead and accept clippy's recommendation. If folks prefer, I would be equally happy putting an #[expect] here so that both methods take in an owned other.

Copy link
Member

Choose a reason for hiding this comment

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

I'm happy to genuflect to Clippy here!

@dcreager dcreager marked this pull request as ready for review September 11, 2025 19:13
Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

Nice!

Comment on lines -115 to -119
/// Returns a constraint set that never holds
fn unsatisfiable(db: &'db dyn Db) -> Self;

/// Returns a constraint set that always holds
fn always_satisfiable(db: &'db dyn Db) -> Self;
Copy link
Member

Choose a reason for hiding this comment

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

In terms of readability, I think I weakly prefer the old spelling, actually! ConstraintSet::unsatisfiable() seems clearer to me about what it means than ConstraintSet::from(false), even if the constructor is strictly-speaking redundant with the new From<bool> implementation. Same for ConstraintSet::always_satisfiable.

Comment on lines +239 to +249
/// Updates this constraint set to hold the union of itself and another constraint set.
pub(crate) fn union(&mut self, db: &'db dyn Db, other: Self) -> &Self {
self.union_set(db, other);
self
}

/// Updates this constraint set to hold the intersection of itself and another constraint set.
pub(crate) fn intersect(&mut self, db: &'db dyn Db, other: &Self) -> &Self {
self.intersect_set(db, other);
self
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm happy to genuflect to Clippy here!

@carljm carljm removed their request for review September 11, 2025 21:30
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
@dcreager dcreager merged commit 1cd8ab3 into main Sep 12, 2025
38 checks passed
@dcreager dcreager deleted the dcreager/remove-constraint-trait branch September 12, 2025 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal An internal refactor or improvement ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants