rustc: encode the optionality of type parameters in HIR paths.
This commit is contained in:
parent
9ca50bd4d5
commit
34d1352f0e
@ -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,
|
||||
}),
|
||||
});
|
||||
|
@ -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>,
|
||||
|
@ -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(",")?
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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());
|
||||
|
Loading…
x
Reference in New Issue
Block a user