Skip to content

[nll] borrows that must be valid for a free lifetime should explain why #54229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 23, 2018
Merged
12 changes: 12 additions & 0 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -1883,6 +1883,18 @@ impl<'tcx> Place<'tcx> {
pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
Place::Projection(Box::new(PlaceProjection { base: self, elem }))
}

/// Find the innermost `Local` from this `Place`.
pub fn local(&self) -> Option<Local> {
match self {
Place::Local(local) |
Place::Projection(box Projection {
base: Place::Local(local),
elem: ProjectionElem::Deref,
}) => Some(*local),
_ => None,
}
}
}

impl<'tcx> Debug for Place<'tcx> {
17 changes: 17 additions & 0 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -1324,6 +1324,23 @@ impl_stable_hash_for!(struct DebruijnIndex { private });

/// Region utilities
impl RegionKind {
/// Is this region named by the user?
pub fn has_name(&self) -> bool {
match *self {
RegionKind::ReEarlyBound(ebr) => ebr.has_name(),
RegionKind::ReLateBound(_, br) => br.is_named(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside: The difference above is... unfortunate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what you mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has_name vs is_named

RegionKind::ReFree(fr) => fr.bound_region.is_named(),
RegionKind::ReScope(..) => false,
RegionKind::ReStatic => true,
RegionKind::ReVar(..) => false,
RegionKind::ReSkolemized(_, br) => br.is_named(),
RegionKind::ReEmpty => false,
RegionKind::ReErased => false,
RegionKind::ReClosureBound(..) => false,
RegionKind::ReCanonical(..) => false,
}
}

pub fn is_late_bound(&self) -> bool {
match *self {
ty::ReLateBound(..) => true,
52 changes: 45 additions & 7 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
@@ -34,7 +34,14 @@ use hir;
thread_local! {
/// Mechanism for highlighting of specific regions for display in NLL region inference errors.
/// Contains region to highlight and counter for number to use when highlighting.
static HIGHLIGHT_REGION: Cell<Option<(RegionVid, usize)>> = Cell::new(None)
static HIGHLIGHT_REGION_FOR_REGIONVID: Cell<Option<(RegionVid, usize)>> = Cell::new(None)
}

thread_local! {
/// Mechanism for highlighting of specific regions for display in NLL's 'borrow does not live
/// long enough' errors. Contains a region to highlight and a counter to use.
static HIGHLIGHT_REGION_FOR_BOUND_REGION: Cell<Option<(ty::BoundRegion, usize)>> =
Cell::new(None)
}

macro_rules! gen_display_debug_body {
@@ -564,12 +571,34 @@ pub fn parameterized<F: fmt::Write>(f: &mut F,
PrintContext::new().parameterized(f, substs, did, projections)
}

fn get_highlight_region() -> Option<(RegionVid, usize)> {
HIGHLIGHT_REGION.with(|hr| hr.get())
fn get_highlight_region_for_regionvid() -> Option<(RegionVid, usize)> {
HIGHLIGHT_REGION_FOR_REGIONVID.with(|hr| hr.get())
}

pub fn with_highlight_region<R>(r: RegionVid, counter: usize, op: impl FnOnce() -> R) -> R {
HIGHLIGHT_REGION.with(|hr| {
pub fn with_highlight_region_for_regionvid<R>(
r: RegionVid,
counter: usize,
op: impl FnOnce() -> R
) -> R {
HIGHLIGHT_REGION_FOR_REGIONVID.with(|hr| {
assert_eq!(hr.get(), None);
hr.set(Some((r, counter)));
let r = op();
hr.set(None);
r
})
}

fn get_highlight_region_for_bound_region() -> Option<(ty::BoundRegion, usize)> {
HIGHLIGHT_REGION_FOR_BOUND_REGION.with(|hr| hr.get())
}

pub fn with_highlight_region_for_bound_region<R>(
r: ty::BoundRegion,
counter: usize,
op: impl Fn() -> R
) -> R {
HIGHLIGHT_REGION_FOR_BOUND_REGION.with(|hr| {
assert_eq!(hr.get(), None);
hr.set(Some((r, counter)));
let r = op();
@@ -726,6 +755,15 @@ define_print! {
return self.print_debug(f, cx);
}

if let Some((region, counter)) = get_highlight_region_for_bound_region() {
if *self == region {
return match *self {
BrNamed(_, name) => write!(f, "{}", name),
BrAnon(_) | BrFresh(_) | BrEnv => write!(f, "'{}", counter)
};
}
}

match *self {
BrNamed(_, name) => write!(f, "{}", name),
BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
@@ -748,7 +786,7 @@ define_print! {
define_print! {
() ty::RegionKind, (self, f, cx) {
display {
if cx.is_verbose || get_highlight_region().is_some() {
if cx.is_verbose || get_highlight_region_for_regionvid().is_some() {
return self.print_debug(f, cx);
}

@@ -923,7 +961,7 @@ impl fmt::Debug for ty::FloatVid {

impl fmt::Debug for ty::RegionVid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some((region, counter)) = get_highlight_region() {
if let Some((region, counter)) = get_highlight_region_for_regionvid() {
debug!("RegionVid.fmt: region={:?} self={:?} counter={:?}", region, self, counter);
return if *self == region {
write!(f, "'{:?}", counter)
Loading