Skip to content

Commit cac6126

Browse files
committed
Thread info about form of variable bindings, including spans of arg types, down into mir::LocalDecls.
As a drive-by: the ref_for_guards created by `fn declare_binding` should not have been tagged as user_variables in the first place. These secret internal locals are *pointers* to user variables, but themselves are not such (IMO. For now at least.)
1 parent 6ec1b62 commit cac6126

File tree

9 files changed

+85
-27
lines changed

9 files changed

+85
-27
lines changed

src/librustc/mir/mod.rs

+52-9
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ impl<'tcx> Mir<'tcx> {
228228
pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
229229
(self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
230230
let local = Local::new(index);
231-
if self.local_decls[local].is_user_variable {
231+
if self.local_decls[local].is_user_variable.is_some() {
232232
None
233233
} else {
234234
Some(local)
@@ -241,7 +241,7 @@ impl<'tcx> Mir<'tcx> {
241241
pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
242242
(self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
243243
let local = Local::new(index);
244-
if self.local_decls[local].is_user_variable {
244+
if self.local_decls[local].is_user_variable.is_some() {
245245
Some(local)
246246
} else {
247247
None
@@ -255,7 +255,7 @@ impl<'tcx> Mir<'tcx> {
255255
(1..self.local_decls.len()).filter_map(move |index| {
256256
let local = Local::new(index);
257257
let decl = &self.local_decls[local];
258-
if (decl.is_user_variable || index < self.arg_count + 1)
258+
if (decl.is_user_variable.is_some() || index < self.arg_count + 1)
259259
&& decl.mutability == Mutability::Mut
260260
{
261261
Some(local)
@@ -351,7 +351,7 @@ impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
351351
}
352352
}
353353

354-
#[derive(Clone, Debug)]
354+
#[derive(Copy, Clone, Debug)]
355355
pub enum ClearCrossCrate<T> {
356356
Clear,
357357
Set(T)
@@ -382,6 +382,16 @@ pub enum Mutability {
382382
Not,
383383
}
384384

385+
impl From<Mutability> for hir::Mutability {
386+
fn from(m: Mutability) -> Self {
387+
match m {
388+
Mutability::Mut => hir::MutMutable,
389+
Mutability::Not => hir::MutImmutable,
390+
}
391+
}
392+
}
393+
394+
385395
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
386396
pub enum BorrowKind {
387397
/// Data must be immutable and is aliasable.
@@ -463,6 +473,33 @@ pub enum LocalKind {
463473
ReturnPointer,
464474
}
465475

476+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
477+
pub struct VarBindingForm {
478+
/// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
479+
pub binding_mode: ty::BindingMode,
480+
/// If an explicit type was provided for this variable binding,
481+
/// this holds the source Span of that type.
482+
///
483+
/// NOTE: If you want to change this to a `HirId`, be wary that
484+
/// doing so breaks incremental compilation (as of this writing),
485+
/// while a `Span` does not cause our tests to fail.
486+
pub opt_ty_info: Option<Span>,
487+
}
488+
489+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
490+
pub enum BindingForm {
491+
/// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
492+
Var(VarBindingForm),
493+
/// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
494+
ImplicitSelf,
495+
}
496+
497+
CloneTypeFoldableAndLiftImpls! { BindingForm, }
498+
499+
impl_stable_hash_for!(struct self::VarBindingForm { binding_mode, opt_ty_info });
500+
501+
impl_stable_hash_for!(enum self::BindingForm { Var(binding), ImplicitSelf, });
502+
466503
/// A MIR local.
467504
///
468505
/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
@@ -474,8 +511,14 @@ pub struct LocalDecl<'tcx> {
474511
/// Temporaries and the return place are always mutable.
475512
pub mutability: Mutability,
476513

477-
/// True if this corresponds to a user-declared local variable.
478-
pub is_user_variable: bool,
514+
/// Some(binding_mode) if this corresponds to a user-declared local variable.
515+
///
516+
/// This is solely used for local diagnostics when generating
517+
/// warnings/errors when compiling the current crate, and
518+
/// therefore it need not be visible across crates. pnkfelix
519+
/// currently hypothesized we *need* to wrap this in a
520+
/// `ClearCrossCrate` as long as it carries as `HirId`.
521+
pub is_user_variable: Option<ClearCrossCrate<BindingForm>>,
479522

480523
/// True if this is an internal local
481524
///
@@ -605,7 +648,7 @@ impl<'tcx> LocalDecl<'tcx> {
605648
},
606649
visibility_scope: OUTERMOST_SOURCE_SCOPE,
607650
internal: false,
608-
is_user_variable: false
651+
is_user_variable: None,
609652
}
610653
}
611654

@@ -622,7 +665,7 @@ impl<'tcx> LocalDecl<'tcx> {
622665
},
623666
visibility_scope: OUTERMOST_SOURCE_SCOPE,
624667
internal: true,
625-
is_user_variable: false
668+
is_user_variable: None,
626669
}
627670
}
628671

@@ -641,7 +684,7 @@ impl<'tcx> LocalDecl<'tcx> {
641684
visibility_scope: OUTERMOST_SOURCE_SCOPE,
642685
internal: false,
643686
name: None, // FIXME maybe we do want some name here?
644-
is_user_variable: false
687+
is_user_variable: None,
645688
}
646689
}
647690
}

src/librustc/ty/binding.rs

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ pub enum BindingMode {
1818
BindByValue(Mutability),
1919
}
2020

21+
CloneTypeFoldableAndLiftImpls! { BindingMode, }
22+
2123
impl BindingMode {
2224
pub fn convert(ba: BindingAnnotation) -> BindingMode {
2325
match ba {

src/librustc_mir/borrow_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
278278
// to the set.
279279
let temporary_used_locals: FxHashSet<Local> =
280280
mbcx.used_mut.iter()
281-
.filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable)
281+
.filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
282282
.cloned()
283283
.collect();
284284

src/librustc_mir/build/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
137137
}
138138
}
139139

140-
this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| {
140+
this.visit_bindings(&pattern, &mut |this, _, _, _, node, span, _| {
141141
this.storage_live_binding(block, node, span, OutsideGuard);
142142
this.schedule_drop_for_binding(node, span, OutsideGuard);
143143
})

src/librustc_mir/build/expr/into.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
249249
source_info,
250250
visibility_scope: source_info.scope,
251251
internal: true,
252-
is_user_variable: false
252+
is_user_variable: None,
253253
});
254254
let ptr_temp = Place::Local(ptr_temp);
255255
let block = unpack!(this.into(&ptr_temp, block, ptr));

src/librustc_mir/build/matches/mod.rs

+23-10
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
307307
assert!(!(visibility_scope.is_some() && lint_level.is_explicit()),
308308
"can't have both a visibility and a lint scope at the same time");
309309
let mut scope = self.source_scope;
310-
self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| {
310+
self.visit_bindings(pattern, &mut |this, mutability, name, mode, var, span, ty| {
311311
if visibility_scope.is_none() {
312312
visibility_scope = Some(this.new_source_scope(scope_span,
313313
LintLevel::Inherited,
@@ -325,7 +325,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
325325
scope,
326326
};
327327
let visibility_scope = visibility_scope.unwrap();
328-
this.declare_binding(source_info, visibility_scope, mutability, name, var,
328+
this.declare_binding(source_info, visibility_scope, mutability, name, mode, var,
329329
ty, has_guard);
330330
});
331331
visibility_scope
@@ -359,11 +359,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
359359
}
360360

361361
pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
362-
where F: FnMut(&mut Self, Mutability, Name, NodeId, Span, Ty<'tcx>)
362+
where F: FnMut(&mut Self, Mutability, Name, BindingMode, NodeId, Span, Ty<'tcx>)
363363
{
364364
match *pattern.kind {
365-
PatternKind::Binding { mutability, name, var, ty, ref subpattern, .. } => {
366-
f(self, mutability, name, var, pattern.span, ty);
365+
PatternKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => {
366+
f(self, mutability, name, mode, var, pattern.span, ty);
367367
if let Some(subpattern) = subpattern.as_ref() {
368368
self.visit_bindings(subpattern, f);
369369
}
@@ -1118,23 +1118,35 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
11181118
visibility_scope: SourceScope,
11191119
mutability: Mutability,
11201120
name: Name,
1121+
mode: BindingMode,
11211122
var_id: NodeId,
11221123
var_ty: Ty<'tcx>,
11231124
has_guard: ArmHasGuard)
11241125
{
1125-
debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, visibility_scope={:?}, \
1126-
source_info={:?})",
1127-
var_id, name, var_ty, visibility_scope, source_info);
1126+
debug!("declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
1127+
visibility_scope={:?}, source_info={:?})",
1128+
var_id, name, mode, var_ty, visibility_scope, source_info);
11281129

11291130
let tcx = self.hir.tcx();
1131+
let binding_mode = match mode {
1132+
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
1133+
BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()),
1134+
};
11301135
let local = LocalDecl::<'tcx> {
11311136
mutability,
11321137
ty: var_ty.clone(),
11331138
name: Some(name),
11341139
source_info,
11351140
visibility_scope,
11361141
internal: false,
1137-
is_user_variable: true,
1142+
is_user_variable: Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
1143+
binding_mode,
1144+
// hypothetically, `visit_bindings` could try to unzip
1145+
// an outermost hir::Ty as we descend, matching up
1146+
// idents in pat; but complex w/ unclear UI payoff.
1147+
// Instead, just abandon providing diagnostic info.
1148+
opt_ty_info: None,
1149+
}))),
11381150
};
11391151
let for_arm_body = self.local_decls.push(local.clone());
11401152
let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() {
@@ -1145,8 +1157,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
11451157
name: Some(name),
11461158
source_info,
11471159
visibility_scope,
1160+
// FIXME: should these secretly injected ref_for_guard's be marked as `internal`?
11481161
internal: false,
1149-
is_user_variable: true,
1162+
is_user_variable: None,
11501163
});
11511164
LocalsForNode::Three { val_for_guard, ref_for_guard, for_arm_body }
11521165
} else {

src/librustc_mir/build/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
668668
visibility_scope: source_info.scope,
669669
name,
670670
internal: false,
671-
is_user_variable: false,
671+
is_user_variable: None,
672672
});
673673
}
674674

src/librustc_mir/shim.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
144144
source_info,
145145
visibility_scope: source_info.scope,
146146
internal: false,
147-
is_user_variable: false
147+
is_user_variable: None,
148148
}
149149
}
150150

src/librustc_mir/transform/generator.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
303303
source_info,
304304
visibility_scope: source_info.scope,
305305
internal: false,
306-
is_user_variable: false,
306+
is_user_variable: None,
307307
};
308308
let new_ret_local = Local::new(mir.local_decls.len());
309309
mir.local_decls.push(new_ret);
@@ -644,7 +644,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
644644
source_info,
645645
visibility_scope: source_info.scope,
646646
internal: false,
647-
is_user_variable: false,
647+
is_user_variable: None,
648648
};
649649

650650
make_generator_state_argument_indirect(tcx, def_id, &mut mir);
@@ -660,7 +660,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
660660
source_info,
661661
visibility_scope: source_info.scope,
662662
internal: false,
663-
is_user_variable: false,
663+
is_user_variable: None,
664664
};
665665

666666
no_landing_pads(tcx, &mut mir);

0 commit comments

Comments
 (0)