Simply joint lifetime/type iteration
This commit is contained in:
parent
8bccfe7a52
commit
a5328bc17b
19 changed files with 123 additions and 218 deletions
|
@ -449,12 +449,6 @@ pub type TyParamBounds = HirVec<TyParamBound>;
|
|||
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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
"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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
};
|
||||
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 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||
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();
|
||||
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;
|
||||
}
|
||||
GenericArg::Type(_) => {}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}) {
|
||||
return self.to_ty(ast_ty).into();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.var_for_def(self.span, param)
|
||||
None
|
||||
}).unwrap_or_else(|| self.var_for_def(self.span, param))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4977,8 +4977,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
)
|
||||
});
|
||||
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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
((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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
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();
|
||||
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() {
|
||||
for method_param in &generics.params {
|
||||
match method_param.kind {
|
||||
// Shadowing is checked in resolve_lifetime.
|
||||
GenericParamDefKind::Lifetime => continue,
|
||||
|
|
|
@ -35,13 +35,8 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
|
|||
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
|
|||
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 @@ impl Clean<GenericArgs> for hir::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 @@ pub trait Visitor<'ast>: Sized {
|
|||
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 @@ impl<'a> TraitDef<'a> {
|
|||
// 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 @@ impl<'a> Ty<'a> {
|
|||
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 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();
|
||||
|
||||
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();
|
||||
|
||||
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>() { }
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
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]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue