summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2015-05-12 12:48:14 +1200
committerNick Cameron <ncameron@mozilla.com>2015-05-12 12:48:14 +1200
commite0216fcc42d5f4961d07378a783c87814097015f (patch)
treee5f503c129942a2b7c2815b1c8e4db85b5bbcf1b /src/libsyntax
parentaa5ca282b20391c6df51fdfa94e0de5672ccfac1 (diff)
parent750f2c63f2737305d33288303cdecb7a470a7922 (diff)
downloadrust-e0216fcc42d5f4961d07378a783c87814097015f.tar.gz
rust-e0216fcc42d5f4961d07378a783c87814097015f.zip
Merge branch 'master' into
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/codemap.rs43
-rw-r--r--src/libsyntax/diagnostic.rs22
-rw-r--r--src/libsyntax/ext/build.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs65
-rw-r--r--src/libsyntax/ext/expand.rs7
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/parse/parser.rs7
-rw-r--r--src/libsyntax/parse/token.rs16
-rw-r--r--src/libsyntax/print/pprust.rs2
-rw-r--r--src/libsyntax/util/parser_testing.rs6
11 files changed, 110 insertions, 65 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 3b7bfb1043a..e00cb82649b 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -595,7 +595,7 @@ pub enum Pat_ {
 
     /// An associated const named using the qualified path `<T>::CONST` or
     /// `<T as Trait>::CONST`. Associated consts from inherent impls can be
-    /// refered to as simply `T::CONST`, in which case they will end up as
+    /// referred to as simply `T::CONST`, in which case they will end up as
     /// PatEnum, and the resolver will have to sort that out.
     PatQPath(QSelf, Path),
 
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 5e0cb647c8b..348bf6f51bb 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -543,7 +543,7 @@ impl CodeMap {
         }
     }
 
