rustc_typeck: use Substs::from_generics instead of manually building them.
This commit is contained in:
parent
4b25f08512
commit
bfdfa1ce1d
4 changed files with 305 additions and 540 deletions
|
|
@ -1234,13 +1234,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
self.tcx.mk_var(ty_var_id)
|
||||
}
|
||||
|
||||
pub fn region_vars_for_defs(&self,
|
||||
span: Span,
|
||||
defs: &[ty::RegionParameterDef])
|
||||
-> Vec<ty::Region> {
|
||||
defs.iter().map(|def| self.region_var_for_def(span, def)).collect()
|
||||
}
|
||||
|
||||
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
|
||||
/// type/region parameter to a fresh inference variable.
|
||||
pub fn fresh_substs_for_generics(&self,
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ use hir::def_id::DefId;
|
|||
use hir::print as pprust;
|
||||
use middle::resolve_lifetime as rl;
|
||||
use rustc::lint;
|
||||
use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
||||
use rustc::ty::subst::{TypeSpace, SelfSpace, Subst, Substs};
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
|
||||
use rustc::ty::wf::object_region_bounds;
|
||||
|
|
@ -350,64 +350,77 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
param_mode: PathParamMode,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
item_segment: &hir::PathSegment)
|
||||
-> Substs<'tcx>
|
||||
-> &'tcx Substs<'tcx>
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
// ast_path_substs() is only called to convert paths that are
|
||||
// known to refer to traits, types, or structs. In these cases,
|
||||
// all type parameters defined for the item being referenced will
|
||||
// be in the TypeSpace or SelfSpace.
|
||||
//
|
||||
// Note: in the case of traits, the self parameter is also
|
||||
// defined, but we don't currently create a `type_param_def` for
|
||||
// `Self` because it is implicit.
|
||||
assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
|
||||
assert!(decl_generics.types.all(|d| d.space != FnSpace));
|
||||
|
||||
let (regions, types, assoc_bindings) = match item_segment.parameters {
|
||||
hir::AngleBracketedParameters(ref data) => {
|
||||
self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data)
|
||||
}
|
||||
match item_segment.parameters {
|
||||
hir::AngleBracketedParameters(_) => {}
|
||||
hir::ParenthesizedParameters(..) => {
|
||||
struct_span_err!(tcx.sess, span, E0214,
|
||||
"parenthesized parameters may only be used with a trait")
|
||||
.span_label(span, &format!("only traits may use parentheses"))
|
||||
.emit();
|
||||
|
||||
let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
|
||||
(Substs::empty(),
|
||||
ty_param_defs.iter().map(|_| tcx.types.err).collect(),
|
||||
vec![])
|
||||
return tcx.mk_substs(Substs::from_generics(decl_generics, |_, _| {
|
||||
ty::ReStatic
|
||||
}, |_, _| {
|
||||
tcx.types.err
|
||||
}));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let (substs, assoc_bindings) =
|
||||
self.create_substs_for_ast_path(rscope,
|
||||
span,
|
||||
param_mode,
|
||||
decl_generics,
|
||||
&item_segment.parameters,
|
||||
None);
|
||||
|
||||
assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span));
|
||||
|
||||
self.create_substs_for_ast_path(span,
|
||||
param_mode,
|
||||
decl_generics,
|
||||
None,
|
||||
types,
|
||||
regions)
|
||||
substs
|
||||
}
|
||||
|
||||
fn create_region_substs(&self,
|
||||
/// Given the type/region arguments provided to some path (along with
|
||||
/// an implicit Self, if this is a trait reference) returns the complete
|
||||
/// set of substitutions. This may involve applying defaulted type parameters.
|
||||
///
|
||||
/// Note that the type listing given here is *exactly* what the user provided.
|
||||
fn create_substs_for_ast_path(&self,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
param_mode: PathParamMode,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
regions_provided: Vec<ty::Region>)
|
||||
-> Substs<'tcx>
|
||||
parameters: &hir::PathParameters,
|
||||
self_ty: Option<Ty<'tcx>>)
|
||||
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
|
||||
parameters={:?})",
|
||||
decl_generics, self_ty, parameters);
|
||||
|
||||
let (lifetimes, num_types_provided) = 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()))
|
||||
}
|
||||
}
|
||||
hir::ParenthesizedParameters(_) => (&[][..], Some(1))
|
||||
};
|
||||
|
||||
// If the type is parameterized by this region, then replace this
|
||||
// region with the current anon region binding (in other words,
|
||||
// whatever & would get replaced with).
|
||||
let expected_num_region_params = decl_generics.regions.len(TypeSpace);
|
||||
let supplied_num_region_params = regions_provided.len();
|
||||
let supplied_num_region_params = lifetimes.len();
|
||||
let regions = if expected_num_region_params == supplied_num_region_params {
|
||||
regions_provided
|
||||
lifetimes.iter().map(|l| ast_region_to_region(tcx, l)).collect()
|
||||
} else {
|
||||
let anon_regions =
|
||||
rscope.anon_regions(span, expected_num_region_params);
|
||||
|
|
@ -423,176 +436,111 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
Err(_) => (0..expected_num_region_params).map(|_| ty::ReStatic).collect()
|
||||
}
|
||||
};
|
||||
Substs::new_type(vec![], regions)
|
||||
}
|
||||
|
||||
/// Given the type/region arguments provided to some path (along with
|
||||
/// an implicit Self, if this is a trait reference) returns the complete
|
||||
/// set of substitutions. This may involve applying defaulted type parameters.
|
||||
///
|
||||
/// Note that the type listing given here is *exactly* what the user provided.
|
||||
///
|
||||
/// The `region_substs` should be the result of `create_region_substs`
|
||||
/// -- that is, a substitution with no types but the correct number of
|
||||
/// regions.
|
||||
fn create_substs_for_ast_path(&self,
|
||||
span: Span,
|
||||
param_mode: PathParamMode,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
types_provided: Vec<Ty<'tcx>>,
|
||||
region_substs: Substs<'tcx>)
|
||||
-> Substs<'tcx>
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
|
||||
types_provided={:?}, region_substs={:?})",
|
||||
decl_generics, self_ty, types_provided,
|
||||
region_substs);
|
||||
|
||||
assert_eq!(region_substs.regions.len(TypeSpace), decl_generics.regions.len(TypeSpace));
|
||||
assert!(region_substs.types.is_empty());
|
||||
|
||||
// Convert the type parameters supplied by the user.
|
||||
let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
|
||||
let formal_ty_param_count = ty_param_defs.len();
|
||||
let required_ty_param_count = ty_param_defs.iter()
|
||||
.take_while(|x| x.default.is_none())
|
||||
.count();
|
||||
|
||||
let mut type_substs = self.get_type_substs_for_defs(span,
|
||||
types_provided,
|
||||
param_mode,
|
||||
ty_param_defs,
|
||||
region_substs.clone(),
|
||||
self_ty);
|
||||
|
||||
let supplied_ty_param_count = type_substs.len();
|
||||
check_type_argument_count(self.tcx(), span, supplied_ty_param_count,
|
||||
required_ty_param_count, formal_ty_param_count);
|
||||
|
||||
if supplied_ty_param_count < required_ty_param_count {
|
||||
while type_substs.len() < required_ty_param_count {
|
||||
type_substs.push(tcx.types.err);
|
||||
}
|
||||
} else if supplied_ty_param_count > formal_ty_param_count {
|
||||
type_substs.truncate(formal_ty_param_count);
|
||||
}
|
||||
assert!(type_substs.len() >= required_ty_param_count &&
|
||||
type_substs.len() <= formal_ty_param_count);
|
||||
|
||||
let mut substs = region_substs;
|
||||
|
||||
// If a self-type was declared, one should be provided.
|
||||
assert_eq!(decl_generics.types.get_self().is_some(), self_ty.is_some());
|
||||
substs.types.extend(SelfSpace, self_ty.into_iter());
|
||||
substs.types.extend(TypeSpace, type_substs.into_iter());
|
||||
|
||||
// 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.get_slice(TypeSpace);
|
||||
check_type_argument_count(tcx, span, num_provided, ty_param_defs);
|
||||
}
|
||||
|
||||
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
|
||||
let actual_supplied_ty_param_count = substs.types.len(TypeSpace);
|
||||
for param in &ty_param_defs[actual_supplied_ty_param_count..] {
|
||||
let default = if let Some(default) = param.default {
|
||||
let default_needs_object_self = |p: &ty::TypeParameterDef<'tcx>| {
|
||||
if let Some(ref default) = p.default {
|
||||
if is_object && default.has_self_ty() {
|
||||
// There is no suitable inference default for a type parameter
|
||||
// that references self, in an object type.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
};
|
||||
|
||||
let mut output_assoc_binding = None;
|
||||
let substs = Substs::from_generics(decl_generics, |def, _| {
|
||||
assert_eq!(def.space, TypeSpace);
|
||||
regions[def.index as usize]
|
||||
}, |def, substs| {
|
||||
assert!(def.space == SelfSpace || def.space == TypeSpace);
|
||||
let i = def.index as usize;
|
||||
if def.space == SelfSpace {
|
||||
// Self, which must have been provided.
|
||||
assert_eq!(i, 0);
|
||||
self_ty.expect("Self type parameter missing")
|
||||
} else if num_types_provided.map_or(false, |n| i < n) {
|
||||
// A provided type parameter.
|
||||
match *parameters {
|
||||
hir::AngleBracketedParameters(ref data) => {
|
||||
self.ast_ty_arg_to_ty(rscope, Some(def), substs, &data.types[i])
|
||||
}
|
||||
hir::ParenthesizedParameters(ref data) => {
|
||||
assert_eq!(i, 0);
|
||||
let (ty, assoc) =
|
||||
self.convert_parenthesized_parameters(rscope, substs, data);
|
||||
output_assoc_binding = Some(assoc);
|
||||
ty
|
||||
}
|
||||
}
|
||||
} else if num_types_provided.is_none() {
|
||||
// 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)
|
||||
} else {
|
||||
self.ty_infer(span)
|
||||
};
|
||||
ty_var
|
||||
} else if let Some(default) = def.default {
|
||||
// No type parameter provided, but a default exists.
|
||||
|
||||
// If we are converting an object type, then the
|
||||
// `Self` parameter is unknown. However, some of the
|
||||
// other type parameters may reference `Self` in their
|
||||
// defaults. This will lead to an ICE if we are not
|
||||
// careful!
|
||||
if is_object && default.has_self_ty() {
|
||||
if default_needs_object_self(def) {
|
||||
span_err!(tcx.sess, span, E0393,
|
||||
"the type parameter `{}` must be explicitly specified \
|
||||
in an object type because its default value `{}` references \
|
||||
the type `Self`",
|
||||
param.name,
|
||||
def.name,
|
||||
default);
|
||||
tcx.types.err
|
||||
} else {
|
||||
// This is a default type parameter.
|
||||
default.subst_spanned(tcx, &substs, Some(span))
|
||||
default.subst_spanned(tcx, substs, Some(span))
|
||||
}
|
||||
} else {
|
||||
span_bug!(span, "extra parameter without default");
|
||||
};
|
||||
substs.types.push(TypeSpace, default);
|
||||
}
|
||||
// We've already errored above about the mismatch.
|
||||
tcx.types.err
|
||||
}
|
||||
});
|
||||
|
||||
let assoc_bindings = match *parameters {
|
||||
hir::AngleBracketedParameters(ref data) => {
|
||||
data.bindings.iter().map(|b| {
|
||||
ConvertedBinding {
|
||||
item_name: b.name,
|
||||
ty: self.ast_ty_to_ty(rscope, &b.ty),
|
||||
span: b.span
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
hir::ParenthesizedParameters(ref data) => {
|
||||
vec![output_assoc_binding.unwrap_or_else(|| {
|
||||
// This is an error condition, but we should
|
||||
// get the associated type binding anyway.
|
||||
self.convert_parenthesized_parameters(rscope, &substs, data).1
|
||||
})]
|
||||
}
|
||||
};
|
||||
|
||||
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
|
||||
decl_generics, self_ty, substs);
|
||||
|
||||
substs
|
||||
}
|
||||
|
||||
/// Returns types_provided if it is not empty, otherwise populating the
|
||||
/// type parameters with inference variables as appropriate.
|
||||
fn get_type_substs_for_defs(&self,
|
||||
span: Span,
|
||||
types_provided: Vec<Ty<'tcx>>,
|
||||
param_mode: PathParamMode,
|
||||
ty_param_defs: &[ty::TypeParameterDef<'tcx>],
|
||||
mut substs: Substs<'tcx>,
|
||||
self_ty: Option<Ty<'tcx>>)
|
||||
-> Vec<Ty<'tcx>>
|
||||
{
|
||||
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
|
||||
let use_default = |p: &ty::TypeParameterDef<'tcx>| {
|
||||
if let Some(ref default) = p.default {
|
||||
if is_object && default.has_self_ty() {
|
||||
// There is no suitable inference default for a type parameter
|
||||
// that references self, in an object type.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
};
|
||||
|
||||
if param_mode == PathParamMode::Optional && types_provided.is_empty() {
|
||||
ty_param_defs.iter().map(|def| {
|
||||
let ty_var = if use_default(def) {
|
||||
self.ty_infer_for_def(def, &substs, span)
|
||||
} else {
|
||||
self.ty_infer(span)
|
||||
};
|
||||
substs.types.push(def.space, ty_var);
|
||||
ty_var
|
||||
}).collect()
|
||||
} else {
|
||||
types_provided
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_angle_bracketed_parameters(&self,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
data: &hir::AngleBracketedParameterData)
|
||||
-> (Substs<'tcx>,
|
||||
Vec<Ty<'tcx>>,
|
||||
Vec<ConvertedBinding<'tcx>>)
|
||||
{
|
||||
let regions: Vec<_> =
|
||||
data.lifetimes.iter()
|
||||
.map(|l| ast_region_to_region(self.tcx(), l))
|
||||
.collect();
|
||||
|
||||
let region_substs =
|
||||
self.create_region_substs(rscope, span, decl_generics, regions);
|
||||
|
||||
let types: Vec<_> =
|
||||
data.types.iter()
|
||||
.enumerate()
|
||||
.map(|(i,t)| self.ast_ty_arg_to_ty(rscope, decl_generics,
|
||||
i, ®ion_substs, t))
|
||||
.collect();
|
||||
|
||||
let assoc_bindings: Vec<_> =
|
||||
data.bindings.iter()
|
||||
.map(|b| ConvertedBinding { item_name: b.name,
|
||||
ty: self.ast_ty_to_ty(rscope, &b.ty),
|
||||
span: b.span })
|
||||
.collect();
|
||||
|
||||
(region_substs, types, assoc_bindings)
|
||||
(tcx.mk_substs(substs), assoc_bindings)
|
||||
}
|
||||
|
||||
/// Returns the appropriate lifetime to use for any output lifetimes
|
||||
|
|
@ -657,29 +605,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
|
||||
fn convert_parenthesized_parameters(&self,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
region_substs: &Substs<'tcx>,
|
||||
data: &hir::ParenthesizedParameterData)
|
||||
-> (Substs<'tcx>,
|
||||
Vec<Ty<'tcx>>,
|
||||
Vec<ConvertedBinding<'tcx>>)
|
||||
-> (Ty<'tcx>, ConvertedBinding<'tcx>)
|
||||
{
|
||||
let region_substs =
|
||||
self.create_region_substs(rscope, span, decl_generics, Vec::new());
|
||||
|
||||
let anon_scope = rscope.anon_type_scope();
|
||||
let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope);
|
||||
let inputs =
|
||||
data.inputs.iter()
|
||||
.map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
|
||||
0, ®ion_substs, a_t))
|
||||
.collect::<Vec<Ty<'tcx>>>();
|
||||
|
||||
let inputs: Vec<_> = data.inputs.iter().map(|a_t| {
|
||||
self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t)
|
||||
}).collect();
|
||||
let input_params = vec![String::new(); inputs.len()];
|
||||
let implied_output_region = self.find_implied_output_region(&inputs, input_params);
|
||||
|
||||
let input_ty = self.tcx().mk_tup(inputs);
|
||||
|
||||
let (output, output_span) = match data.output {
|
||||
Some(ref output_ty) => {
|
||||
(self.convert_ty_with_lifetime_elision(implied_output_region,
|
||||
|
|
@ -698,7 +635,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
span: output_span
|
||||
};
|
||||
|
||||
(region_substs, vec![input_ty], vec![output_binding])
|
||||
(self.tcx().mk_tup(inputs), output_binding)
|
||||
}
|
||||
|
||||
pub fn instantiate_poly_trait_ref(&self,
|
||||
|
|
@ -838,8 +775,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
};
|
||||
|
||||
let (regions, types, assoc_bindings) = match trait_segment.parameters {
|
||||
hir::AngleBracketedParameters(ref data) => {
|
||||
match trait_segment.parameters {
|
||||
hir::AngleBracketedParameters(_) => {
|
||||
// For now, require that parenthetical notation be used
|
||||
// only with `Fn()` etc.
|
||||
if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
|
||||
|
|
@ -850,10 +787,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
type parameters is subject to change. \
|
||||
Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
|
||||
}
|
||||
|
||||
self.convert_angle_bracketed_parameters(rscope, span, &trait_def.generics, data)
|
||||
}
|
||||
hir::ParenthesizedParameters(ref data) => {
|
||||
hir::ParenthesizedParameters(_) => {
|
||||
// For now, require that parenthetical notation be used
|
||||
// only with `Fn()` etc.
|
||||
if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
|
||||
|
|
@ -862,19 +797,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
"\
|
||||
parenthetical notation is only stable when used with `Fn`-family traits");
|
||||
}
|
||||
|
||||
self.convert_parenthesized_parameters(rscope, span, &trait_def.generics, data)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let substs = self.create_substs_for_ast_path(span,
|
||||
param_mode,
|
||||
&trait_def.generics,
|
||||
Some(self_ty),
|
||||
types,
|
||||
regions);
|
||||
|
||||
(self.tcx().mk_substs(substs), assoc_bindings)
|
||||
self.create_substs_for_ast_path(rscope,
|
||||
span,
|
||||
param_mode,
|
||||
&trait_def.generics,
|
||||
&trait_segment.parameters,
|
||||
Some(self_ty))
|
||||
}
|
||||
|
||||
fn ast_type_binding_to_poly_projection_predicate(
|
||||
|
|
@ -1000,7 +931,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
return self.tcx().mk_box(*substs.types.get(TypeSpace, 0));
|
||||
}
|
||||
|
||||
decl_ty.subst(self.tcx(), &substs)
|
||||
decl_ty.subst(self.tcx(), substs)
|
||||
}
|
||||
|
||||
fn ast_ty_to_object_trait_ref(&self,
|
||||
|
|
@ -1473,24 +1404,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
/// # Parameters
|
||||
///
|
||||
/// * `this`, `rscope`: the surrounding context
|
||||
/// * `decl_generics`: the generics of the struct/enum/trait declaration being
|
||||
/// referenced
|
||||
/// * `index`: the index of the type parameter being instantiated from the list
|
||||
/// (we assume it is in the `TypeSpace`)
|
||||
/// * `def`: the type parameter being instantiated (if available)
|
||||
/// * `region_substs`: a partial substitution consisting of
|
||||
/// only the region type parameters being supplied to this type.
|
||||
/// * `ast_ty`: the ast representation of the type being supplied
|
||||
pub fn ast_ty_arg_to_ty(&self,
|
||||
rscope: &RegionScope,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
index: usize,
|
||||
region_substs: &Substs<'tcx>,
|
||||
ast_ty: &hir::Ty)
|
||||
-> Ty<'tcx>
|
||||
fn ast_ty_arg_to_ty(&self,
|
||||
rscope: &RegionScope,
|
||||
def: Option<&ty::TypeParameterDef<'tcx>>,
|
||||
region_substs: &Substs<'tcx>,
|
||||
ast_ty: &hir::Ty)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
if let Some(def) = decl_generics.types.opt_get(TypeSpace, index) {
|
||||
if let Some(def) = def {
|
||||
let object_lifetime_default = def.object_lifetime_default.subst(tcx, region_substs);
|
||||
let rscope1 = &ObjectLifetimeDefaultRscope::new(rscope, object_lifetime_default);
|
||||
self.ast_ty_to_ty(rscope1, ast_ty)
|
||||
|
|
@ -2194,7 +2121,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
let parameters = &segments[segments.len() - 1].parameters;
|
||||
if !parameters.types().is_empty() {
|
||||
check_type_argument_count(tcx, b.trait_ref.path.span,
|
||||
parameters.types().len(), 0, 0);
|
||||
parameters.types().len(), &[]);
|
||||
}
|
||||
if !parameters.lifetimes().is_empty() {
|
||||
report_lifetime_number_error(tcx, b.trait_ref.path.span,
|
||||
|
|
@ -2225,7 +2152,9 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
}
|
||||
|
||||
fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
|
||||
required: usize, accepted: usize) {
|
||||
ty_param_defs: &[ty::TypeParameterDef]) {
|
||||
let accepted = ty_param_defs.len();
|
||||
let required = ty_param_defs.iter().take_while(|x| x.default.is_none()) .count();
|
||||
if supplied < required {
|
||||
let expected = if required < accepted {
|
||||
"expected at least"
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ use hir::def::{Def, PathResolution};
|
|||
use hir::def_id::DefId;
|
||||
use hir::pat_util;
|
||||
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
|
||||
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
|
||||
use rustc::ty::subst::{self, Subst, Substs};
|
||||
use rustc::traits::{self, Reveal};
|
||||
use rustc::ty::{GenericPredicates, TypeScheme};
|
||||
use rustc::ty::{ParamTy, ParameterEnvironment};
|
||||
|
|
@ -1702,7 +1702,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
PathParamMode::Optional,
|
||||
&type_scheme.generics,
|
||||
path.segments.last().unwrap());
|
||||
let substs = self.tcx.mk_substs(substs);
|
||||
debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs);
|
||||
let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
|
||||
let cause = traits::ObligationCause::new(path.span, self.body_id,
|
||||
|
|
@ -4158,7 +4157,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
assert!(!segments.is_empty());
|
||||
|
||||
let mut ufcs_associated = None;
|
||||
let mut segment_spaces: Vec<_>;
|
||||
let mut type_segment = None;
|
||||
let mut fn_segment = None;
|
||||
match def {
|
||||
// Case 1 and 1b. Reference to a *type* or *enum variant*.
|
||||
Def::SelfTy(..) |
|
||||
|
|
@ -4172,40 +4172,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
Def::TyParam(..) => {
|
||||
// Everything but the final segment should have no
|
||||
// parameters at all.
|
||||
segment_spaces = vec![None; segments.len() - 1];
|
||||
segment_spaces.push(Some(subst::TypeSpace));
|
||||
type_segment = segments.last();
|
||||
}
|
||||
|
||||
// Case 2. Reference to a top-level value.
|
||||
Def::Fn(..) |
|
||||
Def::Const(..) |
|
||||
Def::Static(..) => {
|
||||
segment_spaces = vec![None; segments.len() - 1];
|
||||
segment_spaces.push(Some(subst::FnSpace));
|
||||
}
|
||||
|
||||
// Case 3. Reference to a method.
|
||||
Def::Method(def_id) => {
|
||||
let container = self.tcx.impl_or_trait_item(def_id).container();
|
||||
match container {
|
||||
ty::TraitContainer(trait_did) => {
|
||||
callee::check_legal_trait_for_method_call(self.ccx, span, trait_did)
|
||||
}
|
||||
ty::ImplContainer(_) => {}
|
||||
}
|
||||
|
||||
if segments.len() >= 2 {
|
||||
segment_spaces = vec![None; segments.len() - 2];
|
||||
segment_spaces.push(Some(subst::TypeSpace));
|
||||
segment_spaces.push(Some(subst::FnSpace));
|
||||
} else {
|
||||
// `<T>::method` will end up here, and so can `T::method`.
|
||||
let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
|
||||
segment_spaces = vec![Some(subst::FnSpace)];
|
||||
ufcs_associated = Some((container, self_ty));
|
||||
}
|
||||
fn_segment = segments.last();
|
||||
}
|
||||
|
||||
// Case 3. Reference to a method or associated const.
|
||||
Def::Method(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
let container = self.tcx.impl_or_trait_item(def_id).container();
|
||||
match container {
|
||||
|
|
@ -4216,15 +4194,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
if segments.len() >= 2 {
|
||||
segment_spaces = vec![None; segments.len() - 2];
|
||||
segment_spaces.push(Some(subst::TypeSpace));
|
||||
segment_spaces.push(None);
|
||||
type_segment = Some(&segments[segments.len() - 2]);
|
||||
} else {
|
||||
// `<T>::CONST` will end up here, and so can `T::CONST`.
|
||||
let self_ty = opt_self_ty.expect("UFCS sugared const missing Self");
|
||||
segment_spaces = vec![None];
|
||||
// `<T>::assoc` will end up here, and so can `T::assoc`.
|
||||
let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self");
|
||||
ufcs_associated = Some((container, self_ty));
|
||||
}
|
||||
fn_segment = segments.last();
|
||||
}
|
||||
|
||||
// Other cases. Various nonsense that really shouldn't show up
|
||||
|
|
@ -4234,51 +4210,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
Def::ForeignMod(..) |
|
||||
Def::Local(..) |
|
||||
Def::Label(..) |
|
||||
Def::Upvar(..) => {
|
||||
segment_spaces = vec![None; segments.len()];
|
||||
}
|
||||
Def::Upvar(..) => {}
|
||||
|
||||
Def::Err => {
|
||||
self.set_tainted_by_errors();
|
||||
segment_spaces = vec![None; segments.len()];
|
||||
}
|
||||
}
|
||||
assert_eq!(segment_spaces.len(), segments.len());
|
||||
|
||||
// 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!("segment_spaces={:?}", segment_spaces);
|
||||
|
||||
// Next, examine the definition, and determine how many type
|
||||
// parameters we expect from each space.
|
||||
let type_defs = &type_scheme.generics.types;
|
||||
let region_defs = &type_scheme.generics.regions;
|
||||
debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment);
|
||||
|
||||
// Now that we have categorized what space the parameters for each
|
||||
// segment belong to, let's sort out the parameters that the user
|
||||
// provided (if any) into their appropriate spaces. We'll also report
|
||||
// errors if type parameters are provided in an inappropriate place.
|
||||
let mut substs = Substs::empty();
|
||||
for (&opt_space, segment) in segment_spaces.iter().zip(segments) {
|
||||
if let Some(space) = opt_space {
|
||||
self.push_explicit_parameters_from_segment_to_substs(space,
|
||||
span,
|
||||
type_defs,
|
||||
region_defs,
|
||||
segment,
|
||||
&mut substs);
|
||||
} else {
|
||||
self.tcx.prohibit_type_params(slice::ref_slice(segment));
|
||||
}
|
||||
}
|
||||
if let Some(self_ty) = opt_self_ty {
|
||||
if type_defs.len(subst::SelfSpace) == 1 {
|
||||
substs.types.push(subst::SelfSpace, self_ty);
|
||||
}
|
||||
}
|
||||
let poly_segments = type_segment.is_some() as usize +
|
||||
fn_segment.is_some() as usize;
|
||||
self.tcx.prohibit_type_params(&segments[..segments.len() - poly_segments]);
|
||||
|
||||
// Now we have to compare the types that the user *actually*
|
||||
// provided against the types that were *expected*. If the user
|
||||
|
|
@ -4286,19 +4238,77 @@ 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.
|
||||
for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] {
|
||||
self.adjust_type_parameters(span, space, type_defs,
|
||||
require_type_space, &mut substs);
|
||||
assert_eq!(substs.types.len(space), type_defs.len(space));
|
||||
self.check_path_parameter_count(subst::TypeSpace,
|
||||
span,
|
||||
&type_scheme.generics,
|
||||
!require_type_space,
|
||||
&mut type_segment);
|
||||
self.check_path_parameter_count(subst::FnSpace,
|
||||
span,
|
||||
&type_scheme.generics,
|
||||
true,
|
||||
&mut fn_segment);
|
||||
|
||||
self.adjust_region_parameters(span, space, region_defs, &mut substs);
|
||||
assert_eq!(substs.regions.len(space), region_defs.len(space));
|
||||
}
|
||||
let substs = Substs::from_generics(&type_scheme.generics, |def, _| {
|
||||
let i = def.index as usize;
|
||||
let segment = match def.space {
|
||||
subst::SelfSpace => None,
|
||||
subst::TypeSpace => type_segment,
|
||||
subst::FnSpace => fn_segment
|
||||
};
|
||||
let lifetimes = match segment.map(|s| &s.parameters) {
|
||||
Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..],
|
||||
Some(&hir::ParenthesizedParameters(_)) => bug!(),
|
||||
None => &[]
|
||||
};
|
||||
|
||||
if let Some(ast_lifetime) = lifetimes.get(i) {
|
||||
ast_region_to_region(self.tcx, ast_lifetime)
|
||||
} else {
|
||||
self.region_var_for_def(span, def)
|
||||
}
|
||||
}, |def, substs| {
|
||||
let i = def.index as usize;
|
||||
let segment = match def.space {
|
||||
subst::SelfSpace => None,
|
||||
subst::TypeSpace => type_segment,
|
||||
subst::FnSpace => fn_segment
|
||||
};
|
||||
let types = match segment.map(|s| &s.parameters) {
|
||||
Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..],
|
||||
Some(&hir::ParenthesizedParameters(_)) => bug!(),
|
||||
None => &[]
|
||||
};
|
||||
let can_omit = def.space != subst::TypeSpace || !require_type_space;
|
||||
let default = if can_omit && types.len() == 0 {
|
||||
def.default
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if def.space == subst::SelfSpace && opt_self_ty.is_some() {
|
||||
// Self, which has been provided.
|
||||
assert_eq!(i, 0);
|
||||
opt_self_ty.unwrap()
|
||||
} else if let Some(ast_ty) = types.get(i) {
|
||||
// A provided type parameter.
|
||||
self.to_ty(ast_ty)
|
||||
} else if let Some(default) = default {
|
||||
// No type parameter provided, but a default exists.
|
||||
default.subst_spanned(self.tcx, substs, Some(span))
|
||||
} else {
|
||||
// No type parameters were provided, we can infer all.
|
||||
// This can also be reached in some error cases:
|
||||
// We prefer to use inference variables instead of
|
||||
// TyError to let type inference recover somewhat.
|
||||
self.type_var_for_def(span, def, substs)
|
||||
}
|
||||
});
|
||||
|
||||
// The things we are substituting into the type should not contain
|
||||
// escaping late-bound regions, and nor should the base type scheme.
|
||||
let substs = self.tcx.mk_substs(substs);
|
||||
assert!(!substs.has_regions_escaping_depth(0));
|
||||
assert!(!substs.has_escaping_regions());
|
||||
assert!(!type_scheme.has_escaping_regions());
|
||||
|
||||
// Add all the obligations that are required, substituting and
|
||||
|
|
@ -4349,246 +4359,79 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
ty_substituted
|
||||
}
|
||||
|
||||
/// Finds the parameters that the user provided and adds them to `substs`. If too many
|
||||
/// parameters are provided, then reports an error and clears the output vector.
|
||||
///
|
||||
/// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
|
||||
/// use inference variables. This seems less likely to lead to derived errors.
|
||||
///
|
||||
/// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
|
||||
/// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
|
||||
/// here because we can easily use the precise span of the N+1'th parameter.
|
||||
fn push_explicit_parameters_from_segment_to_substs(&self,
|
||||
space: subst::ParamSpace,
|
||||
span: Span,
|
||||
type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
|
||||
region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
|
||||
segment: &hir::PathSegment,
|
||||
substs: &mut Substs<'tcx>)
|
||||
{
|
||||
match segment.parameters {
|
||||
hir::AngleBracketedParameters(ref data) => {
|
||||
self.push_explicit_angle_bracketed_parameters_from_segment_to_substs(
|
||||
space, type_defs, region_defs, data, substs);
|
||||
/// Report errors if the provided parameters are too few or too many.
|
||||
fn check_path_parameter_count(&self,
|
||||
space: subst::ParamSpace,
|
||||
span: Span,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
can_omit: bool,
|
||||
segment: &mut Option<&hir::PathSegment>) {
|
||||
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");
|
||||
}
|
||||
None => (&[][..], &[][..], &[][..])
|
||||
};
|
||||
|
||||
hir::ParenthesizedParameters(ref data) => {
|
||||
span_err!(self.tcx.sess, span, E0238,
|
||||
"parenthesized parameters may only be used with a trait");
|
||||
self.push_explicit_parenthesized_parameters_from_segment_to_substs(
|
||||
space, span, type_defs, data, substs);
|
||||
}
|
||||
}
|
||||
}
|
||||
let count = |n| {
|
||||
format!("{} parameter{}", n, if n == 1 { "" } else { "s" })
|
||||
};
|
||||
|
||||
fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(&self,
|
||||
space: subst::ParamSpace,
|
||||
type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
|
||||
region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
|
||||
data: &hir::AngleBracketedParameterData,
|
||||
substs: &mut Substs<'tcx>)
|
||||
{
|
||||
{
|
||||
let type_count = type_defs.len(space);
|
||||
assert_eq!(substs.types.len(space), 0);
|
||||
for (i, typ) in data.types.iter().enumerate() {
|
||||
let t = self.to_ty(&typ);
|
||||
if i < type_count {
|
||||
substs.types.push(space, t);
|
||||
} else if i == type_count {
|
||||
struct_span_err!(self.tcx.sess, typ.span, E0087,
|
||||
"too many type parameters provided: \
|
||||
expected at most {} parameter{}, \
|
||||
found {} parameter{}",
|
||||
type_count,
|
||||
if type_count == 1 {""} else {"s"},
|
||||
data.types.len(),
|
||||
if data.types.len() == 1 {""} else {"s"})
|
||||
.span_label(typ.span , &format!("expected {} parameter{}",
|
||||
type_count,
|
||||
if type_count == 1 {""} else {"s"})).emit();
|
||||
substs.types.truncate(space, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Check provided lifetime parameters.
|
||||
let lifetime_defs = generics.regions.get_slice(space);
|
||||
if lifetimes.len() > lifetime_defs.len() {
|
||||
let span = lifetimes[lifetime_defs.len()].span;
|
||||
span_err!(self.tcx.sess, span, E0088,
|
||||
"too many lifetime parameters provided: \
|
||||
expected {}, found {}",
|
||||
count(lifetime_defs.len()),
|
||||
count(lifetimes.len()));
|
||||
} else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() {
|
||||
span_err!(self.tcx.sess, span, E0090,
|
||||
"too few lifetime parameters provided: \
|
||||
expected {}, found {}",
|
||||
count(lifetime_defs.len()),
|
||||
count(lifetimes.len()));
|
||||
}
|
||||
|
||||
if !data.bindings.is_empty() {
|
||||
span_err!(self.tcx.sess, data.bindings[0].span, E0182,
|
||||
// Check provided type parameters.
|
||||
let type_defs = generics.types.get_slice(space);
|
||||
let required_len = type_defs.iter()
|
||||
.take_while(|d| d.default.is_none())
|
||||
.count();
|
||||
if types.len() > type_defs.len() {
|
||||
let span = types[type_defs.len()].span;
|
||||
struct_span_err!(self.tcx.sess, span, E0087,
|
||||
"too many type parameters provided: \
|
||||
expected at most {}, found {}",
|
||||
count(type_defs.len()),
|
||||
count(types.len()))
|
||||
.span_label(span, &format!("expected {}",
|
||||
count(type_defs.len()))).emit();
|
||||
|
||||
// To prevent derived errors to accumulate due to extra
|
||||
// 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 {
|
||||
let qualifier =
|
||||
if type_defs.len() != required_len { "at least " } else { "" };
|
||||
span_err!(self.tcx.sess, span, E0089,
|
||||
"too few type parameters provided: \
|
||||
expected {}{}, found {}",
|
||||
qualifier,
|
||||
count(required_len),
|
||||
count(types.len()));
|
||||
}
|
||||
|
||||
if !bindings.is_empty() {
|
||||
span_err!(self.tcx.sess, bindings[0].span, E0182,
|
||||
"unexpected binding of associated item in expression path \
|
||||
(only allowed in type paths)");
|
||||
}
|
||||
|
||||
{
|
||||
let region_count = region_defs.len(space);
|
||||
assert_eq!(substs.regions.len(space), 0);
|
||||
for (i, lifetime) in data.lifetimes.iter().enumerate() {
|
||||
let r = ast_region_to_region(self.tcx, lifetime);
|
||||
if i < region_count {
|
||||
substs.regions.push(space, r);
|
||||
} else if i == region_count {
|
||||
span_err!(self.tcx.sess, lifetime.span, E0088,
|
||||
"too many lifetime parameters provided: \
|
||||
expected {} parameter{}, found {} parameter{}",
|
||||
region_count,
|
||||
if region_count == 1 {""} else {"s"},
|
||||
data.lifetimes.len(),
|
||||
if data.lifetimes.len() == 1 {""} else {"s"});
|
||||
substs.regions.truncate(space, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// As with
|
||||
/// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
|
||||
/// but intended for `Foo(A,B) -> C` form. This expands to
|
||||
/// roughly the same thing as `Foo<(A,B),C>`. One important
|
||||
/// difference has to do with the treatment of anonymous
|
||||
/// regions, which are translated into bound regions (NYI).
|
||||
fn push_explicit_parenthesized_parameters_from_segment_to_substs(&self,
|
||||
space: subst::ParamSpace,
|
||||
span: Span,
|
||||
type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
|
||||
data: &hir::ParenthesizedParameterData,
|
||||
substs: &mut Substs<'tcx>)
|
||||
{
|
||||
let type_count = type_defs.len(space);
|
||||
if type_count < 2 {
|
||||
span_err!(self.tcx.sess, span, E0167,
|
||||
"parenthesized form always supplies 2 type parameters, \
|
||||
but only {} parameter(s) were expected",
|
||||
type_count);
|
||||
}
|
||||
|
||||
let input_tys: Vec<Ty> =
|
||||
data.inputs.iter().map(|ty| self.to_ty(&ty)).collect();
|
||||
|
||||
let tuple_ty = self.tcx.mk_tup(input_tys);
|
||||
|
||||
if type_count >= 1 {
|
||||
substs.types.push(space, tuple_ty);
|
||||
}
|
||||
|
||||
let output_ty: Option<Ty> =
|
||||
data.output.as_ref().map(|ty| self.to_ty(&ty));
|
||||
|
||||
let output_ty =
|
||||
output_ty.unwrap_or(self.tcx.mk_nil());
|
||||
|
||||
if type_count >= 2 {
|
||||
substs.types.push(space, output_ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_type_parameters(&self,
|
||||
span: Span,
|
||||
space: ParamSpace,
|
||||
defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
|
||||
require_type_space: bool,
|
||||
substs: &mut Substs<'tcx>)
|
||||
{
|
||||
let provided_len = substs.types.len(space);
|
||||
let desired = defs.get_slice(space);
|
||||
let required_len = desired.iter()
|
||||
.take_while(|d| d.default.is_none())
|
||||
.count();
|
||||
|
||||
debug!("adjust_type_parameters(space={:?}, \
|
||||
provided_len={}, \
|
||||
desired_len={}, \
|
||||
required_len={})",
|
||||
space,
|
||||
provided_len,
|
||||
desired.len(),
|
||||
required_len);
|
||||
|
||||
// Enforced by `push_explicit_parameters_from_segment_to_substs()`.
|
||||
assert!(provided_len <= desired.len());
|
||||
|
||||
// Nothing specified at all: supply inference variables for
|
||||
// everything.
|
||||
if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
|
||||
substs.types.replace(space, Vec::new());
|
||||
for def in desired {
|
||||
let ty_var = self.type_var_for_def(span, def, substs);
|
||||
substs.types.push(def.space, ty_var);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Too few parameters specified: report an error and use Err
|
||||
// for everything.
|
||||
if provided_len < required_len {
|
||||
let qualifier =
|
||||
if desired.len() != required_len { "at least " } else { "" };
|
||||
span_err!(self.tcx.sess, span, E0089,
|
||||
"too few type parameters provided: expected {}{} parameter{}, \
|
||||
found {} parameter{}",
|
||||
qualifier, required_len,
|
||||
if required_len == 1 {""} else {"s"},
|
||||
provided_len,
|
||||
if provided_len == 1 {""} else {"s"});
|
||||
substs.types.replace(space, vec![self.tcx.types.err; desired.len()]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, add in any optional parameters that the user
|
||||
// omitted. The case of *too many* parameters is handled
|
||||
// already by
|
||||
// push_explicit_parameters_from_segment_to_substs(). Note
|
||||
// that the *default* type are expressed in terms of all prior
|
||||
// parameters, so we have to substitute as we go with the
|
||||
// partial substitution that we have built up.
|
||||
for i in provided_len..desired.len() {
|
||||
let default = desired[i].default.unwrap();
|
||||
let default = default.subst_spanned(self.tcx, substs, Some(span));
|
||||
substs.types.push(space, default);
|
||||
}
|
||||
assert_eq!(substs.types.len(space), desired.len());
|
||||
|
||||
debug!("Final substs: {:?}", substs);
|
||||
}
|
||||
|
||||
fn adjust_region_parameters(&self,
|
||||
span: Span,
|
||||
space: ParamSpace,
|
||||
defs: &VecPerParamSpace<ty::RegionParameterDef>,
|
||||
substs: &mut Substs)
|
||||
{
|
||||
let provided_len = substs.regions.len(space);
|
||||
let desired = defs.get_slice(space);
|
||||
|
||||
// Enforced by `push_explicit_parameters_from_segment_to_substs()`.
|
||||
assert!(provided_len <= desired.len());
|
||||
|
||||
// If nothing was provided, just use inference variables.
|
||||
if provided_len == 0 {
|
||||
substs.regions.replace(
|
||||
space,
|
||||
self.region_vars_for_defs(span, desired));
|
||||
return;
|
||||
}
|
||||
|
||||
// If just the right number were provided, everybody is happy.
|
||||
if provided_len == desired.len() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, too few were provided. Report an error and then
|
||||
// use inference variables.
|
||||
span_err!(self.tcx.sess, span, E0090,
|
||||
"too few lifetime parameters provided: expected {} parameter{}, \
|
||||
found {} parameter{}",
|
||||
desired.len(),
|
||||
if desired.len() == 1 {""} else {"s"},
|
||||
provided_len,
|
||||
if provided_len == 1 {""} else {"s"});
|
||||
|
||||
substs.regions.replace(
|
||||
space,
|
||||
self.region_vars_for_defs(span, desired));
|
||||
}
|
||||
|
||||
fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F)
|
||||
|
|
|
|||
|
|
@ -4018,7 +4018,7 @@ register_diagnostics! {
|
|||
// E0141,
|
||||
// E0159, // use of trait `{}` as struct constructor
|
||||
// E0163, // merged into E0071
|
||||
E0167,
|
||||
// E0167,
|
||||
// E0168,
|
||||
// E0173, // manual implementations of unboxed closure traits are experimental
|
||||
// E0174,
|
||||
|
|
@ -4053,7 +4053,7 @@ register_diagnostics! {
|
|||
// E0235, // structure constructor specifies a structure of type but
|
||||
// E0236, // no lang item for range syntax
|
||||
// E0237, // no lang item for range syntax
|
||||
E0238, // parenthesized parameters may only be used with a trait
|
||||
// E0238, // parenthesized parameters may only be used with a trait
|
||||
// E0239, // `next` method of `Iterator` trait has unexpected type
|
||||
// E0240,
|
||||
// E0241,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue