Name higher-ranked lifetimes properly while displaying
Now they don't shadow other lifetimes.
This commit is contained in:
parent
108706f13a
commit
9b0480bec6
@ -915,6 +915,10 @@ pub struct GlobalCtxt<'tcx> {
|
|||||||
/// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
|
/// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
|
||||||
pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,
|
pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,
|
||||||
|
|
||||||
|
pub display_used_late_bound_region_names: RefCell<Option<FxHashSet<Name>>>,
|
||||||
|
|
||||||
|
pub display_late_bound_region_index: Cell<usize>,
|
||||||
|
|
||||||
/// The definite name of the current crate after taking into account
|
/// The definite name of the current crate after taking into account
|
||||||
/// attributes, commandline parameters, etc.
|
/// attributes, commandline parameters, etc.
|
||||||
pub crate_name: Symbol,
|
pub crate_name: Symbol,
|
||||||
@ -1189,6 +1193,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||||||
selection_cache: traits::SelectionCache::new(),
|
selection_cache: traits::SelectionCache::new(),
|
||||||
evaluation_cache: traits::EvaluationCache::new(),
|
evaluation_cache: traits::EvaluationCache::new(),
|
||||||
rvalue_promotable_to_static: RefCell::new(NodeMap()),
|
rvalue_promotable_to_static: RefCell::new(NodeMap()),
|
||||||
|
display_used_late_bound_region_names: RefCell::new(None),
|
||||||
|
display_late_bound_region_index: Cell::new(0),
|
||||||
crate_name: Symbol::intern(crate_name),
|
crate_name: Symbol::intern(crate_name),
|
||||||
data_layout,
|
data_layout,
|
||||||
layout_interner: RefCell::new(FxHashSet()),
|
layout_interner: RefCell::new(FxHashSet()),
|
||||||
|
@ -20,6 +20,7 @@ use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
|
|||||||
use ty::{TyClosure, TyGenerator, TyProjection, TyAnon};
|
use ty::{TyClosure, TyGenerator, TyProjection, TyAnon};
|
||||||
use ty::{TyDynamic, TyInt, TyUint, TyInfer};
|
use ty::{TyDynamic, TyInt, TyUint, TyInfer};
|
||||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||||
|
use util::nodemap::FxHashSet;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -259,12 +260,34 @@ pub fn parameterized(f: &mut fmt::Formatter,
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LateBoundRegionNameCollector(FxHashSet<Symbol>);
|
||||||
|
|
||||||
|
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector {
|
||||||
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
||||||
|
match *r {
|
||||||
|
ty::ReLateBound(_, ty::BrNamed(_, name)) => {
|
||||||
|
self.0.insert(name);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
r.super_visit_with(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
|
fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
original: &ty::Binder<T>,
|
original: &ty::Binder<T>,
|
||||||
lifted: Option<ty::Binder<U>>) -> fmt::Result
|
lifted: Option<ty::Binder<U>>) -> fmt::Result
|
||||||
where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx>
|
where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx>
|
||||||
{
|
{
|
||||||
|
fn name_by_region_index(index: usize) -> Symbol {
|
||||||
|
match index {
|
||||||
|
0 => Symbol::intern("'r"),
|
||||||
|
1 => Symbol::intern("'s"),
|
||||||
|
i => Symbol::intern(&format!("'t{}", i-2)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Replace any anonymous late-bound regions with named
|
// Replace any anonymous late-bound regions with named
|
||||||
// variants, using gensym'd identifiers, so that we can
|
// variants, using gensym'd identifiers, so that we can
|
||||||
// clearly differentiate between named and unnamed regions in
|
// clearly differentiate between named and unnamed regions in
|
||||||
@ -286,27 +309,54 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_value = tcx.replace_late_bound_regions(&value, |br| {
|
// If displaying is just started, collect named late-bound regions.
|
||||||
let _ = start_or_continue(f, "for<", ", ");
|
let display_just_started = tcx.display_used_late_bound_region_names.borrow().is_none();
|
||||||
let br = match br {
|
if display_just_started {
|
||||||
ty::BrNamed(_, name) => {
|
let mut collector = LateBoundRegionNameCollector(FxHashSet());
|
||||||
let _ = write!(f, "{}", name);
|
value.visit_with(&mut collector);
|
||||||
br
|
*tcx.display_used_late_bound_region_names.borrow_mut() = Some(collector.0);
|
||||||
}
|
}
|
||||||
ty::BrAnon(_) |
|
|
||||||
ty::BrFresh(_) |
|
|
||||||
ty::BrEnv => {
|
|
||||||
let name = Symbol::intern("'r");
|
|
||||||
let _ = write!(f, "{}", name);
|
|
||||||
ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID),
|
|
||||||
name)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br))
|
|
||||||
}).0;
|
|
||||||
|
|
||||||
|
let old_region_index = tcx.display_late_bound_region_index.get();
|
||||||
|
let mut region_index = old_region_index;
|
||||||
|
let new_value = {
|
||||||
|
let used_region_names = tcx.display_used_late_bound_region_names.borrow();
|
||||||
|
let used_region_names = used_region_names.as_ref().unwrap();
|
||||||
|
tcx.replace_late_bound_regions(&value, |br| {
|
||||||
|
let _ = start_or_continue(f, "for<", ", ");
|
||||||
|
let br = match br {
|
||||||
|
ty::BrNamed(_, name) => {
|
||||||
|
let _ = write!(f, "{}", name);
|
||||||
|
br
|
||||||
|
}
|
||||||
|
ty::BrAnon(_) |
|
||||||
|
ty::BrFresh(_) |
|
||||||
|
ty::BrEnv => {
|
||||||
|
let name = loop {
|
||||||
|
let name = name_by_region_index(region_index);
|
||||||
|
region_index += 1;
|
||||||
|
if !used_region_names.contains(&name) {
|
||||||
|
break name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _ = write!(f, "{}", name);
|
||||||
|
ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID),
|
||||||
|
name)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br))
|
||||||
|
}).0
|
||||||
|
};
|
||||||
start_or_continue(f, "", "> ")?;
|
start_or_continue(f, "", "> ")?;
|
||||||
write!(f, "{}", new_value)
|
|
||||||
|
// Push current state to gcx, and restore after writing new_value.
|
||||||
|
tcx.display_late_bound_region_index.set(region_index);
|
||||||
|
write!(f, "{}", new_value)?;
|
||||||
|
tcx.display_late_bound_region_index.set(old_region_index);
|
||||||
|
if display_just_started {
|
||||||
|
*tcx.display_used_late_bound_region_names.borrow_mut() = None;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Display for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
|
impl<'tcx> fmt::Display for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
|
||||||
@ -782,7 +832,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
|
|||||||
write!(f, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
TyFnPtr(ref bare_fn) => {
|
TyFnPtr(ref bare_fn) => {
|
||||||
write!(f, "{}", bare_fn.0)
|
write!(f, "{}", bare_fn)
|
||||||
}
|
}
|
||||||
TyInfer(infer_ty) => write!(f, "{}", infer_ty),
|
TyInfer(infer_ty) => write!(f, "{}", infer_ty),
|
||||||
TyError => write!(f, "[type error]"),
|
TyError => write!(f, "[type error]"),
|
||||||
|
40
src/test/ui/anonymous-higher-ranked-lifetime.rs
Normal file
40
src/test/ui/anonymous-higher-ranked-lifetime.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
f1(|_: (), _: ()| {});
|
||||||
|
f2(|_: (), _: ()| {});
|
||||||
|
f3(|_: (), _: ()| {});
|
||||||
|
f4(|_: (), _: ()| {});
|
||||||
|
f5(|_: (), _: ()| {});
|
||||||
|
g1(|_: (), _: ()| {});
|
||||||
|
g2(|_: (), _: ()| {});
|
||||||
|
g3(|_: (), _: ()| {});
|
||||||
|
g4(|_: (), _: ()| {});
|
||||||
|
h1(|_: (), _: (), _: (), _: ()| {});
|
||||||
|
h2(|_: (), _: (), _: (), _: ()| {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic
|
||||||
|
fn f1<F>(_: F) where F: Fn(&(), &()) {}
|
||||||
|
fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
|
||||||
|
fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
|
||||||
|
fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
|
||||||
|
fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
|
||||||
|
|
||||||
|
// Nested
|
||||||
|
fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
|
||||||
|
fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
|
||||||
|
fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
|
||||||
|
fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
|
||||||
|
|
||||||
|
// Mixed
|
||||||
|
fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
|
||||||
|
fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
|
112
src/test/ui/anonymous-higher-ranked-lifetime.stderr
Normal file
112
src/test/ui/anonymous-higher-ranked-lifetime.stderr
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
|
||||||
|
|
|
||||||
|
12 | f1(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `f1`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:13:5
|
||||||
|
|
|
||||||
|
13 | f2(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `f2`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
|
||||||
|
|
|
||||||
|
14 | f3(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'r> fn(&(), &'r ()) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `f3`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:15:5
|
||||||
|
|
|
||||||
|
15 | f4(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `f4`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
|
||||||
|
|
|
||||||
|
16 | f5(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'r> fn(&'r (), &'r ()) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `f5`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:17:5
|
||||||
|
|
|
||||||
|
17 | g1(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'r> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `g1`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
|
||||||
|
|
|
||||||
|
18 | g2(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `g2`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:19:5
|
||||||
|
|
|
||||||
|
19 | g3(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'s> fn(&'s (), std::boxed::Box<for<'r> std::ops::Fn(&'r ()) + 'static>) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `g3`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
|
||||||
|
|
|
||||||
|
20 | g4(|_: (), _: ()| {});
|
||||||
|
| ^^ ----------------- found signature of `fn((), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `g4`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:21:5
|
||||||
|
|
|
||||||
|
21 | h1(|_: (), _: (), _: (), _: ()| {});
|
||||||
|
| ^^ ------------------------------- found signature of `fn((), (), (), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<for<'t0> std::ops::Fn(&'t0 ()) + 'static>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `h1`
|
||||||
|
|
||||||
|
error[E0631]: type mismatch in closure arguments
|
||||||
|
--> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
|
||||||
|
|
|
||||||
|
22 | h2(|_: (), _: (), _: (), _: ()| {});
|
||||||
|
| ^^ ------------------------------- found signature of `fn((), (), (), ()) -> _`
|
||||||
|
| |
|
||||||
|
| expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
|
||||||
|
|
|
||||||
|
= note: required by `h2`
|
||||||
|
|
||||||
|
error: aborting due to 11 previous errors
|
||||||
|
|
@ -4,7 +4,7 @@ error[E0308]: mismatched types
|
|||||||
51 | want_F(bar); //~ ERROR E0308
|
51 | want_F(bar); //~ ERROR E0308
|
||||||
| ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
|
| ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
|
||||||
|
|
|
|
||||||
= note: expected type `fn(&'cx S) -> &'cx S`
|
= note: expected type `for<'cx> fn(&'cx S) -> &'cx S`
|
||||||
found type `fn(&'a S) -> &S {bar::<'_>}`
|
found type `fn(&'a S) -> &S {bar::<'_>}`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
Loading…
Reference in New Issue
Block a user