Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions crates/hir_ty/src/consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! Handling of concrete const values

/// A concrete constant value
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ConstScalar {
// for now, we only support the trivial case of constant evaluating the length of an array
// Note that this is u64 because the target usize may be bigger than our usize
Usize(u64),

/// Case of an unknown value that rustc might know but we don't
Unknown,
}

impl std::fmt::Display for ConstScalar {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
ConstScalar::Usize(us) => write!(fmt, "{}", us),
ConstScalar::Unknown => write!(fmt, "_"),
}
}
}
2 changes: 1 addition & 1 deletion crates/hir_ty/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ impl HirDisplay for Const {
let param_data = &generics.params.consts[id.local_id];
write!(f, "{}", param_data.name)
}
ConstValue::Concrete(_) => write!(f, "_"),
ConstValue::Concrete(c) => write!(f, "{}", c.interned),
}
}
}
Expand Down
26 changes: 20 additions & 6 deletions crates/hir_ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::iter::{repeat, repeat_with};
use std::{mem, sync::Arc};

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

use crate::{
autoderef, dummy_usize_const,
autoderef,
consts::ConstScalar,
dummy_usize_const,
lower::lower_to_chalk_mutability,
mapping::from_chalk,
method_resolution, op,
primitive::{self, UintTy},
static_lifetime, to_chalk_trait_id,
traits::FnTrait,
utils::{generics, Generics},
AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
AdtId, Binders, CallableDefId, ConstValue, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
};

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

match array {
let len = match array {
Array::ElementList(items) => {
for expr in items.iter() {
self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
}
Some(items.len())
}
Array::Repeat { initializer, repeat } => {
self.infer_expr_coerce(
Expand All @@ -734,10 +737,20 @@ impl<'a> InferenceContext<'a> {
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
),
);
// FIXME: support length for Repeat array expressions
None
}
}
};

TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner)
let cd = ConstData {
ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
value: ConstValue::Concrete(chalk_ir::ConcreteConst {
interned: len
.map(|len| ConstScalar::Usize(len as u64))
.unwrap_or(ConstScalar::Unknown),
}),
};
TyKind::Array(elem_ty, cd.intern(&Interner)).intern(&Interner)
}
Expr::Literal(lit) => match lit {
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
Expand All @@ -747,6 +760,7 @@ impl<'a> InferenceContext<'a> {
}
Literal::ByteString(..) => {
let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);

let array_type =
TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)
Expand Down
16 changes: 11 additions & 5 deletions crates/hir_ty/src/interner.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Implementation of the Chalk `Interner` trait, which allows customizing the
//! representation of the various objects Chalk deals with (types, goals etc.).

use crate::{chalk_db, tls, GenericArg};
use crate::{chalk_db, consts::ConstScalar, tls, GenericArg};
use base_db::salsa::InternId;
use chalk_ir::{Goal, GoalData};
use hir_def::{
Expand Down Expand Up @@ -31,6 +31,7 @@ impl_internable!(
InternedWrapper<chalk_ir::TyData<Interner>>,
InternedWrapper<chalk_ir::LifetimeData<Interner>>,
InternedWrapper<chalk_ir::ConstData<Interner>>,
InternedWrapper<ConstScalar>,
InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
Expand All @@ -41,7 +42,7 @@ impl chalk_ir::interner::Interner for Interner {
type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
type InternedConcreteConst = ();
type InternedConcreteConst = ConstScalar;
type InternedGenericArg = chalk_ir::GenericArgData<Self>;
type InternedGoal = Arc<GoalData<Self>>;
type InternedGoals = Vec<Goal<Self>>;
Expand Down Expand Up @@ -245,10 +246,15 @@ impl chalk_ir::interner::Interner for Interner {
fn const_eq(
&self,
_ty: &Self::InternedType,
_c1: &Self::InternedConcreteConst,
_c2: &Self::InternedConcreteConst,
c1: &Self::InternedConcreteConst,
c2: &Self::InternedConcreteConst,
) -> bool {
true
match (c1, c2) {
(&ConstScalar::Usize(a), &ConstScalar::Usize(b)) => a == b,
// we were previously assuming this to be true, I'm not whether true or false on
// unknown values is safer.
(_, _) => true,
Comment on lines +254 to +256
Copy link
Member

Choose a reason for hiding this comment

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

IIRC this is where you want to "defer" an obligation while returning true so that it's "conditionally true" (and if the condition is the same equality check then it's basically "unknowable", instead of "known true/false"), but @nikomatsakis or someone else familiar with Chalk would have to explain how that integrates.

Copy link
Member

Choose a reason for hiding this comment

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

Under which conditions does this happen in rustc?

}
}

fn intern_generic_arg(
Expand Down
7 changes: 5 additions & 2 deletions crates/hir_ty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod chalk_db;
mod chalk_ext;
mod infer;
mod interner;
mod consts;
mod lower;
mod mapping;
mod op;
Expand Down Expand Up @@ -39,7 +40,7 @@ use chalk_ir::{
};
use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId};

use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
use crate::{consts::ConstScalar, db::HirDatabase, display::HirDisplay, utils::generics};

pub use autoderef::autoderef;
pub use builder::TyBuilder;
Expand Down Expand Up @@ -250,7 +251,9 @@ pub fn dummy_usize_const() -> Const {
let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
chalk_ir::ConstData {
ty: usize_ty,
value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
interned: ConstScalar::Unknown,
}),
}
.intern(&Interner)
}
Expand Down
2 changes: 2 additions & 0 deletions crates/hir_ty/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ impl<'a> TyLoweringContext<'a> {
}
TypeRef::Array(inner) => {
let inner_ty = self.lower_ty(inner);
// FIXME: we don't have length info here because we don't store an expression for
// the length
TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner)
}
TypeRef::Slice(inner) => {
Expand Down
Loading