cleaner code as per review

This commit is contained in:
Saleem Jaffer 2019-03-17 11:12:39 +05:30
parent 7fb1c22da1
commit a837b8a368
11 changed files with 160 additions and 213 deletions

View file

@ -737,16 +737,6 @@ macro_rules! make_mir_visitor {
self.visit_local(local, context, location);
}
Place::Base(PlaceBase::Static(static_)) => {
match static_.promoted {
None => {
self.visit_static(static_, context, location);
}
Some(_) => {
self.visit_ty(
& $($mutability)? static_.ty, TyContext::Location(location)
);
}
}
self.visit_static(static_, context, location);
}
Place::Projection(proj) => {

View file

@ -1602,13 +1602,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
self.append_local_to_string(local, buf)?;
}
Place::Base(PlaceBase::Static(ref static_)) => {
match static_.promoted {
Some(_) => {
buf.push_str("promoted");
}
None => {
buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
}
if static_.promoted.is_some() {
buf.push_str("promoted");
} else {
buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
}
}
Place::Projection(ref proj) => {

View file

@ -1309,15 +1309,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// FIXME: allow thread-locals to borrow other thread locals?
let (might_be_alive, will_be_dropped) = match root_place {
Place::Base(PlaceBase::Static(st)) => {
match st.promoted {
None => {
// Thread-locals might be dropped after the function exits, but
// "true" statics will never be.
let is_thread_local = self.is_place_thread_local(&root_place);
(true, is_thread_local)
}
Some(_) => (true, false),
}
(true, st.promoted.is_none() && self.is_place_thread_local(&root_place))
}
Place::Base(PlaceBase::Local(_)) => {
// Locals are always dropped at function exit, and if they
@ -1990,28 +1982,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}
// The rules for promotion are made by `qualify_consts`, there wouldn't even be a
// `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
// Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace {
// place,
// is_local_mutation_allowed,
// }),
Place::Base(PlaceBase::Static(ref static_)) => {
match static_.promoted {
Some(_) => {
if static_.promoted.is_some() {
Ok(RootPlace {
place,
is_local_mutation_allowed,
})
} else {
if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
Err(place)
} else {
Ok(RootPlace {
place,
is_local_mutation_allowed,
})
}
None => {
if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
Err(place)
} else {
Ok(RootPlace {
place,
is_local_mutation_allowed,
})
}
}
}
}
Place::Projection(ref proj) => {

View file

@ -130,18 +130,14 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
}
Place::Base(PlaceBase::Static(box Static { def_id, ty: _, promoted })) => {
match promoted {
Some(_) => unreachable!(),
None => {
if let Place::Base(PlaceBase::Static(_)) = access_place {
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
reason = String::new();
} else {
item_msg = format!("`{}`", access_place_desc.unwrap());
let static_name = &self.infcx.tcx.item_name(*def_id);
reason = format!(", as `{}` is an immutable static item", static_name);
}
}
assert!(promoted.is_none());
if let Place::Base(PlaceBase::Static(_)) = access_place {
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
reason = String::new();
} else {
item_msg = format!("`{}`", access_place_desc.unwrap());
let static_name = &self.infcx.tcx.item_name(*def_id);
reason = format!(", as `{}` is an immutable static item", static_name);
}
}

View file

@ -454,10 +454,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
ty: self.mir.local_decls[index].ty,
},
Place::Base(PlaceBase::Static(box Static { def_id, ty: sty, promoted })) => {
let sty = self.sanitize_type(place, sty);
match promoted {
Some(pr) => {
let sty = self.sanitize_type(place, sty);
if !self.errors_reported {
let promoted_mir = &self.mir.promoted[pr];
self.sanitize_promoted(promoted_mir, location);
@ -480,15 +479,18 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
);
};
}
PlaceTy::Ty { ty: sty }
}
None => {
let sty = self.sanitize_type(place, sty);
let ty = self.tcx().type_of(def_id);
let ty = self.cx.normalize(ty, location);
if let Err(terr) =
self.cx
.eq_types(ty, sty, location.to_locations(), ConstraintCategory::Boring)
.eq_types(
ty,
sty,
location.to_locations(),
ConstraintCategory::Boring
)
{
span_mirbug!(
self,
@ -498,10 +500,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
sty,
terr
);
}
PlaceTy::Ty { ty: sty }
};
}
}
PlaceTy::Ty { ty: sty }
}
Place::Projection(ref proj) => {
let base_context = if context.is_mutating_use() {

View file

@ -50,11 +50,10 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
}
}
Place::Base(PlaceBase::Static(static_)) => {
match static_.promoted {
Some(_) => false,
None => {
tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
}
if static_.promoted.is_none() {
tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
} else {
false
}
}
Place::Projection(proj) => match proj.elem {

View file

@ -387,7 +387,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
},
(Some(p1), Some(p2)) => {
if p1 == p2 {
if let ty::Array(_, size) =s1.ty.sty {
if let ty::Array(_, size) = s1.ty.sty {
if size.unwrap_usize(tcx) == 0 {
// Ignore conflicts with promoted [T; 0].
debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
@ -404,7 +404,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
}
},
(p1_, p2_) => {
debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
debug!("place_element_conflict: DISJOINT-STATIC-PROMOTED");
Overlap::Disjoint
}
}

View file

@ -582,39 +582,37 @@ where
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
use rustc::mir::Place::*;
use rustc::mir::PlaceBase;
use rustc::mir::Static;
Ok(match *mir_place {
Base(PlaceBase::Static(ref static_)) => {
match static_.promoted {
Some(promoted) => {
let instance = self.frame().instance;
self.const_eval_raw(GlobalId {
instance,
promoted: Some(promoted),
})?
}
None => {
assert!(!static_.ty.needs_subst());
let layout = self.layout_of(static_.ty)?;
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
let cid = GlobalId {
instance,
promoted: None
};
// Just create a lazy reference, so we can support recursive statics.
// tcx takes are of assigning every static one and only one unique AllocId.
// When the data here is ever actually used, memory will notice,
// and it knows how to deal with alloc_id that are present in the
// global table but not in its local memory: It calls back into tcx through
// a query, triggering the CTFE machinery to actually turn this lazy reference
// into a bunch of bytes. IOW, statics are evaluated with CTFE even when
// this EvalContext uses another Machine (e.g., in miri). This is what we
// want! This way, computing statics works concistently between codegen
// and miri: They use the same query to eventually obtain a `ty::Const`
// and use that for further computation.
let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout)
}
}
Base(PlaceBase::Static(box Static {promoted: Some(promoted), ty, ..})) => {
let instance = self.frame().instance;
self.const_eval_raw(GlobalId {
instance,
promoted: Some(promoted),
})?
}
Base(PlaceBase::Static(box Static {promoted: None, ty, def_id})) => {
assert!(!ty.needs_subst());
let layout = self.layout_of(ty)?;
let instance = ty::Instance::mono(*self.tcx, def_id);
let cid = GlobalId {
instance,
promoted: None
};
// Just create a lazy reference, so we can support recursive statics.
// tcx takes are of assigning every static one and only one unique AllocId.
// When the data here is ever actually used, memory will notice,
// and it knows how to deal with alloc_id that are present in the
// global table but not in its local memory: It calls back into tcx through
// a query, triggering the CTFE machinery to actually turn this lazy reference
// into a bunch of bytes. IOW, statics are evaluated with CTFE even when
// this EvalContext uses another Machine (e.g., in miri). This is what we
// want! This way, computing statics works concistently between codegen
// and miri: They use the same query to eventually obtain a `ty::Const`
// and use that for further computation.
let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout)
}
_ => bug!("eval_place_to_mplace called on {:?}", mir_place),

View file

@ -301,32 +301,27 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
// locals are safe
}
&Place::Base(PlaceBase::Static(box Static { def_id, ty: _, promoted })) => {
match promoted {
Some(..) => {
bug!("unsafety checking should happen before promotion")
}
None => {
if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
self.require_unsafe("use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing violations \
or data races will cause undefined behavior",
UnsafetyViolationKind::General);
} else if self.tcx.is_foreign_item(def_id) {
let source_info = self.source_info;
let lint_root =
self.source_scope_local_data[source_info.scope].lint_root;
self.register_violations(&[UnsafetyViolation {
source_info,
description: Symbol::intern("use of extern static").as_interned_str(),
details:
Symbol::intern("extern statics are not controlled by the Rust type \
system: invalid data, aliasing violations or data \
races will cause undefined behavior")
.as_interned_str(),
kind: UnsafetyViolationKind::ExternStatic(lint_root)
}], &[]);
}
}
assert!(promoted.is_none(), "unsafety checking should happen before promotion");
if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
self.require_unsafe("use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing violations \
or data races will cause undefined behavior",
UnsafetyViolationKind::General);
} else if self.tcx.is_foreign_item(def_id) {
let source_info = self.source_info;
let lint_root =
self.source_scope_local_data[source_info.scope].lint_root;
self.register_violations(&[UnsafetyViolation {
source_info,
description: Symbol::intern("use of extern static").as_interned_str(),
details:
Symbol::intern("extern statics are not controlled by the Rust type \
system: invalid data, aliasing violations or data \
races will cause undefined behavior")
.as_interned_str(),
kind: UnsafetyViolationKind::ExternStatic(lint_root)
}], &[]);
}
}
};

View file

@ -266,6 +266,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
}
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
use rustc::mir::Static;
match *place {
Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
Place::Projection(ref proj) => match proj.elem {
@ -282,31 +283,25 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
// an `Index` projection would throw us off-track.
_ => None,
},
Place::Base(PlaceBase::Static(ref static_)) => {
match static_.promoted {
Some(promoted) => {
let generics = self.tcx.generics_of(self.source.def_id());
if generics.requires_monomorphization(self.tcx) {
// FIXME: can't handle code with generics
return None;
}
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
let instance = Instance::new(self.source.def_id(), substs);
let cid = GlobalId {
instance,
promoted: Some(promoted),
};
// cannot use `const_eval` here, because that would require having the MIR
// for the current function available, but we're producing said MIR right now
let res = self.use_ecx(source_info, |this| {
eval_promoted(this.tcx, cid, this.mir, this.param_env)
})?;
trace!("evaluated promoted {:?} to {:?}", promoted, res);
Some((res.into(), source_info.span))
}
None => None
Place::Base(PlaceBase::Static(box Static {promoted: Some(promoted), ty, ..})) => {
let generics = self.tcx.generics_of(self.source.def_id());
if generics.requires_monomorphization(self.tcx) {
// FIXME: can't handle code with generics
return None;
}
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
let instance = Instance::new(self.source.def_id(), substs);
let cid = GlobalId {
instance,
promoted: Some(promoted),
};
// cannot use `const_eval` here, because that would require having the MIR
// for the current function available, but we're producing said MIR right now
let res = self.use_ecx(source_info, |this| {
eval_promoted(this.tcx, cid, this.mir, this.param_env)
})?;
trace!("evaluated promoted {:?} to {:?}", promoted, res);
Some((res.into(), source_info.span))
},
_ => None,
}

View file

@ -189,10 +189,8 @@ trait Qualif {
match *place {
Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
Place::Base(PlaceBase::Static(ref static_)) => {
match static_.promoted {
Some(..) => bug!("qualifying already promoted MIR"),
None => Self::in_static(cx, static_),
}
assert!(static_.promoted.is_none(), "qualifying already promoted MIR");
Self::in_static(cx, static_)
},
Place::Projection(ref proj) => Self::in_projection(cx, proj),
}
@ -773,19 +771,15 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
dest = &proj.base;
},
Place::Base(PlaceBase::Static(st)) => {
match st.promoted {
Some(..) => bug!("promoteds don't exist yet during promotion"),
None => {
// Catch more errors in the destination. `visit_place` also checks that we
// do not try to access statics from constants or try to mutate statics
self.visit_place(
dest,
PlaceContext::MutatingUse(MutatingUseContext::Store),
location
);
return;
}
}
assert!(st.promoted.is_none(), "promoteds don't exist yet during promotion");
// Catch more errors in the destination. `visit_place` also checks that we
// do not try to access statics from constants or try to mutate statics
self.visit_place(
dest,
PlaceContext::MutatingUse(MutatingUseContext::Store),
location
);
return;
}
}
};
@ -928,53 +922,49 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
match *place {
Place::Base(PlaceBase::Local(_)) => {}
Place::Base(PlaceBase::Static(ref global)) => {
match global.promoted {
Some(..) => {}
None => {
if self.tcx
.get_attrs(global.def_id)
.iter()
.any(|attr| attr.check_name("thread_local")) {
if self.mode != Mode::Fn {
span_err!(self.tcx.sess, self.span, E0625,
"thread-local statics cannot be \
accessed at compile-time");
}
return;
}
// Only allow statics (not consts) to refer to other statics.
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
if self.mode == Mode::Static && context.is_mutating_use() {
// this is not strictly necessary as miri will also bail out
// For interior mutability we can't really catch this statically as that
// goes through raw pointers and intermediate temporaries, so miri has
// to catch this anyway
self.tcx.sess.span_err(
self.span,
"cannot mutate statics in the initializer of another static",
);
}
return;
}
unleash_miri!(self);
if self.mode != Mode::Fn {
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
"{}s cannot refer to statics, use \
a constant instead", self.mode);
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"Static and const variables can refer to other const variables. But a \
const variable cannot refer to a static variable."
);
err.help(
"To fix this, the value can be extracted as a const and then used."
);
}
err.emit()
}
assert!(global.promoted.is_none(), {});
if self.tcx
.get_attrs(global.def_id)
.iter()
.any(|attr| attr.check_name("thread_local")) {
if self.mode != Mode::Fn {
span_err!(self.tcx.sess, self.span, E0625,
"thread-local statics cannot be \
accessed at compile-time");
}
return;
}
// Only allow statics (not consts) to refer to other statics.
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
if self.mode == Mode::Static && context.is_mutating_use() {
// this is not strictly necessary as miri will also bail out
// For interior mutability we can't really catch this statically as that
// goes through raw pointers and intermediate temporaries, so miri has
// to catch this anyway
self.tcx.sess.span_err(
self.span,
"cannot mutate statics in the initializer of another static",
);
}
return;
}
unleash_miri!(self);
if self.mode != Mode::Fn {
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
"{}s cannot refer to statics, use \
a constant instead", self.mode);
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"Static and const variables can refer to other const variables. But a \
const variable cannot refer to a static variable."
);
err.help(
"To fix this, the value can be extracted as a const and then used."
);
}
err.emit()
}
}
Place::Projection(ref proj) => {