mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Pass TraitEnvironment
into layout_ty
and const_eval
This commit is contained in:
parent
cc2f0ec32c
commit
eb143383c3
14 changed files with 149 additions and 87 deletions
|
@ -16,7 +16,8 @@ use triomphe::Arc;
|
|||
use crate::{
|
||||
db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode,
|
||||
mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData,
|
||||
ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, Ty, TyBuilder,
|
||||
ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty,
|
||||
TyBuilder,
|
||||
};
|
||||
|
||||
use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
|
||||
|
@ -135,7 +136,7 @@ pub fn intern_const_ref(
|
|||
ty: Ty,
|
||||
krate: CrateId,
|
||||
) -> Const {
|
||||
let layout = db.layout_of_ty(ty.clone(), krate);
|
||||
let layout = db.layout_of_ty(ty.clone(), Arc::new(TraitEnvironment::empty(krate)));
|
||||
let bytes = match value {
|
||||
LiteralConstRef::Int(i) => {
|
||||
// FIXME: We should handle failure of layout better.
|
||||
|
@ -173,7 +174,7 @@ pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option<u128> {
|
|||
chalk_ir::ConstValue::Concrete(c) => match &c.interned {
|
||||
ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(&it, false))),
|
||||
ConstScalar::UnevaluatedConst(c, subst) => {
|
||||
let ec = db.const_eval(*c, subst.clone()).ok()?;
|
||||
let ec = db.const_eval(*c, subst.clone(), None).ok()?;
|
||||
try_const_usize(db, &ec)
|
||||
}
|
||||
_ => None,
|
||||
|
@ -186,6 +187,7 @@ pub(crate) fn const_eval_recover(
|
|||
_: &[String],
|
||||
_: &GeneralConstId,
|
||||
_: &Substitution,
|
||||
_: &Option<Arc<TraitEnvironment>>,
|
||||
) -> Result<Const, ConstEvalError> {
|
||||
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
|
||||
}
|
||||
|
@ -210,6 +212,7 @@ pub(crate) fn const_eval_query(
|
|||
db: &dyn HirDatabase,
|
||||
def: GeneralConstId,
|
||||
subst: Substitution,
|
||||
trait_env: Option<Arc<TraitEnvironment>>,
|
||||
) -> Result<Const, ConstEvalError> {
|
||||
let body = match def {
|
||||
GeneralConstId::ConstId(c) => {
|
||||
|
@ -228,7 +231,7 @@ pub(crate) fn const_eval_query(
|
|||
}
|
||||
GeneralConstId::InTypeConstId(c) => db.mir_body(c.into())?,
|
||||
};
|
||||
let c = interpret_mir(db, body, false).0?;
|
||||
let c = interpret_mir(db, body, false, trait_env).0?;
|
||||
Ok(c)
|
||||
}
|
||||
|
||||
|
@ -241,7 +244,7 @@ pub(crate) fn const_eval_static_query(
|
|||
Substitution::empty(Interner),
|
||||
db.trait_environment_for_body(def.into()),
|
||||
)?;
|
||||
let c = interpret_mir(db, body, false).0?;
|
||||
let c = interpret_mir(db, body, false, None).0?;
|
||||
Ok(c)
|
||||
}
|
||||
|
||||
|
@ -268,7 +271,7 @@ pub(crate) fn const_eval_discriminant_variant(
|
|||
Substitution::empty(Interner),
|
||||
db.trait_environment_for_body(def),
|
||||
)?;
|
||||
let c = interpret_mir(db, mir_body, false).0?;
|
||||
let c = interpret_mir(db, mir_body, false, None).0?;
|
||||
let c = try_const_usize(db, &c).unwrap() as i128;
|
||||
Ok(c)
|
||||
}
|
||||
|
@ -293,7 +296,7 @@ pub(crate) fn eval_to_const(
|
|||
}
|
||||
let infer = ctx.clone().resolve_all();
|
||||
if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) {
|
||||
if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true).0 {
|
||||
if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ fn eval_goal(db: &TestDB, file_id: FileId) -> Result<Const, ConstEvalError> {
|
|||
_ => None,
|
||||
})
|
||||
.expect("No const named GOAL found in the test");
|
||||
db.const_eval(const_id.into(), Substitution::empty(Interner))
|
||||
db.const_eval(const_id.into(), Substitution::empty(Interner), None)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2492,6 +2492,28 @@ fn const_trait_assoc() {
|
|||
"#,
|
||||
5,
|
||||
);
|
||||
check_number(
|
||||
r#"
|
||||
//- minicore: size_of
|
||||
//- /a/lib.rs crate:a
|
||||
use core::mem::size_of;
|
||||
pub struct S<T>(T);
|
||||
impl<T> S<T> {
|
||||
pub const X: usize = core::mem::size_of::<T>();
|
||||
}
|
||||
//- /main.rs crate:main deps:a
|
||||
use a::{S};
|
||||
trait Tr {
|
||||
type Ty;
|
||||
}
|
||||
impl Tr for i32 {
|
||||
type Ty = u64;
|
||||
}
|
||||
struct K<T: Tr>(<T as Tr>::Ty);
|
||||
const GOAL: usize = S::<K<i32>>::X;
|
||||
"#,
|
||||
8,
|
||||
);
|
||||
check_number(
|
||||
r#"
|
||||
struct S<T>(*mut T);
|
||||
|
|
|
@ -77,8 +77,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||
|
||||
#[salsa::invoke(crate::consteval::const_eval_query)]
|
||||
#[salsa::cycle(crate::consteval::const_eval_recover)]
|
||||
fn const_eval(&self, def: GeneralConstId, subst: Substitution)
|
||||
-> Result<Const, ConstEvalError>;
|
||||
fn const_eval(
|
||||
&self,
|
||||
def: GeneralConstId,
|
||||
subst: Substitution,
|
||||
trait_env: Option<Arc<crate::TraitEnvironment>>,
|
||||
) -> Result<Const, ConstEvalError>;
|
||||
|
||||
#[salsa::invoke(crate::consteval::const_eval_static_query)]
|
||||
#[salsa::cycle(crate::consteval::const_eval_static_recover)]
|
||||
|
@ -100,12 +104,16 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||
&self,
|
||||
def: AdtId,
|
||||
subst: Substitution,
|
||||
krate: CrateId,
|
||||
env: Arc<crate::TraitEnvironment>,
|
||||
) -> Result<Arc<Layout>, LayoutError>;
|
||||
|
||||
#[salsa::invoke(crate::layout::layout_of_ty_query)]
|
||||
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
|
||||
fn layout_of_ty(&self, ty: Ty, krate: CrateId) -> Result<Arc<Layout>, LayoutError>;
|
||||
fn layout_of_ty(
|
||||
&self,
|
||||
ty: Ty,
|
||||
env: Arc<crate::TraitEnvironment>,
|
||||
) -> Result<Arc<Layout>, LayoutError>;
|
||||
|
||||
#[salsa::invoke(crate::layout::target_data_layout_query)]
|
||||
fn target_data_layout(&self, krate: CrateId) -> Option<Arc<TargetDataLayout>>;
|
||||
|
|
|
@ -29,6 +29,7 @@ use itertools::Itertools;
|
|||
use la_arena::ArenaMap;
|
||||
use smallvec::SmallVec;
|
||||
use stdx::never;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
consteval::try_const_usize,
|
||||
|
@ -43,7 +44,7 @@ use crate::{
|
|||
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue,
|
||||
DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives,
|
||||
MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar,
|
||||
Substitution, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
|
||||
Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
|
||||
};
|
||||
|
||||
pub trait HirWrite: fmt::Write {
|
||||
|
@ -454,7 +455,9 @@ fn render_const_scalar(
|
|||
) -> Result<(), HirDisplayError> {
|
||||
// FIXME: We need to get krate from the final callers of the hir display
|
||||
// infrastructure and have it here as a field on `f`.
|
||||
let krate = *f.db.crate_graph().crates_in_topological_order().last().unwrap();
|
||||
let trait_env = Arc::new(TraitEnvironment::empty(
|
||||
*f.db.crate_graph().crates_in_topological_order().last().unwrap(),
|
||||
));
|
||||
match ty.kind(Interner) {
|
||||
TyKind::Scalar(s) => match s {
|
||||
Scalar::Bool => write!(f, "{}", if b[0] == 0 { false } else { true }),
|
||||
|
@ -497,7 +500,7 @@ fn render_const_scalar(
|
|||
TyKind::Slice(ty) => {
|
||||
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
|
||||
let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
let size_one = layout.size.bytes_usize();
|
||||
|
@ -523,7 +526,7 @@ fn render_const_scalar(
|
|||
let Ok(t) = memory_map.vtable.ty(ty_id) else {
|
||||
return f.write_str("<ty-missing-in-vtable-map>");
|
||||
};
|
||||
let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
|
||||
let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
let size = layout.size.bytes_usize();
|
||||
|
@ -555,7 +558,7 @@ fn render_const_scalar(
|
|||
return f.write_str("<layout-error>");
|
||||
}
|
||||
});
|
||||
let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
|
||||
let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
let size = layout.size.bytes_usize();
|
||||
|
@ -567,7 +570,7 @@ fn render_const_scalar(
|
|||
}
|
||||
},
|
||||
TyKind::Tuple(_, subst) => {
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
f.write_str("(")?;
|
||||
|
@ -580,7 +583,7 @@ fn render_const_scalar(
|
|||
}
|
||||
let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
|
||||
let offset = layout.fields.offset(id).bytes_usize();
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
|
||||
f.write_str("<layout-error>")?;
|
||||
continue;
|
||||
};
|
||||
|
@ -590,7 +593,7 @@ fn render_const_scalar(
|
|||
f.write_str(")")
|
||||
}
|
||||
TyKind::Adt(adt, subst) => {
|
||||
let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), krate) else {
|
||||
let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), trait_env.clone()) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
match adt.0 {
|
||||
|
@ -602,7 +605,7 @@ fn render_const_scalar(
|
|||
&data.variant_data,
|
||||
f,
|
||||
&field_types,
|
||||
adt.0.module(f.db.upcast()).krate(),
|
||||
f.db.trait_environment(adt.0.into()),
|
||||
&layout,
|
||||
subst,
|
||||
b,
|
||||
|
@ -614,7 +617,7 @@ fn render_const_scalar(
|
|||
}
|
||||
hir_def::AdtId::EnumId(e) => {
|
||||
let Some((var_id, var_layout)) =
|
||||
detect_variant_from_bytes(&layout, f.db, krate, b, e)
|
||||
detect_variant_from_bytes(&layout, f.db, trait_env.clone(), b, e)
|
||||
else {
|
||||
return f.write_str("<failed-to-detect-variant>");
|
||||
};
|
||||
|
@ -626,7 +629,7 @@ fn render_const_scalar(
|
|||
&data.variant_data,
|
||||
f,
|
||||
&field_types,
|
||||
adt.0.module(f.db.upcast()).krate(),
|
||||
f.db.trait_environment(adt.0.into()),
|
||||
&var_layout,
|
||||
subst,
|
||||
b,
|
||||
|
@ -645,7 +648,7 @@ fn render_const_scalar(
|
|||
let Some(len) = try_const_usize(f.db, len) else {
|
||||
return f.write_str("<unknown-array-len>");
|
||||
};
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
let size_one = layout.size.bytes_usize();
|
||||
|
@ -684,7 +687,7 @@ fn render_variant_after_name(
|
|||
data: &VariantData,
|
||||
f: &mut HirFormatter<'_>,
|
||||
field_types: &ArenaMap<LocalFieldId, Binders<Ty>>,
|
||||
krate: CrateId,
|
||||
trait_env: Arc<TraitEnvironment>,
|
||||
layout: &Layout,
|
||||
subst: &Substitution,
|
||||
b: &[u8],
|
||||
|
@ -695,7 +698,7 @@ fn render_variant_after_name(
|
|||
let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
|
||||
let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
|
||||
let ty = field_types[id].clone().substitute(Interner, subst);
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
|
||||
let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
|
||||
return f.write_str("<layout-error>");
|
||||
};
|
||||
let size = layout.size.bytes_usize();
|
||||
|
|
|
@ -252,7 +252,8 @@ impl<'a> InferenceTable<'a> {
|
|||
// and registering an obligation. But it needs chalk support, so we handle the most basic
|
||||
// case (a non associated const without generic parameters) manually.
|
||||
if subst.len(Interner) == 0 {
|
||||
if let Ok(eval) = self.db.const_eval((*c_id).into(), subst.clone())
|
||||
if let Ok(eval) =
|
||||
self.db.const_eval((*c_id).into(), subst.clone(), None)
|
||||
{
|
||||
eval
|
||||
} else {
|
||||
|
@ -785,7 +786,7 @@ impl<'a> InferenceTable<'a> {
|
|||
crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()),
|
||||
// try to evaluate unevaluated const. Replace with new var if const eval failed.
|
||||
crate::ConstScalar::UnevaluatedConst(id, subst) => {
|
||||
if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
|
||||
if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
|
||||
eval
|
||||
} else {
|
||||
self.new_const_var(data.ty.clone())
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
//! Compute the binary representation of a type
|
||||
|
||||
use base_db::CrateId;
|
||||
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
||||
use hir_def::{
|
||||
layout::{
|
||||
|
@ -61,7 +60,6 @@ pub enum LayoutError {
|
|||
}
|
||||
|
||||
struct LayoutCx<'a> {
|
||||
krate: CrateId,
|
||||
target: &'a TargetDataLayout,
|
||||
}
|
||||
|
||||
|
@ -82,7 +80,7 @@ fn layout_of_simd_ty(
|
|||
db: &dyn HirDatabase,
|
||||
id: StructId,
|
||||
subst: &Substitution,
|
||||
krate: CrateId,
|
||||
env: Arc<TraitEnvironment>,
|
||||
dl: &TargetDataLayout,
|
||||
) -> Result<Arc<Layout>, LayoutError> {
|
||||
let fields = db.field_types(id.into());
|
||||
|
@ -111,7 +109,7 @@ fn layout_of_simd_ty(
|
|||
// * the homogeneous field type and the number of fields.
|
||||
let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
|
||||
// Extract the number of elements from the layout of the array field:
|
||||
let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), krate)?.fields else {
|
||||
let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields else {
|
||||
user_error!("Array with non array layout");
|
||||
};
|
||||
|
||||
|
@ -122,7 +120,7 @@ fn layout_of_simd_ty(
|
|||
};
|
||||
|
||||
// Compute the ABI of the element type:
|
||||
let e_ly = db.layout_of_ty(e_ty, krate)?;
|
||||
let e_ly = db.layout_of_ty(e_ty, env.clone())?;
|
||||
let Abi::Scalar(e_abi) = e_ly.abi else {
|
||||
user_error!("simd type with inner non scalar type");
|
||||
};
|
||||
|
@ -152,25 +150,25 @@ fn layout_of_simd_ty(
|
|||
pub fn layout_of_ty_query(
|
||||
db: &dyn HirDatabase,
|
||||
ty: Ty,
|
||||
krate: CrateId,
|
||||
trait_env: Arc<TraitEnvironment>,
|
||||
) -> Result<Arc<Layout>, LayoutError> {
|
||||
let krate = trait_env.krate;
|
||||
let Some(target) = db.target_data_layout(krate) else {
|
||||
return Err(LayoutError::TargetLayoutNotAvailable);
|
||||
};
|
||||
let cx = LayoutCx { krate, target: &target };
|
||||
let cx = LayoutCx { target: &target };
|
||||
let dl = &*cx.current_data_layout();
|
||||
let trait_env = Arc::new(TraitEnvironment::empty(krate));
|
||||
let ty = normalize(db, trait_env, ty.clone());
|
||||
let ty = normalize(db, trait_env.clone(), ty.clone());
|
||||
let result = match ty.kind(Interner) {
|
||||
TyKind::Adt(AdtId(def), subst) => {
|
||||
if let hir_def::AdtId::StructId(s) = def {
|
||||
let data = db.struct_data(*s);
|
||||
let repr = data.repr.unwrap_or_default();
|
||||
if repr.simd() {
|
||||
return layout_of_simd_ty(db, *s, subst, krate, &target);
|
||||
return layout_of_simd_ty(db, *s, subst, trait_env.clone(), &target);
|
||||
}
|
||||
};
|
||||
return db.layout_of_adt(*def, subst.clone(), krate);
|
||||
return db.layout_of_adt(*def, subst.clone(), trait_env.clone());
|
||||
}
|
||||
TyKind::Scalar(s) => match s {
|
||||
chalk_ir::Scalar::Bool => Layout::scalar(
|
||||
|
@ -228,7 +226,7 @@ pub fn layout_of_ty_query(
|
|||
|
||||
let fields = tys
|
||||
.iter(Interner)
|
||||
.map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), krate))
|
||||
.map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone()))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
|
||||
let fields = fields.iter().collect::<Vec<_>>();
|
||||
|
@ -238,7 +236,7 @@ pub fn layout_of_ty_query(
|
|||
let count = try_const_usize(db, &count).ok_or(LayoutError::UserError(
|
||||
"unevaluated or mistyped const generic parameter".to_string(),
|
||||
))? as u64;
|
||||
let element = db.layout_of_ty(element.clone(), krate)?;
|
||||
let element = db.layout_of_ty(element.clone(), trait_env.clone())?;
|
||||
let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?;
|
||||
|
||||
let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) {
|
||||
|
@ -259,7 +257,7 @@ pub fn layout_of_ty_query(
|
|||
}
|
||||
}
|
||||
TyKind::Slice(element) => {
|
||||
let element = db.layout_of_ty(element.clone(), krate)?;
|
||||
let element = db.layout_of_ty(element.clone(), trait_env.clone())?;
|
||||
Layout {
|
||||
variants: Variants::Single { index: struct_variant_idx() },
|
||||
fields: FieldsShape::Array { stride: element.size, count: 0 },
|
||||
|
@ -335,7 +333,7 @@ pub fn layout_of_ty_query(
|
|||
match impl_trait_id {
|
||||
crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
|
||||
let infer = db.infer(func.into());
|
||||
return db.layout_of_ty(infer.type_of_rpit[idx].clone(), krate);
|
||||
return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env.clone());
|
||||
}
|
||||
crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
|
||||
return Err(LayoutError::NotImplemented)
|
||||
|
@ -351,7 +349,7 @@ pub fn layout_of_ty_query(
|
|||
.map(|it| {
|
||||
db.layout_of_ty(
|
||||
it.ty.clone().substitute(Interner, ClosureSubst(subst).parent_subst()),
|
||||
krate,
|
||||
trait_env.clone(),
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
@ -377,7 +375,7 @@ pub fn layout_of_ty_recover(
|
|||
_: &dyn HirDatabase,
|
||||
_: &[String],
|
||||
_: &Ty,
|
||||
_: &CrateId,
|
||||
_: &Arc<TraitEnvironment>,
|
||||
) -> Result<Arc<Layout>, LayoutError> {
|
||||
user_error!("infinite sized recursive type");
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
use std::{cmp, ops::Bound};
|
||||
|
||||
use base_db::CrateId;
|
||||
use hir_def::{
|
||||
data::adt::VariantData,
|
||||
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
|
||||
|
@ -16,7 +15,7 @@ use crate::{
|
|||
db::HirDatabase,
|
||||
lang_items::is_unsafe_cell,
|
||||
layout::{field_ty, Layout, LayoutError, RustcEnumVariantIdx},
|
||||
Substitution,
|
||||
Substitution, TraitEnvironment,
|
||||
};
|
||||
|
||||
use super::LayoutCx;
|
||||
|
@ -29,17 +28,18 @@ pub fn layout_of_adt_query(
|
|||
db: &dyn HirDatabase,
|
||||
def: AdtId,
|
||||
subst: Substitution,
|
||||
krate: CrateId,
|
||||
trait_env: Arc<TraitEnvironment>,
|
||||
) -> Result<Arc<Layout>, LayoutError> {
|
||||
let krate = trait_env.krate;
|
||||
let Some(target) = db.target_data_layout(krate) else {
|
||||
return Err(LayoutError::TargetLayoutNotAvailable);
|
||||
};
|
||||
let cx = LayoutCx { krate, target: &target };
|
||||
let cx = LayoutCx { target: &target };
|
||||
let dl = cx.current_data_layout();
|
||||
let handle_variant = |def: VariantId, var: &VariantData| {
|
||||
var.fields()
|
||||
.iter()
|
||||
.map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), cx.krate))
|
||||
.map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), trait_env.clone()))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
};
|
||||
let (variants, repr) = match def {
|
||||
|
@ -134,7 +134,7 @@ pub fn layout_of_adt_recover(
|
|||
_: &[String],
|
||||
_: &AdtId,
|
||||
_: &Substitution,
|
||||
_: &CrateId,
|
||||
_: &Arc<TraitEnvironment>,
|
||||
) -> Result<Arc<Layout>, LayoutError> {
|
||||
user_error!("infinite sized recursive type");
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
|||
);
|
||||
|
||||
let (db, file_ids) = TestDB::with_many_files(&ra_fixture);
|
||||
let (adt_or_type_alias_id, module_id) = file_ids
|
||||
let adt_or_type_alias_id = file_ids
|
||||
.into_iter()
|
||||
.find_map(|file_id| {
|
||||
let module_id = db.module_for_file(file_id);
|
||||
|
@ -47,7 +47,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
|||
}
|
||||
_ => None,
|
||||
})?;
|
||||
Some((adt_or_type_alias_id, module_id))
|
||||
Some(adt_or_type_alias_id)
|
||||
})
|
||||
.unwrap();
|
||||
let goal_ty = match adt_or_type_alias_id {
|
||||
|
@ -58,7 +58,13 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
|||
db.ty(ty_id.into()).substitute(Interner, &Substitution::empty(Interner))
|
||||
}
|
||||
};
|
||||
db.layout_of_ty(goal_ty, module_id.krate())
|
||||
db.layout_of_ty(
|
||||
goal_ty,
|
||||
db.trait_environment(match adt_or_type_alias_id {
|
||||
Either::Left(adt) => hir_def::GenericDefId::AdtId(adt),
|
||||
Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
/// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
|
||||
|
@ -72,7 +78,7 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
|||
let module_id = db.module_for_file(file_id);
|
||||
let def_map = module_id.def_map(&db);
|
||||
let scope = &def_map[module_id.local_id].scope;
|
||||
let adt_id = scope
|
||||
let function_id = scope
|
||||
.declarations()
|
||||
.find_map(|x| match x {
|
||||
hir_def::ModuleDefId::FunctionId(x) => {
|
||||
|
@ -82,11 +88,11 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
|||
_ => None,
|
||||
})
|
||||
.unwrap();
|
||||
let hir_body = db.body(adt_id.into());
|
||||
let hir_body = db.body(function_id.into());
|
||||
let b = hir_body.bindings.iter().find(|x| x.1.name.to_smol_str() == "goal").unwrap().0;
|
||||
let infer = db.infer(adt_id.into());
|
||||
let infer = db.infer(function_id.into());
|
||||
let goal_ty = infer.type_of_binding[b].clone();
|
||||
db.layout_of_ty(goal_ty, module_id.krate())
|
||||
db.layout_of_ty(goal_ty, db.trait_environment(function_id.into()))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
|
|
@ -484,9 +484,10 @@ pub fn interpret_mir(
|
|||
// a zero size, hoping that they are all outside of our current body. Even without a fix for #7434, we can
|
||||
// (and probably should) do better here, for example by excluding bindings outside of the target expression.
|
||||
assert_placeholder_ty_is_unused: bool,
|
||||
trait_env: Option<Arc<TraitEnvironment>>,
|
||||
) -> (Result<Const>, String, String) {
|
||||
let ty = body.locals[return_slot()].ty.clone();
|
||||
let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused);
|
||||
let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env);
|
||||
let it: Result<Const> = (|| {
|
||||
if evaluator.ptr_size() != std::mem::size_of::<usize>() {
|
||||
not_supported!("targets with different pointer size from host");
|
||||
|
@ -512,9 +513,9 @@ impl Evaluator<'_> {
|
|||
db: &'a dyn HirDatabase,
|
||||
owner: DefWithBodyId,
|
||||
assert_placeholder_ty_is_unused: bool,
|
||||
trait_env: Option<Arc<TraitEnvironment>>,
|
||||
) -> Evaluator<'a> {
|
||||
let crate_id = owner.module(db.upcast()).krate();
|
||||
let trait_env = db.trait_environment_for_body(owner);
|
||||
Evaluator {
|
||||
stack: vec![0],
|
||||
heap: vec![0],
|
||||
|
@ -524,7 +525,7 @@ impl Evaluator<'_> {
|
|||
static_locations: HashMap::default(),
|
||||
db,
|
||||
random_state: oorandom::Rand64::new(0),
|
||||
trait_env,
|
||||
trait_env: trait_env.unwrap_or_else(|| db.trait_environment_for_body(owner)),
|
||||
crate_id,
|
||||
stdout: vec![],
|
||||
stderr: vec![],
|
||||
|
@ -694,14 +695,14 @@ impl Evaluator<'_> {
|
|||
}
|
||||
let r = self
|
||||
.db
|
||||
.layout_of_ty(ty.clone(), self.crate_id)
|
||||
.layout_of_ty(ty.clone(), self.trait_env.clone())
|
||||
.map_err(|e| MirEvalError::LayoutError(e, ty.clone()))?;
|
||||
self.layout_cache.borrow_mut().insert(ty.clone(), r.clone());
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<Arc<Layout>> {
|
||||
self.db.layout_of_adt(adt, subst.clone(), self.crate_id).map_err(|e| {
|
||||
self.db.layout_of_adt(adt, subst.clone(), self.trait_env.clone()).map_err(|e| {
|
||||
MirEvalError::LayoutError(e, TyKind::Adt(chalk_ir::AdtId(adt), subst).intern(Interner))
|
||||
})
|
||||
}
|
||||
|
@ -1582,10 +1583,13 @@ impl Evaluator<'_> {
|
|||
const_id = hir_def::GeneralConstId::ConstId(c);
|
||||
subst = s;
|
||||
}
|
||||
result_owner = self.db.const_eval(const_id.into(), subst).map_err(|e| {
|
||||
let name = const_id.name(self.db.upcast());
|
||||
MirEvalError::ConstEvalError(name, Box::new(e))
|
||||
})?;
|
||||
result_owner = self
|
||||
.db
|
||||
.const_eval(const_id.into(), subst, Some(self.trait_env.clone()))
|
||||
.map_err(|e| {
|
||||
let name = const_id.name(self.db.upcast());
|
||||
MirEvalError::ConstEvalError(name, Box::new(e))
|
||||
})?;
|
||||
if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value {
|
||||
if let ConstScalar::Bytes(v, mm) = &c.interned {
|
||||
break 'b (v, mm);
|
||||
|
@ -1818,9 +1822,13 @@ impl Evaluator<'_> {
|
|||
}
|
||||
AdtId::EnumId(e) => {
|
||||
let layout = this.layout(ty)?;
|
||||
if let Some((v, l)) =
|
||||
detect_variant_from_bytes(&layout, this.db, this.crate_id, bytes, e)
|
||||
{
|
||||
if let Some((v, l)) = detect_variant_from_bytes(
|
||||
&layout,
|
||||
this.db,
|
||||
this.trait_env.clone(),
|
||||
bytes,
|
||||
e,
|
||||
) {
|
||||
let data = &this.db.enum_data(e).variants[v].variant_data;
|
||||
let field_types = this
|
||||
.db
|
||||
|
@ -2409,7 +2417,7 @@ pub fn render_const_using_debug_impl(
|
|||
owner: ConstId,
|
||||
c: &Const,
|
||||
) -> Result<String> {
|
||||
let mut evaluator = Evaluator::new(db, owner.into(), false);
|
||||
let mut evaluator = Evaluator::new(db, owner.into(), false, None);
|
||||
let locals = &Locals {
|
||||
ptr: ArenaMap::new(),
|
||||
body: db
|
||||
|
|
|
@ -30,7 +30,7 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr
|
|||
db.trait_environment(func_id.into()),
|
||||
)
|
||||
.map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?;
|
||||
let (result, stdout, stderr) = interpret_mir(db, body, false);
|
||||
let (result, stdout, stderr) = interpret_mir(db, body, false, None);
|
||||
result?;
|
||||
Ok((stdout, stderr))
|
||||
}
|
||||
|
|
|
@ -1341,7 +1341,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> {
|
||||
let size = self
|
||||
.db
|
||||
.layout_of_ty(ty.clone(), self.owner.module(self.db.upcast()).krate())?
|
||||
.layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner))?
|
||||
.size
|
||||
.bytes_usize();
|
||||
let bytes = match l {
|
||||
|
@ -1418,7 +1418,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
} else {
|
||||
let name = const_id.name(self.db.upcast());
|
||||
self.db
|
||||
.const_eval(const_id.into(), subst)
|
||||
.const_eval(const_id.into(), subst, None)
|
||||
.map_err(|e| MirLowerError::ConstEvalError(name, Box::new(e)))?
|
||||
};
|
||||
Ok(Operand::Constant(c))
|
||||
|
|
|
@ -28,14 +28,15 @@ use intern::Interned;
|
|||
use rustc_hash::FxHashSet;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use stdx::never;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
consteval::unknown_const,
|
||||
db::HirDatabase,
|
||||
layout::{Layout, TagEncoding},
|
||||
mir::pad16,
|
||||
ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitRef, TraitRefExt,
|
||||
Ty, WhereClause,
|
||||
ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitEnvironment,
|
||||
TraitRef, TraitRefExt, Ty, WhereClause,
|
||||
};
|
||||
|
||||
pub(crate) fn fn_traits(
|
||||
|
@ -417,7 +418,7 @@ impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
|
|||
) -> Result<Const, Self::Error> {
|
||||
if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value {
|
||||
if let ConstScalar::UnevaluatedConst(id, subst) = &c.interned {
|
||||
if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
|
||||
if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
|
||||
return Ok(eval);
|
||||
} else {
|
||||
return Ok(unknown_const(constant.data(Interner).ty.clone()));
|
||||
|
@ -431,10 +432,11 @@ impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
|
|||
pub(crate) fn detect_variant_from_bytes<'a>(
|
||||
layout: &'a Layout,
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
trait_env: Arc<TraitEnvironment>,
|
||||
b: &[u8],
|
||||
e: EnumId,
|
||||
) -> Option<(LocalEnumVariantId, &'a Layout)> {
|
||||
let krate = trait_env.krate;
|
||||
let (var_id, var_layout) = match &layout.variants {
|
||||
hir_def::layout::Variants::Single { index } => (index.0, &*layout),
|
||||
hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||
|
|
|
@ -965,8 +965,15 @@ impl Field {
|
|||
}
|
||||
|
||||
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||
db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into())
|
||||
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
|
||||
db.layout_of_ty(
|
||||
self.ty(db).ty.clone(),
|
||||
db.trait_environment(match hir_def::VariantId::from(self.parent) {
|
||||
hir_def::VariantId::EnumVariantId(id) => GenericDefId::EnumVariantId(id),
|
||||
hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
|
||||
hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
|
||||
}),
|
||||
)
|
||||
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
|
||||
}
|
||||
|
||||
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
|
||||
|
@ -1246,8 +1253,12 @@ impl Adt {
|
|||
return Err(LayoutError::HasPlaceholder);
|
||||
}
|
||||
let krate = self.krate(db).id;
|
||||
db.layout_of_adt(self.into(), Substitution::empty(Interner), krate)
|
||||
.map(|layout| Layout(layout, db.target_data_layout(krate).unwrap()))
|
||||
db.layout_of_adt(
|
||||
self.into(),
|
||||
Substitution::empty(Interner),
|
||||
db.trait_environment(self.into()),
|
||||
)
|
||||
.map(|layout| Layout(layout, db.target_data_layout(krate).unwrap()))
|
||||
}
|
||||
|
||||
/// Turns this ADT into a type. Any type parameters of the ADT will be
|
||||
|
@ -1987,7 +1998,7 @@ impl Function {
|
|||
return r;
|
||||
}
|
||||
};
|
||||
let (result, stdout, stderr) = interpret_mir(db, body, false);
|
||||
let (result, stdout, stderr) = interpret_mir(db, body, false, None);
|
||||
let mut text = match result {
|
||||
Ok(_) => "pass".to_string(),
|
||||
Err(e) => {
|
||||
|
@ -2156,7 +2167,7 @@ impl Const {
|
|||
}
|
||||
|
||||
pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
|
||||
let c = db.const_eval(self.id.into(), Substitution::empty(Interner))?;
|
||||
let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?;
|
||||
let data = &c.data(Interner);
|
||||
if let TyKind::Scalar(s) = data.ty.kind(Interner) {
|
||||
if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
|
||||
|
@ -4322,7 +4333,7 @@ impl Type {
|
|||
}
|
||||
|
||||
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||
db.layout_of_ty(self.ty.clone(), self.env.krate)
|
||||
db.layout_of_ty(self.ty.clone(), self.env.clone())
|
||||
.map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
|||
|
||||
use hir::{
|
||||
db::{DefDatabase, ExpandDatabase, HirDatabase},
|
||||
Adt, AssocItem, Crate, DefWithBody, HasCrate, HasSource, HirDisplay, ModuleDef, Name,
|
||||
Adt, AssocItem, Crate, DefWithBody, HasSource, HirDisplay, ModuleDef, Name,
|
||||
};
|
||||
use hir_def::{
|
||||
body::{BodySourceMap, SyntheticSyntax},
|
||||
|
@ -277,7 +277,7 @@ impl flags::AnalysisStats {
|
|||
let Err(e) = db.layout_of_adt(
|
||||
hir_def::AdtId::from(a).into(),
|
||||
Substitution::empty(Interner),
|
||||
a.krate(db).into(),
|
||||
db.trait_environment(a.into()),
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue