Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/lower.rs')
| -rw-r--r-- | crates/hir-ty/src/mir/lower.rs | 474 |
1 files changed, 247 insertions, 227 deletions
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 1439c43e99..1579f00e92 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -12,27 +12,31 @@ use hir_def::{ Pat, PatId, RecordFieldPat, RecordLitField, }, item_tree::FieldsShape, - lang_item::{LangItem, LangItemTarget, lang_item}, + lang_item::LangItems, resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs}, }; use hir_expand::name::Name; use la_arena::ArenaMap; use rustc_apfloat::Float; use rustc_hash::FxHashMap; -use rustc_type_ir::inherent::{Const as _, IntoKind, SliceLike, Ty as _}; +use rustc_type_ir::inherent::{Const as _, GenericArgs as _, IntoKind, Ty as _}; use span::{Edition, FileId}; use syntax::TextRange; use triomphe::Arc; use crate::{ - Adjust, Adjustment, AutoBorrow, CallableDefId, TraitEnvironment, + Adjust, Adjustment, AutoBorrow, CallableDefId, ParamEnvAndCrate, consteval::ConstEvalError, db::{HirDatabase, InternedClosure, InternedClosureId}, display::{DisplayTarget, HirDisplay, hir_display_with_store}, generics::generics, - infer::{CaptureKind, CapturedItem, TypeMismatch, cast::CastTy}, + infer::{ + CaptureKind, CapturedItem, TypeMismatch, cast::CastTy, + closure::analysis::HirPlaceProjection, + }, inhabitedness::is_ty_uninhabited_from, layout::LayoutError, + method_resolution::CandidateId, mir::{ AggregateKind, Arena, BasicBlock, BasicBlockId, BinOp, BorrowKind, CastKind, Either, Expr, FieldId, GenericArgs, Idx, InferenceResult, Local, LocalId, MemoryMap, MirBody, MirSpan, @@ -41,7 +45,9 @@ use crate::{ TupleFieldId, Ty, UnOp, VariantId, return_slot, }, next_solver::{ - Const, DbInterner, ParamConst, Region, TyKind, TypingMode, UnevaluatedConst, + Const, DbInterner, ParamConst, ParamEnv, Region, StoredGenericArgs, StoredTy, TyKind, + TypingMode, UnevaluatedConst, + abi::Safety, infer::{DbInternerInferExt, InferCtxt}, }, traits::FnTrait, @@ -55,39 +61,40 @@ mod pattern_matching; mod tests; #[derive(Debug, Clone)] -struct LoopBlocks<'db> { - begin: BasicBlockId<'db>, +struct LoopBlocks { + begin: BasicBlockId, /// `None` for loops that are not terminating - end: Option<BasicBlockId<'db>>, - place: Place<'db>, + end: Option<BasicBlockId>, + place: Place, drop_scope_index: usize, } #[derive(Debug, Clone, Default)] -struct DropScope<'db> { +struct DropScope { /// locals, in order of definition (so we should run drop glues in reverse order) - locals: Vec<LocalId<'db>>, + locals: Vec<LocalId>, } struct MirLowerCtx<'a, 'db> { - result: MirBody<'db>, + result: MirBody, owner: DefWithBodyId, - current_loop_blocks: Option<LoopBlocks<'db>>, - labeled_loop_blocks: FxHashMap<LabelId, LoopBlocks<'db>>, - discr_temp: Option<Place<'db>>, + current_loop_blocks: Option<LoopBlocks>, + labeled_loop_blocks: FxHashMap<LabelId, LoopBlocks>, + discr_temp: Option<Place>, db: &'db dyn HirDatabase, body: &'a Body, - infer: &'a InferenceResult<'db>, + infer: &'a InferenceResult, + types: &'db crate::next_solver::DefaultAny<'db>, resolver: Resolver<'db>, - drop_scopes: Vec<DropScope<'db>>, - env: Arc<TraitEnvironment<'db>>, + drop_scopes: Vec<DropScope>, + env: ParamEnv<'db>, infcx: InferCtxt<'db>, } // FIXME: Make this smaller, its stored in database queries #[derive(Debug, Clone, PartialEq, Eq)] -pub enum MirLowerError<'db> { - ConstEvalError(Box<str>, Box<ConstEvalError<'db>>), +pub enum MirLowerError { + ConstEvalError(Box<str>, Box<ConstEvalError>), LayoutError(LayoutError), IncompleteExpr, IncompletePattern, @@ -97,9 +104,9 @@ pub enum MirLowerError<'db> { RecordLiteralWithoutPath, UnresolvedMethod(String), UnresolvedField, - UnsizedTemporary(Ty<'db>), + UnsizedTemporary(StoredTy), MissingFunctionDefinition(DefWithBodyId, ExprId), - TypeMismatch(TypeMismatch<'db>), + TypeMismatch(TypeMismatch), HasErrors, /// This should never happen. Type mismatch should catch everything. TypeError(&'static str), @@ -109,14 +116,14 @@ pub enum MirLowerError<'db> { Loop, /// Something that should never happen and is definitely a bug, but we don't want to panic if it happened ImplementationError(String), - LangItemNotFound(LangItem), + LangItemNotFound, MutatingRvalue, UnresolvedLabel, - UnresolvedUpvar(Place<'db>), + UnresolvedUpvar(Place), InaccessibleLocal, // monomorphization errors: - GenericArgNotProvided(GenericParamId, GenericArgs<'db>), + GenericArgNotProvided(GenericParamId, StoredGenericArgs), } /// A token to ensuring that each drop scope is popped at most once, thanks to the compiler that checks moves. @@ -125,9 +132,9 @@ impl DropScopeToken { fn pop_and_drop<'db>( self, ctx: &mut MirLowerCtx<'_, 'db>, - current: BasicBlockId<'db>, + current: BasicBlockId, span: MirSpan, - ) -> BasicBlockId<'db> { + ) -> BasicBlockId { std::mem::forget(self); ctx.pop_drop_scope_internal(current, span) } @@ -157,7 +164,7 @@ impl Drop for DropScopeToken { // } // } -impl MirLowerError<'_> { +impl MirLowerError { pub fn pretty_print( &self, f: &mut String, @@ -189,8 +196,8 @@ impl MirLowerError<'_> { MirLowerError::TypeMismatch(e) => writeln!( f, "Type mismatch: Expected {}, found {}", - e.expected.display(db, display_target), - e.actual.display(db, display_target), + e.expected.as_ref().display(db, display_target), + e.actual.as_ref().display(db, display_target), )?, MirLowerError::GenericArgNotProvided(id, subst) => { let param_name = match *id { @@ -210,7 +217,7 @@ impl MirLowerError<'_> { param_name.unwrap_or(Name::missing()).display(db, display_target.edition) )?; writeln!(f, "Provided args: [")?; - for g in subst.iter() { + for g in subst.as_ref() { write!(f, " {},", g.display(db, display_target))?; } writeln!(f, "]")?; @@ -231,7 +238,7 @@ impl MirLowerError<'_> { | MirLowerError::BreakWithoutLoop | MirLowerError::Loop | MirLowerError::ImplementationError(_) - | MirLowerError::LangItemNotFound(_) + | MirLowerError::LangItemNotFound | MirLowerError::MutatingRvalue | MirLowerError::UnresolvedLabel | MirLowerError::UnresolvedUpvar(_) => writeln!(f, "{self:?}")?, @@ -253,13 +260,13 @@ macro_rules! implementation_error { }}; } -impl From<LayoutError> for MirLowerError<'_> { +impl From<LayoutError> for MirLowerError { fn from(value: LayoutError) -> Self { MirLowerError::LayoutError(value) } } -impl MirLowerError<'_> { +impl MirLowerError { fn unresolved_path( db: &dyn HirDatabase, p: &Path, @@ -272,14 +279,14 @@ impl MirLowerError<'_> { } } -type Result<'db, T> = std::result::Result<T, MirLowerError<'db>>; +type Result<'db, T> = std::result::Result<T, MirLowerError>; impl<'a, 'db> MirLowerCtx<'a, 'db> { fn new( db: &'db dyn HirDatabase, owner: DefWithBodyId, body: &'a Body, - infer: &'a InferenceResult<'db>, + infer: &'a InferenceResult, ) -> Self { let mut basic_blocks = Arena::new(); let start_block = basic_blocks.alloc(BasicBlock { @@ -288,7 +295,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { is_cleanup: false, }); let locals = Arena::new(); - let binding_locals: ArenaMap<BindingId, LocalId<'db>> = ArenaMap::new(); + let binding_locals: ArenaMap<BindingId, LocalId> = ArenaMap::new(); let mir = MirBody { projection_store: ProjectionStore::default(), basic_blocks, @@ -301,7 +308,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { }; let resolver = owner.resolver(db); let env = db.trait_environment_for_body(owner); - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, resolver.krate()); // FIXME(next-solver): Is `non_body_analysis()` correct here? Don't we want to reveal opaque types defined by this body? let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); @@ -310,6 +317,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { db, infer, body, + types: crate::next_solver::default_types(db), owner, resolver, current_loop_blocks: None, @@ -326,16 +334,16 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { self.infcx.interner } - fn temp( - &mut self, - ty: Ty<'db>, - current: BasicBlockId<'db>, - span: MirSpan, - ) -> Result<'db, LocalId<'db>> { + #[inline] + fn lang_items(&self) -> &'db LangItems { + self.infcx.interner.lang_items() + } + + fn temp(&mut self, ty: Ty<'db>, current: BasicBlockId, span: MirSpan) -> Result<'db, LocalId> { if matches!(ty.kind(), TyKind::Slice(_) | TyKind::Dynamic(..)) { - return Err(MirLowerError::UnsizedTemporary(ty)); + return Err(MirLowerError::UnsizedTemporary(ty.store())); } - let l = self.result.locals.alloc(Local { ty }); + let l = self.result.locals.alloc(Local { ty: ty.store() }); self.push_storage_live_for_local(l, current, span)?; Ok(l) } @@ -343,8 +351,8 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_expr_to_some_operand( &mut self, expr_id: ExprId, - current: BasicBlockId<'db>, - ) -> Result<'db, Option<(Operand<'db>, BasicBlockId<'db>)>> { + current: BasicBlockId, + ) -> Result<'db, Option<(Operand, BasicBlockId)>> { if !self.has_adjustments(expr_id) && let Expr::Literal(l) = &self.body[expr_id] { @@ -360,18 +368,14 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_expr_to_place_with_adjust( &mut self, expr_id: ExprId, - place: Place<'db>, - current: BasicBlockId<'db>, - adjustments: &[Adjustment<'db>], - ) -> Result<'db, Option<BasicBlockId<'db>>> { + place: Place, + current: BasicBlockId, + adjustments: &[Adjustment], + ) -> Result<'db, Option<BasicBlockId>> { match adjustments.split_last() { Some((last, rest)) => match &last.kind { Adjust::NeverToAny => { - let temp = self.temp( - Ty::new(self.interner(), TyKind::Never), - current, - MirSpan::Unknown, - )?; + let temp = self.temp(self.types.types.never, current, MirSpan::Unknown)?; self.lower_expr_to_place_with_adjust(expr_id, temp.into(), current, rest) } Adjust::Deref(_) => { @@ -388,15 +392,15 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { ); Ok(Some(current)) } - Adjust::Borrow(AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m)) => { - let Some((p, current)) = - self.lower_expr_as_place_with_adjust(current, expr_id, true, rest)? - else { - return Ok(None); - }; - let bk = BorrowKind::from_rustc(*m); - self.push_assignment(current, place, Rvalue::Ref(bk, p), expr_id.into()); - Ok(Some(current)) + Adjust::Borrow(AutoBorrow::Ref(m)) => self.lower_expr_to_place_with_borrow_adjust( + expr_id, + place, + current, + rest, + (*m).into(), + ), + Adjust::Borrow(AutoBorrow::RawPtr(m)) => { + self.lower_expr_to_place_with_borrow_adjust(expr_id, place, current, rest, *m) } Adjust::Pointer(cast) => { let Some((p, current)) = @@ -410,7 +414,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { Rvalue::Cast( CastKind::PointerCoercion(*cast), Operand { kind: OperandKind::Copy(p), span: None }, - last.target, + last.target.clone(), ), expr_id.into(), ); @@ -421,12 +425,30 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { } } + fn lower_expr_to_place_with_borrow_adjust( + &mut self, + expr_id: ExprId, + place: Place, + current: BasicBlockId, + rest: &[Adjustment], + m: Mutability, + ) -> Result<'db, Option<BasicBlockId>> { + let Some((p, current)) = + self.lower_expr_as_place_with_adjust(current, expr_id, true, rest)? + else { + return Ok(None); + }; + let bk = BorrowKind::from_rustc(m); + self.push_assignment(current, place, Rvalue::Ref(bk, p), expr_id.into()); + Ok(Some(current)) + } + fn lower_expr_to_place( &mut self, expr_id: ExprId, - place: Place<'db>, - prev_block: BasicBlockId<'db>, - ) -> Result<'db, Option<BasicBlockId<'db>>> { + place: Place, + prev_block: BasicBlockId, + ) -> Result<'db, Option<BasicBlockId>> { if let Some(adjustments) = self.infer.expr_adjustments.get(&expr_id) { return self.lower_expr_to_place_with_adjust(expr_id, place, prev_block, adjustments); } @@ -436,9 +458,9 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_expr_to_place_without_adjust( &mut self, expr_id: ExprId, - place: Place<'db>, - mut current: BasicBlockId<'db>, - ) -> Result<'db, Option<BasicBlockId<'db>>> { + place: Place, + mut current: BasicBlockId, + ) -> Result<'db, Option<BasicBlockId>> { match &self.body[expr_id] { Expr::OffsetOf(_) => { not_supported!("builtin#offset_of") @@ -460,18 +482,14 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { let pr = if let Some((assoc, subst)) = self.infer.assoc_resolutions_for_expr(expr_id) { match assoc { - hir_def::AssocItemId::ConstId(c) => { + CandidateId::ConstId(c) => { self.lower_const(c.into(), current, place, subst, expr_id.into())?; return Ok(Some(current)); } - hir_def::AssocItemId::FunctionId(_) => { + CandidateId::FunctionId(_) => { // FnDefs are zero sized, no action is needed. return Ok(Some(current)); } - hir_def::AssocItemId::TypeAliasId(_) => { - // FIXME: If it is unreachable, use proper error instead of `not_supported`. - not_supported!("associated functions and types") - } } } else if let Some(variant) = self.infer.variant_resolution_for_expr(expr_id) { match variant { @@ -517,7 +535,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { const_id.into(), current, place, - GenericArgs::new_from_iter(self.interner(), []), + GenericArgs::empty(self.interner()), expr_id.into(), )?; Ok(Some(current)) @@ -525,7 +543,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { ValueNs::EnumVariantId(variant_id) => { let variant_fields = variant_id.fields(self.db); if variant_fields.shape == FieldsShape::Unit { - let ty = self.infer.type_of_expr[expr_id]; + let ty = self.infer.expr_ty(expr_id); current = self.lower_enum_variant( variant_id, current, @@ -555,8 +573,9 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { konst: Const::new_param( self.interner(), ParamConst { id: p, index }, - ), - ty: self.db.const_param_ty_ns(p), + ) + .store(), + ty: self.db.const_param_ty_ns(p).store(), }, span: None, }), @@ -887,7 +906,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { operands[u32::from(field_id.into_raw()) as usize] = Some(op); } let rvalue = Rvalue::Aggregate( - AggregateKind::Adt(variant_id, subst), + AggregateKind::Adt(variant_id, subst.store()), match spread_place { Some(sp) => operands .into_iter() @@ -958,15 +977,15 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { let rvalue = if self.infer.coercion_casts.contains(expr) { Rvalue::Use(it) } else { - let source_ty = self.infer[*expr]; - let target_ty = self.infer[expr_id]; + let source_ty = self.infer.expr_ty(*expr); + let target_ty = self.infer.expr_ty(expr_id); let cast_kind = if source_ty.as_reference().is_some() { CastKind::PointerCoercion(PointerCast::ArrayToPointer) } else { cast_kind(self.db, source_ty, target_ty)? }; - Rvalue::Cast(cast_kind, it, target_ty) + Rvalue::Cast(cast_kind, it, target_ty.store()) }; self.push_assignment(current, place, rvalue, expr_id.into()); Ok(Some(current)) @@ -984,7 +1003,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { self.push_assignment( current, place, - Rvalue::ShallowInitBoxWithAlloc(ty), + Rvalue::ShallowInitBoxWithAlloc(ty.store()), expr_id.into(), ); let Some((operand, current)) = self.lower_expr_to_some_operand(*expr, current)? @@ -1202,7 +1221,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { current, place, Rvalue::Aggregate( - AggregateKind::Adt(st.into(), subst), + AggregateKind::Adt(st.into(), subst.store()), st.fields(self.db) .fields() .iter() @@ -1242,33 +1261,26 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { .clone() .into_iter() .map(|it| match it { - ProjectionElem::Deref => ProjectionElem::Deref, - ProjectionElem::Field(it) => ProjectionElem::Field(it), - ProjectionElem::ClosureField(it) => { - ProjectionElem::ClosureField(it) - } - ProjectionElem::ConstantIndex { offset, from_end } => { - ProjectionElem::ConstantIndex { offset, from_end } + HirPlaceProjection::Deref => ProjectionElem::Deref, + HirPlaceProjection::Field(field_id) => { + ProjectionElem::Field(Either::Left(field_id)) } - ProjectionElem::Subslice { from, to } => { - ProjectionElem::Subslice { from, to } + HirPlaceProjection::TupleField(idx) => { + ProjectionElem::Field(Either::Right(TupleFieldId { + tuple: TupleId(!0), // Dummy as it's unused + index: idx, + })) } - ProjectionElem::OpaqueCast(it) => { - ProjectionElem::OpaqueCast(it) - } - #[allow(unreachable_patterns)] - ProjectionElem::Index(it) => match it {}, }) .collect(), ), }; match &capture.kind { CaptureKind::ByRef(bk) => { - let tmp_ty = capture.ty.instantiate_identity(); + let tmp_ty = capture.ty.get().instantiate_identity(); // FIXME: Handle more than one span. let capture_spans = capture.spans(); - let tmp: Place<'db> = - self.temp(tmp_ty, current, capture_spans[0])?.into(); + let tmp: Place = self.temp(tmp_ty, current, capture_spans[0])?.into(); self.push_assignment( current, tmp, @@ -1285,7 +1297,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { self.push_assignment( current, place, - Rvalue::Aggregate(AggregateKind::Closure(ty), operands.into()), + Rvalue::Aggregate(AggregateKind::Closure(ty.store()), operands.into()), expr_id.into(), ); Ok(Some(current)) @@ -1305,7 +1317,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { return Ok(None); }; let r = Rvalue::Aggregate( - AggregateKind::Tuple(self.expr_ty_without_adjust(expr_id)), + AggregateKind::Tuple(self.expr_ty_without_adjust(expr_id).store()), values, ); self.push_assignment(current, place, r, expr_id.into()); @@ -1335,7 +1347,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { else { return Ok(None); }; - let r = Rvalue::Aggregate(AggregateKind::Array(elem_ty), values); + let r = Rvalue::Aggregate(AggregateKind::Array(elem_ty.store()), values); self.push_assignment(current, place, r, expr_id.into()); Ok(Some(current)) } @@ -1353,7 +1365,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { )); } }; - let r = Rvalue::Repeat(init, len); + let r = Rvalue::Repeat(init, len.store()); self.push_assignment(current, place, r, expr_id.into()); Ok(Some(current)) } @@ -1368,11 +1380,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { } } - fn push_field_projection( - &mut self, - place: &mut Place<'db>, - expr_id: ExprId, - ) -> Result<'db, ()> { + fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<'db, ()> { if let Expr::Field { expr, name } = &self.body[expr_id] { if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind() { let index = @@ -1401,7 +1409,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { &mut self, ty: Ty<'db>, loc: &ExprId, - ) -> Result<'db, Operand<'db>> { + ) -> Result<'db, Operand> { match &self.body[*loc] { Expr::Literal(l) => self.lower_literal_to_operand(ty, l), Expr::Path(c) => { @@ -1423,7 +1431,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { ResolveValueResult::ValueNs(v, _) => { if let ValueNs::ConstId(c) = v { self.lower_const_to_operand( - GenericArgs::new_from_iter(self.interner(), []), + GenericArgs::empty(self.interner()), c.into(), ) } else { @@ -1441,8 +1449,15 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { } } - fn lower_literal_to_operand(&mut self, ty: Ty<'db>, l: &Literal) -> Result<'db, Operand<'db>> { - let size = || self.db.layout_of_ty(ty, self.env.clone()).map(|it| it.size.bytes_usize()); + fn lower_literal_to_operand(&mut self, ty: Ty<'db>, l: &Literal) -> Result<'db, Operand> { + let size = || { + self.db + .layout_of_ty( + ty.store(), + ParamEnvAndCrate { param_env: self.env, krate: self.krate() }.store(), + ) + .map(|it| it.size.bytes_usize()) + }; const USIZE_SIZE: usize = size_of::<usize>(); let bytes: Box<[_]> = match l { hir_def::hir::Literal::String(b) => { @@ -1488,15 +1503,15 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { Ok(Operand::from_concrete_const(bytes, MemoryMap::default(), ty)) } - fn new_basic_block(&mut self) -> BasicBlockId<'db> { + fn new_basic_block(&mut self) -> BasicBlockId { self.result.basic_blocks.alloc(BasicBlock::default()) } fn lower_const( &mut self, const_id: GeneralConstId, - prev_block: BasicBlockId<'db>, - place: Place<'db>, + prev_block: BasicBlockId, + place: Place, subst: GenericArgs<'db>, span: MirSpan, ) -> Result<'db, ()> { @@ -1509,18 +1524,28 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { &mut self, subst: GenericArgs<'db>, const_id: GeneralConstId, - ) -> Result<'db, Operand<'db>> { - let konst = if subst.len() != 0 { + ) -> Result<'db, Operand> { + let konst = if !subst.is_empty() { // We can't evaluate constant with substitution now, as generics are not monomorphized in lowering. Const::new_unevaluated( self.interner(), UnevaluatedConst { def: const_id.into(), args: subst }, ) } else { - let name = const_id.name(self.db); - self.db - .const_eval(const_id, subst, None) - .map_err(|e| MirLowerError::ConstEvalError(name.into(), Box::new(e)))? + match const_id { + id @ GeneralConstId::ConstId(const_id) => { + self.db.const_eval(const_id, subst, None).map_err(|e| { + let name = id.name(self.db); + MirLowerError::ConstEvalError(name.into(), Box::new(e)) + })? + } + GeneralConstId::StaticId(static_id) => { + self.db.const_eval_static(static_id).map_err(|e| { + let name = const_id.name(self.db); + MirLowerError::ConstEvalError(name.into(), Box::new(e)) + })? + } + } }; let ty = self .db @@ -1530,13 +1555,16 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { }) .unwrap() .instantiate(self.interner(), subst); - Ok(Operand { kind: OperandKind::Constant { konst, ty }, span: None }) + Ok(Operand { + kind: OperandKind::Constant { konst: konst.store(), ty: ty.store() }, + span: None, + }) } fn write_bytes_to_place( &mut self, - prev_block: BasicBlockId<'db>, - place: Place<'db>, + prev_block: BasicBlockId, + place: Place, cv: Box<[u8]>, ty: Ty<'db>, span: MirSpan, @@ -1548,12 +1576,12 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_enum_variant( &mut self, variant_id: EnumVariantId, - prev_block: BasicBlockId<'db>, - place: Place<'db>, + prev_block: BasicBlockId, + place: Place, ty: Ty<'db>, - fields: Box<[Operand<'db>]>, + fields: Box<[Operand]>, span: MirSpan, - ) -> Result<'db, BasicBlockId<'db>> { + ) -> Result<'db, BasicBlockId> { let subst = match ty.kind() { TyKind::Adt(_, subst) => subst, _ => implementation_error!("Non ADT enum"), @@ -1561,7 +1589,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { self.push_assignment( prev_block, place, - Rvalue::Aggregate(AggregateKind::Adt(variant_id.into(), subst), fields), + Rvalue::Aggregate(AggregateKind::Adt(variant_id.into(), subst.store()), fields), span, ); Ok(prev_block) @@ -1569,13 +1597,13 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_call_and_args( &mut self, - func: Operand<'db>, + func: Operand, args: impl Iterator<Item = ExprId>, - place: Place<'db>, - mut current: BasicBlockId<'db>, + place: Place, + mut current: BasicBlockId, is_uninhabited: bool, span: MirSpan, - ) -> Result<'db, Option<BasicBlockId<'db>>> { + ) -> Result<'db, Option<BasicBlockId>> { let Some(args) = args .map(|arg| { if let Some((temp, c)) = self.lower_expr_to_some_operand(arg, current)? { @@ -1594,13 +1622,13 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_call( &mut self, - func: Operand<'db>, - args: Box<[Operand<'db>]>, - place: Place<'db>, - current: BasicBlockId<'db>, + func: Operand, + args: Box<[Operand]>, + place: Place, + current: BasicBlockId, is_uninhabited: bool, span: MirSpan, - ) -> Result<'db, Option<BasicBlockId<'db>>> { + ) -> Result<'db, Option<BasicBlockId>> { let b = if is_uninhabited { None } else { Some(self.new_basic_block()) }; self.set_terminator( current, @@ -1617,25 +1645,20 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { Ok(b) } - fn is_unterminated(&mut self, source: BasicBlockId<'db>) -> bool { + fn is_unterminated(&mut self, source: BasicBlockId) -> bool { self.result.basic_blocks[source].terminator.is_none() } - fn set_terminator( - &mut self, - source: BasicBlockId<'db>, - terminator: TerminatorKind<'db>, - span: MirSpan, - ) { + fn set_terminator(&mut self, source: BasicBlockId, terminator: TerminatorKind, span: MirSpan) { self.result.basic_blocks[source].terminator = Some(Terminator { span, kind: terminator }); } - fn set_goto(&mut self, source: BasicBlockId<'db>, target: BasicBlockId<'db>, span: MirSpan) { + fn set_goto(&mut self, source: BasicBlockId, target: BasicBlockId, span: MirSpan) { self.set_terminator(source, TerminatorKind::Goto { target }, span); } fn expr_ty_without_adjust(&self, e: ExprId) -> Ty<'db> { - self.infer[e] + self.infer.expr_ty(e) } fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> { @@ -1643,36 +1666,36 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { if let Some(it) = self.infer.expr_adjustments.get(&e) && let Some(it) = it.last() { - ty = Some(it.target); + ty = Some(it.target.as_ref()); } ty.unwrap_or_else(|| self.expr_ty_without_adjust(e)) } - fn push_statement(&mut self, block: BasicBlockId<'db>, statement: Statement<'db>) { + fn push_statement(&mut self, block: BasicBlockId, statement: Statement) { self.result.basic_blocks[block].statements.push(statement); } - fn push_fake_read(&mut self, block: BasicBlockId<'db>, p: Place<'db>, span: MirSpan) { + fn push_fake_read(&mut self, block: BasicBlockId, p: Place, span: MirSpan) { self.push_statement(block, StatementKind::FakeRead(p).with_span(span)); } fn push_assignment( &mut self, - block: BasicBlockId<'db>, - place: Place<'db>, - rvalue: Rvalue<'db>, + block: BasicBlockId, + place: Place, + rvalue: Rvalue, span: MirSpan, ) { self.push_statement(block, StatementKind::Assign(place, rvalue).with_span(span)); } - fn discr_temp_place(&mut self, current: BasicBlockId<'db>) -> Place<'db> { + fn discr_temp_place(&mut self, current: BasicBlockId) -> Place { match &self.discr_temp { Some(it) => *it, None => { // FIXME: rustc's ty is dependent on the adt type, maybe we need to do that as well let discr_ty = Ty::new_int(self.interner(), rustc_type_ir::IntTy::I128); - let tmp: Place<'db> = self + let tmp: Place = self .temp(discr_ty, current, MirSpan::Unknown) .expect("discr_ty is never unsized") .into(); @@ -1684,12 +1707,12 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn lower_loop( &mut self, - prev_block: BasicBlockId<'db>, - place: Place<'db>, + prev_block: BasicBlockId, + place: Place, label: Option<LabelId>, span: MirSpan, - f: impl FnOnce(&mut MirLowerCtx<'_, 'db>, BasicBlockId<'db>) -> Result<'db, ()>, - ) -> Result<'db, Option<BasicBlockId<'db>>> { + f: impl FnOnce(&mut MirLowerCtx<'_, 'db>, BasicBlockId) -> Result<'db, ()>, + ) -> Result<'db, Option<BasicBlockId>> { let begin = self.new_basic_block(); let prev = self.current_loop_blocks.replace(LoopBlocks { begin, @@ -1724,10 +1747,10 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn merge_blocks( &mut self, - b1: Option<BasicBlockId<'db>>, - b2: Option<BasicBlockId<'db>>, + b1: Option<BasicBlockId>, + b2: Option<BasicBlockId>, span: MirSpan, - ) -> Option<BasicBlockId<'db>> { + ) -> Option<BasicBlockId> { match (b1, b2) { (None, None) => None, (None, Some(b)) | (Some(b), None) => Some(b), @@ -1740,7 +1763,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { } } - fn current_loop_end(&mut self) -> Result<'db, BasicBlockId<'db>> { + fn current_loop_end(&mut self) -> Result<'db, BasicBlockId> { let r = match self .current_loop_blocks .as_mut() @@ -1767,23 +1790,23 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn is_uninhabited(&self, expr_id: ExprId) -> bool { is_ty_uninhabited_from( &self.infcx, - self.infer[expr_id], + self.infer.expr_ty(expr_id), self.owner.module(self.db), - self.env.clone(), + self.env, ) } /// This function push `StorageLive` statement for the binding, and applies changes to add `StorageDead` and /// `Drop` in the appropriated places. - fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId<'db>) -> Result<'db, ()> { + fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId) -> Result<'db, ()> { let l = self.binding_local(b)?; self.push_storage_live_for_local(l, current, MirSpan::BindingId(b)) } fn push_storage_live_for_local( &mut self, - l: LocalId<'db>, - current: BasicBlockId<'db>, + l: LocalId, + current: BasicBlockId, span: MirSpan, ) -> Result<'db, ()> { self.drop_scopes.last_mut().unwrap().locals.push(l); @@ -1791,19 +1814,14 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { Ok(()) } - fn resolve_lang_item(&self, item: LangItem) -> Result<'db, LangItemTarget> { - let crate_id = self.owner.module(self.db).krate(); - lang_item(self.db, crate_id, item).ok_or(MirLowerError::LangItemNotFound(item)) - } - fn lower_block_to_place( &mut self, statements: &[hir_def::hir::Statement], - mut current: BasicBlockId<'db>, + mut current: BasicBlockId, tail: Option<ExprId>, - place: Place<'db>, + place: Place, span: MirSpan, - ) -> Result<'db, Option<Idx<BasicBlock<'db>>>> { + ) -> Result<'db, Option<Idx<BasicBlock>>> { let scope = self.push_drop_scope(); for statement in statements.iter() { match statement { @@ -1879,11 +1897,11 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { params: impl Iterator<Item = (PatId, Ty<'db>)> + Clone, self_binding: Option<(BindingId, Ty<'db>)>, pick_binding: impl Fn(BindingId) -> bool, - ) -> Result<'db, BasicBlockId<'db>> { + ) -> Result<'db, BasicBlockId> { let base_param_count = self.result.param_locals.len(); let self_binding = match self_binding { Some((self_binding, ty)) => { - let local_id = self.result.locals.alloc(Local { ty }); + let local_id = self.result.locals.alloc(Local { ty: ty.store() }); self.drop_scopes.last_mut().unwrap().locals.push(local_id); self.result.binding_locals.insert(self_binding, local_id); self.result.param_locals.push(local_id); @@ -1892,7 +1910,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { None => None, }; self.result.param_locals.extend(params.clone().map(|(it, ty)| { - let local_id = self.result.locals.alloc(Local { ty }); + let local_id = self.result.locals.alloc(Local { ty: ty.store() }); self.drop_scopes.last_mut().unwrap().locals.push(local_id); if let Pat::Bind { id, subpat: None } = self.body[it] && matches!( @@ -1910,9 +1928,10 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { continue; } if !self.result.binding_locals.contains_idx(id) { - self.result - .binding_locals - .insert(id, self.result.locals.alloc(Local { ty: self.infer[id] })); + self.result.binding_locals.insert( + id, + self.result.locals.alloc(Local { ty: self.infer.binding_ty(id).store() }), + ); } } let mut current = self.result.start_block; @@ -1947,7 +1966,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { Ok(current) } - fn binding_local(&self, b: BindingId) -> Result<'db, LocalId<'db>> { + fn binding_local(&self, b: BindingId) -> Result<'db, LocalId> { match self.result.binding_locals.get(b) { Some(it) => Ok(*it), None => { @@ -1996,9 +2015,9 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn drop_until_scope( &mut self, scope_index: usize, - mut current: BasicBlockId<'db>, + mut current: BasicBlockId, span: MirSpan, - ) -> BasicBlockId<'db> { + ) -> BasicBlockId { for scope in self.drop_scopes[scope_index..].to_vec().iter().rev() { self.emit_drop_and_storage_dead_for_scope(scope, &mut current, span); } @@ -2018,9 +2037,9 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { /// Don't call directly fn pop_drop_scope_internal( &mut self, - mut current: BasicBlockId<'db>, + mut current: BasicBlockId, span: MirSpan, - ) -> BasicBlockId<'db> { + ) -> BasicBlockId { let scope = self.drop_scopes.pop().unwrap(); self.emit_drop_and_storage_dead_for_scope(&scope, &mut current, span); current @@ -2028,9 +2047,9 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn pop_drop_scope_assert_finished( &mut self, - mut current: BasicBlockId<'db>, + mut current: BasicBlockId, span: MirSpan, - ) -> Result<'db, BasicBlockId<'db>> { + ) -> Result<'db, BasicBlockId> { current = self.pop_drop_scope_internal(current, span); if !self.drop_scopes.is_empty() { implementation_error!("Mismatched count between drop scope push and pops"); @@ -2040,12 +2059,13 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { fn emit_drop_and_storage_dead_for_scope( &mut self, - scope: &DropScope<'db>, - current: &mut Idx<BasicBlock<'db>>, + scope: &DropScope, + current: &mut Idx<BasicBlock>, span: MirSpan, ) { for &l in scope.locals.iter().rev() { - if !self.infcx.type_is_copy_modulo_regions(self.env.env, self.result.locals[l].ty) { + if !self.infcx.type_is_copy_modulo_regions(self.env, self.result.locals[l].ty.as_ref()) + { let prev = std::mem::replace(current, self.new_basic_block()); self.set_terminator( prev, @@ -2083,46 +2103,43 @@ fn cast_kind<'db>( pub fn mir_body_for_closure_query<'db>( db: &'db dyn HirDatabase, closure: InternedClosureId, -) -> Result<'db, Arc<MirBody<'db>>> { +) -> Result<'db, Arc<MirBody>> { let InternedClosure(owner, expr) = db.lookup_intern_closure(closure); let body = db.body(owner); - let infer = db.infer(owner); + let infer = InferenceResult::for_body(db, owner); let Expr::Closure { args, body: root, .. } = &body[expr] else { implementation_error!("closure expression is not closure"); }; - let crate::next_solver::TyKind::Closure(_, substs) = infer[expr].kind() else { + let crate::next_solver::TyKind::Closure(_, substs) = infer.expr_ty(expr).kind() else { implementation_error!("closure expression is not closure"); }; let (captures, kind) = infer.closure_info(closure); - let mut ctx = MirLowerCtx::new(db, owner, &body, &infer); + let mut ctx = MirLowerCtx::new(db, owner, &body, infer); // 0 is return local - ctx.result.locals.alloc(Local { ty: infer[*root] }); + ctx.result.locals.alloc(Local { ty: infer.expr_ty(*root).store() }); let closure_local = ctx.result.locals.alloc(Local { ty: match kind { - FnTrait::FnOnce | FnTrait::AsyncFnOnce => infer[expr], + FnTrait::FnOnce | FnTrait::AsyncFnOnce => infer.expr_ty(expr), FnTrait::FnMut | FnTrait::AsyncFnMut => Ty::new_ref( ctx.interner(), Region::error(ctx.interner()), - infer[expr], + infer.expr_ty(expr), Mutability::Mut, ), FnTrait::Fn | FnTrait::AsyncFn => Ty::new_ref( ctx.interner(), Region::error(ctx.interner()), - infer[expr], + infer.expr_ty(expr), Mutability::Not, ), - }, + } + .store(), }); ctx.result.param_locals.push(closure_local); - let Some(sig) = - substs.split_closure_args_untupled().closure_sig_as_fn_ptr_ty.callable_sig(ctx.interner()) - else { - implementation_error!("closure has not callable sig"); - }; + let sig = ctx.interner().signature_unclosure(substs.as_closure().sig(), Safety::Safe); let resolver_guard = ctx.resolver.update_to_inner_scope(db, owner, expr); let current = ctx.lower_params_and_bindings( - args.iter().zip(sig.skip_binder().inputs().iter()).map(|(it, y)| (*it, y)), + args.iter().zip(sig.skip_binder().inputs().iter()).map(|(it, y)| (*it, *y)), None, |_| true, )?; @@ -2131,8 +2148,7 @@ pub fn mir_body_for_closure_query<'db>( let current = ctx.pop_drop_scope_assert_finished(current, root.into())?; ctx.set_terminator(current, TerminatorKind::Return, (*root).into()); } - let mut upvar_map: FxHashMap<LocalId<'db>, Vec<(&CapturedItem<'_>, usize)>> = - FxHashMap::default(); + let mut upvar_map: FxHashMap<LocalId, Vec<(&CapturedItem, usize)>> = FxHashMap::default(); for (i, capture) in captures.iter().enumerate() { let local = ctx.binding_local(capture.place.local)?; upvar_map.entry(local).or_default().push((capture, i)); @@ -2154,10 +2170,13 @@ pub fn mir_body_for_closure_query<'db>( for (it, y) in p.projection.lookup(store).iter().zip(it.0.place.projections.iter()) { match (it, y) { - (ProjectionElem::Deref, ProjectionElem::Deref) => (), - (ProjectionElem::Field(it), ProjectionElem::Field(y)) if it == y => (), - (ProjectionElem::ClosureField(it), ProjectionElem::ClosureField(y)) + (ProjectionElem::Deref, HirPlaceProjection::Deref) => (), + (ProjectionElem::Field(Either::Left(it)), HirPlaceProjection::Field(y)) if it == y => {} + ( + ProjectionElem::Field(Either::Right(it)), + HirPlaceProjection::TupleField(y), + ) if it.index == *y => (), _ => return false, } } @@ -2197,7 +2216,7 @@ pub fn mir_body_for_closure_query<'db>( pub fn mir_body_query<'db>( db: &'db dyn HirDatabase, def: DefWithBodyId, -) -> Result<'db, Arc<MirBody<'db>>> { +) -> Result<'db, Arc<MirBody>> { let krate = def.krate(db); let edition = krate.data(db).edition; let detail = match def { @@ -2224,16 +2243,17 @@ pub fn mir_body_query<'db>( }; let _p = tracing::info_span!("mir_body_query", ?detail).entered(); let body = db.body(def); - let infer = db.infer(def); - let mut result = lower_to_mir(db, def, &body, &infer, body.body_expr)?; + let infer = InferenceResult::for_body(db, def); + let mut result = lower_to_mir(db, def, &body, infer, body.body_expr)?; result.shrink_to_fit(); Ok(Arc::new(result)) } pub(crate) fn mir_body_cycle_result<'db>( _db: &'db dyn HirDatabase, + _: salsa::Id, _def: DefWithBodyId, -) -> Result<'db, Arc<MirBody<'db>>> { +) -> Result<'db, Arc<MirBody>> { Err(MirLowerError::Loop) } @@ -2241,17 +2261,17 @@ pub fn lower_to_mir<'db>( db: &'db dyn HirDatabase, owner: DefWithBodyId, body: &Body, - infer: &InferenceResult<'db>, + infer: &InferenceResult, // FIXME: root_expr should always be the body.body_expr, but since `X` in `[(); X]` doesn't have its own specific body yet, we // need to take this input explicitly. root_expr: ExprId, -) -> Result<'db, MirBody<'db>> { +) -> Result<'db, MirBody> { if infer.type_mismatches().next().is_some() || infer.is_erroneous() { return Err(MirLowerError::HasErrors); } let mut ctx = MirLowerCtx::new(db, owner, body, infer); // 0 is return local - ctx.result.locals.alloc(Local { ty: ctx.expr_ty_after_adjustments(root_expr) }); + ctx.result.locals.alloc(Local { ty: ctx.expr_ty_after_adjustments(root_expr).store() }); let binding_picker = |b: BindingId| { let owner = ctx.body.binding_owner(b); if root_expr == body.body_expr { owner.is_none() } else { owner == Some(root_expr) } @@ -2264,7 +2284,7 @@ pub fn lower_to_mir<'db>( if let DefWithBodyId::FunctionId(fid) = owner { let callable_sig = db.callable_item_signature(fid.into()).instantiate_identity().skip_binder(); - let mut params = callable_sig.inputs().iter(); + let mut params = callable_sig.inputs().iter().copied(); let self_param = body.self_param.and_then(|id| Some((id, params.next()?))); break 'b ctx.lower_params_and_bindings( body.params.iter().zip(params).map(|(it, y)| (*it, y)), |