Skip to content

Commit 57e13e0

Browse files
committed
Auto merge of #61653 - oli-obk:visit_place_recursion, r=spastorino
get rid of visit_place recursion r? @spastorino this is groundwork for #60913, since after that PR we won't be able to implement `visit_place` in a recursive manner without heavy cloning everywhere. cc @eddyb this touches const qualif
2 parents 053666f + b137a47 commit 57e13e0

File tree

3 files changed

+142
-119
lines changed

3 files changed

+142
-119
lines changed

src/librustc/mir/visit.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ macro_rules! make_mir_visitor {
160160

161161
fn visit_projection(&mut self,
162162
place: & $($mutability)? Projection<'tcx>,
163+
context: PlaceContext,
163164
location: Location) {
164-
self.super_projection(place, location);
165+
self.super_projection(place, context, location);
165166
}
166167

167168
fn visit_constant(&mut self,
@@ -686,8 +687,7 @@ macro_rules! make_mir_visitor {
686687
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
687688
};
688689

689-
self.visit_place(& $($mutability)? proj.base, context, location);
690-
self.visit_projection(proj, location);
690+
self.visit_projection(proj, context, location);
691691
}
692692
}
693693
}
@@ -708,7 +708,12 @@ macro_rules! make_mir_visitor {
708708

709709
fn super_projection(&mut self,
710710
proj: & $($mutability)? Projection<'tcx>,
711+
context: PlaceContext,
711712
location: Location) {
713+
// this is calling `super_place` in preparation for changing `Place` to be
714+
// a struct with a base and a slice of projections. `visit_place` should only ever
715+
// be called for the outermost place now.
716+
self.super_place(& $($mutability)? proj.base, context, location);
712717
match & $($mutability)? proj.elem {
713718
ProjectionElem::Deref => {
714719
}

src/librustc_mir/transform/generator.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
103103
place: &mut Place<'tcx>,
104104
context: PlaceContext,
105105
location: Location) {
106-
if *place == Place::Base(PlaceBase::Local(self_arg())) {
107-
*place = Place::Projection(Box::new(Projection {
108-
base: place.clone(),
106+
if place.base_local() == Some(self_arg()) {
107+
replace_base(place, Place::Projection(Box::new(Projection {
108+
base: Place::Base(PlaceBase::Local(self_arg())),
109109
elem: ProjectionElem::Deref,
110-
}));
110+
})));
111111
} else {
112112
self.super_place(place, context, location);
113113
}
@@ -130,17 +130,25 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
130130
place: &mut Place<'tcx>,
131131
context: PlaceContext,
132132
location: Location) {
133-
if *place == Place::Base(PlaceBase::Local(self_arg())) {
134-
*place = Place::Projection(Box::new(Projection {
135-
base: place.clone(),
133+
if place.base_local() == Some(self_arg()) {
134+
replace_base(place, Place::Projection(Box::new(Projection {
135+
base: Place::Base(PlaceBase::Local(self_arg())),
136136
elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty),
137-
}));
137+
})));
138138
} else {
139139
self.super_place(place, context, location);
140140
}
141141
}
142142
}
143143

144+
fn replace_base(place: &mut Place<'tcx>, new_base: Place<'tcx>) {
145+
if let Place::Projection(proj) = place {
146+
replace_base(&mut proj.base, new_base);
147+
} else {
148+
*place = new_base;
149+
}
150+
}
151+
144152
fn self_arg() -> Local {
145153
Local::new(1)
146154
}
@@ -236,10 +244,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
236244
place: &mut Place<'tcx>,
237245
context: PlaceContext,
238246
location: Location) {
239-
if let Place::Base(PlaceBase::Local(l)) = *place {
247+
if let Some(l) = place.base_local() {
240248
// Replace an Local in the remap with a generator struct access
241249
if let Some(&(ty, variant_index, idx)) = self.remap.get(&l) {
242-
*place = self.make_field(variant_index, idx, ty);
250+
replace_base(place, self.make_field(variant_index, idx, ty));
243251
}
244252
} else {
245253
self.super_place(place, context, location);

src/librustc_mir/transform/qualify_consts.rs

+116-106
Original file line numberDiff line numberDiff line change
@@ -926,125 +926,135 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
926926
/// For functions (constant or not), it also records
927927
/// candidates for promotion in `promotion_candidates`.
928928
impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
929-
fn visit_place(&mut self,
930-
place: &Place<'tcx>,
931-
context: PlaceContext,
932-
location: Location) {
933-
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
934-
place.iterate(|place_base, place_projections| {
935-
match place_base {
936-
PlaceBase::Local(_) => {}
937-
PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => {
938-
unreachable!()
939-
}
940-
PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
941-
if self.tcx
942-
.get_attrs(*def_id)
943-
.iter()
944-
.any(|attr| attr.check_name(sym::thread_local)) {
945-
if self.mode != Mode::Fn {
946-
span_err!(self.tcx.sess, self.span, E0625,
947-
"thread-local statics cannot be \
948-
accessed at compile-time");
949-
}
950-
return;
929+
fn visit_place_base(
930+
&mut self,
931+
place_base: &PlaceBase<'tcx>,
932+
context: PlaceContext,
933+
location: Location,
934+
) {
935+
self.super_place_base(place_base, context, location);
936+
match place_base {
937+
PlaceBase::Local(_) => {}
938+
PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => {
939+
unreachable!()
940+
}
941+
PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
942+
if self.tcx
943+
.get_attrs(*def_id)
944+
.iter()
945+
.any(|attr| attr.check_name(sym::thread_local)) {
946+
if self.mode != Mode::Fn {
947+
span_err!(self.tcx.sess, self.span, E0625,
948+
"thread-local statics cannot be \
949+
accessed at compile-time");
951950
}
951+
return;
952+
}
952953

953-
// Only allow statics (not consts) to refer to other statics.
954-
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
955-
if self.mode == Mode::Static && context.is_mutating_use() {
956-
// this is not strictly necessary as miri will also bail out
957-
// For interior mutability we can't really catch this statically as that
958-
// goes through raw pointers and intermediate temporaries, so miri has
959-
// to catch this anyway
960-
self.tcx.sess.span_err(
961-
self.span,
962-
"cannot mutate statics in the initializer of another static",
963-
);
964-
}
965-
return;
954+
// Only allow statics (not consts) to refer to other statics.
955+
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
956+
if self.mode == Mode::Static && context.is_mutating_use() {
957+
// this is not strictly necessary as miri will also bail out
958+
// For interior mutability we can't really catch this statically as that
959+
// goes through raw pointers and intermediate temporaries, so miri has
960+
// to catch this anyway
961+
self.tcx.sess.span_err(
962+
self.span,
963+
"cannot mutate statics in the initializer of another static",
964+
);
966965
}
967-
unleash_miri!(self);
966+
return;
967+
}
968+
unleash_miri!(self);
968969

969-
if self.mode != Mode::Fn {
970-
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
971-
"{}s cannot refer to statics, use \
972-
a constant instead", self.mode);
973-
if self.tcx.sess.teach(&err.get_code().unwrap()) {
974-
err.note(
975-
"Static and const variables can refer to other const variables. \
976-
But a const variable cannot refer to a static variable."
977-
);
978-
err.help(
979-
"To fix this, the value can be extracted as a const and then used."
980-
);
981-
}
982-
err.emit()
970+
if self.mode != Mode::Fn {
971+
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
972+
"{}s cannot refer to statics, use \
973+
a constant instead", self.mode);
974+
if self.tcx.sess.teach(&err.get_code().unwrap()) {
975+
err.note(
976+
"Static and const variables can refer to other const variables. \
977+
But a const variable cannot refer to a static variable."
978+
);
979+
err.help(
980+
"To fix this, the value can be extracted as a const and then used."
981+
);
983982
}
983+
err.emit()
984984
}
985985
}
986+
}
987+
}
986988

987-
for proj in place_projections {
988-
match proj.elem {
989-
ProjectionElem::Deref => {
990-
if context.is_mutating_use() {
991-
// `not_const` errors out in const contexts
992-
self.not_const()
993-
}
994-
let base_ty = proj.base.ty(self.mir, self.tcx).ty;
995-
match self.mode {
996-
Mode::Fn => {},
997-
_ => {
998-
if let ty::RawPtr(_) = base_ty.sty {
999-
if !self.tcx.features().const_raw_ptr_deref {
1000-
emit_feature_err(
1001-
&self.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
1002-
self.span, GateIssue::Language,
1003-
&format!(
1004-
"dereferencing raw pointers in {}s is unstable",
1005-
self.mode,
1006-
),
1007-
);
1008-
}
1009-
}
989+
fn visit_projection(
990+
&mut self,
991+
proj: &Projection<'tcx>,
992+
context: PlaceContext,
993+
location: Location,
994+
) {
995+
debug!(
996+
"visit_place_projection: proj={:?} context={:?} location={:?}",
997+
proj, context, location,
998+
);
999+
self.super_projection(proj, context, location);
1000+
match proj.elem {
1001+
ProjectionElem::Deref => {
1002+
if context.is_mutating_use() {
1003+
// `not_const` errors out in const contexts
1004+
self.not_const()
1005+
}
1006+
let base_ty = proj.base.ty(self.mir, self.tcx).ty;
1007+
match self.mode {
1008+
Mode::Fn => {},
1009+
_ => {
1010+
if let ty::RawPtr(_) = base_ty.sty {
1011+
if !self.tcx.features().const_raw_ptr_deref {
1012+
emit_feature_err(
1013+
&self.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
1014+
self.span, GateIssue::Language,
1015+
&format!(
1016+
"dereferencing raw pointers in {}s is unstable",
1017+
self.mode,
1018+
),
1019+
);
10101020
}
10111021
}
10121022
}
1023+
}
1024+
}
10131025

1014-
ProjectionElem::ConstantIndex {..} |
1015-
ProjectionElem::Subslice {..} |
1016-
ProjectionElem::Field(..) |
1017-
ProjectionElem::Index(_) => {
1018-
let base_ty = proj.base.ty(self.mir, self.tcx).ty;
1019-
if let Some(def) = base_ty.ty_adt_def() {
1020-
if def.is_union() {
1021-
match self.mode {
1022-
Mode::ConstFn => {
1023-
if !self.tcx.features().const_fn_union {
1024-
emit_feature_err(
1025-
&self.tcx.sess.parse_sess, sym::const_fn_union,
1026-
self.span, GateIssue::Language,
1027-
"unions in const fn are unstable",
1028-
);
1029-
}
1030-
},
1031-
1032-
| Mode::Fn
1033-
| Mode::Static
1034-
| Mode::StaticMut
1035-
| Mode::Const
1036-
=> {},
1026+
ProjectionElem::ConstantIndex {..} |
1027+
ProjectionElem::Subslice {..} |
1028+
ProjectionElem::Field(..) |
1029+
ProjectionElem::Index(_) => {
1030+
let base_ty = proj.base.ty(self.mir, self.tcx).ty;
1031+
if let Some(def) = base_ty.ty_adt_def() {
1032+
if def.is_union() {
1033+
match self.mode {
1034+
Mode::ConstFn => {
1035+
if !self.tcx.features().const_fn_union {
1036+
emit_feature_err(
1037+
&self.tcx.sess.parse_sess, sym::const_fn_union,
1038+
self.span, GateIssue::Language,
1039+
"unions in const fn are unstable",
1040+
);
10371041
}
1038-
}
1039-
}
1040-
}
1042+
},
10411043

1042-
ProjectionElem::Downcast(..) => {
1043-
self.not_const()
1044+
| Mode::Fn
1045+
| Mode::Static
1046+
| Mode::StaticMut
1047+
| Mode::Const
1048+
=> {},
1049+
}
10441050
}
10451051
}
10461052
}
1047-
});
1053+
1054+
ProjectionElem::Downcast(..) => {
1055+
self.not_const()
1056+
}
1057+
}
10481058
}
10491059

10501060
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
@@ -1069,17 +1079,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
10691079
// Check nested operands and places.
10701080
if let Rvalue::Ref(_, kind, ref place) = *rvalue {
10711081
// Special-case reborrows.
1072-
let mut is_reborrow = false;
1082+
let mut reborrow_place = None;
10731083
if let Place::Projection(ref proj) = *place {
10741084
if let ProjectionElem::Deref = proj.elem {
10751085
let base_ty = proj.base.ty(self.mir, self.tcx).ty;
10761086
if let ty::Ref(..) = base_ty.sty {
1077-
is_reborrow = true;
1087+
reborrow_place = Some(&proj.base);
10781088
}
10791089
}
10801090
}
10811091

1082-
if is_reborrow {
1092+
if let Some(place) = reborrow_place {
10831093
let ctx = match kind {
10841094
BorrowKind::Shared => PlaceContext::NonMutatingUse(
10851095
NonMutatingUseContext::SharedBorrow,
@@ -1094,7 +1104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
10941104
MutatingUseContext::Borrow,
10951105
),
10961106
};
1097-
self.super_place(place, ctx, location);
1107+
self.visit_place(place, ctx, location);
10981108
} else {
10991109
self.super_rvalue(rvalue, location);
11001110
}

0 commit comments

Comments
 (0)