提交 a5328bc1 编写于 作者: V varkor

Simply joint lifetime/type iteration

上级 8bccfe7a
......@@ -449,12 +449,6 @@ pub enum TraitBoundModifier {
pub enum GenericParamKind {
/// A lifetime definition, eg `'a: 'b + 'c + 'd`.
Lifetime {
/// Either "'a", referring to a named lifetime definition,
/// or "" (aka keywords::Invalid), for elision placeholders.
///
/// HIR lowering inserts these placeholders in type paths that
/// refer to type definitions needing lifetime parameters,
/// `&T` and `&mut T`, and trait objects without `... + 'a`.
name: LifetimeName,
bounds: HirVec<Lifetime>,
// Indicates that the lifetime definition was synthetically added
......
......@@ -934,10 +934,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
sig.push_str(&generics
.params
.iter()
.map(|param| match param.kind {
ast::GenericParamKind::Lifetime { .. } => param.ident.name.to_string(),
ast::GenericParamKind::Type { .. } => param.ident.to_string(),
})
.map(|param| param.ident.to_string())
.collect::<Vec<_>>()
.join(", "));
sig.push_str("> ");
......
......@@ -996,13 +996,12 @@ fn qpath_to_ty(&self,
pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
for segment in segments {
segment.with_generic_args(|generic_args| {
let mut err_for_lifetime = false;
let mut err_for_type = false;
let (mut err_for_lt, mut err_for_ty) = (false, false);
for arg in &generic_args.args {
let (mut span_err, span, kind) = match arg {
hir::GenericArg::Lifetime(lt) => {
if err_for_lifetime { continue }
err_for_lifetime = true;
if err_for_lt { continue }
err_for_lt = true;
(struct_span_err!(self.tcx().sess, lt.span, E0110,
"lifetime parameters are not allowed on \
this type"),
......@@ -1010,8 +1009,8 @@ pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
"lifetime")
}
hir::GenericArg::Type(ty) => {
if err_for_type { continue }
err_for_type = true;
if err_for_ty { continue }
err_for_ty = true;
(struct_span_err!(self.tcx().sess, ty.span, E0109,
"type parameters are not allowed on this type"),
ty.span,
......@@ -1020,7 +1019,7 @@ pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
};
span_err.span_label(span, format!("{} parameter not allowed", kind))
.emit();
if err_for_lifetime && err_for_type {
if err_for_lt && err_for_ty {
break;
}
}
......
......@@ -329,46 +329,32 @@ fn instantiate_method_substs(
if i < parent_substs.len() {
parent_substs[i]
} else {
match param.kind {
GenericParamDefKind::Lifetime => {
if let Some(lifetime) = provided.as_ref().and_then(|data| {
for arg in &data.args {
match arg {
GenericArg::Lifetime(lt) => {
if i == parent_substs.len() {
return Some(lt);
}
i -= 1;
}
_ => {}
let (is_lt, is_ty) = match param.kind {
GenericParamDefKind::Lifetime => (true, false),
GenericParamDefKind::Type { .. } => (false, true),
};
provided.as_ref().and_then(|data| {
for arg in &data.args {
match arg {
GenericArg::Lifetime(lt) if is_lt => {
if i == parent_substs.len() {
return Some(AstConv::ast_region_to_region(
self.fcx, lt, Some(param)).into());
}
i -= 1;
}
None
}) {
return AstConv::ast_region_to_region(
self.fcx, lifetime, Some(param)).into();
}
}
GenericParamDefKind::Type {..} => {
if let Some(ast_ty) = provided.as_ref().and_then(|data| {
for arg in &data.args {
match arg {
GenericArg::Type(ty) => {
if i == parent_substs.len() + own_counts.lifetimes {
return Some(ty);
}
i -= 1;
}
_ => {}
GenericArg::Lifetime(_) => {}
GenericArg::Type(ty) if is_ty => {
if i == parent_substs.len() + own_counts.lifetimes {
return Some(self.to_ty(ty).into());
}
i -= 1;
}
None
}) {
return self.to_ty(ast_ty).into();
GenericArg::Type(_) => {}
}
}
}
self.var_for_def(self.span, param)
None
}).unwrap_or_else(|| self.var_for_def(self.span, param))
}
})
}
......
......@@ -4977,8 +4977,7 @@ fn check_generic_arg_count(&self,
s.args.as_ref().map_or(
(vec![], vec![], s.infer_types, &[][..]),
|data| {
let mut lifetimes = vec![];
let mut types = vec![];
let (mut lifetimes, mut types) = (vec![], vec![]);
data.args.iter().for_each(|arg| match arg {
GenericArg::Lifetime(lt) => lifetimes.push(lt),
GenericArg::Type(ty) => types.push(ty),
......@@ -4987,14 +4986,6 @@ fn check_generic_arg_count(&self,
}
)
});
let infer_lifetimes = lifetimes.len() == 0;
let count_lifetime_params = |n| {
format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
};
let count_type_params = |n| {
format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
};
// Check provided parameters.
let ((ty_required, ty_accepted), lt_accepted) =
......@@ -5008,9 +4999,7 @@ struct ParamRange {
let mut ty_params = ParamRange { required: 0, accepted: 0 };
for param in &generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {
lt_accepted += 1;
}
GenericParamDefKind::Lifetime => lt_accepted += 1,
GenericParamDefKind::Type { has_default, .. } => {
ty_params.accepted += 1;
if !has_default {
......@@ -5027,36 +5016,37 @@ struct ParamRange {
((ty_params.required, ty_params.accepted), lt_accepted)
});
if types.len() > ty_accepted {
let span = types[ty_accepted].span;
let expected_text = count_type_params(ty_accepted);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0087,
"too many type parameters provided: \
expected at most {}, found {}",
expected_text, actual_text)
.span_label(span, format!("expected {}", expected_text))
.emit();
let count_type_params = |n| {
format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
};
let expected_text = count_type_params(ty_accepted);
let actual_text = count_type_params(types.len());
if let Some((mut err, span)) = if types.len() > ty_accepted {
// 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;
let span = types[ty_accepted].span;
Some((struct_span_err!(self.tcx.sess, span, E0087,
"too many type parameters provided: \
expected at most {}, found {}",
expected_text, actual_text), span))
} else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
let expected_text = count_type_params(ty_required);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0089,
"too few type parameters provided: \
expected {}, found {}",
expected_text, actual_text)
.span_label(span, format!("expected {}", expected_text))
.emit();
Some((struct_span_err!(self.tcx.sess, span, E0089,
"too few type parameters provided: \
expected {}, found {}",
expected_text, actual_text), span))
} else {
None
} {
err.span_label(span, format!("expected {}", expected_text)).emit();
}
if !bindings.is_empty() {
AstConv::prohibit_projection(self, bindings[0].span);
}
let infer_lifetimes = lifetimes.len() == 0;
// Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
let has_late_bound_lifetime_defs =
segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
......@@ -5080,25 +5070,26 @@ struct ParamRange {
return;
}
if lifetimes.len() > lt_accepted {
let count_lifetime_params = |n| {
format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
};
let expected_text = count_lifetime_params(lt_accepted);
let actual_text = count_lifetime_params(lifetimes.len());
if let Some((mut err, span)) = if lifetimes.len() > lt_accepted {
let span = lifetimes[lt_accepted].span;
let expected_text = count_lifetime_params(lt_accepted);
let actual_text = count_lifetime_params(lifetimes.len());
struct_span_err!(self.tcx.sess, span, E0088,
"too many lifetime parameters provided: \
expected at most {}, found {}",
expected_text, actual_text)
.span_label(span, format!("expected {}", expected_text))
.emit();
Some((struct_span_err!(self.tcx.sess, span, E0088,
"too many lifetime parameters provided: \
expected at most {}, found {}",
expected_text, actual_text), span))
} else if lifetimes.len() < lt_accepted && !infer_lifetimes {
let expected_text = count_lifetime_params(lt_accepted);
let actual_text = count_lifetime_params(lifetimes.len());
struct_span_err!(self.tcx.sess, span, E0090,
"too few lifetime parameters provided: \
expected {}, found {}",
expected_text, actual_text)
.span_label(span, format!("expected {}", expected_text))
.emit();
Some((struct_span_err!(self.tcx.sess, span, E0090,
"too few lifetime parameters provided: \
expected {}, found {}",
expected_text, actual_text), span))
} else {
None
} {
err.span_label(span, format!("expected {}", expected_text)).emit();
}
}
......
......@@ -660,15 +660,12 @@ fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) {
let generics = tcx.generics_of(def_id);
let parent = tcx.generics_of(generics.parent.unwrap());
let impl_params: FxHashMap<_, _> =
parent.params.iter()
.flat_map(|param| match param.kind {
GenericParamDefKind::Lifetime => None,
GenericParamDefKind::Type {..} => Some((param.name, param.def_id)),
})
.collect();
for method_param in generics.params.iter() {
let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind {
GenericParamDefKind::Lifetime => None,
GenericParamDefKind::Type {..} => Some((param.name, param.def_id)),
}).collect();
for method_param in &generics.params {
match method_param.kind {
// Shadowing is checked in resolve_lifetime.
GenericParamDefKind::Lifetime => continue,
......
......@@ -35,13 +35,8 @@ fn check_unsafety_coherence(&mut self,
Some(trait_ref) => {
let trait_def = self.tcx.trait_def(trait_ref.def_id);
let unsafe_attr = impl_generics.and_then(|g| {
for param in &g.params {
if param.pure_wrt_drop {
return Some("may_dangle");
}
}
None
let unsafe_attr = impl_generics.and_then(|generics| {
generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
});
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
......
......@@ -117,12 +117,11 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
for param in &generics.params {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}
hir::GenericParamKind::Type { ref default, .. } => {
if default.is_some() {
let def_id = self.tcx.hir.local_def_id(param.id);
self.tcx.type_of(def_id);
}
hir::GenericParamKind::Type { ref default, .. } if default.is_some() => {
let def_id = self.tcx.hir.local_def_id(param.id);
self.tcx.type_of(def_id);
}
hir::GenericParamKind::Type { .. } => {}
}
}
intravisit::walk_generics(self, generics);
......@@ -316,11 +315,8 @@ fn type_parameter_bounds_in_generics(&self,
let from_ty_params =
ast_generics.params.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Type { ref bounds, .. } => {
if param.id == param_id {
return Some(bounds);
}
None
GenericParamKind::Type { ref bounds, .. } if param.id == param_id => {
Some(bounds)
}
_ => None
})
......@@ -1470,11 +1466,8 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.to_ty(tcx);
index += 1;
let bounds = compute_bounds(&icx,
param_ty,
bounds,
SizedByDefault::Yes,
param.span);
let bounds =
compute_bounds(&icx, param_ty, bounds, SizedByDefault::Yes, param.span);
predicates.extend(bounds.predicates(tcx, param_ty));
}
_ => {}
......
......@@ -1501,12 +1501,12 @@ struct Foo {
"##,
E0131: r##"
It is not possible to define `main` with type parameters, or even with function
parameters. When `main` is present, it must take no arguments and return `()`.
It is not possible to define `main` with generic parameters.
When `main` is present, it must take no arguments and return `()`.
Erroneous code example:
```compile_fail,E0131
fn main<T>() { // error: main function is not allowed to have type parameters
fn main<T>() { // error: main function is not allowed to have generic parameters
}
```
"##,
......
......@@ -191,16 +191,9 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
hir::ItemFn(.., ref generics, _) => {
let mut error = false;
if !generics.params.is_empty() {
let param_type = if generics.is_lt_parameterized() {
"lifetime"
} else {
"type"
};
let msg =
format!("`main` function is not allowed to have {} parameters",
param_type);
let label =
format!("`main` cannot have {} parameters", param_type);
let msg = format!("`main` function is not allowed to have generic \
parameters");
let label = format!("`main` cannot have generic parameters");
struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
.span_label(generics.span, label)
.emit();
......
......@@ -3540,27 +3540,23 @@ fn clean(&self, cx: &DocContext) -> GenericArgs {
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
}
} else {
let mut lifetimes = vec![];
let mut types = vec![];
let (mut lifetimes, mut types) = (vec![], vec![]);
let mut elided_lifetimes = true;
for arg in &self.args {
match arg {
GenericArg::Lifetime(lt) if elided_lifetimes => {
if lt.is_elided() {
GenericArg::Lifetime(lt) => {
if !lt.is_elided() {
elided_lifetimes = false;
lifetimes = vec![];
continue;
}
lifetimes.push(lt.clean(cx));
}
GenericArg::Lifetime(_) => {}
GenericArg::Type(ty) => {
types.push(ty.clean(cx));
}
}
}
GenericArgs::AngleBracketed {
lifetimes,
lifetimes: if elided_lifetimes { vec![] } else { lifetimes },
types,
bindings: self.bindings.clean(cx),
}
......
......@@ -136,7 +136,7 @@ fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArg
fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
match generic_arg {
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
GenericArg::Type(ty) => self.visit_ty(ty),
GenericArg::Type(ty) => self.visit_ty(ty),
}
}
fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) {
......
......@@ -665,35 +665,18 @@ fn create_derived_impl(&self,
// Create the reference to the trait.
let trait_ref = cx.trait_ref(trait_path);
// Create the type parameters on the `self` path.
let self_ty_params: Vec<P<ast::Ty>> = generics.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Type { .. } => Some(cx.ty_ident(self.span, param.ident)),
_ => None,
})
.collect();
let self_lifetimes: Vec<ast::Lifetime> = generics.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { ref lifetime, .. } => Some(*lifetime),
_ => None,
})
.collect();
let self_params = self_lifetimes.into_iter()
.map(|lt| GenericArg::Lifetime(lt))
.chain(self_ty_params.into_iter().map(|ty|
GenericArg::Type(ty)))
.collect();
let self_params: Vec<_> = generics.params.iter().map(|param| match param.kind {
GenericParamKind::Lifetime { ref lifetime, .. } => {
GenericArg::Lifetime(*lifetime)
}
GenericParamKind::Type { .. } => {
GenericArg::Type(cx.ty_ident(self.span, param.ident))
}
}).collect();
// Create the type of `self`.
let self_type = cx.ty_path(cx.path_all(self.span,
false,
vec![type_ident],
self_params,
Vec::new()));
let path = cx.path_all(self.span, false, vec![type_ident], self_params, vec![]);
let self_type = cx.ty_path(path);
let attr = cx.attribute(self.span,
cx.meta_word(self.span,
......
......@@ -185,41 +185,22 @@ pub fn to_path(&self,
cx: &ExtCtxt,
span: Span,
self_ty: Ident,
self_generics: &Generics)
generics: &Generics)
-> ast::Path {
match *self {
Self_ => {
let ty_params: Vec<P<ast::Ty>> = self_generics.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Type { .. } => {
Some(cx.ty_ident(span, param.ident))
}
_ => None,
})
.collect();
let lifetimes: Vec<ast::Lifetime> = self_generics.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { ref lifetime, .. } => Some(*lifetime),
_ => None,
})
.collect();
let params = lifetimes.into_iter()
.map(|lt| GenericArg::Lifetime(lt))
.chain(ty_params.into_iter().map(|ty|
GenericArg::Type(ty)))
.collect();
let params: Vec<_> = generics.params.iter().map(|param| match param.kind {
GenericParamKind::Lifetime { ref lifetime, .. } => {
GenericArg::Lifetime(*lifetime)
}
GenericParamKind::Type { .. } => {
GenericArg::Type(cx.ty_ident(span, param.ident))
}
}).collect();
cx.path_all(span,
false,
vec![self_ty],
params,
Vec::new())
cx.path_all(span, false, vec![self_ty], params, vec![])
}
Literal(ref p) => p.to_path(cx, span, self_ty, self_generics),
Literal(ref p) => p.to_path(cx, span, self_ty, generics),
Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"),
Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"),
}
......
......@@ -43,7 +43,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
cx.ty_ident(sp, Ident::from_str("str")),
Some(lt),
ast::Mutability::Immutable))],
Vec::new()))
vec![]))
}
Ok(s) => {
cx.expr_call_global(sp,
......
......@@ -8,5 +8,5 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: `main` function is not allowed to have type parameters
// error-pattern: `main` function is not allowed to have generic parameters
fn main<T>() { }
error[E0131]: `main` function is not allowed to have type parameters
error[E0131]: `main` function is not allowed to have generic parameters
--> $DIR/E0131.rs:11:8
|
LL | fn main<T>() {
| ^^^ `main` cannot have type parameters
| ^^^ `main` cannot have generic parameters
error: aborting due to previous error
......
......@@ -9,4 +9,4 @@
// except according to those terms.
fn main<'a>() { }
//~^ ERROR `main` function is not allowed to have lifetime parameters [E0131]
//~^ ERROR `main` function is not allowed to have generic parameters [E0131]
error[E0131]: `main` function is not allowed to have lifetime parameters
error[E0131]: `main` function is not allowed to have generic parameters
--> $DIR/issue-51022.rs:11:8
|
LL | fn main<'a>() { }
| ^^^^ `main` cannot have lifetime parameters
| ^^^^ `main` cannot have generic parameters
error: aborting due to previous error
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册