rustc: encode the optionality of type parameters in HIR paths.

This commit is contained in:
Eduard Burtescu 2016-10-17 06:02:23 +03:00 committed by Eduard-Mihai Burtescu
parent 9ca50bd4d5
commit 34d1352f0e
6 changed files with 112 additions and 106 deletions

View 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 @@ 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,
}),
});

View File

@ -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>,

View File

@ -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(",")?

View File

@ -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,
})
}

View File

@ -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(),

View File

@ -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[..])
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, &[][..])
}
Some(&hir::ParenthesizedParameters(_)) => {
span_bug!(span, "parenthesized parameters cannot appear in ExprPath");
}
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());