Skip to content

feat: MIR episode 5 #14787

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

Merged
merged 1 commit into from
May 18, 2023
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
5 changes: 3 additions & 2 deletions crates/hir-def/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ impl Body {
};
let expander = Expander::new(db, file_id, module);
let (mut body, source_map) =
Body::new(db, expander, params, body, module.krate, is_async_fn);
Body::new(db, def, expander, params, body, module.krate, is_async_fn);
body.shrink_to_fit();

(Arc::new(body), Arc::new(source_map))
Expand All @@ -189,13 +189,14 @@ impl Body {

fn new(
db: &dyn DefDatabase,
owner: DefWithBodyId,
expander: Expander,
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
body: Option<ast::Expr>,
krate: CrateId,
is_async_fn: bool,
) -> (Body, BodySourceMap) {
lower::lower(db, expander, params, body, krate, is_async_fn)
lower::lower(db, owner, expander, params, body, krate, is_async_fn)
}

fn shrink_to_fit(&mut self) {
Expand Down
22 changes: 11 additions & 11 deletions crates/hir-def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ use crate::{
nameres::{DefMap, MacroSubNs},
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
AdtId, BlockId, BlockLoc, DefWithBodyId, ModuleDefId, UnresolvedMacro,
};

pub(super) fn lower(
db: &dyn DefDatabase,
owner: DefWithBodyId,
expander: Expander,
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
body: Option<ast::Expr>,
Expand All @@ -53,6 +54,7 @@ pub(super) fn lower(
) -> (Body, BodySourceMap) {
ExprCollector {
db,
owner,
krate,
def_map: expander.module.def_map(db),
source_map: BodySourceMap::default(),
Expand Down Expand Up @@ -80,6 +82,7 @@ pub(super) fn lower(
struct ExprCollector<'a> {
db: &'a dyn DefDatabase,
expander: Expander,
owner: DefWithBodyId,
def_map: Arc<DefMap>,
ast_id_map: Arc<AstIdMap>,
krate: CrateId,
Expand Down Expand Up @@ -269,16 +272,13 @@ impl ExprCollector<'_> {
}
Some(ast::BlockModifier::Const(_)) => {
self.with_label_rib(RibKind::Constant, |this| {
this.collect_as_a_binding_owner_bad(
|this| {
this.collect_block_(e, |id, statements, tail| Expr::Const {
id,
statements,
tail,
})
},
syntax_ptr,
)
let (result_expr_id, prev_binding_owner) =
this.initialize_binding_owner(syntax_ptr);
let inner_expr = this.collect_block(e);
let x = this.db.intern_anonymous_const((this.owner, inner_expr));
this.body.exprs[result_expr_id] = Expr::Const(x);
this.current_binding_owner = prev_binding_owner;
result_expr_id
})
}
None => self.collect_block(e),
Expand Down
4 changes: 2 additions & 2 deletions crates/hir-def/src/body/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,8 @@ impl<'a> Printer<'a> {
Expr::Async { id: _, statements, tail } => {
self.print_block(Some("async "), statements, tail);
}
Expr::Const { id: _, statements, tail } => {
self.print_block(Some("const "), statements, tail);
Expr::Const(id) => {
w!(self, "const {{ /* {id:?} */ }}");
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions crates/hir-def/src/body/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,10 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
scopes.set_scope(expr, scope);
compute_block_scopes(statements, *tail, body, scopes, &mut scope);
}
Expr::Unsafe { id, statements, tail }
| Expr::Async { id, statements, tail }
| Expr::Const { id, statements, tail } => {
Expr::Const(_) => {
// FIXME: This is broken.
}
Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => {
let mut scope = scopes.new_block_scope(*scope, *id, None);
// Overwrite the old scope for the block expr, so that every block scope can be found
// via the block itself (important for blocks that only contain items, no expressions).
Expand Down
13 changes: 8 additions & 5 deletions crates/hir-def/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@ use crate::{
TraitAliasData, TraitData, TypeAliasData,
},
generics::GenericParams,
hir::ExprId,
import_map::ImportMap,
item_tree::{AttrOwner, ItemTree},
lang_item::{LangItem, LangItemTarget, LangItems},
nameres::{diagnostics::DefDiagnostic, DefMap},
visibility::{self, Visibility},
AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId,
ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId,
LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc,
StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc,
TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
AnonymousConstId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId,
EnumLoc, ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc,
LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc,
ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId,
TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
};

#[salsa::query_group(InternDatabaseStorage)]
Expand Down Expand Up @@ -60,6 +61,8 @@ pub trait InternDatabase: SourceDatabase {
fn intern_proc_macro(&self, loc: ProcMacroLoc) -> ProcMacroId;
#[salsa::interned]
fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId;
#[salsa::interned]
fn intern_anonymous_const(&self, id: (DefWithBodyId, ExprId)) -> AnonymousConstId;
}

#[salsa::query_group(DefDatabaseStorage)]
Expand Down
12 changes: 4 additions & 8 deletions crates/hir-def/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
BlockId,
AnonymousConstId, BlockId,
};

pub use syntax::ast::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp};
Expand Down Expand Up @@ -169,11 +169,7 @@ pub enum Expr {
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Const {
id: Option<BlockId>,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Const(AnonymousConstId),
Unsafe {
id: Option<BlockId>,
statements: Box<[Statement]>,
Expand Down Expand Up @@ -355,10 +351,10 @@ impl Expr {
Expr::Let { expr, .. } => {
f(*expr);
}
Expr::Const(_) => (),
Expr::Block { statements, tail, .. }
| Expr::Unsafe { statements, tail, .. }
| Expr::Async { statements, tail, .. }
| Expr::Const { statements, tail, .. } => {
| Expr::Async { statements, tail, .. } => {
for stmt in statements.iter() {
match stmt {
Statement::Let { initializer, else_branch, .. } => {
Expand Down
46 changes: 45 additions & 1 deletion crates/hir-def/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ mod pretty;

use std::hash::{Hash, Hasher};

use base_db::{impl_intern_key, salsa, CrateId, ProcMacroKind};
use base_db::{
impl_intern_key,
salsa::{self, InternId},
CrateId, ProcMacroKind,
};
use hir_expand::{
ast_id_map::FileAstId,
attrs::{Attr, AttrId, AttrInput},
Expand Down Expand Up @@ -472,6 +476,46 @@ impl_from!(
for ModuleDefId
);

// FIXME: make this a DefWithBodyId
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct AnonymousConstId(InternId);
impl_intern_key!(AnonymousConstId);

/// A constant, which might appears as a const item, an annonymous const block in expressions
/// or patterns, or as a constant in types with const generics.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GeneralConstId {
ConstId(ConstId),
AnonymousConstId(AnonymousConstId),
}

impl_from!(ConstId, AnonymousConstId for GeneralConstId);

impl GeneralConstId {
pub fn generic_def(self, db: &dyn db::DefDatabase) -> Option<GenericDefId> {
match self {
GeneralConstId::ConstId(x) => Some(x.into()),
GeneralConstId::AnonymousConstId(x) => {
let (parent, _) = db.lookup_intern_anonymous_const(x);
parent.as_generic_def_id()
}
}
}

pub fn name(self, db: &dyn db::DefDatabase) -> String {
match self {
GeneralConstId::ConstId(const_id) => db
.const_data(const_id)
.name
.as_ref()
.and_then(|x| x.as_str())
.unwrap_or("_")
.to_owned(),
GeneralConstId::AnonymousConstId(id) => format!("{{anonymous const {id:?}}}"),
}
}
}

/// The defs which have a body.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DefWithBodyId {
Expand Down
3 changes: 3 additions & 0 deletions crates/hir-def/src/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use crate::{
};

pub(crate) fn print_path(path: &Path, buf: &mut dyn Write) -> fmt::Result {
if let Path::LangItem(x) = path {
return write!(buf, "$lang_item::{x:?}");
}
match path.type_anchor() {
Some(anchor) => {
write!(buf, "<")?;
Expand Down
1 change: 1 addition & 0 deletions crates/hir-expand/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ pub mod known {
deref,
div_assign,
div,
drop,
fn_mut,
fn_once,
future_trait,
Expand Down
9 changes: 9 additions & 0 deletions crates/hir-ty/src/chalk_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub trait TyExt {
fn as_closure(&self) -> Option<ClosureId>;
fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)>;
fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>;
fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>;

Expand Down Expand Up @@ -146,13 +147,21 @@ impl TyExt for Ty {
Some(CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_)) | None => None,
}
}

fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
match self.kind(Interner) {
TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
_ => None,
}
}

fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)> {
match self.kind(Interner) {
TyKind::Raw(mutability, ty) => Some((ty, *mutability)),
_ => None,
}
}

fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
match self.kind(Interner) {
TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
Expand Down
48 changes: 39 additions & 9 deletions crates/hir-ty/src/consteval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ use hir_def::{
path::Path,
resolver::{Resolver, ValueNs},
type_ref::ConstRef,
DefWithBodyId, EnumVariantId,
EnumVariantId, GeneralConstId, StaticId,
};
use la_arena::{Idx, RawIdx};
use stdx::never;
use triomphe::Arc;

use crate::{
db::HirDatabase, infer::InferenceContext, layout::layout_of_ty, lower::ParamLoweringMode,
Expand Down Expand Up @@ -158,13 +159,17 @@ pub fn usize_const(db: &dyn HirDatabase, value: Option<u128>, krate: CrateId) ->
)
}

pub fn try_const_usize(c: &Const) -> Option<u128> {
pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option<u128> {
match &c.data(Interner).value {
chalk_ir::ConstValue::BoundVar(_) => None,
chalk_ir::ConstValue::InferenceVar(_) => None,
chalk_ir::ConstValue::Placeholder(_) => None,
chalk_ir::ConstValue::Concrete(c) => match &c.interned {
ConstScalar::Bytes(x, _) => Some(u128::from_le_bytes(pad16(&x, false))),
ConstScalar::UnevaluatedConst(c, subst) => {
let ec = db.const_eval(*c, subst.clone()).ok()?;
try_const_usize(db, &ec)
}
_ => None,
},
}
Expand All @@ -173,12 +178,20 @@ pub fn try_const_usize(c: &Const) -> Option<u128> {
pub(crate) fn const_eval_recover(
_: &dyn HirDatabase,
_: &[String],
_: &DefWithBodyId,
_: &GeneralConstId,
_: &Substitution,
) -> Result<Const, ConstEvalError> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}

pub(crate) fn const_eval_static_recover(
_: &dyn HirDatabase,
_: &[String],
_: &StaticId,
) -> Result<Const, ConstEvalError> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}

pub(crate) fn const_eval_discriminant_recover(
_: &dyn HirDatabase,
_: &[String],
Expand All @@ -189,11 +202,28 @@ pub(crate) fn const_eval_discriminant_recover(

pub(crate) fn const_eval_query(
db: &dyn HirDatabase,
def: DefWithBodyId,
def: GeneralConstId,
subst: Substitution,
) -> Result<Const, ConstEvalError> {
let body = db.mir_body(def)?;
let c = interpret_mir(db, &body, subst, false)?;
let body = match def {
GeneralConstId::ConstId(c) => db.mir_body(c.into())?,
GeneralConstId::AnonymousConstId(c) => {
let (def, root) = db.lookup_intern_anonymous_const(c);
let body = db.body(def);
let infer = db.infer(def);
Arc::new(lower_to_mir(db, def, &body, &infer, root)?)
}
};
let c = interpret_mir(db, &body, subst, false).0?;
Ok(c)
}

pub(crate) fn const_eval_static_query(
db: &dyn HirDatabase,
def: StaticId,
) -> Result<Const, ConstEvalError> {
let body = db.mir_body(def.into())?;
let c = interpret_mir(db, &body, Substitution::empty(Interner), false).0?;
Ok(c)
}

Expand All @@ -216,8 +246,8 @@ pub(crate) fn const_eval_discriminant_variant(
return Ok(value);
}
let mir_body = db.mir_body(def)?;
let c = interpret_mir(db, &mir_body, Substitution::empty(Interner), false)?;
let c = try_const_usize(&c).unwrap() as i128;
let c = interpret_mir(db, &mir_body, Substitution::empty(Interner), false).0?;
let c = try_const_usize(db, &c).unwrap() as i128;
Ok(c)
}

Expand All @@ -241,7 +271,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, &mir_body, Substitution::empty(Interner), true) {
if let Ok(result) = interpret_mir(db, &mir_body, Substitution::empty(Interner), true).0 {
return result;
}
}
Expand Down
Loading