Skip to content

Commit 034d7c8

Browse files
committed
Auto merge of rust-lang#14787 - HKalbasi:mir2, r=HKalbasi
MIR episode 5 This PR inits drop support (it is very broken at this stage, some things are dropped multiple time, drop scopes are wrong, ...) and adds stdout support (`println!` doesn't work since its expansion is dummy, but `stdout().write(b"hello world\n")` works if you use `RA_SYSROOT_HACK`) for interpreting. There is no useful unit test that it can interpret yet, but it is a good sign that it didn't hit a major road block yet. In MIR lowering, it adds support for slice pattern and anonymous const blocks, and some fixes so that we can evaluate `SmolStr::new_inline` in const eval. With these changes, 57 failed mir body remains.
2 parents f9be796 + cbcafd3 commit 034d7c8

36 files changed

+1529
-357
lines changed

crates/hir-def/src/body.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl Body {
165165
};
166166
let expander = Expander::new(db, file_id, module);
167167
let (mut body, source_map) =
168-
Body::new(db, expander, params, body, module.krate, is_async_fn);
168+
Body::new(db, def, expander, params, body, module.krate, is_async_fn);
169169
body.shrink_to_fit();
170170

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

190190
fn new(
191191
db: &dyn DefDatabase,
192+
owner: DefWithBodyId,
192193
expander: Expander,
193194
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
194195
body: Option<ast::Expr>,
195196
krate: CrateId,
196197
is_async_fn: bool,
197198
) -> (Body, BodySourceMap) {
198-
lower::lower(db, expander, params, body, krate, is_async_fn)
199+
lower::lower(db, owner, expander, params, body, krate, is_async_fn)
199200
}
200201

201202
fn shrink_to_fit(&mut self) {

crates/hir-def/src/body/lower.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ use crate::{
4040
nameres::{DefMap, MacroSubNs},
4141
path::{GenericArgs, Path},
4242
type_ref::{Mutability, Rawness, TypeRef},
43-
AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
43+
AdtId, BlockId, BlockLoc, DefWithBodyId, ModuleDefId, UnresolvedMacro,
4444
};
4545

4646
pub(super) fn lower(
4747
db: &dyn DefDatabase,
48+
owner: DefWithBodyId,
4849
expander: Expander,
4950
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
5051
body: Option<ast::Expr>,
@@ -53,6 +54,7 @@ pub(super) fn lower(
5354
) -> (Body, BodySourceMap) {
5455
ExprCollector {
5556
db,
57+
owner,
5658
krate,
5759
def_map: expander.module.def_map(db),
5860
source_map: BodySourceMap::default(),
@@ -80,6 +82,7 @@ pub(super) fn lower(
8082
struct ExprCollector<'a> {
8183
db: &'a dyn DefDatabase,
8284
expander: Expander,
85+
owner: DefWithBodyId,
8386
def_map: Arc<DefMap>,
8487
ast_id_map: Arc<AstIdMap>,
8588
krate: CrateId,
@@ -269,16 +272,13 @@ impl ExprCollector<'_> {
269272
}
270273
Some(ast::BlockModifier::Const(_)) => {
271274
self.with_label_rib(RibKind::Constant, |this| {
272-
this.collect_as_a_binding_owner_bad(
273-
|this| {
274-
this.collect_block_(e, |id, statements, tail| Expr::Const {
275-
id,
276-
statements,
277-
tail,
278-
})
279-
},
280-
syntax_ptr,
281-
)
275+
let (result_expr_id, prev_binding_owner) =
276+
this.initialize_binding_owner(syntax_ptr);
277+
let inner_expr = this.collect_block(e);
278+
let x = this.db.intern_anonymous_const((this.owner, inner_expr));
279+
this.body.exprs[result_expr_id] = Expr::Const(x);
280+
this.current_binding_owner = prev_binding_owner;
281+
result_expr_id
282282
})
283283
}
284284
None => self.collect_block(e),

crates/hir-def/src/body/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,8 @@ impl<'a> Printer<'a> {
436436
Expr::Async { id: _, statements, tail } => {
437437
self.print_block(Some("async "), statements, tail);
438438
}
439-
Expr::Const { id: _, statements, tail } => {
440-
self.print_block(Some("const "), statements, tail);
439+
Expr::Const(id) => {
440+
w!(self, "const {{ /* {id:?} */ }}");
441441
}
442442
}
443443
}

crates/hir-def/src/body/scope.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,10 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
218218
scopes.set_scope(expr, scope);
219219
compute_block_scopes(statements, *tail, body, scopes, &mut scope);
220220
}
221-
Expr::Unsafe { id, statements, tail }
222-
| Expr::Async { id, statements, tail }
223-
| Expr::Const { id, statements, tail } => {
221+
Expr::Const(_) => {
222+
// FIXME: This is broken.
223+
}
224+
Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => {
224225
let mut scope = scopes.new_block_scope(*scope, *id, None);
225226
// Overwrite the old scope for the block expr, so that every block scope can be found
226227
// via the block itself (important for blocks that only contain items, no expressions).

crates/hir-def/src/db.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,17 @@ use crate::{
1616
TraitAliasData, TraitData, TypeAliasData,
1717
},
1818
generics::GenericParams,
19+
hir::ExprId,
1920
import_map::ImportMap,
2021
item_tree::{AttrOwner, ItemTree},
2122
lang_item::{LangItem, LangItemTarget, LangItems},
2223
nameres::{diagnostics::DefDiagnostic, DefMap},
2324
visibility::{self, Visibility},
24-
AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId,
25-
ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId,
26-
LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc,
27-
StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc,
28-
TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
25+
AnonymousConstId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId,
26+
EnumLoc, ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc,
27+
LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc,
28+
ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId,
29+
TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
2930
};
3031

3132
#[salsa::query_group(InternDatabaseStorage)]
@@ -60,6 +61,8 @@ pub trait InternDatabase: SourceDatabase {
6061
fn intern_proc_macro(&self, loc: ProcMacroLoc) -> ProcMacroId;
6162
#[salsa::interned]
6263
fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId;
64+
#[salsa::interned]
65+
fn intern_anonymous_const(&self, id: (DefWithBodyId, ExprId)) -> AnonymousConstId;
6366
}
6467

6568
#[salsa::query_group(DefDatabaseStorage)]

crates/hir-def/src/hir.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
2727
path::{GenericArgs, Path},
2828
type_ref::{Mutability, Rawness, TypeRef},
29-
BlockId,
29+
AnonymousConstId, BlockId,
3030
};
3131

3232
pub use syntax::ast::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp};
@@ -169,11 +169,7 @@ pub enum Expr {
169169
statements: Box<[Statement]>,
170170
tail: Option<ExprId>,
171171
},
172-
Const {
173-
id: Option<BlockId>,
174-
statements: Box<[Statement]>,
175-
tail: Option<ExprId>,
176-
},
172+
Const(AnonymousConstId),
177173
Unsafe {
178174
id: Option<BlockId>,
179175
statements: Box<[Statement]>,
@@ -355,10 +351,10 @@ impl Expr {
355351
Expr::Let { expr, .. } => {
356352
f(*expr);
357353
}
354+
Expr::Const(_) => (),
358355
Expr::Block { statements, tail, .. }
359356
| Expr::Unsafe { statements, tail, .. }
360-
| Expr::Async { statements, tail, .. }
361-
| Expr::Const { statements, tail, .. } => {
357+
| Expr::Async { statements, tail, .. } => {
362358
for stmt in statements.iter() {
363359
match stmt {
364360
Statement::Let { initializer, else_branch, .. } => {

crates/hir-def/src/lib.rs

+45-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ mod pretty;
5959

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

62-
use base_db::{impl_intern_key, salsa, CrateId, ProcMacroKind};
62+
use base_db::{
63+
impl_intern_key,
64+
salsa::{self, InternId},
65+
CrateId, ProcMacroKind,
66+
};
6367
use hir_expand::{
6468
ast_id_map::FileAstId,
6569
attrs::{Attr, AttrId, AttrInput},
@@ -472,6 +476,46 @@ impl_from!(
472476
for ModuleDefId
473477
);
474478

479+
// FIXME: make this a DefWithBodyId
480+
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
481+
pub struct AnonymousConstId(InternId);
482+
impl_intern_key!(AnonymousConstId);
483+
484+
/// A constant, which might appears as a const item, an annonymous const block in expressions
485+
/// or patterns, or as a constant in types with const generics.
486+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
487+
pub enum GeneralConstId {
488+
ConstId(ConstId),
489+
AnonymousConstId(AnonymousConstId),
490+
}
491+
492+
impl_from!(ConstId, AnonymousConstId for GeneralConstId);
493+
494+
impl GeneralConstId {
495+
pub fn generic_def(self, db: &dyn db::DefDatabase) -> Option<GenericDefId> {
496+
match self {
497+
GeneralConstId::ConstId(x) => Some(x.into()),
498+
GeneralConstId::AnonymousConstId(x) => {
499+
let (parent, _) = db.lookup_intern_anonymous_const(x);
500+
parent.as_generic_def_id()
501+
}
502+
}
503+
}
504+
505+
pub fn name(self, db: &dyn db::DefDatabase) -> String {
506+
match self {
507+
GeneralConstId::ConstId(const_id) => db
508+
.const_data(const_id)
509+
.name
510+
.as_ref()
511+
.and_then(|x| x.as_str())
512+
.unwrap_or("_")
513+
.to_owned(),
514+
GeneralConstId::AnonymousConstId(id) => format!("{{anonymous const {id:?}}}"),
515+
}
516+
}
517+
}
518+
475519
/// The defs which have a body.
476520
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
477521
pub enum DefWithBodyId {

crates/hir-def/src/pretty.rs

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ use crate::{
1212
};
1313

1414
pub(crate) fn print_path(path: &Path, buf: &mut dyn Write) -> fmt::Result {
15+
if let Path::LangItem(x) = path {
16+
return write!(buf, "$lang_item::{x:?}");
17+
}
1518
match path.type_anchor() {
1619
Some(anchor) => {
1720
write!(buf, "<")?;

crates/hir-expand/src/name.rs

+1
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ pub mod known {
376376
deref,
377377
div_assign,
378378
div,
379+
drop,
379380
fn_mut,
380381
fn_once,
381382
future_trait,

crates/hir-ty/src/chalk_ext.rs

+9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub trait TyExt {
3434
fn as_closure(&self) -> Option<ClosureId>;
3535
fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
3636
fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
37+
fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)>;
3738
fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>;
3839
fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>;
3940

@@ -146,13 +147,21 @@ impl TyExt for Ty {
146147
Some(CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_)) | None => None,
147148
}
148149
}
150+
149151
fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
150152
match self.kind(Interner) {
151153
TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
152154
_ => None,
153155
}
154156
}
155157

158+
fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)> {
159+
match self.kind(Interner) {
160+
TyKind::Raw(mutability, ty) => Some((ty, *mutability)),
161+
_ => None,
162+
}
163+
}
164+
156165
fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
157166
match self.kind(Interner) {
158167
TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),

crates/hir-ty/src/consteval.rs

+39-9
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ use hir_def::{
77
path::Path,
88
resolver::{Resolver, ValueNs},
99
type_ref::ConstRef,
10-
DefWithBodyId, EnumVariantId,
10+
EnumVariantId, GeneralConstId, StaticId,
1111
};
1212
use la_arena::{Idx, RawIdx};
1313
use stdx::never;
14+
use triomphe::Arc;
1415

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

161-
pub fn try_const_usize(c: &Const) -> Option<u128> {
162+
pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option<u128> {
162163
match &c.data(Interner).value {
163164
chalk_ir::ConstValue::BoundVar(_) => None,
164165
chalk_ir::ConstValue::InferenceVar(_) => None,
165166
chalk_ir::ConstValue::Placeholder(_) => None,
166167
chalk_ir::ConstValue::Concrete(c) => match &c.interned {
167168
ConstScalar::Bytes(x, _) => Some(u128::from_le_bytes(pad16(&x, false))),
169+
ConstScalar::UnevaluatedConst(c, subst) => {
170+
let ec = db.const_eval(*c, subst.clone()).ok()?;
171+
try_const_usize(db, &ec)
172+
}
168173
_ => None,
169174
},
170175
}
@@ -173,12 +178,20 @@ pub fn try_const_usize(c: &Const) -> Option<u128> {
173178
pub(crate) fn const_eval_recover(
174179
_: &dyn HirDatabase,
175180
_: &[String],
176-
_: &DefWithBodyId,
181+
_: &GeneralConstId,
177182
_: &Substitution,
178183
) -> Result<Const, ConstEvalError> {
179184
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
180185
}
181186

187+
pub(crate) fn const_eval_static_recover(
188+
_: &dyn HirDatabase,
189+
_: &[String],
190+
_: &StaticId,
191+
) -> Result<Const, ConstEvalError> {
192+
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
193+
}
194+
182195
pub(crate) fn const_eval_discriminant_recover(
183196
_: &dyn HirDatabase,
184197
_: &[String],
@@ -189,11 +202,28 @@ pub(crate) fn const_eval_discriminant_recover(
189202

190203
pub(crate) fn const_eval_query(
191204
db: &dyn HirDatabase,
192-
def: DefWithBodyId,
205+
def: GeneralConstId,
193206
subst: Substitution,
194207
) -> Result<Const, ConstEvalError> {
195-
let body = db.mir_body(def)?;
196-
let c = interpret_mir(db, &body, subst, false)?;
208+
let body = match def {
209+
GeneralConstId::ConstId(c) => db.mir_body(c.into())?,
210+
GeneralConstId::AnonymousConstId(c) => {
211+
let (def, root) = db.lookup_intern_anonymous_const(c);
212+
let body = db.body(def);
213+
let infer = db.infer(def);
214+
Arc::new(lower_to_mir(db, def, &body, &infer, root)?)
215+
}
216+
};
217+
let c = interpret_mir(db, &body, subst, false).0?;
218+
Ok(c)
219+
}
220+
221+
pub(crate) fn const_eval_static_query(
222+
db: &dyn HirDatabase,
223+
def: StaticId,
224+
) -> Result<Const, ConstEvalError> {
225+
let body = db.mir_body(def.into())?;
226+
let c = interpret_mir(db, &body, Substitution::empty(Interner), false).0?;
197227
Ok(c)
198228
}
199229

@@ -216,8 +246,8 @@ pub(crate) fn const_eval_discriminant_variant(
216246
return Ok(value);
217247
}
218248
let mir_body = db.mir_body(def)?;
219-
let c = interpret_mir(db, &mir_body, Substitution::empty(Interner), false)?;
220-
let c = try_const_usize(&c).unwrap() as i128;
249+
let c = interpret_mir(db, &mir_body, Substitution::empty(Interner), false).0?;
250+
let c = try_const_usize(db, &c).unwrap() as i128;
221251
Ok(c)
222252
}
223253

@@ -241,7 +271,7 @@ pub(crate) fn eval_to_const(
241271
}
242272
let infer = ctx.clone().resolve_all();
243273
if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) {
244-
if let Ok(result) = interpret_mir(db, &mir_body, Substitution::empty(Interner), true) {
274+
if let Ok(result) = interpret_mir(db, &mir_body, Substitution::empty(Interner), true).0 {
245275
return result;
246276
}
247277
}

0 commit comments

Comments
 (0)