]> git.lizzy.rs Git - rust.git/commitdiff
Name higher-ranked lifetimes properly while displaying
authorWonwoo Choi <chwo9843@gmail.com>
Mon, 25 Sep 2017 15:36:08 +0000 (00:36 +0900)
committerWonwoo Choi <chwo9843@gmail.com>
Sun, 8 Oct 2017 11:53:14 +0000 (20:53 +0900)
Now they don't shadow other lifetimes.

src/librustc/ty/context.rs
src/librustc/util/ppaux.rs
src/test/ui/anonymous-higher-ranked-lifetime.rs [new file with mode: 0644]
src/test/ui/anonymous-higher-ranked-lifetime.stderr [new file with mode: 0644]
src/test/ui/regions-fn-subtyping-return-static.stderr

index 740299b91f118d6b24810704a327928bab862c64..a7eacc3744db0d485203065dcb43dfe1a04188dc 100644 (file)
@@ -915,6 +915,10 @@ pub struct GlobalCtxt<'tcx> {
     /// 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,
@@ -1189,6 +1193,8 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             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()),
index 214973e3085865bad8412e8f1be483d4aec7d87f..a6fb7a0f25ce3b19193ce03f1da83a0b3e00e644 100644 (file)
@@ -20,6 +20,7 @@
 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;
@@ -259,12 +260,34 @@ pub fn parameterized(f: &mut fmt::Formatter,
     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
@@ -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| {
-        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>> {
@@ -782,7 +832,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 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]"),
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.rs b/src/test/ui/anonymous-higher-ranked-lifetime.rs
new file mode 100644 (file)
index 0000000..f2d04c1
--- /dev/null
@@ -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(&(), &())) {}
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
new file mode 100644 (file)
index 0000000..f962b77
--- /dev/null
@@ -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
+
index 1598a8a40d2f0b8bfd30b1f42629ee6e4c23e1c1..0c88c63edeb643883138921dd5f18a6461fb3122 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 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