diff options
| author | Eduard Burtescu <edy.burt@gmail.com> | 2016-10-17 06:02:23 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2016-11-28 04:18:10 +0200 |
| commit | 34d1352f0eb7e7511e34b1e7640e854ffaf3f137 (patch) | |
| tree | 090943b69607f2ce56b50f523ded1dd0fb23ccd2 | |
| parent | 9ca50bd4d50b55456e88a8c3ad8fcc9798f57522 (diff) | |
| download | rust-34d1352f0eb7e7511e34b1e7640e854ffaf3f137.tar.gz rust-34d1352f0eb7e7511e34b1e7640e854ffaf3f137.zip | |
rustc: encode the optionality of type parameters in HIR paths.
| -rw-r--r-- | src/librustc/hir/lowering.rs | 98 | ||||
| -rw-r--r-- | src/librustc/hir/mod.rs | 6 | ||||
| -rw-r--r-- | src/librustc/hir/print.rs | 10 | ||||
| -rw-r--r-- | src/librustc/infer/error_reporting.rs | 1 | ||||
| -rw-r--r-- | src/librustc_typeck/astconv.rs | 59 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 44 |
6 files changed, 112 insertions, 106 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5af7c18e1a1..264a5722bcd 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { } } - 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { } 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 @@ impl<'a> LoweringContext<'a> { }; } 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { lifetimes: lifetimes, types: types, + infer_types: true, bindings: bindings, }), }); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 31648765224..6f0a3a02380 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -167,6 +167,7 @@ impl 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>, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index c109e84bf61..9934259c5d1 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1696,6 +1696,16 @@ impl<'a> State<'a> { 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(",")? diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 8db09d0b73d..b9b97473340 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -1609,6 +1609,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { hir::AngleBracketedParameters(hir::AngleBracketedParameterData { lifetimes: new_lts.into(), types: new_types, + infer_types: data.infer_types, bindings: new_bindings, }) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c5db8bc8ced..831426c3f06 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -149,14 +149,6 @@ pub trait AstConv<'gcx, 'tcx> { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let (substs, assoc_bindings) = self.create_substs_for_ast_path(rscope, span, - param_mode, def_id, &item_segment.parameters, None); @@ -385,7 +375,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.create_substs_for_ast_path(rscope, span, - param_mode, trait_def_id, &trait_segment.parameters, Some(self_ty)) @@ -929,7 +906,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let substs = self.ast_path_substs_for_ty(rscope, span, - param_mode, did, item_segment); @@ -983,7 +958,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }); 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { 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(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index eeb7bb28700..ea84786e06b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -80,7 +80,7 @@ pub use self::Expectation::*; 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, |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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // 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()); |
