]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/util/ppaux.rs
rollup merge of #17355 : gamazeps/issue17210
[rust.git] / src / librustc / util / ppaux.rs
index 5dff183108ce8f78290c96d27bb35413a4860400..5b83f024309bf34acb582b6f0f9cbee42932e5b2 100644 (file)
 use middle::ty::{ty_unboxed_closure};
 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
 use middle::ty;
-use middle::typeck::infer::region_inference;
-use middle::typeck::infer::unify::VarValue as VV;
-use middle::typeck::infer::unify;
-use middle::typeck::infer;
 use middle::typeck;
+use middle::typeck::check::regionmanip;
+use middle::typeck::infer;
 
-use std::gc::Gc;
 use std::rc::Rc;
 use syntax::abi;
 use syntax::ast_map;
@@ -66,6 +63,22 @@ pub fn note_and_explain_region(cx: &ctxt,
     }
 }
 
+fn item_scope_tag(item: &ast::Item) -> &'static str {
+    /*!
+     * When a free region is associated with `item`, how should we describe
+     * the item in the error message.
+     */
+
+    match item.node {
+        ast::ItemImpl(..) => "impl",
+        ast::ItemStruct(..) => "struct",
+        ast::ItemEnum(..) => "enum",
+        ast::ItemTrait(..) => "trait",
+        ast::ItemFn(..) => "function body",
+        _ => "item"
+    }
+}
+
 pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
                             -> (String, Option<Span>) {
     return match region {
@@ -87,9 +100,9 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
           Some(ast_map::NodeStmt(stmt)) => {
               explain_span(cx, "statement", stmt.span)
           }
-          Some(ast_map::NodeItem(it)) if (match it.node {
-                ast::ItemFn(..) => true, _ => false}) => {
-              explain_span(cx, "function body", it.span)
+          Some(ast_map::NodeItem(it)) => {
+              let tag = item_scope_tag(&*it);
+              explain_span(cx, tag, it.span)
           }
           Some(_) | None => {
             // this really should not happen
@@ -112,17 +125,17 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
 
         match cx.map.find(fr.scope_id) {
           Some(ast_map::NodeBlock(ref blk)) => {
-            let (msg, opt_span) = explain_span(cx, "block", blk.span);
-            (format!("{} {}", prefix, msg), opt_span)
+              let (msg, opt_span) = explain_span(cx, "block", blk.span);
+              (format!("{} {}", prefix, msg), opt_span)
           }
-          Some(ast_map::NodeItem(it)) if match it.node {
-                ast::ItemImpl(..) => true, _ => false} => {
-            let (msg, opt_span) = explain_span(cx, "impl", it.span);
-            (format!("{} {}", prefix, msg), opt_span)
+          Some(ast_map::NodeItem(it)) => {
+              let tag = item_scope_tag(&*it);
+              let (msg, opt_span) = explain_span(cx, tag, it.span);
+              (format!("{} {}", prefix, msg), opt_span)
           }
           Some(_) | None => {
-            // this really should not happen
-            (format!("{} node {}", prefix, fr.scope_id), None)
+              // this really should not happen
+              (format!("{} node {}", prefix, fr.scope_id), None)
           }
         }
       }
@@ -143,7 +156,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
     };
 
     fn explain_span(cx: &ctxt, heading: &str, span: Span)
-        -> (String, Option<Span>) {
+                    -> (String, Option<Span>) {
         let lo = cx.sess.codemap().lookup_char_pos_adj(span.lo);
         (format!("the {} at {}:{}", heading, lo.line, lo.col.to_uint()),
          Some(span))
@@ -273,7 +286,7 @@ fn bare_fn_to_string(cx: &ctxt,
             _ => { }
         }
 
-        push_sig_to_string(cx, &mut s, '(', ')', sig);
+        push_sig_to_string(cx, &mut s, '(', ')', sig, "");
 
         s
     }
@@ -296,34 +309,34 @@ fn closure_to_string(cx: &ctxt, cty: &ty::ClosureTy) -> String {
             }
         };
 
+        let bounds_str = cty.bounds.user_string(cx);
+
         match cty.store {
             ty::UniqTraitStore => {
                 assert_eq!(cty.onceness, ast::Once);
                 s.push_str("proc");
-                push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
+                push_sig_to_string(cx, &mut s, '(', ')', &cty.sig,
+                                   bounds_str.as_slice());
             }
             ty::RegionTraitStore(..) => {
                 match cty.onceness {
                     ast::Many => {}
                     ast::Once => s.push_str("once ")
                 }
-                push_sig_to_string(cx, &mut s, '|', '|', &cty.sig);
+                push_sig_to_string(cx, &mut s, '|', '|', &cty.sig,
+                                   bounds_str.as_slice());
             }
         }
 
-        if !cty.bounds.is_empty() {
-            s.push_str(":");
-            s.push_str(cty.bounds.repr(cx).as_slice());
-        }
-
-        s
+        s.into_owned()
     }
 
     fn push_sig_to_string(cx: &ctxt,
                        s: &mut String,
                        bra: char,
                        ket: char,
-                       sig: &ty::FnSig) {
+                       sig: &ty::FnSig,
+                       bounds: &str) {
         s.push_char(bra);
         let strs: Vec<String> = sig.inputs.iter().map(|a| fn_input_to_string(cx, *a)).collect();
         s.push_str(strs.connect(", ").as_slice());
@@ -332,6 +345,11 @@ fn push_sig_to_string(cx: &ctxt,
         }
         s.push_char(ket);
 
+        if !bounds.is_empty() {
+            s.push_str(":");
+            s.push_str(bounds);
+        }
+
         if ty::get(sig.output).sty != ty_nil {
             s.push_str(" -> ");
             if ty::type_is_bot(sig.output) {
@@ -383,18 +401,8 @@ fn push_sig_to_string(cx: &ctxt,
       }
       ty_infer(infer_ty) => infer_ty.to_string(),
       ty_err => "[type error]".to_string(),
-      ty_param(ParamTy {idx: id, def_id: did, ..}) => {
-          let ident = match cx.ty_param_defs.borrow().find(&did.node) {
-              Some(def) => token::get_ident(def.ident).get().to_string(),
-              // This can only happen when a type mismatch error happens and
-              // the actual type has more type parameters than the expected one.
-              None => format!("<generic #{}>", id),
-          };
-          if !cx.sess.verbose() {
-              ident
-          } else {
-              format!("{}:{:?}", ident, did)
-          }
+      ty_param(ref param_ty) => {
+          param_ty.repr(cx)
       }
       ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
           let base = ty::item_path_str(cx, did);
@@ -408,8 +416,8 @@ fn push_sig_to_string(cx: &ctxt,
           let trait_def = ty::lookup_trait_def(cx, did);
           let ty = parameterized(cx, base.as_slice(),
                                  substs, &trait_def.generics);
-          let bound_sep = if bounds.is_empty() { "" } else { "+" };
-          let bound_str = bounds.repr(cx);
+          let bound_str = bounds.user_string(cx);
+          let bound_sep = if bound_str.is_empty() { "" } else { "+" };
           format!("{}{}{}",
                   ty,
                   bound_sep,
@@ -488,7 +496,13 @@ pub fn parameterized(cx: &ctxt,
 
     if cx.sess.verbose() {
         for t in substs.types.get_slice(subst::SelfSpace).iter() {
-            strs.push(format!("for {}", t.repr(cx)));
+            strs.push(format!("self {}", t.repr(cx)));
+        }
+
+        // generally there shouldn't be any substs in the fn param
+        // space, but in verbose mode, print them out.
+        for t in substs.types.get_slice(subst::FnSpace).iter() {
+            strs.push(format!("fn {}", t.repr(cx)));
         }
     }
 
@@ -531,13 +545,13 @@ fn repr(&self, _tcx: &ctxt) -> String {
     }
 }
 
-impl<T:Repr> Repr for Rc<T> {
+impl<'a,T:Repr> Repr for &'a T {
     fn repr(&self, tcx: &ctxt) -> String {
         (&**self).repr(tcx)
     }
 }
 
-impl<T:Repr + 'static> Repr for Gc<T> {
+impl<T:Repr> Repr for Rc<T> {
     fn repr(&self, tcx: &ctxt) -> String {
         (&**self).repr(tcx)
     }
@@ -573,6 +587,14 @@ fn repr(&self, tcx: &ctxt) -> String {
     }
 }
 
+impl<T:UserString> UserString for Vec<T> {
+    fn user_string(&self, tcx: &ctxt) -> String {
+        let strs: Vec<String> =
+            self.iter().map(|t| t.user_string(tcx)).collect();
+        strs.connect(", ")
+    }
+}
+
 impl Repr for def::Def {
     fn repr(&self, _tcx: &ctxt) -> String {
         format!("{:?}", *self)
@@ -581,16 +603,20 @@ fn repr(&self, _tcx: &ctxt) -> String {
 
 impl Repr for ty::TypeParameterDef {
     fn repr(&self, tcx: &ctxt) -> String {
-        format!("TypeParameterDef({:?}, {})", self.def_id,
-                self.bounds.repr(tcx))
+        format!("TypeParameterDef({}, {}, {}/{})",
+                self.def_id,
+                self.bounds.repr(tcx),
+                self.space,
+                self.index)
     }
 }
 
 impl Repr for ty::RegionParameterDef {
-    fn repr(&self, _tcx: &ctxt) -> String {
-        format!("RegionParameterDef({}, {:?})",
+    fn repr(&self, tcx: &ctxt) -> String {
+        format!("RegionParameterDef(name={}, def_id={}, bounds={})",
                 token::get_name(self.name),
-                self.def_id)
+                self.def_id.repr(tcx),
+                self.bounds.repr(tcx))
     }
 }
 
@@ -638,18 +664,31 @@ fn repr(&self, tcx: &ctxt) -> String {
     }
 }
 
-impl Repr for ty::ParamBounds {
-    fn repr(&self, tcx: &ctxt) -> String {
+impl Repr for ty::BuiltinBounds {
+    fn repr(&self, _tcx: &ctxt) -> String {
         let mut res = Vec::new();
-        for b in self.builtin_bounds.iter() {
+        for b in self.iter() {
             res.push(match b {
-                ty::BoundStatic => "'static".to_string(),
-                ty::BoundSend => "Send".to_string(),
-                ty::BoundSized => "Sized".to_string(),
-                ty::BoundCopy => "Copy".to_string(),
-                ty::BoundSync => "Sync".to_string(),
+                ty::BoundSend => "Send".to_owned(),
+                ty::BoundSized => "Sized".to_owned(),
+                ty::BoundCopy => "Copy".to_owned(),
+                ty::BoundSync => "Sync".to_owned(),
             });
         }
+        res.connect("+")
+    }
+}
+
+impl Repr for ty::ExistentialBounds {
+    fn repr(&self, tcx: &ctxt) -> String {
+        self.user_string(tcx)
+    }
+}
+
+impl Repr for ty::ParamBounds {
+    fn repr(&self, tcx: &ctxt) -> String {
+        let mut res = Vec::new();
+        res.push(self.builtin_bounds.repr(tcx));
         for t in self.trait_bounds.iter() {
             res.push(t.repr(tcx));
         }
@@ -659,7 +698,20 @@ fn repr(&self, tcx: &ctxt) -> String {
 
 impl Repr for ty::TraitRef {
     fn repr(&self, tcx: &ctxt) -> String {
-        trait_ref_to_string(tcx, self)
+        let base = ty::item_path_str(tcx, self.def_id);
+        let trait_def = ty::lookup_trait_def(tcx, self.def_id);
+        format!("<{} as {}>",
+                self.substs.self_ty().repr(tcx),
+                parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics))
+    }
+}
+
+impl Repr for ty::TraitDef {
+    fn repr(&self, tcx: &ctxt) -> String {
+        format!("TraitDef(generics={}, bounds={}, trait_ref={})",
+                self.generics.repr(tcx),
+                self.bounds.repr(tcx),
+                self.trait_ref.repr(tcx))
     }
 }
 
@@ -675,12 +727,24 @@ fn repr(&self, _tcx: &ctxt) -> String {
     }
 }
 
+impl UserString for ast::Path {
+    fn user_string(&self, _tcx: &ctxt) -> String {
+        pprust::path_to_string(self)
+    }
+}
+
 impl Repr for ast::Item {
     fn repr(&self, tcx: &ctxt) -> String {
         format!("item({})", tcx.map.node_to_string(self.id))
     }
 }
 
+impl Repr for ast::Lifetime {
+    fn repr(&self, _tcx: &ctxt) -> String {
+        format!("lifetime({}: {})", self.id, pprust::lifetime_to_string(self))
+    }
+}
+
 impl Repr for ast::Stmt {
     fn repr(&self, _tcx: &ctxt) -> String {
         format!("stmt({}: {})",
@@ -724,11 +788,7 @@ fn repr(&self, tcx: &ctxt) -> String {
                         bound_region.repr(tcx))
             }
 
-            ty::ReFree(ref fr) => {
-                format!("ReFree({}, {})",
-                        fr.scope_id,
-                        fr.bound_region.repr(tcx))
-            }
+            ty::ReFree(ref fr) => fr.repr(tcx),
 
             ty::ReScope(id) => {
                 format!("ReScope({})", id)
@@ -753,27 +813,39 @@ fn repr(&self, tcx: &ctxt) -> String {
     }
 }
 
+impl UserString for ty::Region {
+    fn user_string(&self, tcx: &ctxt) -> String {
+        region_to_string(tcx, "", false, *self)
+    }
+}
+
+impl Repr for ty::FreeRegion {
+    fn repr(&self, tcx: &ctxt) -> String {
+        format!("ReFree({}, {})",
+                self.scope_id,
+                self.bound_region.repr(tcx))
+    }
+}
+
 impl Repr for ast::DefId {
     fn repr(&self, tcx: &ctxt) -> String {
         // Unfortunately, there seems to be no way to attempt to print
         // a path for a def-id, so I'll just make a best effort for now
         // and otherwise fallback to just printing the crate/node pair
         if self.krate == ast::LOCAL_CRATE {
-            {
-                match tcx.map.find(self.node) {
-                    Some(ast_map::NodeItem(..)) |
-                    Some(ast_map::NodeForeignItem(..)) |
-                    Some(ast_map::NodeImplItem(..)) |
-                    Some(ast_map::NodeTraitItem(..)) |
-                    Some(ast_map::NodeVariant(..)) |
-                    Some(ast_map::NodeStructCtor(..)) => {
-                        return format!(
+            match tcx.map.find(self.node) {
+                Some(ast_map::NodeItem(..)) |
+                Some(ast_map::NodeForeignItem(..)) |
+                Some(ast_map::NodeImplItem(..)) |
+                Some(ast_map::NodeTraitItem(..)) |
+                Some(ast_map::NodeVariant(..)) |
+                Some(ast_map::NodeStructCtor(..)) => {
+                    return format!(
                                 "{:?}:{}",
                                 *self,
                                 ty::item_path_str(tcx, *self))
-                    }
-                    _ => {}
                 }
+                _ => {}
             }
         }
         return format!("{:?}", *self)
@@ -833,6 +905,12 @@ fn repr(&self, _tcx: &ctxt) -> String {
     }
 }
 
+impl UserString for ast::Name {
+    fn user_string(&self, _tcx: &ctxt) -> String {
+        token::get_name(*self).get().to_string()
+    }
+}
+
 impl Repr for ast::Ident {
     fn repr(&self, _tcx: &ctxt) -> String {
         token::get_ident(*self).get().to_string()
@@ -884,10 +962,10 @@ fn repr(&self, tcx: &ctxt) -> String {
             &typeck::MethodStaticUnboxedClosure(def_id) => {
                 format!("MethodStaticUnboxedClosure({})", def_id.repr(tcx))
             }
-            &typeck::MethodParam(ref p) => {
+            &typeck::MethodTypeParam(ref p) => {
                 p.repr(tcx)
             }
-            &typeck::MethodObject(ref p) => {
+            &typeck::MethodTraitObject(ref p) => {
                 p.repr(tcx)
             }
         }
@@ -896,18 +974,16 @@ fn repr(&self, tcx: &ctxt) -> String {
 
 impl Repr for typeck::MethodParam {
     fn repr(&self, tcx: &ctxt) -> String {
-        format!("MethodParam({},{:?},{:?},{:?})",
-                self.trait_id.repr(tcx),
-                self.method_num,
-                self.param_num,
-                self.bound_num)
+        format!("MethodParam({},{})",
+                self.trait_ref.repr(tcx),
+                self.method_num)
     }
 }
 
 impl Repr for typeck::MethodObject {
     fn repr(&self, tcx: &ctxt) -> String {
         format!("MethodObject({},{:?},{:?})",
-                self.trait_id.repr(tcx),
+                self.trait_ref.repr(tcx),
                 self.method_num,
                 self.real_index)
     }
@@ -928,21 +1004,14 @@ fn repr(&self, _tcx: &ctxt) -> String {
 impl UserString for ty::BuiltinBound {
     fn user_string(&self, _tcx: &ctxt) -> String {
         match *self {
-            ty::BoundStatic => "'static".to_string(),
-            ty::BoundSend => "Send".to_string(),
-            ty::BoundSized => "Sized".to_string(),
-            ty::BoundCopy => "Copy".to_string(),
-            ty::BoundSync => "Sync".to_string(),
+            ty::BoundSend => "Send".to_owned(),
+            ty::BoundSized => "Sized".to_owned(),
+            ty::BoundCopy => "Copy".to_owned(),
+            ty::BoundSync => "Sync".to_owned(),
         }
     }
 }
 
-impl Repr for ty::BuiltinBounds {
-    fn repr(&self, tcx: &ctxt) -> String {
-        self.user_string(tcx)
-    }
-}
-
 impl Repr for Span {
     fn repr(&self, tcx: &ctxt) -> String {
         tcx.sess.codemap().span_to_string(*self).to_string()
@@ -956,6 +1025,43 @@ fn user_string(&self, tcx: &ctxt) -> String {
     }
 }
 
+impl UserString for ty::ParamBounds {
+    fn user_string(&self, tcx: &ctxt) -> String {
+        let mut result = Vec::new();
+        let s = self.builtin_bounds.user_string(tcx);
+        if !s.is_empty() {
+            result.push(s);
+        }
+        for n in self.trait_bounds.iter() {
+            result.push(n.user_string(tcx));
+        }
+        result.connect("+")
+    }
+}
+
+impl UserString for ty::ExistentialBounds {
+    fn user_string(&self, tcx: &ctxt) -> String {
+        if self.builtin_bounds.contains_elem(ty::BoundSend) &&
+            self.region_bound == ty::ReStatic
+        { // Region bound is implied by builtin bounds:
+            return self.builtin_bounds.repr(tcx);
+        }
+
+        let mut res = Vec::new();
+
+        let region_str = self.region_bound.user_string(tcx);
+        if !region_str.is_empty() {
+            res.push(region_str);
+        }
+
+        for bound in self.builtin_bounds.iter() {
+            res.push(bound.user_string(tcx));
+        }
+
+        res.connect("+")
+    }
+}
+
 impl UserString for ty::BuiltinBounds {
     fn user_string(&self, tcx: &ctxt) -> String {
         self.iter()
@@ -1083,33 +1189,56 @@ fn repr(&self, tcx: &ctxt) -> String {
     }
 }
 
-impl<K:Repr,V:Repr> Repr for VV<K,V> {
+impl Repr for ty::ExplicitSelfCategory {
+    fn repr(&self, _: &ctxt) -> String {
+        explicit_self_category_to_str(self).to_string()
+    }
+}
+
+
+impl Repr for regionmanip::WfConstraint {
     fn repr(&self, tcx: &ctxt) -> String {
         match *self {
-            unify::Redirect(ref k) =>
-                format!("Redirect({})", k.repr(tcx)),
-            unify::Root(ref v, r) =>
-                format!("Root({}, {})", v.repr(tcx), r)
+            regionmanip::RegionSubRegionConstraint(_, r_a, r_b) => {
+                format!("RegionSubRegionConstraint({}, {})",
+                        r_a.repr(tcx),
+                        r_b.repr(tcx))
+            }
+
+            regionmanip::RegionSubParamConstraint(_, r, p) => {
+                format!("RegionSubParamConstraint({}, {})",
+                        r.repr(tcx),
+                        p.repr(tcx))
+            }
         }
     }
 }
 
-impl Repr for region_inference::VarValue {
+impl UserString for ParamTy {
+    fn user_string(&self, tcx: &ctxt) -> String {
+        let id = self.idx;
+        let did = self.def_id;
+        let ident = match tcx.ty_param_defs.borrow().find(&did.node) {
+            Some(def) => token::get_ident(def.ident).get().to_string(),
+
+            // This can only happen when a type mismatch error happens and
+            // the actual type has more type parameters than the expected one.
+            None => format!("<generic #{}>", id),
+        };
+        ident
+    }
+}
+
+impl Repr for ParamTy {
     fn repr(&self, tcx: &ctxt) -> String {
-        match *self {
-            infer::region_inference::NoValue =>
-                format!("NoValue"),
-            infer::region_inference::Value(r) =>
-                format!("Value({})", r.repr(tcx)),
-            infer::region_inference::ErrorValue =>
-                format!("ErrorValue"),
-        }
+        self.user_string(tcx)
     }
 }
 
-impl Repr for ty::ExplicitSelfCategory {
-    fn repr(&self, _: &ctxt) -> String {
-        explicit_self_category_to_str(self).to_string()
+impl<A:Repr,B:Repr> Repr for (A,B) {
+    fn repr(&self, tcx: &ctxt) -> String {
+        let &(ref a, ref b) = self;
+        format!("({},{})", a.repr(tcx), b.repr(tcx))
     }
 }