}.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> {
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())
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))
}
}
- 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(),
}
}
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,
})
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,
}
}
}
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 {
};
}
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),
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))))
}
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,
}
}
parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
lifetimes: lifetimes,
types: types,
+ infer_types: true,
bindings: bindings,
}),
});
AngleBracketedParameters(AngleBracketedParameterData {
lifetimes: HirVec::new(),
types: HirVec::new(),
+ infer_types: true,
bindings: HirVec::new(),
})
}
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>,
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(",")?
hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
lifetimes: new_lts.into(),
types: new_types,
+ infer_types: data.infer_types,
bindings: new_bindings,
})
}
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>,
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>
let (substs, assoc_bindings) =
self.create_substs_for_ast_path(rscope,
span,
- param_mode,
def_id,
&item_segment.parameters,
None);
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>>)
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
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);
}
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) => {
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)
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,
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())
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,
let (substs, assoc_bindings) =
self.create_substs_for_ast_trait_ref(shifted_rscope,
span,
- param_mode,
trait_def_id,
self_ty,
trait_segment);
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)
let (substs, assoc_bindings) =
self.create_substs_for_ast_trait_ref(rscope,
span,
- param_mode,
trait_def_id,
self_ty,
trait_segment);
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)
self.create_substs_for_ast_path(rscope,
span,
- param_mode,
trait_def_id,
&trait_segment.parameters,
Some(self_ty))
fn ast_path_to_ty(&self,
rscope: &RegionScope,
span: Span,
- param_mode: PathParamMode,
did: DefId,
item_segment: &hir::PathSegment)
-> Ty<'tcx>
let substs = self.ast_path_substs_for_ty(rscope,
span,
- param_mode,
did,
item_segment);
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(),
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,
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,
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,
let trait_ref = self.ast_path_to_mono_trait_ref(rscope,
span,
- param_mode,
trait_def_id,
self_ty,
trait_segment);
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,
self.trait_path_to_object_type(rscope,
span,
- param_mode,
trait_def_id,
base_path_ref_id,
base_segments.last().unwrap(),
}
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.
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],
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,
assoc_segments);
let base_ty = self.base_def_to_ty(rscope,
span,
- param_mode,
base_def,
opt_self_ty,
base_path_ref_id,
});
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,
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(),
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};
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,
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,
_ => 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
// 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))) => {
}, |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 {
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.
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 {
/// 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| {
// 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());