Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beef up infer-mut-hack #904

Merged
merged 4 commits into from
Nov 23, 2024
Merged

Beef up infer-mut-hack #904

merged 4 commits into from
Nov 23, 2024

Conversation

ranjitjhala
Copy link
Contributor

(To avoid it getting "confused" be extraneous Constr)

@ranjitjhala ranjitjhala merged commit 9837ed7 into main Nov 23, 2024
7 checks passed
@ranjitjhala ranjitjhala deleted the mut-hack-constr branch November 23, 2024 01:10
@@ -1704,6 +1707,29 @@ fn all_predicates_of(
.flatten()
}

struct SkipConstr;
Copy link
Member

Choose a reason for hiding this comment

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

@ranjitjhala

We already have Ty::unconstr which is a more general version of this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting -- didn't know about it!

But, not really, replacing

let ty = SkipConstr.fold_ty(ty);

with

 let (ty, _) = ty.unconstr();

Doesn't seem to work -- looks like unconstr is not "deep": it expects the Constr at the very top?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like unconstr just peels away all the "topmost" Constr -- the moment it hits something else it stops.

So it won't work with

#[flux::sig(fn (xs: &mut { [i32][@n] | n > 1}))]
fn lib1(_xs: &mut [i32]) {}

Copy link
Member

@nilehmann nilehmann Nov 23, 2024

Choose a reason for hiding this comment

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

You first need to match on the &mut T and then unconstr the T

 if let rty::Ref!(_, deref_ty, Mutability::Mut) = ty.kind()
    && let (deref_ty, _) = deref_ty.unconstr()
    && let TyKind::Indexed(..) = inner_ty.kind()

I wonder though if there's a clean way to handle this during canonicalization (the thing unpack is implementing on top of). It is always safe to turn an &mut {T | p} into {&mut T | p} so we could get rid of it during unpack

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is why I have two tests -- the other one flips the order which fails your method

#[flux::sig(fn (xs: &mut { [i32][@n] | n > 1}))]
fn lib1(_xs: &mut [i32]) {}

#[flux::sig(fn (xs: { &mut  [i32][@n] | n > 1}))]
fn lib2(_xs: &mut [i32]) {}

But yes, if you had canonicalized presumably lib1 gets turned into lib2?

Copy link
Member

Choose a reason for hiding this comment

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

ah yeah, you'd need to unconstr twice

let (ty, _) = ty.unconstr();
if let rty::Ref!(_, deref_ty, Mutability::Mut) = ty.kind() 
    && let (deref_ty, _) = deref_ty.unconstr() 
    && let TyKind::Indexed(..) = inner_ty.kind()

I still think there has to be a nice way in which we can canonicalize types before pattern matching on them. The canonicalize infra is almost there...

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.

2 participants