-    pub fn new_filemap(&self, filename: FileName, src: String) -> Rc<FileMap> {
+    pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
         let mut files = self.files.borrow_mut();
         let start_pos = match files.last() {
             None => 0,
@@ -551,13 +551,9 @@ impl CodeMap {
         };
 
         // Remove utf-8 BOM if any.
-        // FIXME #12884: no efficient/safe way to remove from the start of a string
-        // and reuse the allocation.
-        let mut src = if src.starts_with("\u{feff}") {
-            String::from(&src[3..])
-        } else {
-            String::from(&src[..])
-        };
+        if src.starts_with("\u{feff}") {
+            src.drain(..3);
+        }
 
         // Append '\n' in case it's not already there.
         // This is a workaround to prevent CodeMap.lookup_filemap_idx from
@@ -667,9 +663,22 @@ impl CodeMap {
         self.lookup_char_pos(sp.lo).file.name.to_string()
     }
 
-    pub fn span_to_lines(&self, sp: Span) -> FileLines {
+    pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
+        if sp.lo > sp.hi {
+            return Err(SpanLinesError::IllFormedSpan(sp));
+        }
+
         let lo = self.lookup_char_pos(sp.lo);
         let hi = self.lookup_char_pos(sp.hi);
+
+        if lo.file.start_pos != hi.file.start_pos {
+            return Err(SpanLinesError::DistinctSources(DistinctSources {
+                begin: (lo.file.name.clone(), lo.file.start_pos),
+                end: (hi.file.name.clone(), hi.file.start_pos),
+            }));
+        }
+        assert!(hi.line >= lo.line);
+
         let mut lines = Vec::with_capacity(hi.line - lo.line + 1);
 
         // The span starts partway through the first line,
@@ -693,7 +702,7 @@ impl CodeMap {
                               start_col: start_col,
                               end_col: hi.col });
 
-        FileLines {file: lo.file, lines: lines}
+        Ok(FileLines {file: lo.file, lines: lines})
     }
 
     pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
@@ -918,9 +927,17 @@ impl CodeMap {
 }
 
 // _____________________________________________________________________________
-// SpanSnippetError, DistinctSources, MalformedCodemapPositions
+// SpanLinesError, SpanSnippetError, DistinctSources, MalformedCodemapPositions
 //
 
+pub type FileLinesResult = Result<FileLines, SpanLinesError>;
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum SpanLinesError {
+    IllFormedSpan(Span),
+    DistinctSources(DistinctSources),
+}
+
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub enum SpanSnippetError {
     IllFormedSpan(Span),
@@ -1086,7 +1103,7 @@ mod tests {
         // Test span_to_lines for a span ending at the end of filemap
         let cm = init_code_map();
         let span = Span {lo: BytePos(12), hi: BytePos(23), expn_id: NO_EXPANSION};
-        let file_lines = cm.span_to_lines(span);
+        let file_lines = cm.span_to_lines(span).unwrap();
 
         assert_eq!(file_lines.file.name, "blork.rs");
         assert_eq!(file_lines.lines.len(), 1);
@@ -1131,7 +1148,7 @@ mod tests {
         assert_eq!(&cm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD");
 
         // check that span_to_lines gives us the complete result with the lines/cols we expected
-        let lines = cm.span_to_lines(span);
+        let lines = cm.span_to_lines(span).unwrap();
         let expected = vec![
             LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) },
             LineInfo { line_index: 2, start_col: CharPos(0), end_col: CharPos(3) },
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index a7453636c44..aa649b4d99a 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -522,7 +522,7 @@ fn highlight_suggestion(err: &mut EmitterWriter,
                         suggestion: &str)
                         -> io::Result<()>
 {
-    let lines = cm.span_to_lines(sp);
+    let lines = cm.span_to_lines(sp).unwrap();
     assert!(!lines.lines.is_empty());
 
     // To build up the result, we want to take the snippet from the first
@@ -567,9 +567,17 @@ fn highlight_lines(err: &mut EmitterWriter,
                    cm: &codemap::CodeMap,
                    sp: Span,
                    lvl: Level,
-                   lines: codemap::FileLines)
+                   lines: codemap::FileLinesResult)
                    -> io::Result<()>
 {
+    let lines = match lines {
+        Ok(lines) => lines,
+        Err(_) => {
+            try!(write!(&mut err.dst, "(internal compiler error: unprintable span)\n"));
+            return Ok(());
+        }
+    };
+
     let fm = &*lines.file;
 
     let line_strings: Option<Vec<&str>> =
@@ -690,8 +698,16 @@ fn end_highlight_lines(w: &mut EmitterWriter,
                           cm: &codemap::CodeMap,
                           sp: Span,
                           lvl: Level,
-                          lines: codemap::FileLines)
+                          lines: codemap::FileLinesResult)
                           -> io::Result<()> {
+    let lines = match lines {
+        Ok(lines) => lines,
+        Err(_) => {
+            try!(write!(&mut w.dst, "(internal compiler error: unprintable span)\n"));
+            return Ok(());
+        }
+    };
+
     let fm = &*lines.file;
 
     let lines = &lines.lines[..];
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index cde16d25412..354a0bff749 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -146,7 +146,7 @@ pub trait AstBuilder {
     fn expr_lit(&self, sp: Span, lit: ast::Lit_) -> P<ast::Expr>;
 
     fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr>;
-    fn expr_int(&self, sp: Span, i: isize) -> P<ast::Expr>;
+    fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr>;
     fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr>;
     fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr>;
     fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr>;
@@ -698,7 +698,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
         self.expr_lit(span, ast::LitInt(i as u64, ast::UnsignedIntLit(ast::TyUs)))
     }
-    fn expr_int(&self, sp: Span, i: isize) -> P<ast::Expr> {
+    fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitInt(i as u64, ast::SignedIntLit(ast::TyIs,
                                                                   ast::Sign::new(i))))
     }
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 4a54b36f8c4..78c2faea9d2 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -77,7 +77,7 @@
 //!
 //! The `cs_...` functions ("combine substructure) are designed to
 //! make life easier by providing some pre-made recipes for common
-//! tasks; mostly calling the function being derived on all the
+//! threads; mostly calling the function being derived on all the
 //! arguments and then combining them back together in some way (or
 //! letting the user chose that). They are not meant to be the only
 //! way to handle the structures that this code creates.
@@ -270,7 +270,7 @@ pub struct Substructure<'a> {
 }
 
 /// Summary of the relevant parts of a struct/enum field.
-pub struct FieldInfo {
+pub struct FieldInfo<'a> {
     pub span: Span,
     /// None for tuple structs/normal enum variants, Some for normal
     /// structs/struct enum variants.
@@ -281,6 +281,8 @@ pub struct FieldInfo {
     /// The expressions corresponding to references to this field in
     /// the other `Self` arguments.
     pub other: Vec<P<Expr>>,
+    /// The attributes on the field
+    pub attrs: &'a [ast::Attribute],
 }
 
 /// Fields for a static method
@@ -293,11 +295,11 @@ pub enum StaticFields {
 
 /// A summary of the possible sets of fields.
 pub enum SubstructureFields<'a> {
-    Struct(Vec<FieldInfo>),
+    Struct(Vec<FieldInfo<'a>>),
     /// Matching variants of the enum: variant index, ast::Variant,
     /// fields: the field name is only non-`None` in the case of a struct
     /// variant.
-    EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo>),
+    EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
 
     /// Non-matching variants of the enum, but with all state hidden from
     /// the consequent code.  The first component holds `Ident`s for all of
@@ -617,7 +619,7 @@ impl<'a> TraitDef<'a> {
 
     fn expand_struct_def(&self,
                          cx: &mut ExtCtxt,
-                         struct_def: &StructDef,
+                         struct_def: &'a StructDef,
                          type_ident: Ident,
                          generics: &Generics) -> P<ast::Item> {
         let field_tys: Vec<P<ast::Ty>> = struct_def.fields.iter()
@@ -661,7 +663,7 @@ impl<'a> TraitDef<'a> {
 
     fn expand_enum_def(&self,
                        cx: &mut ExtCtxt,
-                       enum_def: &EnumDef,
+                       enum_def: &'a EnumDef,
                        type_attrs: &[ast::Attribute],
                        type_ident: Ident,
                        generics: &Generics) -> P<ast::Item> {
@@ -893,10 +895,10 @@ impl<'a> MethodDef<'a> {
     ///     }
     /// }
     /// ```
-    fn expand_struct_method_body(&self,
+    fn expand_struct_method_body<'b>(&self,
                                  cx: &mut ExtCtxt,
-                                 trait_: &TraitDef,
-                                 struct_def: &StructDef,
+                                 trait_: &TraitDef<'b>,
+                                 struct_def: &'b StructDef,
                                  type_ident: Ident,
                                  self_args: &[P<Expr>],
                                  nonself_args: &[P<Expr>])
@@ -922,18 +924,19 @@ impl<'a> MethodDef<'a> {
         let fields = if !raw_fields.is_empty() {
             let mut raw_fields = raw_fields.into_iter().map(|v| v.into_iter());
             let first_field = raw_fields.next().unwrap();
-            let mut other_fields: Vec<vec::IntoIter<(Span, Option<Ident>, P<Expr>)>>
+            let mut other_fields: Vec<vec::IntoIter<_>>
                 = raw_fields.collect();
-            first_field.map(|(span, opt_id, field)| {
+            first_field.map(|(span, opt_id, field, attrs)| {
                 FieldInfo {
                     span: span,
                     name: opt_id,
                     self_: field,
                     other: other_fields.iter_mut().map(|l| {
                         match l.next().unwrap() {
-                            (_, _, ex) => ex
+                            (_, _, ex, _) => ex
                         }
-                    }).collect()
+                    }).collect(),
+                    attrs: attrs,
                 }
             }).collect()
         } else {
@@ -1007,10 +1010,10 @@ impl<'a> MethodDef<'a> {
     /// `PartialEq`, and those subcomputations will hopefully be removed
     /// as their results are unused.  The point of `__self_vi` and
     /// `__arg_1_vi` is for `PartialOrd`; see #15503.)
-    fn expand_enum_method_body(&self,
+    fn expand_enum_method_body<'b>(&self,
                                cx: &mut ExtCtxt,
-                               trait_: &TraitDef,
-                               enum_def: &EnumDef,
+                               trait_: &TraitDef<'b>,
+                               enum_def: &'b EnumDef,
                                type_attrs: &[ast::Attribute],
                                type_ident: Ident,
                                self_args: Vec<P<Expr>>,
@@ -1046,11 +1049,11 @@ impl<'a> MethodDef<'a> {
     ///   }
     /// }
     /// ```
-    fn build_enum_match_tuple(
+    fn build_enum_match_tuple<'b>(
         &self,
         cx: &mut ExtCtxt,
-        trait_: &TraitDef,
-        enum_def: &EnumDef,
+        trait_: &TraitDef<'b>,
+        enum_def: &'b EnumDef,
         type_attrs: &[ast::Attribute],
         type_ident: Ident,
         self_args: Vec<P<Expr>>,
@@ -1133,7 +1136,7 @@ impl<'a> MethodDef<'a> {
                 // arg fields of the variant for the first self pat.
                 let field_tuples = first_self_pat_idents.into_iter().enumerate()
                     // For each arg field of self, pull out its getter expr ...
-                    .map(|(field_index, (sp, opt_ident, self_getter_expr))| {
+                    .map(|(field_index, (sp, opt_ident, self_getter_expr, attrs))| {
                         // ... but FieldInfo also wants getter expr
                         // for matching other arguments of Self type;
                         // so walk across the *other* self_pats_idents
@@ -1141,7 +1144,7 @@ impl<'a> MethodDef<'a> {
                         // of them (using `field_index` tracked above).
                         // That is the heart of the transposition.
                         let others = self_pats_idents.iter().map(|fields| {
-                            let (_, _opt_ident, ref other_getter_expr) =
+                            let (_, _opt_ident, ref other_getter_expr, _) =
                                 fields[field_index];
 
                             // All Self args have same variant, so
@@ -1157,6 +1160,7 @@ impl<'a> MethodDef<'a> {
                                     name: opt_ident,
                                     self_: self_getter_expr,
                                     other: others,
+                                    attrs: attrs,
                         }
                     }).collect::<Vec<FieldInfo>>();
 
@@ -1408,10 +1412,12 @@ impl<'a> TraitDef<'a> {
     fn create_struct_pattern(&self,
                              cx: &mut ExtCtxt,
                              struct_path: ast::Path,
-                             struct_def: &StructDef,
+                             struct_def: &'a StructDef,
                              prefix: &str,
                              mutbl: ast::Mutability)
-                             -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>)>) {
+                             -> (P<ast::Pat>, Vec<(Span, Option<Ident>,
+                                                   P<Expr>,
+                                                   &'a [ast::Attribute])>) {
         if struct_def.fields.is_empty() {
             return (cx.pat_enum(self.span, struct_path, vec![]), vec![]);
         }
@@ -1441,7 +1447,7 @@ impl<'a> TraitDef<'a> {
             paths.push(codemap::Spanned{span: sp, node: ident});
             let val = cx.expr(
                 sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)))));
-            ident_expr.push((sp, opt_id, val));
+            ident_expr.push((sp, opt_id, val, &struct_field.node.attrs[..]));
         }
 
         let subpats = self.create_subpatterns(cx, paths, mutbl);
@@ -1449,7 +1455,8 @@ impl<'a> TraitDef<'a> {
         // struct_type is definitely not Unknown, since struct_def.fields
         // must be nonempty to reach here
         let pattern = if struct_type == Record {
-            let field_pats = subpats.into_iter().zip(ident_expr.iter()).map(|(pat, &(_, id, _))| {
+            let field_pats = subpats.into_iter().zip(ident_expr.iter())
+                                    .map(|(pat, &(_, id, _, _))| {
                 // id is guaranteed to be Some
                 codemap::Spanned {
                     span: pat.span,
@@ -1467,10 +1474,10 @@ impl<'a> TraitDef<'a> {
     fn create_enum_variant_pattern(&self,
                                    cx: &mut ExtCtxt,
                                    enum_ident: ast::Ident,
-                                   variant: &ast::Variant,
+                                   variant: &'a ast::Variant,
                                    prefix: &str,
                                    mutbl: ast::Mutability)
-        -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>)>) {
+        -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
         let variant_ident = variant.node.name;
         let variant_path = cx.path(variant.span, vec![enum_ident, variant_ident]);
         match variant.node.kind {
@@ -1480,7 +1487,7 @@ impl<'a> TraitDef<'a> {
                 }
 
                 let mut paths = Vec::new();
-                let mut ident_expr = Vec::new();
+                let mut ident_expr: Vec<(_, _, _, &'a [ast::Attribute])> = Vec::new();
                 for (i, va) in variant_args.iter().enumerate() {
                     let sp = self.set_expn_info(cx, va.ty.span);
                     let ident = cx.ident_of(&format!("{}_{}", prefix, i));
@@ -1488,7 +1495,7 @@ impl<'a> TraitDef<'a> {
                     paths.push(path1);
                     let expr_path = cx.expr_path(cx.path_ident(sp, ident));
                     let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path)));
-                    ident_expr.push((sp, None, val));
+                    ident_expr.push((sp, None, val, &[]));
                 }
 
                 let subpats = self.create_subpatterns(cx, paths, mutbl);
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index b8a79b0658d..476ab0fbf11 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -934,9 +934,10 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
                     let fm = fresh_mark();
                     let marked_before = mark_tts(&tts[..], fm);
                     let mac_span = fld.cx.original_span();
-                    let expanded = match expander.expand(fld.cx,
-                                        mac_span,
-                                        &marked_before[..]).make_pat() {
+                    let pat = expander.expand(fld.cx,
+                                              mac_span,
+                                              &marked_before[..]).make_pat();
+                    let expanded = match pat {
                         Some(e) => e,
                         None => {
                             fld.cx.span_err(
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 275400009f5..330fe86deeb 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -27,6 +27,7 @@
 
 #![feature(associated_consts)]
 #![feature(collections)]
+#![feature(collections_drain)]
 #![feature(core)]
 #![feature(libc)]
 #![feature(rustc_private)]
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5f76c214927..eb1c338ac85 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -88,7 +88,6 @@ use std::slice;
 
 bitflags! {
     flags Restrictions: u8 {
-        const UNRESTRICTED                  = 0,
         const RESTRICTION_STMT_EXPR         = 1 << 0,
         const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
     }
@@ -339,7 +338,7 @@ impl<'a> Parser<'a> {
             buffer_start: 0,
             buffer_end: 0,
             tokens_consumed: 0,
-            restrictions: Restrictions::UNRESTRICTED,
+            restrictions: Restrictions::empty(),
             quote_depth: 0,
             obsolete_set: HashSet::new(),
             mod_path_stack: Vec::new(),
@@ -2991,7 +2990,7 @@ impl<'a> Parser<'a> {
 
     /// Parse an expression
     pub fn parse_expr_nopanic(&mut self) -> PResult<P<Expr>> {
-        return self.parse_expr_res(Restrictions::UNRESTRICTED);
+        self.parse_expr_res(Restrictions::empty())
     }
 
     /// Parse an expression, subject to the given restrictions
@@ -4775,7 +4774,7 @@ impl<'a> Parser<'a> {
         return self.parse_single_struct_field(Inherited, attrs);
     }
 
-    /// Parse visibility: PUB, PRIV, or nothing
+    /// Parse visibility: PUB or nothing
     fn parse_visibility(&mut self) -> PResult<Visibility> {
         if try!(self.eat_keyword(keywords::Pub)) { Ok(Public) }
         else { Ok(Inherited) }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 0106de913bb..53ed4f351d3 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -601,7 +601,7 @@ pub type IdentInterner = StrInterner;
 
 // if an interner exists in TLS, return it. Otherwise, prepare a
 // fresh one.
-// FIXME(eddyb) #8726 This should probably use a task-local reference.
+// FIXME(eddyb) #8726 This should probably use a thread-local reference.
 pub fn get_ident_interner() -> Rc<IdentInterner> {
     thread_local!(static KEY: Rc<::parse::token::IdentInterner> = {
         Rc::new(mk_fresh_ident_interner())
@@ -615,14 +615,14 @@ pub fn reset_ident_interner() {
     interner.reset(mk_fresh_ident_interner());
 }
 
-/// Represents a string stored in the task-local interner. Because the
-/// interner lives for the life of the task, this can be safely treated as an
-/// immortal string, as long as it never crosses between tasks.
+/// Represents a string stored in the thread-local interner. Because the
+/// interner lives for the life of the thread, this can be safely treated as an
+/// immortal string, as long as it never crosses between threads.
 ///
 /// FIXME(pcwalton): You must be careful about what you do in the destructors
 /// of objects stored in TLS, because they may run after the interner is
 /// destroyed. In particular, they must not access string contents. This can
-/// be fixed in the future by just leaking all strings until task death
+/// be fixed in the future by just leaking all strings until thread death
 /// somehow.
 #[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
 pub struct InternedString {
@@ -697,14 +697,14 @@ impl Encodable for InternedString {
     }
 }
 
-/// Returns the string contents of a name, using the task-local interner.
+/// Returns the string contents of a name, using the thread-local interner.
 #[inline]
 pub fn get_name(name: ast::Name) -> InternedString {
     let interner = get_ident_interner();
     InternedString::new_from_rc_str(interner.get(name))
 }
 
-/// Returns the string contents of an identifier, using the task-local
+/// Returns the string contents of an identifier, using the thread-local
 /// interner.
 #[inline]
 pub fn get_ident(ident: ast::Ident) -> InternedString {
@@ -712,7 +712,7 @@ pub fn get_ident(ident: ast::Ident) -> InternedString {
 }
 
 /// Interns and returns the string contents of an identifier, using the
-/// task-local interner.
+/// thread-local interner.
 #[inline]
 pub fn intern_and_get_ident(s: &str) -> InternedString {
     get_name(intern(s))
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 828a334a40f..5a002dd790f 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -902,10 +902,10 @@ impl<'a> State<'a> {
                 try!(self.print_generics(params));
                 try!(self.end()); // end the inner ibox
 
+                try!(self.print_where_clause(&params.where_clause));
                 try!(space(&mut self.s));
                 try!(self.word_space("="));
                 try!(self.print_type(&**ty));
-                try!(self.print_where_clause(&params.where_clause));
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end the outer ibox
             }
diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs
index d016eb39239..929f2a6abd6 100644
--- a/src/libsyntax/util/parser_testing.rs
+++ b/src/libsyntax/util/parser_testing.rs
@@ -73,7 +73,11 @@ pub fn string_to_stmt(source_str : String) -> P<ast::Stmt> {
 /// Parse a string, return a pat. Uses "irrefutable"... which doesn't
 /// (currently) affect parsing.
 pub fn string_to_pat(source_str: String) -> P<ast::Pat> {
-    string_to_parser(&new_parse_sess(), source_str).parse_pat()
+    // Binding `sess` and `parser` works around dropck-injected
+    // region-inference issues; see #25212, #22323, #22321.
+    let sess = new_parse_sess();
+    let mut parser = string_to_parser(&sess, source_str);
+    parser.parse_pat()
 }
 
 /// Convert a vector of strings to a vector of ast::Ident's