Now they don't shadow other lifetimes.
/// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
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
/// attributes, commandline parameters, etc.
pub crate_name: Symbol,
selection_cache: traits::SelectionCache::new(),
evaluation_cache: traits::EvaluationCache::new(),
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),
data_layout,
layout_interner: RefCell::new(FxHashSet()),
use ty::{TyClosure, TyGenerator, TyProjection, TyAnon};
use ty::{TyDynamic, TyInt, TyUint, TyInfer};
use ty::{self, Ty, TyCtxt, TypeFoldable};
+use util::nodemap::FxHashSet;
use std::cell::Cell;
use std::fmt;
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,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
original: &ty::Binder<T>,
lifted: Option<ty::Binder<U>>) -> fmt::Result
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
// variants, using gensym'd identifiers, so that we can
// clearly differentiate between named and unnamed regions in
}
};
- let new_value = 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 = 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;
+ // If displaying is just started, collect named late-bound regions.
+ let display_just_started = tcx.display_used_late_bound_region_names.borrow().is_none();
+ if display_just_started {
+ let mut collector = LateBoundRegionNameCollector(FxHashSet());
+ value.visit_with(&mut collector);
+ *tcx.display_used_late_bound_region_names.borrow_mut() = Some(collector.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, "", "> ")?;
- 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>> {
write!(f, "}}")
}
TyFnPtr(ref bare_fn) => {
- write!(f, "{}", bare_fn.0)
+ write!(f, "{}", bare_fn)
}
TyInfer(infer_ty) => write!(f, "{}", infer_ty),
TyError => write!(f, "[type error]"),
--- /dev/null
+// 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(&(), &())) {}
--- /dev/null
+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
+
51 | want_F(bar); //~ ERROR E0308
| ^^^ 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::<'_>}`
error: aborting due to previous error