]> git.lizzy.rs Git - rust.git/commitdiff
rustc: encode the optionality of type parameters in HIR paths.
authorEduard Burtescu <edy.burt@gmail.com>
Mon, 17 Oct 2016 03:02:23 +0000 (06:02 +0300)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Mon, 28 Nov 2016 02:18:10 +0000 (04:18 +0200)
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/infer/error_reporting.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/mod.rs

index 5af7c18e1a1078f4c9cc14849f59b0691d8b01ba..264a5722bcd76ad7f8c4f079ee85550769c18c7f 100644 (file)
@@ -101,6 +101,14 @@ pub fn lower_crate(sess: &Session,
     }.lower_crate(krate)
 }
 
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum ParamMode {
+    /// Any path in a type context.
+    Explicit,
+    /// The `module::Type` in `module::Type::method` in an expression.
+    Optional
+}
+
 impl<'a> LoweringContext<'a> {
     fn lower_crate(&mut self, c: &Crate) -> hir::Crate {
         struct ItemLowerer<'lcx, 'interner: 'lcx> {
@@ -179,13 +187,14 @@ fn lower_view_path(&mut self, view_path: &ViewPath) -> P<hir::ViewPath> {
         P(Spanned {
             node: match view_path.node {
                 ViewPathSimple(ident, ref path) => {
-                    hir::ViewPathSimple(ident.name, self.lower_path(path))
+                    hir::ViewPathSimple(ident.name,
+                                        self.lower_path(path, None, ParamMode::Explicit))
                 }
                 ViewPathGlob(ref path) => {
-                    hir::ViewPathGlob(self.lower_path(path))
+                    hir::ViewPathGlob(self.lower_path(path, None, ParamMode::Explicit))
                 }
                 ViewPathList(ref path, ref path_list_idents) => {
-                    hir::ViewPathList(self.lower_path(path),
+                    hir::ViewPathList(self.lower_path(path, None, ParamMode::Explicit),
                                       path_list_idents.iter()
                                                       .map(|item| self.lower_path_list_item(item))
                                                       .collect())
@@ -256,7 +265,8 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
                             position: position,
                         }
                     });
-                    hir::TyPath(qself, self.lower_path(path))
+                    let path = self.lower_path(path, qself.as_ref(), ParamMode::Explicit);
+                    hir::TyPath(qself, path)
                 }
                 TyKind::ObjectSum(ref ty, ref bounds) => {
                     hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
@@ -298,38 +308,56 @@ fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
         }
     }
 
-    fn lower_path(&mut self, p: &Path) -> hir::Path {
+    fn lower_path(&mut self,
+                  p: &Path,
+                  qself: Option<&hir::QSelf>,
+                  param_mode: ParamMode)
+                  -> hir::Path {
         hir::Path {
             global: p.global,
-            segments: p.segments
-                       .iter()
-                       .map(|&PathSegment { identifier, ref parameters }| {
-                           hir::PathSegment {
-                               name: identifier.name,
-                               parameters: self.lower_path_parameters(parameters),
-                           }
-                       })
-                       .collect(),
+            segments: p.segments.iter().enumerate().map(|(i, segment)| {
+                let PathSegment { identifier, ref parameters } = *segment;
+                let param_mode = match (qself, param_mode) {
+                    (Some(qself), ParamMode::Optional) if i < qself.position => {
+                        // This segment is part of the trait path in a
+                        // qualified path - one of `a`, `b` or `Trait`
+                        // in `<X as a::b::Trait>::T::U::method`.
+                        ParamMode::Explicit
+                    }
+                    _ => param_mode
+                };
+                hir::PathSegment {
+                    name: identifier.name,
+                    parameters: self.lower_path_parameters(parameters, param_mode),
+                }
+            }).collect(),
             span: p.span,
         }
     }
 
-    fn lower_path_parameters(&mut self, path_parameters: &PathParameters) -> hir::PathParameters {
+    fn lower_path_parameters(&mut self,
+                             path_parameters: &PathParameters,
+                             param_mode: ParamMode)
+                             -> hir::PathParameters {
         match *path_parameters {
-            PathParameters::AngleBracketed(ref data) =>
-                hir::AngleBracketedParameters(self.lower_angle_bracketed_parameter_data(data)),
+            PathParameters::AngleBracketed(ref data) => {
+                let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
+                hir::AngleBracketedParameters(data)
+            }
             PathParameters::Parenthesized(ref data) =>
                 hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
         }
     }
 
     fn lower_angle_bracketed_parameter_data(&mut self,
-                                            data: &AngleBracketedParameterData)
+                                            data: &AngleBracketedParameterData,
+                                            param_mode: ParamMode)
                                             -> hir::AngleBracketedParameterData {
         let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
         hir::AngleBracketedParameterData {
             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(),
         }
     }
@@ -493,7 +521,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                                                           span}) => {
                 hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
                     id: id,
-                    path: self.lower_path(path),
+                    path: self.lower_path(path, None, ParamMode::Explicit),
                     ty: self.lower_ty(ty),
                     span: span,
                 })
@@ -523,7 +551,7 @@ fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
 
     fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
         hir::TraitRef {
-            path: self.lower_path(&p.path),
+            path: self.lower_path(&p.path, None, ParamMode::Explicit),
             ref_id: p.ref_id,
         }
     }
