Make visit_projection iterative
This commit is contained in:
parent
a8d70d1b4a
commit
b9ed64268d
@ -734,9 +734,10 @@ macro_rules! make_mir_visitor {
|
||||
projection: & $($mutability)? [PlaceElem<'tcx>],
|
||||
context: PlaceContext,
|
||||
location: Location) {
|
||||
if let [proj_base @ .., elem] = projection {
|
||||
self.visit_projection(base, proj_base, context, location);
|
||||
self.visit_projection_elem(base, proj_base, elem, context, location);
|
||||
let mut cursor = projection;
|
||||
while let [proj_base @ .., elem] = cursor {
|
||||
cursor = proj_base;
|
||||
self.visit_projection_elem(base, cursor, elem, context, location);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,25 +404,25 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
|
||||
self.super_assign(dest, rvalue, location);
|
||||
}
|
||||
|
||||
fn visit_projection(
|
||||
fn visit_projection_elem(
|
||||
&mut self,
|
||||
place_base: &PlaceBase<'tcx>,
|
||||
proj: &[PlaceElem<'tcx>],
|
||||
proj_base: &[PlaceElem<'tcx>],
|
||||
elem: &PlaceElem<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
trace!(
|
||||
"visit_place_projection: proj={:?} context={:?} location={:?}",
|
||||
proj,
|
||||
"visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \
|
||||
context={:?} location={:?}",
|
||||
place_base,
|
||||
proj_base,
|
||||
elem,
|
||||
context,
|
||||
location,
|
||||
);
|
||||
self.super_projection(place_base, proj, context, location);
|
||||
|
||||
let (elem, proj_base) = match proj.split_last() {
|
||||
Some(x) => x,
|
||||
None => return,
|
||||
};
|
||||
self.super_projection_elem(place_base, proj_base, elem, context, location);
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
|
@ -1156,82 +1156,87 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_projection(
|
||||
fn visit_projection_elem(
|
||||
&mut self,
|
||||
place_base: &PlaceBase<'tcx>,
|
||||
proj: &[PlaceElem<'tcx>],
|
||||
proj_base: &[PlaceElem<'tcx>],
|
||||
elem: &PlaceElem<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
debug!(
|
||||
"visit_place_projection: proj={:?} context={:?} location={:?}",
|
||||
proj, context, location,
|
||||
"visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \
|
||||
context={:?} location={:?}",
|
||||
place_base,
|
||||
proj_base,
|
||||
elem,
|
||||
context,
|
||||
location,
|
||||
);
|
||||
self.super_projection(place_base, proj, context, location);
|
||||
|
||||
if let [proj_base @ .., elem] = proj {
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
if context.is_mutating_use() {
|
||||
// `not_const` errors out in const contexts
|
||||
self.not_const(ops::MutDeref)
|
||||
self.super_projection_elem(place_base, proj_base, elem, context, location);
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
if context.is_mutating_use() {
|
||||
// `not_const` errors out in const contexts
|
||||
self.not_const(ops::MutDeref)
|
||||
}
|
||||
let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
|
||||
match self.mode {
|
||||
Mode::NonConstFn => {}
|
||||
_ if self.suppress_errors => {}
|
||||
_ => {
|
||||
if let ty::RawPtr(_) = base_ty.kind {
|
||||
if !self.tcx.features().const_raw_ptr_deref {
|
||||
self.record_error(ops::RawPtrDeref);
|
||||
emit_feature_err(
|
||||
&self.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
|
||||
self.span, GateIssue::Language,
|
||||
&format!(
|
||||
"dereferencing raw pointers in {}s is unstable",
|
||||
self.mode,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
|
||||
match self.mode {
|
||||
Mode::NonConstFn => {}
|
||||
_ if self.suppress_errors => {}
|
||||
_ => {
|
||||
if let ty::RawPtr(_) = base_ty.kind {
|
||||
if !self.tcx.features().const_raw_ptr_deref {
|
||||
self.record_error(ops::RawPtrDeref);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectionElem::ConstantIndex {..} |
|
||||
ProjectionElem::Subslice {..} |
|
||||
ProjectionElem::Field(..) |
|
||||
ProjectionElem::Index(_) => {
|
||||
let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
|
||||
if let Some(def) = base_ty.ty_adt_def() {
|
||||
if def.is_union() {
|
||||
match self.mode {
|
||||
Mode::ConstFn => {
|
||||
if !self.tcx.features().const_fn_union
|
||||
&& !self.suppress_errors
|
||||
{
|
||||
self.record_error(ops::UnionAccess);
|
||||
emit_feature_err(
|
||||
&self.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
|
||||
&self.tcx.sess.parse_sess, sym::const_fn_union,
|
||||
self.span, GateIssue::Language,
|
||||
&format!(
|
||||
"dereferencing raw pointers in {}s is unstable",
|
||||
self.mode,
|
||||
),
|
||||
"unions in const fn are unstable",
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
| Mode::NonConstFn
|
||||
| Mode::Static
|
||||
| Mode::StaticMut
|
||||
| Mode::Const
|
||||
=> {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProjectionElem::ConstantIndex {..} |
|
||||
ProjectionElem::Subslice {..} |
|
||||
ProjectionElem::Field(..) |
|
||||
ProjectionElem::Index(_) => {
|
||||
let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
|
||||
if let Some(def) = base_ty.ty_adt_def() {
|
||||
if def.is_union() {
|
||||
match self.mode {
|
||||
Mode::ConstFn => {
|
||||
if !self.tcx.features().const_fn_union
|
||||
&& !self.suppress_errors
|
||||
{
|
||||
self.record_error(ops::UnionAccess);
|
||||
emit_feature_err(
|
||||
&self.tcx.sess.parse_sess, sym::const_fn_union,
|
||||
self.span, GateIssue::Language,
|
||||
"unions in const fn are unstable",
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
| Mode::NonConstFn
|
||||
| Mode::Static
|
||||
| Mode::StaticMut
|
||||
| Mode::Const
|
||||
=> {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProjectionElem::Downcast(..) => {
|
||||
self.not_const(ops::Downcast)
|
||||
}
|
||||
ProjectionElem::Downcast(..) => {
|
||||
self.not_const(ops::Downcast)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user