Skip to content

Commit 75c82b4

Browse files
committed
drop redundant ParamEnv, and avoid constructing InternVisitor without visiting
1 parent 7b8693e commit 75c82b4

File tree

2 files changed

+95
-81
lines changed

2 files changed

+95
-81
lines changed

src/librustc_mir/const_eval.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,8 @@ fn eval_body_using_ecx<'mir, 'tcx>(
134134
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
135135
cid: GlobalId<'tcx>,
136136
body: &'mir mir::Body<'tcx>,
137-
param_env: ty::ParamEnv<'tcx>,
138137
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
139-
debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
138+
debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
140139
let tcx = ecx.tcx.tcx;
141140
let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
142141
assert!(!layout.is_unsized());
@@ -162,7 +161,6 @@ fn eval_body_using_ecx<'mir, 'tcx>(
162161
ecx,
163162
cid.instance.def_id(),
164163
ret,
165-
param_env,
166164
)?;
167165

168166
debug!("eval_body_using_ecx done: {:?}", *ret);
@@ -658,7 +656,7 @@ pub fn const_eval_raw_provider<'tcx>(
658656

659657
let res = ecx.load_mir(cid.instance.def, cid.promoted);
660658
res.and_then(
661-
|body| eval_body_using_ecx(&mut ecx, cid, body, key.param_env)
659+
|body| eval_body_using_ecx(&mut ecx, cid, body)
662660
).and_then(|place| {
663661
Ok(RawConst {
664662
alloc_id: place.ptr.assert_ptr().alloc_id,

src/librustc_mir/interpret/intern.rs

+93-77
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! After a const evaluation has computed a value, before we destroy the const evaluator's session
44
//! memory, we need to extract all memory allocations to the global memory pool so they stay around.
55
6-
use rustc::ty::{Ty, ParamEnv, self};
6+
use rustc::ty::{Ty, self};
77
use rustc::mir::interpret::{InterpResult, ErrorHandled};
88
use rustc::hir;
99
use rustc::hir::def_id::DefId;
@@ -18,10 +18,10 @@ use super::{
1818
use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};
1919

2020
struct InternVisitor<'rt, 'mir, 'tcx> {
21-
/// previously encountered safe references
22-
ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
21+
/// The ectx from which we intern.
2322
ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
24-
param_env: ParamEnv<'tcx>,
23+
/// Previously encountered safe references.
24+
ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
2525
/// The root node of the value that we're looking at. This field is never mutated and only used
2626
/// for sanity assertions that will ICE when `const_qualif` screws up.
2727
mode: InternMode,
@@ -53,74 +53,93 @@ enum InternMode {
5353
/// into the memory of other constants or statics
5454
struct IsStaticOrFn;
5555

56+
/// Intern an allocation without looking at its children.
57+
/// `mode` is the mode of the environment where we found this pointer.
58+
/// `mutablity` is the mutability of the place to be interned; even if that says
59+
/// `immutable` things might become mutable if `ty` is not frozen.
60+
fn intern_shallow<'rt, 'mir, 'tcx>(
61+
ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
62+
leftover_relocations: &'rt mut FxHashSet<AllocId>,
63+
mode: InternMode,
64+
alloc_id: AllocId,
65+
mutability: Mutability,
66+
ty: Option<Ty<'tcx>>,
67+
) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
68+
trace!(
69+
"InternVisitor::intern {:?} with {:?}",
70+
alloc_id, mutability,
71+
);
72+
// remove allocation
73+
let tcx = ecx.tcx;
74+
let memory = ecx.memory_mut();
75+
let (kind, mut alloc) = match memory.alloc_map.remove(&alloc_id) {
76+
Some(entry) => entry,
77+
None => {
78+
// Pointer not found in local memory map. It is either a pointer to the global
79+
// map, or dangling.
80+
// If the pointer is dangling (neither in local nor global memory), we leave it
81+
// to validation to error. The `delay_span_bug` ensures that we don't forget such
82+
// a check in validation.
83+
if tcx.alloc_map.lock().get(alloc_id).is_none() {
84+
tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer");
85+
}
86+
// treat dangling pointers like other statics
87+
// just to stop trying to recurse into them
88+
return Ok(Some(IsStaticOrFn));
89+
},
90+
};
91+
// This match is just a canary for future changes to `MemoryKind`, which most likely need
92+
// changes in this function.
93+
match kind {
94+
MemoryKind::Stack | MemoryKind::Vtable => {},
95+
}
96+
// Set allocation mutability as appropriate. This is used by LLVM to put things into
97+
// read-only memory, and also by Miri when evluating other constants/statics that
98+
// access this one.
99+
if mode == InternMode::Static {
100+
let frozen = ty.map_or(true, |ty| ty.is_freeze(
101+
ecx.tcx.tcx,
102+
ecx.param_env,
103+
ecx.tcx.span,
104+
));
105+
// For statics, allocation mutability is the combination of the place mutability and
106+
// the type mutability.
107+
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
108+
if mutability == Mutability::Immutable && frozen {
109+
alloc.mutability = Mutability::Immutable;
110+
} else {
111+
// Just making sure we are not "upgrading" an immutable allocation to mutable.
112+
assert_eq!(alloc.mutability, Mutability::Mutable);
113+
}
114+
} else {
115+
// We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`.
116+
// But we still intern that as immutable as the memory cannot be changed once the
117+
// initial value was computed.
118+
// Constants are never mutable.
119+
alloc.mutability = Mutability::Immutable;
120+
};
121+
// link the alloc id to the actual allocation
122+
let alloc = tcx.intern_const_alloc(alloc);
123+
leftover_relocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
124+
tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
125+
Ok(None)
126+
}
127+
56128
impl<'rt, 'mir, 'tcx> InternVisitor<'rt, 'mir, 'tcx> {
57-
/// Intern an allocation without looking at its children.
58-
/// `mutablity` is the mutability of the place to be interned; even if that says
59-
/// `immutable` things might become mutable if `ty` is not frozen.
60129
fn intern_shallow(
61130
&mut self,
62131
alloc_id: AllocId,
63132
mutability: Mutability,
64133
ty: Option<Ty<'tcx>>,
65134
) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
66-
trace!(
67-
"InternVisitor::intern {:?} with {:?}",
68-
alloc_id, mutability,
69-
);
70-
// remove allocation
71-
let tcx = self.ecx.tcx;
72-
let memory = self.ecx.memory_mut();
73-
let (kind, mut alloc) = match memory.alloc_map.remove(&alloc_id) {
74-
Some(entry) => entry,
75-
None => {
76-
// Pointer not found in local memory map. It is either a pointer to the global
77-
// map, or dangling.
78-
// If the pointer is dangling (neither in local nor global memory), we leave it
79-
// to validation to error. The `delay_span_bug` ensures that we don't forget such
80-
// a check in validation.
81-
if tcx.alloc_map.lock().get(alloc_id).is_none() {
82-
tcx.sess.delay_span_bug(self.ecx.tcx.span, "tried to intern dangling pointer");
83-
}
84-
// treat dangling pointers like other statics
85-
// just to stop trying to recurse into them
86-
return Ok(Some(IsStaticOrFn));
87-
},
88-
};
89-
// This match is just a canary for future changes to `MemoryKind`, which most likely need
90-
// changes in this function.
91-
match kind {
92-
MemoryKind::Stack | MemoryKind::Vtable => {},
93-
}
94-
// Set allocation mutability as appropriate. This is used by LLVM to put things into
95-
// read-only memory, and also by Miri when evluating other constants/statics that
96-
// access this one.
97-
if self.mode == InternMode::Static {
98-
let frozen = ty.map_or(true, |ty| ty.is_freeze(
99-
self.ecx.tcx.tcx,
100-
self.param_env,
101-
self.ecx.tcx.span,
102-
));
103-
// For statics, allocation mutability is the combination of the place mutability and
104-
// the type mutability.
105-
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
106-
if mutability == Mutability::Immutable && frozen {
107-
alloc.mutability = Mutability::Immutable;
108-
} else {
109-
// Just making sure we are not "upgrading" an immutable allocation to mutable.
110-
assert_eq!(alloc.mutability, Mutability::Mutable);
111-
}
112-
} else {
113-
// We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`.
114-
// But we still intern that as immutable as the memory cannot be changed once the
115-
// initial value was computed.
116-
// Constants are never mutable.
117-
alloc.mutability = Mutability::Immutable;
118-
};
119-
// link the alloc id to the actual allocation
120-
let alloc = tcx.intern_const_alloc(alloc);
121-
self.leftover_relocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
122-
tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
123-
Ok(None)
135+
intern_shallow(
136+
self.ecx,
137+
self.leftover_relocations,
138+
self.mode,
139+
alloc_id,
140+
mutability,
141+
ty,
142+
)
124143
}
125144
}
126145

@@ -171,7 +190,8 @@ for
171190
// Handle trait object vtables
172191
if let Ok(meta) = value.to_meta() {
173192
if let ty::Dynamic(..) =
174-
self.ecx.tcx.struct_tail_erasing_lifetimes(referenced_ty, self.param_env).sty
193+
self.ecx.tcx.struct_tail_erasing_lifetimes(
194+
referenced_ty, self.ecx.param_env).sty
175195
{
176196
if let Ok(vtable) = meta.unwrap().to_ptr() {
177197
// explitly choose `Immutable` here, since vtables are immutable, even
@@ -203,7 +223,7 @@ for
203223
(InternMode::Const, hir::Mutability::MutMutable) => {
204224
match referenced_ty.sty {
205225
ty::Array(_, n)
206-
if n.eval_usize(self.ecx.tcx.tcx, self.param_env) == 0 => {}
226+
if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {}
207227
ty::Slice(_)
208228
if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {}
209229
_ => bug!("const qualif failed to prevent mutable references"),
@@ -246,9 +266,6 @@ pub fn intern_const_alloc_recursive(
246266
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
247267
def_id: DefId,
248268
ret: MPlaceTy<'tcx>,
249-
// FIXME(oli-obk): can we scrap the param env? I think we can, the final value of a const eval
250-
// must always be monomorphic, right?
251-
param_env: ty::ParamEnv<'tcx>,
252269
) -> InterpResult<'tcx> {
253270
let tcx = ecx.tcx;
254271
// this `mutability` is the mutability of the place, ignoring the type
@@ -264,22 +281,21 @@ pub fn intern_const_alloc_recursive(
264281
let leftover_relocations = &mut FxHashSet::default();
265282

266283
// start with the outermost allocation
267-
InternVisitor {
268-
ref_tracking: &mut ref_tracking,
284+
intern_shallow(
269285
ecx,
270-
mode: base_intern_mode,
271286
leftover_relocations,
272-
param_env,
273-
mutability: base_mutability,
274-
}.intern_shallow(ret.ptr.to_ptr()?.alloc_id, base_mutability, Some(ret.layout.ty))?;
287+
base_intern_mode,
288+
ret.ptr.to_ptr()?.alloc_id,
289+
base_mutability,
290+
Some(ret.layout.ty)
291+
)?;
275292

276293
while let Some(((mplace, mutability, mode), _)) = ref_tracking.todo.pop() {
277294
let interned = InternVisitor {
278295
ref_tracking: &mut ref_tracking,
279296
ecx,
280297
mode,
281298
leftover_relocations,
282-
param_env,
283299
mutability,
284300
}.visit_value(mplace);
285301
if let Err(error) = interned {

0 commit comments

Comments
 (0)