about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/diagnostics.rs15
-rw-r--r--src/librustc/hir/intravisit.rs14
-rw-r--r--src/librustc/hir/lowering.rs98
-rw-r--r--src/librustc/hir/mod.rs95
-rw-r--r--src/librustc/hir/print.rs90
-rw-r--r--src/librustc/ich/impls_hir.rs16
-rw-r--r--src/librustc/middle/resolve_lifetime.rs23
-rw-r--r--src/librustc_driver/driver.rs8
-rw-r--r--src/librustc_passes/ast_validation.rs8
-rw-r--r--src/librustc_typeck/astconv.rs164
-rw-r--r--src/librustc_typeck/check/method/confirm.rs13
-rw-r--r--src/librustc_typeck/check/mod.rs37
-rw-r--r--src/librustc_typeck/diagnostics.rs55
-rw-r--r--src/librustdoc/clean/mod.rs37
-rw-r--r--src/test/compile-fail/associated-types-eq-expr-path.rs2
-rw-r--r--src/test/compile-fail/issue-43431.rs24
-rw-r--r--src/test/compile-fail/method-call-type-binding.rs2
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs1
18 files changed, 264 insertions, 438 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 34d31028385..412759e1142 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -687,6 +687,21 @@ attributes:
 See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html
 "##,
 
+E0214: r##"
+A generic type was described using parentheses rather than angle brackets. For
+example:
+
+```compile_fail,E0214
+fn main() {
+    let v: Vec(&str) = vec!["foo"];
+}
+```
+
+This is not currently supported: `v` should be defined as `Vec<&str>`.
+Parentheses are currently only used with generic types when defining parameters
+for `Fn`-family traits.
+"##,
+
 E0261: r##"
 When using a lifetime like `'a` in a type, it must be declared before being
 used.
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 2a0c76d99bf..483885b3d23 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -617,17 +617,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
                                                 _path_span: Span,
                                                 path_parameters: &'v PathParameters) {
-    match *path_parameters {
-        AngleBracketedParameters(ref data) => {
-            walk_list!(visitor, visit_ty, &data.types);
-            walk_list!(visitor, visit_lifetime, &data.lifetimes);
-            walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
-        }
-        ParenthesizedParameters(ref data) => {
-            walk_list!(visitor, visit_ty, &data.inputs);
-            walk_list!(visitor, visit_ty, &data.output);
-        }
-    }
+    walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes);
+    walk_list!(visitor, visit_ty, &path_parameters.types);
+    walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings);
 }
 
 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 58bb5b9580f..89ce52af77c 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -45,15 +45,16 @@ use hir::map::{Definitions, DefKey, REGULAR_SPACE};
 use hir::map::definitions::DefPathData;
 use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX};
 use hir::def::{Def, PathResolution};
+use lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
 use rustc_data_structures::indexed_vec::IndexVec;
 use session::Session;
+use util::common::FN_OUTPUT_NAME;
 use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
 
 use std::collections::BTreeMap;
 use std::fmt::Debug;
 use std::iter;
 use std::mem;
-
 use syntax::attr;
 use syntax::ast::*;
 use syntax::errors;
@@ -160,6 +161,12 @@ struct LoweredNodeId {
     hir_id: hir::HirId,
 }
 
+enum ParenthesizedGenericArgs {
+    Ok,
+    Warn,
+    Err,
+}
+
 impl<'a> LoweringContext<'a> {
     fn lower_crate(mut self, c: &Crate) -> hir::Crate {
         /// Full-crate AST visitor that inserts into a fresh
@@ -749,6 +756,21 @@ impl<'a> LoweringContext<'a> {
                     Def::Trait(def_id) if i + 1 == proj_start => Some(def_id),
                     _ => None
                 };
+                let parenthesized_generic_args = match resolution.base_def() {
+                    // `a::b::Trait(Args)`
+                    Def::Trait(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Ok,
+                    // `a::b::Trait(Args)::TraitItem`
+                    Def::Method(..) |
+                    Def::AssociatedConst(..) |
+                    Def::AssociatedTy(..) if i + 2 == proj_start => ParenthesizedGenericArgs::Ok,
+                    // Avoid duplicated errors
+                    Def::Err => ParenthesizedGenericArgs::Ok,
+                    // An error
+                    Def::Struct(..) | Def::Enum(..) | Def::Union(..) | Def::TyAlias(..) |
+                    Def::Variant(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Err,
+                    // A warning for now, for compatibility reasons
+                    _ => ParenthesizedGenericArgs::Warn,
+                };
 
                 let num_lifetimes = type_def_id.map_or(0, |def_id| {
                     if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
@@ -759,7 +781,8 @@ impl<'a> LoweringContext<'a> {
                     self.type_def_lifetime_params.insert(def_id, n);
                     n
                 });
-                self.lower_path_segment(p.span, segment, param_mode, num_lifetimes)
+                self.lower_path_segment(p.span, segment, param_mode, num_lifetimes,
+                                        parenthesized_generic_args)
             }).collect(),
             span: p.span,
         });
@@ -794,7 +817,8 @@ impl<'a> LoweringContext<'a> {
         //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
         // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
         for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
-            let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0));
+            let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0,
+                                                    ParenthesizedGenericArgs::Warn));
             let qpath = hir::QPath::TypeRelative(ty, segment);
 
             // It's finished, return the extension of the right node type.
@@ -827,7 +851,8 @@ impl<'a> LoweringContext<'a> {
         hir::Path {
             def: self.expect_full_def(id),
             segments: segments.map(|segment| {
-                self.lower_path_segment(p.span, segment, param_mode, 0)
+                self.lower_path_segment(p.span, segment, param_mode, 0,
+                                        ParenthesizedGenericArgs::Err)
             }).chain(name.map(|name| {
                 hir::PathSegment {
                     name,
@@ -851,29 +876,37 @@ impl<'a> LoweringContext<'a> {
                           path_span: Span,
                           segment: &PathSegment,
                           param_mode: ParamMode,
-                          expected_lifetimes: usize)
+                          expected_lifetimes: usize,
+                          parenthesized_generic_args: ParenthesizedGenericArgs)
                           -> hir::PathSegment {
         let mut parameters = if let Some(ref parameters) = segment.parameters {
+            let msg = "parenthesized parameters may only be used with a trait";
             match **parameters {
                 PathParameters::AngleBracketed(ref data) => {
-                    let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
-                    hir::AngleBracketedParameters(data)
+                    self.lower_angle_bracketed_parameter_data(data, param_mode)
                 }
-                PathParameters::Parenthesized(ref data) => {
-                    hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
+                PathParameters::Parenthesized(ref data) => match parenthesized_generic_args {
+                    ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
+                    ParenthesizedGenericArgs::Warn => {
+                        self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+                                              CRATE_NODE_ID, data.span, msg.into());
+                        hir::PathParameters::none()
+                    }
+                    ParenthesizedGenericArgs::Err => {
+                        struct_span_err!(self.sess, data.span, E0214, "{}", msg)
+                            .span_label(data.span, "only traits may use parentheses").emit();
+                        hir::PathParameters::none()
+                    }
                 }
             }
         } else {
-            let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
-            hir::AngleBracketedParameters(data)
+            self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode)
         };
 
-        if let hir::AngleBracketedParameters(ref mut data) = parameters {
-            if data.lifetimes.is_empty() {
-                data.lifetimes = (0..expected_lifetimes).map(|_| {
-                    self.elided_lifetime(path_span)
-                }).collect();
-            }
+        if !parameters.parenthesized && parameters.lifetimes.is_empty() {
+            parameters.lifetimes = (0..expected_lifetimes).map(|_| {
+                self.elided_lifetime(path_span)
+            }).collect();
         }
 
         hir::PathSegment {
@@ -885,24 +918,38 @@ impl<'a> LoweringContext<'a> {
     fn lower_angle_bracketed_parameter_data(&mut self,
                                             data: &AngleBracketedParameterData,
                                             param_mode: ParamMode)
-                                            -> hir::AngleBracketedParameterData {
+                                            -> hir::PathParameters {
         let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
-        hir::AngleBracketedParameterData {
+        hir::PathParameters {
             lifetimes: self.lower_lifetimes(lifetimes),
             types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
             infer_types: types.is_empty() && param_mode == ParamMode::Optional,
             bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
+            parenthesized: false,
         }
     }
 
     fn lower_parenthesized_parameter_data(&mut self,
                                           data: &ParenthesizedParameterData)
-                                          -> hir::ParenthesizedParameterData {
+                                          -> hir::PathParameters {
         let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
-        hir::ParenthesizedParameterData {
-            inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
-            output: output.as_ref().map(|ty| self.lower_ty(ty)),
-            span,
+        let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect();
+        let mk_tup = |this: &mut Self, tys, span| {
+            P(hir::Ty { node: hir::TyTup(tys), id: this.next_id().node_id, span })
+        };
+
+        hir::PathParameters {
+            lifetimes: hir::HirVec::new(),
+            types: hir_vec![mk_tup(self, inputs, span)],
+            infer_types: false,
+            bindings: hir_vec![hir::TypeBinding {
+                id: self.next_id().node_id,
+                name: Symbol::intern(FN_OUTPUT_NAME),
+                ty: output.as_ref().map(|ty| self.lower_ty(&ty))
+                                   .unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)),
+                span: output.as_ref().map_or(span, |ty| ty.span),
+            }],
+            parenthesized: true,
         }
     }
 
@@ -1877,7 +1924,8 @@ impl<'a> LoweringContext<'a> {
                 hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
             }
             ExprKind::MethodCall(ref seg, ref args) => {
-                let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0);
+                let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0,
+                                                      ParenthesizedGenericArgs::Err);
                 let args = args.iter().map(|x| self.lower_expr(x)).collect();
                 hir::ExprMethodCall(hir_seg, seg.span, args)
             }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 400f46d66f8..01f5d268815 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -26,7 +26,6 @@ pub use self::TyParamBound::*;
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
 pub use self::Visibility::{Public, Inherited};
-pub use self::PathParameters::*;
 
 use hir::def::Def;
 use hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
@@ -227,65 +226,7 @@ impl PathSegment {
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum PathParameters {
-    /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
-    AngleBracketedParameters(AngleBracketedParameterData),
-    /// The `(A,B)` and `C` in `Foo(A,B) -> C`
-    ParenthesizedParameters(ParenthesizedParameterData),
-}
-
-impl PathParameters {
-    pub fn none() -> PathParameters {
-        AngleBracketedParameters(AngleBracketedParameterData {
-            lifetimes: HirVec::new(),
-            types: HirVec::new(),
-            infer_types: true,
-            bindings: HirVec::new(),
-        })
-    }
-
-    /// Returns the types that the user wrote. Note that these do not necessarily map to the type
-    /// parameters in the parenthesized case.
-    pub fn types(&self) -> HirVec<&P<Ty>> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.types.iter().collect()
-            }
-            ParenthesizedParameters(ref data) => {
-                data.inputs
-                    .iter()
-                    .chain(data.output.iter())
-                    .collect()
-            }
-        }
-    }
-
-    pub fn lifetimes(&self) -> HirVec<&Lifetime> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.lifetimes.iter().collect()
-            }
-            ParenthesizedParameters(_) => {
-                HirVec::new()
-            }
-        }
-    }
-
-    pub fn bindings(&self) -> HirVec<&TypeBinding> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.bindings.iter().collect()
-            }
-            ParenthesizedParameters(_) => {
-                HirVec::new()
-            }
-        }
-    }
-}
-
-/// A path like `Foo<'a, T>`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct AngleBracketedParameterData {
+pub struct PathParameters {
     /// The lifetime parameters for this path segment.
     pub lifetimes: HirVec<Lifetime>,
     /// The type parameters for this path segment, if present.
@@ -298,19 +239,33 @@ pub struct AngleBracketedParameterData {
     /// Bindings (equality constraints) on associated types, if present.
     /// E.g., `Foo<A=Bar>`.
     pub bindings: HirVec<TypeBinding>,
+    /// Were parameters written in parenthesized form `Fn(T) -> U`?
+    /// This is required mostly for pretty-printing and diagnostics,
+    /// but also for changing lifetime elision rules to be "function-like".
+    pub parenthesized: bool,
 }
 
-/// A path like `Foo(A,B) -> C`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct ParenthesizedParameterData {
-    /// Overall span
-    pub span: Span,
-
-    /// `(A,B)`
-    pub inputs: HirVec<P<Ty>>,
+impl PathParameters {
+    pub fn none() -> Self {
+        Self {
+            lifetimes: HirVec::new(),
+            types: HirVec::new(),
+            infer_types: true,
+            bindings: HirVec::new(),
+            parenthesized: false,
+        }
+    }
 
-    /// `C`
-    pub output: Option<P<Ty>>,
+    pub fn inputs(&self) -> &[P<Ty>] {
+        if self.parenthesized {
+            if let Some(ref ty) = self.types.get(0) {
+                if let TyTup(ref tys) = ty.node {
+                    return tys;
+                }
+            }
+        }
+        bug!("PathParameters::inputs: not a `Fn(T) -> U`");
+    }
 }
 
 /// The AST represents all type param bounds as types.
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index abfb00a24a1..876875bce4a 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1194,9 +1194,9 @@ impl<'a> State<'a> {
         self.print_expr(&args[0])?;
         self.s.word(".")?;
         self.print_name(segment.name)?;
-        if !segment.parameters.lifetimes().is_empty() ||
-                !segment.parameters.types().is_empty() ||
-                !segment.parameters.bindings().is_empty() {
+        if !segment.parameters.lifetimes.is_empty() ||
+                !segment.parameters.types.is_empty() ||
+                !segment.parameters.bindings.is_empty() {
             self.print_path_parameters(&segment.parameters, true)?;
         }
         self.print_call_post(base_args)
@@ -1581,61 +1581,55 @@ impl<'a> State<'a> {
                              parameters: &hir::PathParameters,
                              colons_before_params: bool)
                              -> io::Result<()> {
-        match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                let start = if colons_before_params { "::<" } else { "<" };
-                let empty = Cell::new(true);
-                let start_or_comma = |this: &mut Self| {
-                    if empty.get() {
-                        empty.set(false);
-                        this.s.word(start)
-                    } else {
-                        this.word_space(",")
-                    }
-                };
+        if parameters.parenthesized {
+            self.s.word("(")?;
+            self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?;
+            self.s.word(")")?;
 
-                if !data.lifetimes.iter().all(|lt| lt.is_elided()) {
-                    for lifetime in &data.lifetimes {
-                        start_or_comma(self)?;
-                        self.print_lifetime(lifetime)?;
-                    }
-                }
-
-                if !data.types.is_empty() {
-                    start_or_comma(self)?;
-                    self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?;
+            self.space_if_not_bol()?;
+            self.word_space("->")?;
+            self.print_type(&parameters.bindings[0].ty)?;
+        } else {
+            let start = if colons_before_params { "::<" } else { "<" };
+            let empty = Cell::new(true);
+            let start_or_comma = |this: &mut Self| {
+                if empty.get() {
+                    empty.set(false);
+                    this.s.word(start)
+                } else {
+                    this.word_space(",")
                 }
+            };
 
-                // FIXME(eddyb) This would leak into error messages, e.g.:
-                // "non-exhaustive patterns: `Some::<..>(_)` not covered".
-                if data.infer_types && false {
+            if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) {
+                for lifetime in &parameters.lifetimes {
                     start_or_comma(self)?;
-                    self.s.word("..")?;
+                    self.print_lifetime(lifetime)?;
                 }
+            }
 
-                for binding in data.bindings.iter() {
-                    start_or_comma(self)?;
-                    self.print_name(binding.name)?;
-                    self.s.space()?;
-                    self.word_space("=")?;
-                    self.print_type(&binding.ty)?;
-                }
+            if !parameters.types.is_empty() {
+                start_or_comma(self)?;
+                self.commasep(Inconsistent, &parameters.types, |s, ty| s.print_type(&ty))?;
+            }
 
-                if !empty.get() {
-                    self.s.word(">")?
-                }
+            // FIXME(eddyb) This would leak into error messages, e.g.:
+            // "non-exhaustive patterns: `Some::<..>(_)` not covered".
+            if parameters.infer_types && false {
+                start_or_comma(self)?;
+                self.s.word("..")?;
             }
 
-            hir::ParenthesizedParameters(ref data) => {
-                self.s.word("(")?;
-                self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?;
-                self.s.word(")")?;
+            for binding in parameters.bindings.iter() {
+                start_or_comma(self)?;
+                self.print_name(binding.name)?;
+                self.s.space()?;
+                self.word_space("=")?;
+                self.print_type(&binding.ty)?;
+            }
 
-                if let Some(ref ty) = data.output {
-                    self.space_if_not_bol()?;
-                    self.word_space("->")?;
-                    self.print_type(&ty)?;
-                }
+            if !empty.get() {
+                self.s.word(">")?
             }
         }
 
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 4c70816c0b8..c5222c2d6cb 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -133,22 +133,12 @@ impl_stable_hash_for!(struct hir::PathSegment {
     parameters
 });
 
-impl_stable_hash_for!(enum hir::PathParameters {
-    AngleBracketedParameters(data),
-    ParenthesizedParameters(data)
-});
-
-impl_stable_hash_for!(struct hir::AngleBracketedParameterData {
+impl_stable_hash_for!(struct hir::PathParameters {
     lifetimes,
     types,
     infer_types,
-    bindings
-});
-
-impl_stable_hash_for!(struct hir::ParenthesizedParameterData {
-    span,
-    inputs,
-    output
+    bindings,
+    parenthesized
 });
 
 impl_stable_hash_for!(enum hir::TyParamBound {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 12362c8d3bf..a8e98e53db3 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -915,18 +915,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                                 def: Def,
                                 depth: usize,
                                 params: &'tcx hir::PathParameters) {
-        let data = match *params {
-            hir::ParenthesizedParameters(ref data) => {
-                self.visit_fn_like_elision(&data.inputs, data.output.as_ref());
-                return;
-            }
-            hir::AngleBracketedParameters(ref data) => data
-        };
+        if params.parenthesized {
+            self.visit_fn_like_elision(params.inputs(), Some(&params.bindings[0].ty));
+            return;
+        }
 
-        if data.lifetimes.iter().all(|l| l.is_elided()) {
-            self.resolve_elided_lifetimes(&data.lifetimes);
+        if params.lifetimes.iter().all(|l| l.is_elided()) {
+            self.resolve_elided_lifetimes(&params.lifetimes);
         } else {
-            for l in &data.lifetimes { self.visit_lifetime(l); }
+            for l in &params.lifetimes { self.visit_lifetime(l); }
         }
 
         // Figure out if this is a type/trait segment,
@@ -995,13 +992,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                             Some(Region::Static)
                         }
                     }
-                    Set1::One(r) => r.subst(&data.lifetimes, map),
+                    Set1::One(r) => r.subst(&params.lifetimes, map),
                     Set1::Many => None
                 }
             }).collect()
         });
 
-        for (i, ty) in data.types.iter().enumerate() {
+        for (i, ty) in params.types.iter().enumerate() {
             if let Some(&lt) = object_lifetime_defaults.get(i) {
                 let scope = Scope::ObjectLifetimeDefault {
                     lifetime: lt,
@@ -1013,7 +1010,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
         }
 
-        for b in &data.bindings { self.visit_assoc_type_binding(b); }
+        for b in &params.bindings { self.visit_assoc_type_binding(b); }
     }
 
     fn visit_fn_like_elision(&mut self, inputs: &'tcx [P<hir::Ty>],
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 246fc7fc524..882d4e16884 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -833,10 +833,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         })
     })?;
 
-    time(time_passes,
-         "early lint checks",
-         || lint::check_ast_crate(sess, &krate));
-
     // Lower ast -> hir.
     let hir_forest = time(time_passes, "lowering ast -> hir", || {
         let hir_crate = lower_crate(sess, &krate, &mut resolver);
@@ -848,6 +844,10 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         hir_map::Forest::new(hir_crate, &sess.dep_graph)
     });
 
+    time(time_passes,
+         "early lint checks",
+         || lint::check_ast_crate(sess, &krate));
+
     // Discard hygiene data, which isn't required after lowering to HIR.
     if !keep_hygiene_data(sess) {
         syntax::ext::hygiene::clear_markings();
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index b22f8112d7a..ffe444933a3 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -140,14 +140,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             ExprKind::Continue(Some(ident)) => {
                 self.check_label(ident.node, ident.span);
             }
-            ExprKind::MethodCall(ref segment, ..) => {
-                if let Some(ref params) = segment.parameters {
-                    if let PathParameters::Parenthesized(..) = **params {
-                        self.err_handler().span_err(expr.span,
-                            "parenthesized parameters cannot be used on method calls");
-                    }
-                }
-            }
             _ => {}
         }
 
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 32fa0534db6..ee1e6bd950f 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -22,16 +22,14 @@ use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
-use rustc::lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
 use rustc_back::slice;
 use require_c_abi_if_variadic;
-use util::common::{ErrorReported, FN_OUTPUT_NAME};
+use util::common::ErrorReported;
 use util::nodemap::FxHashSet;
 
 use std::iter;
 use syntax::{abi, ast};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub trait AstConv<'gcx, 'tcx> {
@@ -152,21 +150,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         item_segment: &hir::PathSegment)
         -> &'tcx Substs<'tcx>
     {
-        let tcx = self.tcx();
-
-        match item_segment.parameters {
-            hir::AngleBracketedParameters(_) => {}
-            hir::ParenthesizedParameters(..) => {
-                self.prohibit_parenthesized_params(item_segment, true);
-
-                return Substs::for_item(tcx, def_id, |_, _| {
-                    tcx.types.re_static
-                }, |_, _| {
-                    tcx.types.err
-                });
-            }
-        }
-
         let (substs, assoc_bindings) =
             self.create_substs_for_ast_path(span,
                                             def_id,
@@ -196,19 +179,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                parameters={:?})",
                def_id, self_ty, parameters);
 
-        let (lifetimes, num_types_provided, infer_types) = match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                (&data.lifetimes[..], data.types.len(), data.infer_types)
-            }
-            hir::ParenthesizedParameters(_) => (&[][..], 1, false)
-        };
-
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
         let decl_generics = tcx.generics_of(def_id);
+        let num_types_provided = parameters.types.len();
         let expected_num_region_params = decl_generics.regions.len();
-        let supplied_num_region_params = lifetimes.len();
+        let supplied_num_region_params = parameters.lifetimes.len();
         if expected_num_region_params != supplied_num_region_params {
             report_lifetime_number_error(tcx, span,
                                          supplied_num_region_params,
@@ -220,7 +197,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
         // Check the number of type parameters supplied by the user.
         let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
-        if !infer_types || num_types_provided > ty_param_defs.len() {
+        if !parameters.infer_types || num_types_provided > ty_param_defs.len() {
             check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
         }
 
@@ -237,10 +214,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             false
         };
 
-        let mut output_assoc_binding = None;
         let substs = Substs::for_item(tcx, def_id, |def, _| {
             let i = def.index as usize - self_ty.is_some() as usize;
-            if let Some(lifetime) = lifetimes.get(i) {
+            if let Some(lifetime) = parameters.lifetimes.get(i) {
                 self.ast_region_to_region(lifetime, Some(def))
             } else {
                 tcx.types.re_static
@@ -256,18 +232,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             let i = i - self_ty.is_some() as usize - decl_generics.regions.len();
             if i < num_types_provided {
                 // A provided type parameter.
-                match *parameters {
-                    hir::AngleBracketedParameters(ref data) => {
-                        self.ast_ty_to_ty(&data.types[i])
-                    }
-                    hir::ParenthesizedParameters(ref data) => {
-                        assert_eq!(i, 0);
-                        let (ty, assoc) = self.convert_parenthesized_parameters(data);
-                        output_assoc_binding = Some(assoc);
-                        ty
-                    }
-                }
-            } else if infer_types {
+                self.ast_ty_to_ty(&parameters.types[i])
+            } else if parameters.infer_types {
                 // No type parameters were provided, we can infer all.
                 let ty_var = if !default_needs_object_self(def) {
                     self.ty_infer_for_def(def, substs, span)
@@ -306,24 +272,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             }
         });
 
-        let assoc_bindings = match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                data.bindings.iter().map(|b| {
-                    ConvertedBinding {
-                        item_name: b.name,
-                        ty: self.ast_ty_to_ty(&b.ty),
-                        span: b.span
-                    }
-                }).collect()
-            }
-            hir::ParenthesizedParameters(ref data) => {
-                vec![output_assoc_binding.unwrap_or_else(|| {
-                    // This is an error condition, but we should
-                    // get the associated type binding anyway.
-                    self.convert_parenthesized_parameters(data).1
-                })]
+        let assoc_bindings = parameters.bindings.iter().map(|binding| {
+            ConvertedBinding {
+                item_name: binding.name,
+                ty: self.ast_ty_to_ty(&binding.ty),
+                span: binding.span,
             }
-        };
+        }).collect();
 
         debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
                decl_generics, self_ty, substs);
@@ -331,32 +286,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         (substs, assoc_bindings)
     }
 
-    fn convert_parenthesized_parameters(&self,
-                                        data: &hir::ParenthesizedParameterData)
-                                        -> (Ty<'tcx>, ConvertedBinding<'tcx>)
-    {
-        let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
-            self.ast_ty_to_ty(a_t)
-        }));
-
-        let (output, output_span) = match data.output {
-            Some(ref output_ty) => {
-                (self.ast_ty_to_ty(output_ty), output_ty.span)
-            }
-            None => {
-                (self.tcx().mk_nil(), data.span)
-            }
-        };
-
-        let output_binding = ConvertedBinding {
-            item_name: Symbol::intern(FN_OUTPUT_NAME),
-            ty: output,
-            span: output_span
-        };
-
-        (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding)
-    }
-
     /// Instantiates the path for the given trait reference, assuming that it's
     /// bound to a valid trait type. Returns the def_id for the defining trait.
     /// Fails if the type is a type other than a trait type.
