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

feat: Get some more array lengths! #8813

Merged
merged 6 commits into from
May 16, 2021
Merged

feat: Get some more array lengths! #8813

merged 6 commits into from
May 16, 2021

Conversation

lf-
Copy link
Contributor

@lf- lf- commented May 12, 2021

This is built on #8799 and thus contains its changes. I'll rebase it onto master when that one gets merged. It adds support for r-a understanding the length of:

  • let a: [u8; 2] = ...
  • let a = b"aaa"
  • let a = [0u8; 4]

I have added support for getting the values of byte strings, which was not previously there. I am least confident in the correctness of this part and it probably needs some more tests, as we currently have only one test that exercised that part (!).

Fixes #2922.

lf- added 4 commits May 12, 2021 21:22
Now e.g.

```rust
fn a(b: [u8; 2]) {
}
```

will know about the length of b.
I am not confident that my added byte string parsing is right.
@lf-
Copy link
Contributor Author

lf- commented May 13, 2021

I've force pushed a rebase of this onto the latest master and added some more examples to the test for byte strings. I now am more confident it's right. Ready for review :)

@Veykril
Copy link
Member

Veykril commented May 13, 2021

I think after merging this we can also close #2922? Given that's not really an issue with the assist but just the fact that we have been ignoring const generics completely so far

@lf-
Copy link
Contributor Author

lf- commented May 13, 2021

I think after merging this we can also close #2922? Given that's not really an issue with the assist but just the fact that we have been ignoring const generics completely so far

I'm not sure! We should write a test for that bug. It probably would, given r-a now does understand most arrays now, assuming there's not something like [0u8; 2+2].

crates/hir_ty/src/infer/expr.rs Outdated Show resolved Hide resolved
crates/hir_ty/src/infer/expr.rs Outdated Show resolved Hide resolved
crates/hir_def/src/type_ref.rs Show resolved Hide resolved
crates/hir_def/src/type_ref.rs Show resolved Hide resolved
@flodiebold
Copy link
Member

Can you check analysis-stats again? I'm a bit worried that this will lead to a regression because we don't support const generics yet, so now trait impls for arrays won't work anymore (inherent impls probably still will, due to the fact that our own unification algorithm doesn't care about the consts...)

@flodiebold
Copy link
Member

flodiebold commented May 13, 2021

(We probably don't have tests for things like impl<T, const N: usize> AsRef<[T]> for [T; N] {} because we don't support const generics, but the fact that we currently ignore array sizes makes these impls work anyway. Some tests for this might be good to add. Similarly impl<T, const N: usize> [T; N] {} itself, though there additionally it's also our unification at work, so it 'works' anyway.)

A very hacky way of working around this for now might be to continue lowering array sizes to Unknown only in impls...

Edit: Ah wait, these sizes will be Unknown anyway, never mind... 🤦‍♂️

@lf-
Copy link
Contributor Author

lf- commented May 13, 2021

Can you check analysis-stats again? I'm a bit worried that this will lead to a regression because we don't support const generics yet, so now trait impls for arrays won't work anymore (inherent impls probably still will, due to the fact that our own unification algorithm doesn't care about the consts...)

I did, it was not perceptibly changed.

(We probably don't have tests for things like impl<T, const N: usize> AsRef<[T]> for [T; N] {} because we don't support const generics, but the fact that we currently ignore array sizes makes these impls work anyway. Some tests for this might be good to add. Similarly impl<T, const N: usize> [T; N] {} itself, though there additionally it's also our unification at work, so it 'works' anyway.)

A very hacky way of working around this for now might be to continue lowering array sizes to Unknown only in impls...

Edit: Ah wait, these sizes will be Unknown anyway, never mind... man_facepalming

OH WAIT, is this what the deciding that all unknown constants are equal for the purposes of chalk is accomplishing? 🤦🏻‍♀️ oh my.....

However, we're probably (?) getting the right trait more of the time now... Thankfully, since we're an IDE, we have more leeway to do stuff wrong 😆

I shall have to look at the rustc chalk code again to try to understand how they're handling concrete constants.

@flodiebold
Copy link
Member

flodiebold commented May 13, 2021

I shall have to look at the rustc chalk code again to try to understand how they're handling concrete constants.

So, from the discussion in Zulip, it seems that Chalk is missing a piece to handle unevaluated constants. So ConcreteConst is really just an actual value, and unevaluated / unevaluatable constants would be represented differently. I think for us, we'll need to keep ConstValue::Unknown at least for now, and hope that the fact that our const_eq isn't transitive won't pose too many problems. Once we can handle Const inference variables, we can probably use them in many cases to handle expressions that we can't evaluate yet, but that won't help in type definitions or impls.

Fix rust-lang#2922: add unknown length as a condition for a type having unknown.

Incorporate reviews:

* Extract some of the const evaluation workings into functions
* Add fixmes on the hacks
* Add tests for impls on specific array lengths (these work!!! 😁)
* Add tests for const generics (indeed we don't support it yet)
ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: *len }),
}
.intern(&Interner);
Copy link
Member

Choose a reason for hiding this comment

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

this can be a call to usize_const?

use crate::{Const, ConstData, ConstValue, Interner, TyKind};

/// Extension trait for [`Const`]
pub trait ConstExtension {
Copy link
Member

Choose a reason for hiding this comment

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

I think usually we'd call this ConstExt

}

/// Extension trait for [`Expr`]
pub trait ExprEval {
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 not sure why this needs to be an extension trait, as opposed to just a function?

@flodiebold
Copy link
Member

bors d+

@bors
Copy link
Contributor

bors bot commented May 15, 2021

✌️ lf- can now approve this pull request. To approve and merge a pull request, simply reply with bors r+. More detailed instructions are available here.

* rename ConstExtension->ConstExt
* refactor a manual construction of a Const
@lf-
Copy link
Contributor Author

lf- commented May 16, 2021

bors r+

@bors
Copy link
Contributor

bors bot commented May 16, 2021

@bors bors bot merged commit a57bd59 into rust-lang:master May 16, 2021
@lnicola lnicola changed the title Get some more array lengths! feat: Get some more array lengths! May 16, 2021
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.

"Insert explicit type" suggestion produces invalid code for array
3 participants