Skip to content

Commit 312f1fe

Browse files
bors[bot]lf-
andauthored
Merge #8799
8799: Add basic support for array lengths in types r=flodiebold a=lf- This recognizes `let a = [1u8, 2, 3]` as having type `[u8; 3]` instead of the previous `[u8; _]`. Byte strings and `[0u8; 2]` kinds of range array declarations are unsupported as before. I don't know why a bunch of our rustc tests had single quotes inside strings un-escaped by `UPDATE_EXPECT=1 cargo t`, but I don't think it's bad? Maybe something in a nightly? Co-authored-by: Jade <[email protected]>
2 parents 1c927d2 + f28c053 commit 312f1fe

File tree

12 files changed

+156
-110
lines changed

12 files changed

+156
-110
lines changed

crates/hir_ty/src/consts.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//! Handling of concrete const values
2+
3+
/// A concrete constant value
4+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5+
pub enum ConstScalar {
6+
// for now, we only support the trivial case of constant evaluating the length of an array
7+
// Note that this is u64 because the target usize may be bigger than our usize
8+
Usize(u64),
9+
10+
/// Case of an unknown value that rustc might know but we don't
11+
Unknown,
12+
}
13+
14+
impl std::fmt::Display for ConstScalar {
15+
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
16+
match self {
17+
ConstScalar::Usize(us) => write!(fmt, "{}", us),
18+
ConstScalar::Unknown => write!(fmt, "_"),
19+
}
20+
}
21+
}

crates/hir_ty/src/display.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ impl HirDisplay for Const {
308308
let param_data = &generics.params.consts[id.local_id];
309309
write!(f, "{}", param_data.name)
310310
}
311-
ConstValue::Concrete(_) => write!(f, "_"),
311+
ConstValue::Concrete(c) => write!(f, "{}", c.interned),
312312
}
313313
}
314314
}

crates/hir_ty/src/infer/expr.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::iter::{repeat, repeat_with};
44
use std::{mem, sync::Arc};
55

6-
use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
6+
use chalk_ir::{cast::Cast, fold::Shift, ConstData, Mutability, TyVariableKind};
77
use hir_def::{
88
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
99
path::{GenericArg, GenericArgs},
@@ -15,15 +15,17 @@ use stdx::always;
1515
use syntax::ast::RangeOp;
1616

1717
use crate::{
18-
autoderef, dummy_usize_const,
18+
autoderef,
19+
consts::ConstScalar,
20+
dummy_usize_const,
1921
lower::lower_to_chalk_mutability,
2022
mapping::from_chalk,
2123
method_resolution, op,
2224
primitive::{self, UintTy},
2325
static_lifetime, to_chalk_trait_id,
2426
traits::FnTrait,
2527
utils::{generics, Generics},
26-
AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
28+
AdtId, Binders, CallableDefId, ConstValue, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
2729
ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
2830
};
2931

@@ -717,11 +719,12 @@ impl<'a> InferenceContext<'a> {
717719
_ => self.table.new_type_var(),
718720
};
719721

720-
match array {
722+
let len = match array {
721723
Array::ElementList(items) => {
722724
for expr in items.iter() {
723725
self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
724726
}
727+
Some(items.len())
725728
}
726729
Array::Repeat { initializer, repeat } => {
727730
self.infer_expr_coerce(
@@ -734,10 +737,20 @@ impl<'a> InferenceContext<'a> {
734737
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
735738
),
736739
);
740+
// FIXME: support length for Repeat array expressions
741+
None
737742
}
738-
}
743+
};
739744

740-
TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner)
745+
let cd = ConstData {
746+
ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
747+
value: ConstValue::Concrete(chalk_ir::ConcreteConst {
748+
interned: len
749+
.map(|len| ConstScalar::Usize(len as u64))
750+
.unwrap_or(ConstScalar::Unknown),
751+
}),
752+
};
753+
TyKind::Array(elem_ty, cd.intern(&Interner)).intern(&Interner)
741754
}
742755
Expr::Literal(lit) => match lit {
743756
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
@@ -747,6 +760,7 @@ impl<'a> InferenceContext<'a> {
747760
}
748761
Literal::ByteString(..) => {
749762
let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
763+
750764
let array_type =
751765
TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
752766
TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)

crates/hir_ty/src/interner.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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, tls, GenericArg};
4+
use crate::{chalk_db, consts::ConstScalar, tls, GenericArg};
55
use base_db::salsa::InternId;
66
use chalk_ir::{Goal, GoalData};
77
use hir_def::{
@@ -31,6 +31,7 @@ impl_internable!(
3131
InternedWrapper<chalk_ir::TyData<Interner>>,
3232
InternedWrapper<chalk_ir::LifetimeData<Interner>>,
3333
InternedWrapper<chalk_ir::ConstData<Interner>>,
34+
InternedWrapper<ConstScalar>,
3435
InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
3536
InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
3637
InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
@@ -41,7 +42,7 @@ impl chalk_ir::interner::Interner for Interner {
4142
type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
4243
type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
4344
type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
44-
type InternedConcreteConst = ();
45+
type InternedConcreteConst = ConstScalar;
4546
type InternedGenericArg = chalk_ir::GenericArgData<Self>;
4647
type InternedGoal = Arc<GoalData<Self>>;
4748
type InternedGoals = Vec<Goal<Self>>;
@@ -245,10 +246,15 @@ impl chalk_ir::interner::Interner for Interner {
245246
fn const_eq(
246247
&self,
247248
_ty: &Self::InternedType,
248-
_c1: &Self::InternedConcreteConst,
249-
_c2: &Self::InternedConcreteConst,
249+
c1: &Self::InternedConcreteConst,
250+
c2: &Self::InternedConcreteConst,
250251
) -> bool {
251-
true
252+
match (c1, c2) {
253+
(&ConstScalar::Usize(a), &ConstScalar::Usize(b)) => a == b,
254+
// we were previously assuming this to be true, I'm not whether true or false on
255+
// unknown values is safer.
256+
(_, _) => true,
257+
}
252258
}
253259

254260
fn intern_generic_arg(

crates/hir_ty/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod chalk_db;
1212
mod chalk_ext;
1313
mod infer;
1414
mod interner;
15+
mod consts;
1516
mod lower;
1617
mod mapping;
1718
mod op;
@@ -39,7 +40,7 @@ use chalk_ir::{
3940
};
4041
use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId};
4142

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

4445
pub use autoderef::autoderef;
4546
pub use builder::TyBuilder;
@@ -250,7 +251,9 @@ pub fn dummy_usize_const() -> Const {
250251
let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
251252
chalk_ir::ConstData {
252253
ty: usize_ty,
253-
value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
254+
value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
255+
interned: ConstScalar::Unknown,
256+
}),
254257
}
255258
.intern(&Interner)
256259
}

crates/hir_ty/src/lower.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ impl<'a> TyLoweringContext<'a> {
174174
}
175175
TypeRef::Array(inner) => {
176176
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
177179
TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner)
178180
}
179181
TypeRef::Slice(inner) => {

0 commit comments

Comments
 (0)