Skip to content

Commit 8b14762

Browse files
committed
Add lowering of array lengths in types
Now e.g. ```rust fn a(b: [u8; 2]) { } ``` will know about the length of b.
1 parent 312f1fe commit 8b14762

File tree

10 files changed

+114
-79
lines changed

10 files changed

+114
-79
lines changed

crates/hir_def/src/type_ref.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! be directly created from an ast::TypeRef, without further queries.
33
44
use hir_expand::{name::Name, AstId, InFile};
5+
use std::convert::TryInto;
56
use syntax::ast;
67

78
use crate::{body::LowerCtx, path::Path};
@@ -79,7 +80,7 @@ pub enum TypeRef {
7980
Path(Path),
8081
RawPtr(Box<TypeRef>, Mutability),
8182
Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability),
82-
Array(Box<TypeRef> /*, Expr*/),
83+
Array(Box<TypeRef>, ConstScalar),
8384
Slice(Box<TypeRef>),
8485
/// A fn pointer. Last element of the vector is the return type.
8586
Fn(Vec<TypeRef>, bool /*varargs*/),
@@ -140,7 +141,12 @@ impl TypeRef {
140141
TypeRef::RawPtr(Box::new(inner_ty), mutability)
141142
}
142143
ast::Type::ArrayType(inner) => {
143-
TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())))
144+
let len = inner
145+
.expr()
146+
.map(ConstScalar::usize_from_literal_expr)
147+
.unwrap_or(ConstScalar::Unknown);
148+
149+
TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())), len)
144150
}
145151
ast::Type::SliceType(inner) => {
146152
TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())))
@@ -212,7 +218,7 @@ impl TypeRef {
212218
}
213219
TypeRef::RawPtr(type_ref, _)
214220
| TypeRef::Reference(type_ref, ..)
215-
| TypeRef::Array(type_ref)
221+
| TypeRef::Array(type_ref, _)
216222
| TypeRef::Slice(type_ref) => go(&type_ref, f),
217223
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
218224
for bound in bounds {
@@ -298,3 +304,44 @@ impl TypeBound {
298304
}
299305
}
300306
}
307+
308+
/// A concrete constant value
309+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
310+
pub enum ConstScalar {
311+
// for now, we only support the trivial case of constant evaluating the length of an array
312+
// Note that this is u64 because the target usize may be bigger than our usize
313+
Usize(u64),
314+
315+
/// Case of an unknown value that rustc might know but we don't
316+
Unknown,
317+
}
318+
319+
impl std::fmt::Display for ConstScalar {
320+
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
321+
match self {
322+
ConstScalar::Usize(us) => write!(fmt, "{}", us),
323+
ConstScalar::Unknown => write!(fmt, "_"),
324+
}
325+
}
326+
}
327+
328+
impl ConstScalar {
329+
fn usize_from_literal_expr(expr: ast::Expr) -> ConstScalar {
330+
match expr {
331+
ast::Expr::Literal(lit) => {
332+
let lkind = lit.kind();
333+
match lkind {
334+
ast::LiteralKind::IntNumber(num)
335+
if num.suffix() == None || num.suffix() == Some("usize") =>
336+
{
337+
num.value().and_then(|v| v.try_into().ok())
338+
}
339+
_ => None,
340+
}
341+
}
342+
_ => None,
343+
}
344+
.map(ConstScalar::Usize)
345+
.unwrap_or(ConstScalar::Unknown)
346+
}
347+
}

crates/hir_ty/src/consts.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

crates/hir_ty/src/display.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -962,11 +962,10 @@ impl HirDisplay for TypeRef {
962962
write!(f, "{}", mutability)?;
963963
inner.hir_fmt(f)?;
964964
}
965-
TypeRef::Array(inner) => {
965+
TypeRef::Array(inner, len) => {
966966
write!(f, "[")?;
967967
inner.hir_fmt(f)?;
968-
// FIXME: Array length?
969-
write!(f, "; _]")?;
968+
write!(f, "; {}]", len)?;
970969
}
971970
TypeRef::Slice(inner) => {
972971
write!(f, "[")?;

crates/hir_ty/src/infer/expr.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@ use hir_def::{
88
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
99
path::{GenericArg, GenericArgs},
1010
resolver::resolver_for_expr,
11+
type_ref::ConstScalar,
1112
AssocContainerId, FieldId, Lookup,
1213
};
1314
use hir_expand::name::{name, Name};
1415
use stdx::always;
1516
use syntax::ast::RangeOp;
1617

1718
use crate::{
18-
autoderef,
19-
consts::ConstScalar,
20-
dummy_usize_const,
19+
autoderef, dummy_usize_const,
2120
lower::lower_to_chalk_mutability,
2221
mapping::from_chalk,
2322
method_resolution, op,
@@ -737,7 +736,8 @@ impl<'a> InferenceContext<'a> {
737736
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
738737
),
739738
);
740-
// FIXME: support length for Repeat array expressions
739+
// FIXME: we don't know the length here because hir Exprs don't actually
740+
// get the value out of the AST, even though it is there.
741741
None
742742
}
743743
};

crates/hir_ty/src/interner.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//! Implementation of the Chalk `Interner` trait, which allows customizing the
22
//! representation of the various objects Chalk deals with (types, goals etc.).
33
4-
use crate::{chalk_db, consts::ConstScalar, tls, GenericArg};
4+
use crate::{chalk_db, tls, GenericArg};
55
use base_db::salsa::InternId;
66
use chalk_ir::{Goal, GoalData};
77
use hir_def::{
88
intern::{impl_internable, InternStorage, Internable, Interned},
9+
type_ref::ConstScalar,
910
TypeAliasId,
1011
};
1112
use smallvec::SmallVec;

crates/hir_ty/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ mod chalk_db;
1212
mod chalk_ext;
1313
mod infer;
1414
mod interner;
15-
mod consts;
1615
mod lower;
1716
mod mapping;
1817
mod op;
@@ -38,9 +37,13 @@ use chalk_ir::{
3837
interner::HasInterner,
3938
UintTy,
4039
};
41-
use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId};
40+
use hir_def::{
41+
expr::ExprId,
42+
type_ref::{ConstScalar, Rawness},
43+
TypeParamId,
44+
};
4245

43-
use crate::{consts::ConstScalar, db::HirDatabase, display::HirDisplay, utils::generics};
46+
use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
4447

4548
pub use autoderef::autoderef;
4649
pub use builder::TyBuilder;

crates/hir_ty/src/lower.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ use std::cell::{Cell, RefCell};
99
use std::{iter, sync::Arc};
1010

1111
use base_db::CrateId;
12-
use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
12+
use chalk_ir::{
13+
cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety, Scalar, UintTy,
14+
};
1315
use hir_def::{
1416
adt::StructKind,
1517
body::{Expander, LowerCtx},
@@ -30,16 +32,15 @@ use syntax::ast;
3032

3133
use crate::{
3234
db::HirDatabase,
33-
dummy_usize_const,
3435
mapping::ToChalk,
3536
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
3637
utils::{
3738
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
3839
},
39-
AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
40-
FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
41-
QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution,
42-
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
40+
AliasEq, AliasTy, Binders, BoundVar, CallableSig, ConstData, ConstValue, DebruijnIndex, DynTy,
41+
FnPointer, FnSig, FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy,
42+
QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits,
43+
Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
4344
};
4445

4546
#[derive(Debug)]
@@ -172,11 +173,16 @@ impl<'a> TyLoweringContext<'a> {
172173
let inner_ty = self.lower_ty(inner);
173174
TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
174175
}
175-
TypeRef::Array(inner) => {
176+
TypeRef::Array(inner, len) => {
176177
let inner_ty = self.lower_ty(inner);
177-
// FIXME: we don't have length info here because we don't store an expression for
178-
// the length
179-
TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner)
178+
179+
let const_len = ConstData {
180+
ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
181+
value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: *len }),
182+
}
183+
.intern(&Interner);
184+
185+
TyKind::Array(inner_ty, const_len).intern(&Interner)
180186
}
181187
TypeRef::Slice(inner) => {
182188
let inner_ty = self.lower_ty(inner);

crates/hir_ty/src/tests/coercion.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,42 +64,42 @@ fn coerce_places() {
6464
81..92 '{ loop {} }': T
6565
83..90 'loop {}': !
6666
88..90 '{}': ()
67-
121..132 '{ loop {} }': *mut [T; _]
67+
121..132 '{ loop {} }': *mut [T; 2]
6868
123..130 'loop {}': !
6969
128..130 '{}': ()
7070
159..172 '{ gen() }': *mut [U]
71-
165..168 'gen': fn gen<U>() -> *mut [U; _]
72-
165..170 'gen()': *mut [U; _]
71+
165..168 'gen': fn gen<U>() -> *mut [U; 2]
72+
165..170 'gen()': *mut [U; 2]
7373
185..419 '{ ...rr); }': ()
74-
195..198 'arr': &[u8; _]
74+
195..198 'arr': &[u8; 1]
7575
211..215 '&[1]': &[u8; 1]
7676
212..215 '[1]': [u8; 1]
7777
213..214 '1': u8
7878
226..227 'a': &[u8]
79-
236..239 'arr': &[u8; _]
79+
236..239 'arr': &[u8; 1]
8080
249..250 'b': u8
8181
253..254 'f': fn f<u8>(&[u8]) -> u8
8282
253..259 'f(arr)': u8
83-
255..258 'arr': &[u8; _]
83+
255..258 'arr': &[u8; 1]
8484
269..270 'c': &[u8]
8585
279..286 '{ arr }': &[u8]
86-
281..284 'arr': &[u8; _]
86+
281..284 'arr': &[u8; 1]
8787
296..297 'd': u8
8888
300..301 'g': fn g<u8>(S<&[u8]>) -> u8
8989
300..315 'g(S { a: arr })': u8
9090
302..314 'S { a: arr }': S<&[u8]>
91-
309..312 'arr': &[u8; _]
92-
325..326 'e': [&[u8]; _]
91+
309..312 'arr': &[u8; 1]
92+
325..326 'e': [&[u8]; 1]
9393
340..345 '[arr]': [&[u8]; 1]
94-
341..344 'arr': &[u8; _]
95-
355..356 'f': [&[u8]; _]
94+
341..344 'arr': &[u8; 1]
95+
355..356 'f': [&[u8]; 2]
9696
370..378 '[arr; 2]': [&[u8]; _]
97-
371..374 'arr': &[u8; _]
97+
371..374 'arr': &[u8; 1]
9898
376..377 '2': usize
9999
388..389 'g': (&[u8], &[u8])
100100
406..416 '(arr, arr)': (&[u8], &[u8])
101-
407..410 'arr': &[u8; _]
102-
412..415 'arr': &[u8; _]
101+
407..410 'arr': &[u8; 1]
102+
412..415 'arr': &[u8; 1]
103103
"#]],
104104
);
105105
}
@@ -159,7 +159,7 @@ fn infer_custom_coerce_unsized() {
159159
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
160160
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
161161
"#,
162-
expect![[r"
162+
expect![[r#"
163163
257..258 'x': A<[T]>
164164
278..283 '{ x }': A<[T]>
165165
280..281 'x': A<[T]>
@@ -169,23 +169,23 @@ fn infer_custom_coerce_unsized() {
169169
333..334 'x': C<[T]>
170170
354..359 '{ x }': C<[T]>
171171
356..357 'x': C<[T]>
172-
369..370 'a': A<[u8; _]>
173-
384..385 'b': B<[u8; _]>
174-
399..400 'c': C<[u8; _]>
172+
369..370 'a': A<[u8; 2]>
173+
384..385 'b': B<[u8; 2]>
174+
399..400 'c': C<[u8; 2]>
175175
414..480 '{ ...(c); }': ()
176176
424..425 'd': A<[{unknown}]>
177177
428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
178178
428..435 'foo1(a)': A<[{unknown}]>
179-
433..434 'a': A<[u8; _]>
179+
433..434 'a': A<[u8; 2]>
180180
445..446 'e': B<[u8]>
181181
449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
182182
449..456 'foo2(b)': B<[u8]>
183-
454..455 'b': B<[u8; _]>
183+
454..455 'b': B<[u8; 2]>
184184
466..467 'f': C<[u8]>
185185
470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
186186
470..477 'foo3(c)': C<[u8]>
187-
475..476 'c': C<[u8; _]>
188-
"]],
187+
475..476 'c': C<[u8; 2]>
188+
"#]],
189189
);
190190
}
191191

crates/hir_ty/src/tests/patterns.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,19 +345,19 @@ fn infer_pattern_match_arr() {
345345
"#,
346346
expect![[r#"
347347
10..179 '{ ... } }': ()
348-
20..23 'arr': [f64; _]
348+
20..23 'arr': [f64; 2]
349349
36..46 '[0.0, 1.0]': [f64; 2]
350350
37..40 '0.0': f64
351351
42..45 '1.0': f64
352352
52..177 'match ... }': ()
353-
58..61 'arr': [f64; _]
354-
72..80 '[1.0, a]': [f64; _]
353+
58..61 'arr': [f64; 2]
354+
72..80 '[1.0, a]': [f64; 2]
355355
73..76 '1.0': f64
356356
73..76 '1.0': f64
357357
78..79 'a': f64
358358
84..110 '{ ... }': ()
359359
98..99 'a': f64
360-
120..126 '[b, c]': [f64; _]
360+
120..126 '[b, c]': [f64; 2]
361361
121..122 'b': f64
362362
124..125 'c': f64
363363
130..171 '{ ... }': ()

0 commit comments

Comments
 (0)