1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
//! Locals are in a private module as updating `LocalRef::Operand` has to
//! be careful wrt to subtyping. To deal with this we only allow updates by using
//! `FunctionCx::overwrite_local` which handles it automatically.
use crate::mir::{FunctionCx, LocalRef};
use crate::traits::BuilderMethods;
use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::print::with_no_trimmed_paths;
use std::ops::{Index, IndexMut};
pub(super) struct Locals<'tcx, V> {
values: IndexVec<mir::Local, LocalRef<'tcx, V>>,
}
impl<'tcx, V> Index<mir::Local> for Locals<'tcx, V> {
type Output = LocalRef<'tcx, V>;
#[inline]
fn index(&self, index: mir::Local) -> &LocalRef<'tcx, V> {
&self.values[index]
}
}
/// To mutate locals, use `FunctionCx::overwrite_local` instead.
impl<'tcx, V, Idx: ?Sized> !IndexMut<Idx> for Locals<'tcx, V> {}
impl<'tcx, V> Locals<'tcx, V> {
pub(super) fn empty() -> Locals<'tcx, V> {
Locals { values: IndexVec::default() }
}
pub(super) fn indices(&self) -> impl DoubleEndedIterator<Item = mir::Local> + Clone + 'tcx {
self.values.indices()
}
}
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub(super) fn initialize_locals(&mut self, values: Vec<LocalRef<'tcx, Bx::Value>>) {
assert!(self.locals.values.is_empty());
// FIXME(#115215): After #115025 get's merged this might not be necessary
for (local, value) in values.into_iter().enumerate() {
match value {
LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (),
LocalRef::Operand(op) => {
let local = mir::Local::from_usize(local);
let expected_ty = self.monomorphize(self.mir.local_decls[local].ty);
if expected_ty != op.layout.ty {
warn!("Unexpected initial operand type. See the issues/114858");
}
}
}
self.locals.values.push(value);
}
}
pub(super) fn overwrite_local(
&mut self,
local: mir::Local,
mut value: LocalRef<'tcx, Bx::Value>,
) {
match value {
LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (),
LocalRef::Operand(ref mut op) => {
let local_ty = self.monomorphize(self.mir.local_decls[local].ty);
if local_ty != op.layout.ty {
// FIXME(#112651): This can be changed to an ICE afterwards.
debug!("updating type of operand due to subtyping");
with_no_trimmed_paths!(debug!(?op.layout.ty));
with_no_trimmed_paths!(debug!(?local_ty));
op.layout.ty = local_ty;
}
}
};
self.locals.values[local] = value;
}
}
|