@@ -887,17 +915,19 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                 }
                 PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
                 PatKind::TupleStruct(ref path, ref pats, ddpos) => {
-                    hir::PatKind::TupleStruct(self.lower_path(path),
-                                        pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
+                    hir::PatKind::TupleStruct(self.lower_path(path, None, ParamMode::Optional),
+                                              pats.iter().map(|x| self.lower_pat(x)).collect(),
+                                              ddpos)
                 }
-                PatKind::Path(ref opt_qself, ref path) => {
-                    let opt_qself = opt_qself.as_ref().map(|qself| {
+                PatKind::Path(ref qself, ref path) => {
+                    let qself = qself.as_ref().map(|qself| {
                         hir::QSelf { ty: self.lower_ty(&qself.ty), position: qself.position }
                     });
-                    hir::PatKind::Path(opt_qself, self.lower_path(path))
+                    let path = self.lower_path(path, qself.as_ref(), ParamMode::Optional);
+                    hir::PatKind::Path(qself, path)
                 }
                 PatKind::Struct(ref pth, ref fields, etc) => {
-                    let pth = self.lower_path(pth);
+                    let pth = self.lower_path(pth, None, ParamMode::Optional);
                     let fs = fields.iter()
                                    .map(|f| {
                                        Spanned {
@@ -1236,13 +1266,14 @@ fn make_struct(this: &mut LoweringContext,
                     };
                 }
                 ExprKind::Path(ref qself, ref path) => {
-                    let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
+                    let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
                         hir::QSelf {
                             ty: self.lower_ty(ty),
                             position: position,
                         }
                     });
-                    hir::ExprPath(hir_qself, self.lower_path(path))
+                    let path = self.lower_path(path, qself.as_ref(), ParamMode::Optional);
+                    hir::ExprPath(qself, path)
                 }
                 ExprKind::Break(opt_ident, ref opt_expr) => {
                     hir::ExprBreak(self.lower_opt_sp_ident(opt_ident),
@@ -1275,7 +1306,7 @@ fn make_struct(this: &mut LoweringContext,
                     hir::ExprInlineAsm(P(hir_asm), outputs, inputs)
                 }
                 ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
-                    hir::ExprStruct(P(self.lower_path(path)),
+                    hir::ExprStruct(P(self.lower_path(path, None, ParamMode::Optional)),
                                     fields.iter().map(|x| self.lower_field(x)).collect(),
                                     maybe_expr.as_ref().map(|x| P(self.lower_expr(x))))
                 }
@@ -1655,8 +1686,12 @@ fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
         match *v {
             Visibility::Public => hir::Public,
             Visibility::Crate(_) => hir::Visibility::Crate,
-            Visibility::Restricted { ref path, id } =>
-                hir::Visibility::Restricted { path: P(self.lower_path(path)), id: id },
+            Visibility::Restricted { ref path, id } => {
+                hir::Visibility::Restricted {
+                    path: P(self.lower_path(path, None, ParamMode::Explicit)),
+                    id: id
+                }
+            }
             Visibility::Inherited => hir::Inherited,
         }
     }
@@ -1949,6 +1984,7 @@ fn path_all(&mut self,
             parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
                 lifetimes: lifetimes,
                 types: types,
+                infer_types: true,
                 bindings: bindings,
             }),
         });
index 31648765224254796ca75be5e292b5035ac9470b..6f0a3a02380845104df96ce1ef0de7410c40c7ee 100644 (file)
@@ -167,6 +167,7 @@ pub fn none() -> PathParameters {
         AngleBracketedParameters(AngleBracketedParameterData {
             lifetimes: HirVec::new(),
             types: HirVec::new(),
+            infer_types: true,
             bindings: HirVec::new(),
         })
     }
@@ -241,6 +242,11 @@ pub struct AngleBracketedParameterData {
     pub lifetimes: HirVec<Lifetime>,
     /// The type parameters for this path segment, if present.
     pub types: HirVec<P<Ty>>,
+    /// Whether to infer remaining type parameters, if any.
+    /// This only applies to expression and pattern paths, and
+    /// out of those only the segments with no type parameters
+    /// to begin with, e.g. `Vec::new` is `<Vec<..>>::new::<..>`.
+    pub infer_types: bool,
     /// Bindings (equality constraints) on associated types, if present.
     /// E.g., `Foo<A=Bar>`.
     pub bindings: HirVec<TypeBinding>,
index c109e84bf6186a65ee7b224d962e5d3b982b6a31..9934259c5d19106466f809ae053cdb96961c0549 100644 (file)
@@ -1696,6 +1696,16 @@ fn print_path_parameters(&mut self,
                     comma = true;
                 }
 
+                // FIXME(eddyb) This would leak into error messages, e.g.:
+                // "non-exhaustive patterns: `Some::<..>(_)` not covered".
+                if data.infer_types && false {
+                    if comma {
+                        self.word_space(",")?
+                    }
+                    word(&mut self.s, "..")?;
+                    comma = true;
+                }
+
                 for binding in data.bindings.iter() {
                     if comma {
                         self.word_space(",")?
index 8db09d0b73d32485d1e2ba0f48f56e26f4a48a4c..b9b974733409fd67df8389dbe6a2f05a36a2a3ed 100644 (file)
@@ -1609,6 +1609,7 @@ fn rebuild_path(&self,
                 hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
                     lifetimes: new_lts.into(),
                     types: new_types,
+                    infer_types: data.infer_types,
                     bindings: new_bindings,
                })
             }
index c5db8bc8cedc769d152913c6f8edc05d4348dbb5..831426c3f06b67bada3a7fc9cae9bdd4e1dd278a 100644 (file)
@@ -149,14 +149,6 @@ fn projected_ty(&self,
     fn set_tainted_by_errors(&self);
 }
 
-#[derive(PartialEq, Eq)]
-pub enum PathParamMode {
-    // Any path in a type context.
-    Explicit,
-    // The `module::Type` in `module::Type::method` in an expression.
-    Optional
-}
-
 struct ConvertedBinding<'tcx> {
     item_name: ast::Name,
     ty: Ty<'tcx>,
@@ -341,7 +333,6 @@ pub fn opt_ast_region_to_region(&self,
     pub fn ast_path_substs_for_ty(&self,
         rscope: &RegionScope,
         span: Span,
-        param_mode: PathParamMode,
         def_id: DefId,
         item_segment: &hir::PathSegment)
         -> &'tcx Substs<'tcx>
@@ -367,7 +358,6 @@ pub fn ast_path_substs_for_ty(&self,
         let (substs, assoc_bindings) =
             self.create_substs_for_ast_path(rscope,
                                             span,
-                                            param_mode,
                                             def_id,
                                             &item_segment.parameters,
                                             None);
@@ -385,7 +375,6 @@ pub fn ast_path_substs_for_ty(&self,
     fn create_substs_for_ast_path(&self,
         rscope: &RegionScope,
         span: Span,
-        param_mode: PathParamMode,
         def_id: DefId,
         parameters: &hir::PathParameters,
         self_ty: Option<Ty<'tcx>>)
@@ -397,15 +386,11 @@ fn create_substs_for_ast_path(&self,
                parameters={:?})",
                def_id, self_ty, parameters);
 
-        let (lifetimes, num_types_provided) = match *parameters {
+        let (lifetimes, num_types_provided, infer_types) = match *parameters {
             hir::AngleBracketedParameters(ref data) => {
-                if param_mode == PathParamMode::Optional && data.types.is_empty() {
-                    (&data.lifetimes[..], None)
-                } else {
-                    (&data.lifetimes[..], Some(data.types.len()))
-                }
+                (&data.lifetimes[..], data.types.len(), data.infer_types)
             }
-            hir::ParenthesizedParameters(_) => (&[][..], Some(1))
+            hir::ParenthesizedParameters(_) => (&[][..], 1, false)
         };
 
         // If the type is parameterized by this region, then replace this
@@ -443,9 +428,9 @@ fn create_substs_for_ast_path(&self,
         assert_eq!(decl_generics.has_self, self_ty.is_some());
 
         // Check the number of type parameters supplied by the user.
-        if let Some(num_provided) = num_types_provided {
-            let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
-            check_type_argument_count(tcx, span, num_provided, ty_param_defs);
+        let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
+        if !infer_types || num_types_provided > ty_param_defs.len() {
+            check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
         }
 
         let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
@@ -474,7 +459,7 @@ fn create_substs_for_ast_path(&self,
             }
 
             let i = i - self_ty.is_some() as usize - decl_generics.regions.len();
-            if num_types_provided.map_or(false, |n| i < n) {
+            if i < num_types_provided {
                 // A provided type parameter.
                 match *parameters {
                     hir::AngleBracketedParameters(ref data) => {
@@ -488,7 +473,7 @@ fn create_substs_for_ast_path(&self,
                         ty
                     }
                 }
-            } else if num_types_provided.is_none() {
+            } else if 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)
@@ -664,7 +649,6 @@ pub fn instantiate_poly_trait_ref(&self,
         let trait_def_id = self.trait_def_id(trait_ref);
         self.ast_path_to_poly_trait_ref(rscope,
                                         trait_ref.path.span,
-                                        PathParamMode::Explicit,
                                         trait_def_id,
                                         self_ty,
                                         trait_ref.ref_id,
@@ -687,7 +671,6 @@ pub fn instantiate_mono_trait_ref(&self,
         let trait_def_id = self.trait_def_id(trait_ref);
         self.ast_path_to_mono_trait_ref(rscope,
                                         trait_ref.path.span,
-                                        PathParamMode::Explicit,
                                         trait_def_id,
                                         self_ty,
                                         trait_ref.path.segments.last().unwrap())
@@ -710,7 +693,6 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
     fn ast_path_to_poly_trait_ref(&self,
         rscope: &RegionScope,
         span: Span,
-        param_mode: PathParamMode,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
         path_id: ast::NodeId,
@@ -729,7 +711,6 @@ fn ast_path_to_poly_trait_ref(&self,
         let (substs, assoc_bindings) =
             self.create_substs_for_ast_trait_ref(shifted_rscope,
                                                  span,
-                                                 param_mode,
                                                  trait_def_id,
                                                  self_ty,
                                                  trait_segment);
@@ -752,7 +733,6 @@ fn ast_path_to_poly_trait_ref(&self,
     fn ast_path_to_mono_trait_ref(&self,
                                   rscope: &RegionScope,
                                   span: Span,
-                                  param_mode: PathParamMode,
                                   trait_def_id: DefId,
                                   self_ty: Ty<'tcx>,
                                   trait_segment: &hir::PathSegment)
@@ -761,7 +741,6 @@ fn ast_path_to_mono_trait_ref(&self,
         let (substs, assoc_bindings) =
             self.create_substs_for_ast_trait_ref(rscope,
                                                  span,
-                                                 param_mode,
                                                  trait_def_id,
                                                  self_ty,
                                                  trait_segment);
@@ -772,7 +751,6 @@ fn ast_path_to_mono_trait_ref(&self,
     fn create_substs_for_ast_trait_ref(&self,
                                        rscope: &RegionScope,
                                        span: Span,
-                                       param_mode: PathParamMode,
                                        trait_def_id: DefId,
                                        self_ty: Ty<'tcx>,
                                        trait_segment: &hir::PathSegment)
@@ -817,7 +795,6 @@ fn create_substs_for_ast_trait_ref(&self,
 
         self.create_substs_for_ast_path(rscope,
                                         span,
-                                        param_mode,
                                         trait_def_id,
                                         &trait_segment.parameters,
                                         Some(self_ty))
@@ -929,7 +906,6 @@ fn ast_type_binding_to_poly_projection_predicate(
     fn ast_path_to_ty(&self,
         rscope: &RegionScope,
         span: Span,
-        param_mode: PathParamMode,
         did: DefId,
         item_segment: &hir::PathSegment)
         -> Ty<'tcx>
@@ -944,7 +920,6 @@ fn ast_path_to_ty(&self,
 
         let substs = self.ast_path_substs_for_ty(rscope,
                                                  span,
-                                                 param_mode,
                                                  did,
                                                  item_segment);
 
@@ -983,7 +958,6 @@ fn ast_ty_to_object_trait_ref(&self,
                     Def::Trait(trait_def_id) if resolution.depth == 0 => {
                         self.trait_path_to_object_type(rscope,
                                                        path.span,
-                                                       PathParamMode::Explicit,
                                                        trait_def_id,
                                                        ty.id,
                                                        path.segments.last().unwrap(),
@@ -1055,7 +1029,6 @@ fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
     fn trait_path_to_object_type(&self,
                                  rscope: &RegionScope,
                                  path_span: Span,
-                                 param_mode: PathParamMode,
                                  trait_def_id: DefId,
                                  trait_path_ref_id: ast::NodeId,
                                  trait_segment: &hir::PathSegment,
@@ -1068,7 +1041,6 @@ fn trait_path_to_object_type(&self,
         let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
         let principal = self.ast_path_to_poly_trait_ref(rscope,
                                                         path_span,
-                                                        param_mode,
                                                         trait_def_id,
                                                         dummy_self,
                                                         trait_path_ref_id,
@@ -1377,7 +1349,6 @@ fn associated_path_def_to_ty(&self,
     fn qpath_to_ty(&self,
                    rscope: &RegionScope,
                    span: Span,
-                   param_mode: PathParamMode,
                    opt_self_ty: Option<Ty<'tcx>>,
                    trait_def_id: DefId,
                    trait_segment: &hir::PathSegment,
@@ -1403,7 +1374,6 @@ fn qpath_to_ty(&self,
 
         let trait_ref = self.ast_path_to_mono_trait_ref(rscope,
                                                         span,
-                                                        param_mode,
                                                         trait_def_id,
                                                         self_ty,
                                                         trait_segment);
@@ -1448,7 +1418,6 @@ fn ast_ty_arg_to_ty(&self,
     fn base_def_to_ty(&self,
                       rscope: &RegionScope,
                       span: Span,
-                      param_mode: PathParamMode,
                       def: Def,
                       opt_self_ty: Option<Ty<'tcx>>,
                       base_path_ref_id: ast::NodeId,
@@ -1469,7 +1438,6 @@ fn base_def_to_ty(&self,
 
                 self.trait_path_to_object_type(rscope,
                                                span,
-                                               param_mode,
                                                trait_def_id,
                                                base_path_ref_id,
                                                base_segments.last().unwrap(),
@@ -1478,11 +1446,7 @@ fn base_def_to_ty(&self,
             }
             Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => {
                 tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
-                self.ast_path_to_ty(rscope,
-                                    span,
-                                    param_mode,
-                                    did,
-                                    base_segments.last().unwrap())
+                self.ast_path_to_ty(rscope, span, did, base_segments.last().unwrap())
             }
             Def::Variant(did) if permit_variants => {
                 // Convert "variant type" as if it were a real type.
@@ -1535,7 +1499,6 @@ fn base_def_to_ty(&self,
                 let trait_did = tcx.parent_def_id(def_id).unwrap();
                 self.qpath_to_ty(rscope,
                                  span,
-                                 param_mode,
                                  opt_self_ty,
                                  trait_did,
                                  &base_segments[base_segments.len()-2],
@@ -1577,7 +1540,6 @@ fn base_def_to_ty(&self,
     pub fn finish_resolving_def_to_ty(&self,
                                       rscope: &RegionScope,
                                       span: Span,
-                                      param_mode: PathParamMode,
                                       base_def: Def,
                                       opt_self_ty: Option<Ty<'tcx>>,
                                       base_path_ref_id: ast::NodeId,
@@ -1594,7 +1556,6 @@ pub fn finish_resolving_def_to_ty(&self,
                assoc_segments);
         let base_ty = self.base_def_to_ty(rscope,
                                           span,
-                                          param_mode,
                                           base_def,
                                           opt_self_ty,
                                           base_path_ref_id,
@@ -1749,7 +1710,6 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 });
                 let (ty, def) = self.finish_resolving_def_to_ty(rscope,
                                                                 ast_ty.span,
-                                                                PathParamMode::Explicit,
                                                                 path_res.base_def,
                                                                 opt_self_ty,
                                                                 ast_ty.id,
@@ -2007,7 +1967,6 @@ fn conv_object_ty_poly_trait_ref(&self,
         let trait_def_id = self.trait_def_id(trait_ref);
         self.trait_path_to_object_type(rscope,
                                        trait_ref.path.span,
-                                       PathParamMode::Explicit,
                                        trait_def_id,
                                        trait_ref.ref_id,
                                        trait_ref.path.segments.last().unwrap(),
index eeb7bb287002f7ffb32a93718ff8b2943a667a37..ea84786e06b986ffdaf6fdcab8ba62848c07ca9d 100644 (file)
@@ -80,7 +80,7 @@
 pub use self::compare_method::{compare_impl_method, compare_const_impl};
 use self::TupleArgumentsFlag::*;
 
-use astconv::{AstConv, ast_region_to_region, PathParamMode};
+use astconv::{AstConv, ast_region_to_region};
 use dep_graph::DepNode;
 use fmt_macros::{Parser, Piece, Position};
 use hir::def::{Def, CtorKind, PathResolution};
@@ -4006,7 +4006,6 @@ fn finish_resolving_struct_path(&self,
         let path_res = self.tcx.expect_resolution(node_id);
         let base_ty_end = path.segments.len() - path_res.depth;
         let (ty, def) = AstConv::finish_resolving_def_to_ty(self, self, path.span,
-                                                            PathParamMode::Optional,
                                                             path_res.base_def,
                                                             None,
                                                             node_id,
@@ -4038,7 +4037,6 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
             let ty_segments = path.segments.split_last().unwrap().1;
             let base_ty_end = path.segments.len() - path_res.depth;
             let (ty, _def) = AstConv::finish_resolving_def_to_ty(self, self, span,
-                                                                 PathParamMode::Optional,
                                                                  path_res.base_def,
                                                                  opt_self_ty,
                                                                  node_id,
@@ -4379,11 +4377,6 @@ pub fn instantiate_value_path(&self,
             _ => bug!("unexpected definition: {:?}", def),
         }
 
-        // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
-        // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
-        // type parameters are not mandatory.
-        let require_type_space = opt_self_ty.is_some() && ufcs_associated.is_none();
-
         debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment);
 
         // Now that we have categorized what space the parameters for each
@@ -4414,8 +4407,8 @@ pub fn instantiate_value_path(&self,
         // variables. If the user provided some types, we may still need
         // to add defaults. If the user provided *too many* types, that's
         // a problem.
-        self.check_path_parameter_count(span, !require_type_space, &mut type_segment);
-        self.check_path_parameter_count(span, true, &mut fn_segment);
+        self.check_path_parameter_count(span, &mut type_segment);
+        self.check_path_parameter_count(span, &mut fn_segment);
 
         let (fn_start, has_self) = match (type_segment, fn_segment) {
             (_, Some((_, generics))) => {
@@ -4450,7 +4443,6 @@ pub fn instantiate_value_path(&self,
         }, |def, substs| {
             let mut i = def.index as usize;
 
-            let can_omit = i >= fn_start || !require_type_space;
             let segment = if i < fn_start {
                 // Handle Self first, so we can adjust the index to match the AST.
                 if has_self && i == 0 {
@@ -4464,10 +4456,12 @@ pub fn instantiate_value_path(&self,
                 i -= fn_start;
                 fn_segment
             };
-            let types = match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..],
+            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 => &[]
+                None => (&[][..], true)
             };
 
             // Skip over the lifetimes in the same segment.
@@ -4475,11 +4469,10 @@ pub fn instantiate_value_path(&self,
                 i -= generics.regions.len();
             }
 
-            let omitted = can_omit && types.is_empty();
             if let Some(ast_ty) = types.get(i) {
                 // A provided type parameter.
                 self.to_ty(ast_ty)
-            } else if let (false, Some(default)) = (omitted, def.default) {
+            } else if let (false, Some(default)) = (infer_types, def.default) {
                 // No type parameter provided, but a default exists.
                 default.subst_spanned(self.tcx, substs, Some(span))
             } else {
@@ -4539,16 +4532,17 @@ pub fn instantiate_value_path(&self,
     /// Report errors if the provided parameters are too few or too many.
     fn check_path_parameter_count(&self,
                                   span: Span,
-                                  can_omit: bool,
                                   segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) {
-        let (lifetimes, types, bindings) = match segment.map(|(s, _)| &s.parameters) {
-            Some(&hir::AngleBracketedParameters(ref data)) => {
-                (&data.lifetimes[..], &data.types[..], &data.bindings[..])
-            }
-            Some(&hir::ParenthesizedParameters(_)) => {
-                span_bug!(span, "parenthesized parameters cannot appear in ExprPath");
+        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(_)) => {
+                    span_bug!(span, "parenthesized parameters cannot appear in ExprPath");
+                }
+                None => (&[][..], &[][..], true, &[][..])
             }
-            None => (&[][..], &[][..], &[][..])
         };
 
         let count = |n| {
@@ -4597,7 +4591,7 @@ fn check_path_parameter_count(&self,
             // type parameters, we force instantiate_value_path to
             // use inference variables instead of the provided types.
             *segment = None;
-        } else if !(can_omit && types.len() == 0) && types.len() < required_len {
+        } else if !infer_types && types.len() < required_len {
             let adjust = |len| if len > 1 { "parameters" } else { "parameter" };
             let required_param_str = adjust(required_len);
             let actual_param_str = adjust(types.len());