@@ -453,29 +382,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
         let trait_def = self.tcx().trait_def(trait_def_id);
 
-        match trait_segment.parameters {
-            hir::AngleBracketedParameters(_) => {
-                // For now, require that parenthetical notation be used
-                // only with `Fn()` etc.
-                if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
-                    emit_feature_err(&self.tcx().sess.parse_sess,
-                                     "unboxed_closures", span, GateIssue::Language,
-                                     "\
-                        the precise format of `Fn`-family traits' \
-                        type parameters is subject to change. \
-                        Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
-                }
-            }
-            hir::ParenthesizedParameters(_) => {
-                // For now, require that parenthetical notation be used
-                // only with `Fn()` etc.
-                if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
-                    emit_feature_err(&self.tcx().sess.parse_sess,
-                                     "unboxed_closures", span, GateIssue::Language,
-                                     "\
-                        parenthetical notation is only stable when used with `Fn`-family traits");
-                }
-            }
+        if !self.tcx().sess.features.borrow().unboxed_closures &&
+           trait_segment.parameters.parenthesized != trait_def.paren_sugar {
+            // For now, require that parenthetical notation be used only with `Fn()` etc.
+            let msg = if trait_def.paren_sugar {
+                "the precise format of `Fn`-family traits' type parameters is subject to change. \
+                 Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead"
+            } else {
+                "parenthetical notation is only stable when used with `Fn`-family traits"
+            };
+            emit_feature_err(&self.tcx().sess.parse_sess, "unboxed_closures",
+                             span, GateIssue::Language, msg);
         }
 
         self.create_substs_for_ast_path(span,
@@ -951,18 +868,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
     pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
         for segment in segments {
-            if let hir::ParenthesizedParameters(_) = segment.parameters {
-                self.prohibit_parenthesized_params(segment, false);
-                break;
-            }
-            for typ in segment.parameters.types() {
+            for typ in &segment.parameters.types {
                 struct_span_err!(self.tcx().sess, typ.span, E0109,
                                  "type parameters are not allowed on this type")
                     .span_label(typ.span, "type parameter not allowed")
                     .emit();
                 break;
             }
-            for lifetime in segment.parameters.lifetimes() {
+            for lifetime in &segment.parameters.lifetimes {
                 struct_span_err!(self.tcx().sess, lifetime.span, E0110,
                                  "lifetime parameters are not allowed on this type")
                     .span_label(lifetime.span,
@@ -970,28 +883,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     .emit();
                 break;
             }
-            for binding in segment.parameters.bindings() {
+            for binding in &segment.parameters.bindings {
                 self.prohibit_projection(binding.span);
                 break;
             }
         }
     }
 
-    pub fn prohibit_parenthesized_params(&self, segment: &hir::PathSegment, emit_error: bool) {
-        if let hir::ParenthesizedParameters(ref data) = segment.parameters {
-            if emit_error {
-                struct_span_err!(self.tcx().sess, data.span, E0214,
-                          "parenthesized parameters may only be used with a trait")
-                    .span_label(data.span, "only traits may use parentheses")
-                    .emit();
-            } else {
-                let msg = "parenthesized parameters may only be used with a trait";
-                self.tcx().lint_node(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
-                                     ast::CRATE_NODE_ID, data.span, msg);
-            }
-        }
-    }
-
     pub fn prohibit_projection(&self, span: Span) {
         let mut err = struct_span_err!(self.tcx().sess, span, E0229,
                                        "associated type bindings are not allowed here");
@@ -1392,13 +1290,13 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     Some(trait_did) == tcx.lang_items.sync_trait() {
                     let segments = &bound.trait_ref.path.segments;
                     let parameters = &segments[segments.len() - 1].parameters;
-                    if !parameters.types().is_empty() {
+                    if !parameters.types.is_empty() {
                         check_type_argument_count(tcx, bound.trait_ref.path.span,
-                                                  parameters.types().len(), &[]);
+                                                  parameters.types.len(), &[]);
                     }
-                    if !parameters.lifetimes().is_empty() {
+                    if !parameters.lifetimes.is_empty() {
                         report_lifetime_number_error(tcx, bound.trait_ref.path.span,
-                                                     parameters.lifetimes().len(), 0);
+                                                     parameters.lifetimes.len(), 0);
                     }
                     true
                 } else {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index cd2adfb7ab0..db383b6305b 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -311,17 +311,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
-        let (supplied_types, supplied_lifetimes) = match segment.parameters {
-            hir::AngleBracketedParameters(ref data) => (&data.types, &data.lifetimes),
-            _ => bug!("unexpected generic arguments: {:?}", segment.parameters),
-        };
         assert_eq!(method_generics.parent_count(), parent_substs.len());
+        let provided = &segment.parameters;
         Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
             let i = def.index as usize;
             if i < parent_substs.len() {
                 parent_substs.region_at(i)
-            } else if let Some(lifetime) =
-                    supplied_lifetimes.get(i - parent_substs.len()) {
+            } else if let Some(lifetime)
+                    = provided.lifetimes.get(i - parent_substs.len()) {
                 AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
             } else {
                 self.region_var_for_def(self.span, def)
@@ -330,8 +327,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             let i = def.index as usize;
             if i < parent_substs.len() {
                 parent_substs.type_at(i)
-            } else if let Some(ast_ty) =
-                    supplied_types.get(i - parent_substs.len() - method_generics.regions.len()) {
+            } else if let Some(ast_ty)
+                    = provided.types.get(i - parent_substs.len() - method_generics.regions.len()) {
                 self.to_ty(ast_ty)
             } else {
                 self.type_var_for_def(self.span, def, cur_substs)
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index dbdaabfee8a..955171203e1 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4620,11 +4620,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 i -= fn_start;
                 fn_segment
             };
-            let lifetimes = match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..],
-                Some(&hir::ParenthesizedParameters(_)) => bug!(),
-                None => &[]
-            };
+            let lifetimes = segment.map_or(&[][..], |(s, _)| &s.parameters.lifetimes[..]);
 
             if let Some(lifetime) = lifetimes.get(i) {
                 AstConv::ast_region_to_region(self, lifetime, Some(def))
@@ -4647,13 +4643,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 i -= fn_start;
                 fn_segment
             };
-            let (types, infer_types) = match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => {
-                    (&data.types[..], data.infer_types)
-                }
-                Some(&hir::ParenthesizedParameters(_)) => bug!(),
-                None => (&[][..], true)
-            };
+            let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
+                (&s.parameters.types[..], s.parameters.infer_types)
+            });
 
             // Skip over the lifetimes in the same segment.
             if let Some((_, generics)) = segment {
@@ -4727,19 +4719,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                   span: Span,
                                   segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
                                   is_method_call: bool) {
-        let (lifetimes, types, infer_types, bindings) = {
-            match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => {
-                    (&data.lifetimes[..], &data.types[..], data.infer_types, &data.bindings[..])
-                }
-                Some(&hir::ParenthesizedParameters(_)) => {
-                    AstConv::prohibit_parenthesized_params(self, &segment.as_ref().unwrap().0,
-                                                           false);
-                    (&[][..], &[][..], true, &[][..])
-                }
-                None => (&[][..], &[][..], true, &[][..])
-            }
-        };
+        let (lifetimes, types, infer_types, bindings) = segment.map_or(
+            (&[][..], &[][..], true, &[][..]),
+            |(s, _)| (&s.parameters.lifetimes[..], &s.parameters.types[..],
+                      s.parameters.infer_types, &s.parameters.bindings[..]));
         let infer_lifetimes = lifetimes.len() == 0;
 
         let count_lifetime_params = |n| {
@@ -4785,9 +4768,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
 
         if !bindings.is_empty() {
-            span_err!(self.tcx.sess, bindings[0].span, E0182,
-                      "unexpected binding of associated item in expression path \
-                       (only allowed in type paths)");
+            AstConv::prohibit_projection(self, bindings[0].span);
         }
 
         // Check provided lifetime parameters.
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index c74dc24ddc3..cb430efd950 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1636,45 +1636,6 @@ fn bar(foo: Foo) -> u32 {
 ```
 "##,
 
-E0182: r##"
-You bound an associated type in an expression path which is not
-allowed.
-
-Erroneous code example:
-
-```compile_fail,E0182
-trait Foo {
-    type A;
-    fn bar() -> isize;
-}
-
-impl Foo for isize {
-    type A = usize;
-    fn bar() -> isize { 42 }
-}
-
-// error: unexpected binding of associated item in expression path
-let x: isize = Foo::<A=usize>::bar();
-```
-
-To give a concrete type when using the Universal Function Call Syntax,
-use "Type as Trait". Example:
-
-```
-trait Foo {
-    type A;
-    fn bar() -> isize;
-}
-
-impl Foo for isize {
-    type A = usize;
-    fn bar() -> isize { 42 }
-}
-
-let x: isize = <isize as Foo>::bar(); // ok!
-```
-"##,
-
 E0184: r##"
 Explicitly implementing both Drop and Copy for a type is currently disallowed.
 This feature can make some sense in theory, but the current implementation is
@@ -2359,21 +2320,6 @@ impl Foo {
 "##,
      */
 
-E0214: r##"
-A generic type was described using parentheses rather than angle brackets. For
-example:
-
-```compile_fail,E0214
-fn main() {
-    let v: Vec(&str) = vec!["foo"];
-}
-```
-
-This is not currently supported: `v` should be defined as `Vec<&str>`.
-Parentheses are currently only used with generic types when defining parameters
-for `Fn`-family traits.
-"##,
-
 E0220: r##"
 You used an associated type which isn't defined in the trait.
 Erroneous code example:
@@ -4721,6 +4667,7 @@ register_diagnostics! {
 //  E0172, // non-trait found in a type sum, moved to resolve
 //  E0173, // manual implementations of unboxed closure traits are experimental
 //  E0174,
+//  E0182, // merged into E0229
     E0183,
 //  E0187, // can't infer the kind of the closure
 //  E0188, // can not cast an immutable reference to a mutable pointer
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f4aef8ab377..92b3180c5cb 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1794,16 +1794,14 @@ impl Clean<Type> for hir::Ty {
                     let mut lt_substs = FxHashMap();
                     for (i, ty_param) in generics.ty_params.iter().enumerate() {
                         let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
-                        if let Some(ty) = provided_params.types().get(i).cloned()
-                                                                        .cloned() {
+                        if let Some(ty) = provided_params.types.get(i).cloned() {
                             ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
                         } else if let Some(default) = ty_param.default.clone() {
                             ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
                         }
                     }
                     for (i, lt_param) in generics.lifetimes.iter().enumerate() {
-                        if let Some(lt) = provided_params.lifetimes().get(i).cloned()
-                                                                            .cloned() {
+                        if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
                             if !lt.is_elided() {
                                 lt_substs.insert(lt_param.lifetime.id, lt.clean(cx));
                             }
@@ -2314,24 +2312,21 @@ pub enum PathParameters {
 
 impl Clean<PathParameters> for hir::PathParameters {
     fn clean(&self, cx: &DocContext) -> PathParameters {
-        match *self {
-            hir::AngleBracketedParameters(ref data) => {
-                PathParameters::AngleBracketed {
-                    lifetimes: if data.lifetimes.iter().all(|lt| lt.is_elided()) {
-                        vec![]
-                    } else {
-                        data.lifetimes.clean(cx)
-                    },
-                    types: data.types.clean(cx),
-                    bindings: data.bindings.clean(cx),
-                }
+        if self.parenthesized {
+            let output = self.bindings[0].ty.clean(cx);
+            PathParameters::Parenthesized {
+                inputs: self.inputs().clean(cx),
+                output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
             }
-
-            hir::ParenthesizedParameters(ref data) => {
-                PathParameters::Parenthesized {
-                    inputs: data.inputs.clean(cx),
-                    output: data.output.clean(cx),
-                }
+        } else {
+            PathParameters::AngleBracketed {
+                lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
+                    vec![]
+                } else {
+                    self.lifetimes.clean(cx)
+                },
+                types: self.types.clean(cx),
+                bindings: self.bindings.clean(cx),
             }
         }
     }
diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs
index 1f9dfdb1847..847393ba2b8 100644
--- a/src/test/compile-fail/associated-types-eq-expr-path.rs
+++ b/src/test/compile-fail/associated-types-eq-expr-path.rs
@@ -22,5 +22,5 @@ impl Foo for isize {
 
 pub fn main() {
     let x: isize = Foo::<A=usize>::bar();
-    //~^ ERROR unexpected binding of associated item in expression path
+    //~^ ERROR associated type bindings are not allowed here
 }
diff --git a/src/test/compile-fail/issue-43431.rs b/src/test/compile-fail/issue-43431.rs
new file mode 100644
index 00000000000..e9f62152888
--- /dev/null
+++ b/src/test/compile-fail/issue-43431.rs
@@ -0,0 +1,24 @@
+// Copyright 2017 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.
+
+#![feature(fn_traits)]
+
+trait CallSingle<A, B> {
+    fn call(&self, a: A) -> B where Self: Fn(A) -> B;
+}
+
+impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F {
+    fn call(&self, a: A) -> B {
+        <Self as Fn(A) -> B>::call(self, (a,))
+        //~^ ERROR associated type bindings are not allowed here
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/method-call-type-binding.rs b/src/test/compile-fail/method-call-type-binding.rs
index 3ae878ed1cb..6c0793ee78f 100644
--- a/src/test/compile-fail/method-call-type-binding.rs
+++ b/src/test/compile-fail/method-call-type-binding.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    0.clone::<T = u8>(); //~ ERROR unexpected binding of associated item
+    0.clone::<T = u8>(); //~ ERROR associated type bindings are not allowed here
 }
diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
index fd6c8ad08d6..5fcde4facbe 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
@@ -16,6 +16,7 @@ struct Bar<A> {
 
 fn foo(b: Box<Bar()>) {
     //~^ ERROR parenthesized parameters may only be used with a trait
+    //~| ERROR the type placeholder `_` is not allowed within types on item signatures
 }
 
 fn main() { }