rollup merge of #18630 : nikomatsakis/purge-the-bars
This commit is contained in:
commit
76d2abe0e7
@ -57,7 +57,6 @@ register_diagnostics!(
|
||||
E0044,
|
||||
E0045,
|
||||
E0046,
|
||||
E0047,
|
||||
E0049,
|
||||
E0050,
|
||||
E0051,
|
||||
@ -111,7 +110,6 @@ register_diagnostics!(
|
||||
E0108,
|
||||
E0109,
|
||||
E0110,
|
||||
E0113,
|
||||
E0116,
|
||||
E0117,
|
||||
E0118,
|
||||
@ -145,5 +143,6 @@ register_diagnostics!(
|
||||
E0163,
|
||||
E0164,
|
||||
E0165,
|
||||
E0166
|
||||
E0166,
|
||||
E0167
|
||||
)
|
||||
|
@ -138,7 +138,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) -> bool {
|
||||
// to handle on-demand instantiation of functions via
|
||||
// foo::<bar> in a const. Currently that is only done on
|
||||
// a path in trans::callee that only works in block contexts.
|
||||
if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
|
||||
if !pth.segments.iter().all(|segment| segment.parameters.is_empty()) {
|
||||
span_err!(v.tcx.sess, e.span, E0013,
|
||||
"paths in constants may only refer to items without \
|
||||
type parameters");
|
||||
|
@ -16,7 +16,6 @@ use std::collections::HashMap;
|
||||
use syntax::ast::*;
|
||||
use syntax::ast_util::{walk_pat};
|
||||
use syntax::codemap::{Span, DUMMY_SP};
|
||||
use syntax::owned_slice::OwnedSlice;
|
||||
|
||||
pub type PatIdMap = HashMap<Ident, NodeId>;
|
||||
|
||||
@ -133,8 +132,7 @@ pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
|
||||
global: false,
|
||||
segments: path.last().map(|elem| PathSegment {
|
||||
identifier: Ident::new(elem.name()),
|
||||
lifetimes: vec!(),
|
||||
types: OwnedSlice::empty()
|
||||
parameters: PathParameters::none(),
|
||||
}).into_iter().collect(),
|
||||
span: DUMMY_SP,
|
||||
})
|
||||
|
@ -27,7 +27,6 @@ use syntax::ast_map;
|
||||
use syntax::ast_util::{is_local, local_def, PostExpansionMethod};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
use syntax::owned_slice::OwnedSlice;
|
||||
use syntax::visit;
|
||||
use syntax::visit::Visitor;
|
||||
|
||||
@ -945,8 +944,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
debug!("privacy - ident item {}", id);
|
||||
let seg = ast::PathSegment {
|
||||
identifier: name,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
};
|
||||
let segs = vec![seg];
|
||||
let path = ast::Path {
|
||||
|
@ -40,7 +40,7 @@ use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32};
|
||||
use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt};
|
||||
use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyProc, TyQPath};
|
||||
use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
|
||||
use syntax::ast::{TypeImplItem, UnboxedFnTyParamBound, UnnamedField};
|
||||
use syntax::ast::{TypeImplItem, UnnamedField};
|
||||
use syntax::ast::{Variant, ViewItem, ViewItemExternCrate};
|
||||
use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use syntax::ast::{Visibility};
|
||||
@ -4523,41 +4523,6 @@ impl<'a> Resolver<'a> {
|
||||
TraitTyParamBound(ref tref) => {
|
||||
self.resolve_trait_reference(id, tref, reference_type)
|
||||
}
|
||||
UnboxedFnTyParamBound(ref unboxed_function) => {
|
||||
match self.resolve_path(unboxed_function.ref_id,
|
||||
&unboxed_function.path,
|
||||
TypeNS,
|
||||
true) {
|
||||
None => {
|
||||
let path_str = self.path_names_to_string(
|
||||
&unboxed_function.path);
|
||||
self.resolve_error(unboxed_function.path.span,
|
||||
format!("unresolved trait `{}`",
|
||||
path_str).as_slice())
|
||||
}
|
||||
Some(def) => {
|
||||
match def {
|
||||
(DefTrait(_), _) => {
|
||||
self.record_def(unboxed_function.ref_id, def);
|
||||
}
|
||||
_ => {
|
||||
let msg =
|
||||
format!("`{}` is not a trait",
|
||||
self.path_names_to_string(
|
||||
&unboxed_function.path));
|
||||
self.resolve_error(unboxed_function.path.span,
|
||||
msg.as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for argument in unboxed_function.decl.inputs.iter() {
|
||||
self.resolve_type(&*argument.ty);
|
||||
}
|
||||
|
||||
self.resolve_type(&*unboxed_function.decl.output);
|
||||
}
|
||||
RegionTyParamBound(..) => {}
|
||||
}
|
||||
}
|
||||
@ -4951,12 +4916,12 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
if path.segments
|
||||
.iter()
|
||||
.any(|s| !s.lifetimes.is_empty()) {
|
||||
.any(|s| s.parameters.has_lifetimes()) {
|
||||
span_err!(self.session, path.span, E0157,
|
||||
"lifetime parameters are not allowed on this type");
|
||||
} else if path.segments
|
||||
.iter()
|
||||
.any(|s| s.types.len() > 0) {
|
||||
.any(|s| !s.parameters.is_empty()) {
|
||||
span_err!(self.session, path.span, E0153,
|
||||
"type parameters are not allowed on this type");
|
||||
}
|
||||
@ -5234,7 +5199,7 @@ impl<'a> Resolver<'a> {
|
||||
// Check the types in the path pattern.
|
||||
for ty in path.segments
|
||||
.iter()
|
||||
.flat_map(|s| s.types.iter()) {
|
||||
.flat_map(|s| s.parameters.types().into_iter()) {
|
||||
self.resolve_type(&**ty);
|
||||
}
|
||||
}
|
||||
@ -5340,7 +5305,7 @@ impl<'a> Resolver<'a> {
|
||||
namespace: Namespace,
|
||||
check_ribs: bool) -> Option<(Def, LastPrivate)> {
|
||||
// First, resolve the types.
|
||||
for ty in path.segments.iter().flat_map(|s| s.types.iter()) {
|
||||
for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) {
|
||||
self.resolve_type(&**ty);
|
||||
}
|
||||
|
||||
|
@ -204,9 +204,6 @@ impl<'a> LifetimeContext<'a> {
|
||||
ast::TraitTyParamBound(ref trait_ref) => {
|
||||
self.visit_trait_ref(trait_ref);
|
||||
}
|
||||
ast::UnboxedFnTyParamBound(ref fn_decl) => {
|
||||
self.visit_unboxed_fn_ty_param_bound(&**fn_decl);
|
||||
}
|
||||
ast::RegionTyParamBound(ref lifetime) => {
|
||||
self.visit_lifetime_ref(lifetime);
|
||||
}
|
||||
@ -226,18 +223,6 @@ impl<'a> LifetimeContext<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_unboxed_fn_ty_param_bound(&mut self,
|
||||
bound: &ast::UnboxedFnBound) {
|
||||
self.with(|scope, f| {
|
||||
f(LateScope(bound.ref_id, &bound.lifetimes, scope))
|
||||
}, |v| {
|
||||
for argument in bound.decl.inputs.iter() {
|
||||
v.visit_ty(&*argument.ty);
|
||||
}
|
||||
v.visit_ty(&*bound.decl.output);
|
||||
})
|
||||
}
|
||||
|
||||
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
|
||||
fn visit_fn_decl(&mut self,
|
||||
n: ast::NodeId,
|
||||
|
@ -705,7 +705,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
ast::TraitTyParamBound(ref trait_ref) => {
|
||||
trait_ref
|
||||
}
|
||||
ast::UnboxedFnTyParamBound(..) | ast::RegionTyParamBound(..) => {
|
||||
ast::RegionTyParamBound(..) => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
@ -1836,11 +1836,7 @@ pub fn trans_closure(ccx: &CrateContext,
|
||||
NotUnboxedClosure => monomorphized_arg_types,
|
||||
|
||||
// Tuple up closure argument types for the "rust-call" ABI.
|
||||
IsUnboxedClosure => vec![if monomorphized_arg_types.is_empty() {
|
||||
ty::mk_nil()
|
||||
} else {
|
||||
ty::mk_tup(ccx.tcx(), monomorphized_arg_types)
|
||||
}]
|
||||
IsUnboxedClosure => vec![ty::mk_tup_or_nil(ccx.tcx(), monomorphized_arg_types)]
|
||||
};
|
||||
for monomorphized_arg_type in monomorphized_arg_types.iter() {
|
||||
debug!("trans_closure: monomorphized_arg_type: {}",
|
||||
|
@ -625,7 +625,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
|
||||
}
|
||||
ast::ExprPath(ref pth) => {
|
||||
// Assert that there are no type parameters in this path.
|
||||
assert!(pth.segments.iter().all(|seg| seg.types.is_empty()));
|
||||
assert!(pth.segments.iter().all(|seg| !seg.parameters.has_types()));
|
||||
|
||||
let opt_def = cx.tcx().def_map.borrow().find_copy(&e.id);
|
||||
match opt_def {
|
||||
|
@ -1838,6 +1838,14 @@ pub fn mk_slice(cx: &ctxt, r: Region, tm: mt) -> t {
|
||||
|
||||
pub fn mk_tup(cx: &ctxt, ts: Vec<t>) -> t { mk_t(cx, ty_tup(ts)) }
|
||||
|
||||
pub fn mk_tup_or_nil(cx: &ctxt, ts: Vec<t>) -> t {
|
||||
if ts.len() == 0 {
|
||||
ty::mk_nil()
|
||||
} else {
|
||||
mk_t(cx, ty_tup(ts))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_closure(cx: &ctxt, fty: ClosureTy) -> t {
|
||||
mk_t(cx, ty_closure(box fty))
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ use middle::subst::{VecPerParamSpace};
|
||||
use middle::ty;
|
||||
use middle::typeck::lookup_def_tcx;
|
||||
use middle::typeck::infer;
|
||||
use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope};
|
||||
use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope, BindingRscope};
|
||||
use middle::typeck::rscope;
|
||||
use middle::typeck::TypeAndSubsts;
|
||||
use middle::typeck;
|
||||
@ -207,15 +207,16 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
}
|
||||
|
||||
fn ast_path_substs<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
decl_def_id: ast::DefId,
|
||||
decl_generics: &ty::Generics,
|
||||
self_ty: Option<ty::t>,
|
||||
associated_ty: Option<ty::t>,
|
||||
path: &ast::Path)
|
||||
-> Substs
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
decl_def_id: ast::DefId,
|
||||
decl_generics: &ty::Generics,
|
||||
self_ty: Option<ty::t>,
|
||||
associated_ty: Option<ty::t>,
|
||||
path: &ast::Path,
|
||||
binder_id: ast::NodeId)
|
||||
-> Substs
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
/*!
|
||||
* Given a path `path` that refers to an item `I` with the
|
||||
@ -236,45 +237,51 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||
assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
|
||||
assert!(decl_generics.types.all(|d| d.space != FnSpace));
|
||||
|
||||
let (regions, types) = match path.segments.last().unwrap().parameters {
|
||||
ast::AngleBracketedParameters(ref data) =>
|
||||
angle_bracketed_parameters(this, rscope, data),
|
||||
ast::ParenthesizedParameters(ref data) =>
|
||||
parenthesized_parameters(this, binder_id, data),
|
||||
};
|
||||
|
||||
// If the type is parameterized by the 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 = path.segments.last().unwrap().lifetimes.len();
|
||||
let supplied_num_region_params = regions.len();
|
||||
let regions = if expected_num_region_params == supplied_num_region_params {
|
||||
path.segments.last().unwrap().lifetimes.iter().map(
|
||||
|l| ast_region_to_region(this.tcx(), l)).collect::<Vec<_>>()
|
||||
regions
|
||||
} else {
|
||||
let anon_regions =
|
||||
rscope.anon_regions(path.span, expected_num_region_params);
|
||||
|
||||
if supplied_num_region_params != 0 || anon_regions.is_err() {
|
||||
span_err!(tcx.sess, path.span, E0107,
|
||||
"wrong number of lifetime parameters: expected {}, found {}",
|
||||
expected_num_region_params, supplied_num_region_params);
|
||||
"wrong number of lifetime parameters: expected {}, found {}",
|
||||
expected_num_region_params, supplied_num_region_params);
|
||||
}
|
||||
|
||||
match anon_regions {
|
||||
Ok(v) => v.into_iter().collect(),
|
||||
Err(_) => Vec::from_fn(expected_num_region_params,
|
||||
|_| ty::ReStatic) // hokey
|
||||
|_| ty::ReStatic) // hokey
|
||||
}
|
||||
};
|
||||
|
||||
// Convert the type parameters supplied by the user.
|
||||
let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
|
||||
let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).count();
|
||||
let supplied_ty_param_count = types.len();
|
||||
let formal_ty_param_count =
|
||||
ty_param_defs.iter()
|
||||
.take_while(|x| !ty::is_associated_type(tcx, x.def_id))
|
||||
.count();
|
||||
.take_while(|x| !ty::is_associated_type(tcx, x.def_id))
|
||||
.count();
|
||||
let required_ty_param_count =
|
||||
ty_param_defs.iter()
|
||||
.take_while(|x| {
|
||||
x.default.is_none() &&
|
||||
!ty::is_associated_type(tcx, x.def_id)
|
||||
})
|
||||
.count();
|
||||
.take_while(|x| {
|
||||
x.default.is_none() &&
|
||||
!ty::is_associated_type(tcx, x.def_id)
|
||||
})
|
||||
.count();
|
||||
if supplied_ty_param_count < required_ty_param_count {
|
||||
let expected = if required_ty_param_count < formal_ty_param_count {
|
||||
"expected at least"
|
||||
@ -282,10 +289,10 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||
"expected"
|
||||
};
|
||||
this.tcx().sess.span_fatal(path.span,
|
||||
format!("wrong number of type arguments: {} {}, found {}",
|
||||
expected,
|
||||
required_ty_param_count,
|
||||
supplied_ty_param_count).as_slice());
|
||||
format!("wrong number of type arguments: {} {}, found {}",
|
||||
expected,
|
||||
required_ty_param_count,
|
||||
supplied_ty_param_count).as_slice());
|
||||
} else if supplied_ty_param_count > formal_ty_param_count {
|
||||
let expected = if required_ty_param_count < formal_ty_param_count {
|
||||
"expected at most"
|
||||
@ -293,10 +300,10 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||
"expected"
|
||||
};
|
||||
this.tcx().sess.span_fatal(path.span,
|
||||
format!("wrong number of type arguments: {} {}, found {}",
|
||||
expected,
|
||||
formal_ty_param_count,
|
||||
supplied_ty_param_count).as_slice());
|
||||
format!("wrong number of type arguments: {} {}, found {}",
|
||||
expected,
|
||||
formal_ty_param_count,
|
||||
supplied_ty_param_count).as_slice());
|
||||
}
|
||||
|
||||
if supplied_ty_param_count > required_ty_param_count
|
||||
@ -307,13 +314,7 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||
"add #![feature(default_type_params)] to the crate attributes to enable");
|
||||
}
|
||||
|
||||
let tps = path.segments
|
||||
.iter()
|
||||
.flat_map(|s| s.types.iter())
|
||||
.map(|a_t| ast_ty_to_ty(this, rscope, &**a_t))
|
||||
.collect();
|
||||
|
||||
let mut substs = Substs::new_type(tps, regions);
|
||||
let mut substs = Substs::new_type(types, regions);
|
||||
|
||||
match self_ty {
|
||||
None => {
|
||||
@ -354,7 +355,47 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||
param.def_id))
|
||||
}
|
||||
|
||||
substs
|
||||
return substs;
|
||||
|
||||
fn angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
data: &ast::AngleBracketedParameterData)
|
||||
-> (Vec<ty::Region>, Vec<ty::t>)
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
let regions: Vec<_> =
|
||||
data.lifetimes.iter()
|
||||
.map(|l| ast_region_to_region(this.tcx(), l))
|
||||
.collect();
|
||||
|
||||
let types: Vec<_> =
|
||||
data.types.iter()
|
||||
.map(|t| ast_ty_to_ty(this, rscope, &**t))
|
||||
.collect();
|
||||
|
||||
(regions, types)
|
||||
}
|
||||
|
||||
fn parenthesized_parameters<'tcx,AC>(this: &AC,
|
||||
binder_id: ast::NodeId,
|
||||
data: &ast::ParenthesizedParameterData)
|
||||
-> (Vec<ty::Region>, Vec<ty::t>)
|
||||
where AC: AstConv<'tcx>
|
||||
{
|
||||
let binding_rscope = BindingRscope::new(binder_id);
|
||||
|
||||
let inputs = data.inputs.iter()
|
||||
.map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t))
|
||||
.collect();
|
||||
let input_ty = ty::mk_tup_or_nil(this.tcx(), inputs);
|
||||
|
||||
let output = match data.output {
|
||||
Some(ref output_ty) => ast_ty_to_ty(this, &binding_rscope, &**output_ty),
|
||||
None => ty::mk_nil()
|
||||
};
|
||||
|
||||
(Vec::new(), vec![input_ty, output])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
@ -362,7 +403,8 @@ pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
trait_def_id: ast::DefId,
|
||||
self_ty: Option<ty::t>,
|
||||
associated_type: Option<ty::t>,
|
||||
path: &ast::Path)
|
||||
path: &ast::Path,
|
||||
binder_id: ast::NodeId)
|
||||
-> Rc<ty::TraitRef>
|
||||
where AC: AstConv<'tcx>,
|
||||
RS: RegionScope {
|
||||
@ -375,7 +417,8 @@ pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
&trait_def.generics,
|
||||
self_ty,
|
||||
associated_type,
|
||||
path)
|
||||
path,
|
||||
binder_id)
|
||||
})
|
||||
}
|
||||
|
||||
@ -383,8 +426,10 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
did: ast::DefId,
|
||||
path: &ast::Path)
|
||||
-> TypeAndSubsts {
|
||||
path: &ast::Path,
|
||||
binder_id: ast::NodeId)
|
||||
-> TypeAndSubsts
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
let ty::Polytype {
|
||||
generics,
|
||||
@ -397,7 +442,8 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
&generics,
|
||||
None,
|
||||
None,
|
||||
path);
|
||||
path,
|
||||
binder_id);
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
TypeAndSubsts { substs: substs, ty: ty }
|
||||
}
|
||||
@ -407,24 +453,29 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
/// and/or region variables are substituted.
|
||||
///
|
||||
/// This is used when checking the constructor in struct literals.
|
||||
pub fn ast_path_to_ty_relaxed<'tcx, AC: AstConv<'tcx>,
|
||||
RS:RegionScope>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
did: ast::DefId,
|
||||
path: &ast::Path)
|
||||
-> TypeAndSubsts {
|
||||
pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
did: ast::DefId,
|
||||
path: &ast::Path,
|
||||
binder_id: ast::NodeId)
|
||||
-> TypeAndSubsts
|
||||
where AC : AstConv<'tcx>, RS : RegionScope
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
let ty::Polytype {
|
||||
generics,
|
||||
ty: decl_ty
|
||||
} = this.get_item_ty(did);
|
||||
|
||||
let substs = if (generics.has_type_params(TypeSpace) ||
|
||||
generics.has_region_params(TypeSpace)) &&
|
||||
path.segments.iter().all(|s| {
|
||||
s.lifetimes.len() == 0 && s.types.len() == 0
|
||||
}) {
|
||||
let wants_params =
|
||||
generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
|
||||
|
||||
let needs_defaults =
|
||||
wants_params &&
|
||||
path.segments.iter().all(|s| s.parameters.is_empty());
|
||||
|
||||
let substs = if needs_defaults {
|
||||
let type_params = Vec::from_fn(generics.types.len(TypeSpace),
|
||||
|_| this.ty_infer(path.span));
|
||||
let region_params =
|
||||
@ -433,7 +484,7 @@ pub fn ast_path_to_ty_relaxed<'tcx, AC: AstConv<'tcx>,
|
||||
Substs::new(VecPerParamSpace::params_from_type(type_params),
|
||||
VecPerParamSpace::params_from_type(region_params))
|
||||
} else {
|
||||
ast_path_substs(this, rscope, did, &generics, None, None, path)
|
||||
ast_path_substs(this, rscope, did, &generics, None, None, path, binder_id)
|
||||
};
|
||||
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
@ -450,14 +501,14 @@ fn check_path_args(tcx: &ty::ctxt,
|
||||
path: &ast::Path,
|
||||
flags: uint) {
|
||||
if (flags & NO_TPS) != 0u {
|
||||
if !path.segments.iter().all(|s| s.types.is_empty()) {
|
||||
if path.segments.iter().any(|s| s.parameters.has_types()) {
|
||||
span_err!(tcx.sess, path.span, E0109,
|
||||
"type parameters are not allowed on this type");
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & NO_REGIONS) != 0u {
|
||||
if !path.segments.last().unwrap().lifetimes.is_empty() {
|
||||
if path.segments.iter().any(|s| s.parameters.has_lifetimes()) {
|
||||
span_err!(tcx.sess, path.span, E0110,
|
||||
"region parameters are not allowed on this type");
|
||||
}
|
||||
@ -538,29 +589,23 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
// FIXME(#12938): This is a hack until we have full support for
|
||||
// DST.
|
||||
match a_def {
|
||||
def::DefTy(did, _) | def::DefStruct(did)
|
||||
if Some(did) == this.tcx().lang_items.owned_box() => {
|
||||
if path.segments
|
||||
.iter()
|
||||
.flat_map(|s| s.types.iter())
|
||||
.count() > 1 {
|
||||
span_err!(this.tcx().sess, path.span, E0047,
|
||||
"`Box` has only one type parameter");
|
||||
def::DefTy(did, _) |
|
||||
def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => {
|
||||
let ty = ast_path_to_ty(this, rscope, did, path, id).ty;
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_struct(struct_def_id, ref substs) => {
|
||||
assert_eq!(struct_def_id, did);
|
||||
assert_eq!(substs.types.len(TypeSpace), 1);
|
||||
let referent_ty = *substs.types.get(TypeSpace, 0);
|
||||
Some(ty::mk_uniq(this.tcx(), referent_ty))
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.span_bug(
|
||||
path.span,
|
||||
format!("converting `Box` to `{}`",
|
||||
ty.repr(this.tcx()))[]);
|
||||
}
|
||||
}
|
||||
|
||||
for inner_ast_type in path.segments
|
||||
.iter()
|
||||
.flat_map(|s| s.types.iter()) {
|
||||
return Some(mk_pointer(this,
|
||||
rscope,
|
||||
ast::MutImmutable,
|
||||
&**inner_ast_type,
|
||||
Uniq,
|
||||
|typ| ty::mk_uniq(this.tcx(), typ)));
|
||||
}
|
||||
span_err!(this.tcx().sess, path.span, E0113,
|
||||
"not enough type parameters supplied to `Box<T>`");
|
||||
Some(ty::mk_err())
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
@ -575,15 +620,6 @@ enum PointerTy {
|
||||
Uniq
|
||||
}
|
||||
|
||||
impl PointerTy {
|
||||
fn default_region(&self) -> ty::Region {
|
||||
match *self {
|
||||
Uniq => ty::ReStatic,
|
||||
RPtr(r) => r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trait_ref_for_unboxed_function<'tcx, AC: AstConv<'tcx>,
|
||||
RS:RegionScope>(
|
||||
this: &AC,
|
||||
@ -603,11 +639,7 @@ pub fn trait_ref_for_unboxed_function<'tcx, AC: AstConv<'tcx>,
|
||||
.map(|input| {
|
||||
ast_ty_to_ty(this, rscope, &*input.ty)
|
||||
}).collect::<Vec<_>>();
|
||||
let input_tuple = if input_types.len() == 0 {
|
||||
ty::mk_nil()
|
||||
} else {
|
||||
ty::mk_tup(this.tcx(), input_types)
|
||||
};
|
||||
let input_tuple = ty::mk_tup_or_nil(this.tcx(), input_types);
|
||||
let output_type = ast_ty_to_ty(this, rscope, &*decl.output);
|
||||
let mut substs = Substs::new_type(vec!(input_tuple, output_type),
|
||||
Vec::new());
|
||||
@ -646,31 +678,6 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
let ty = ast_ty_to_ty(this, rscope, &**ty);
|
||||
return constr(ty::mk_vec(tcx, ty, None));
|
||||
}
|
||||
ast::TyUnboxedFn(ref unboxed_function) => {
|
||||
let ty::TraitRef {
|
||||
def_id,
|
||||
substs
|
||||
} = trait_ref_for_unboxed_function(this,
|
||||
rscope,
|
||||
unboxed_function.kind,
|
||||
&*unboxed_function.decl,
|
||||
None);
|
||||
let r = ptr_ty.default_region();
|
||||
let tr = ty::mk_trait(this.tcx(),
|
||||
def_id,
|
||||
substs,
|
||||
ty::region_existential_bound(r));
|
||||
match ptr_ty {
|
||||
Uniq => {
|
||||
return ty::mk_uniq(this.tcx(), tr);
|
||||
}
|
||||
RPtr(r) => {
|
||||
return ty::mk_rptr(this.tcx(),
|
||||
r,
|
||||
ty::mt {mutbl: a_seq_mutbl, ty: tr});
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TyPath(ref path, ref opt_bounds, id) => {
|
||||
// Note that the "bounds must be empty if path is not a trait"
|
||||
// restriction is enforced in the below case for ty_path, which
|
||||
@ -693,7 +700,8 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
trait_def_id,
|
||||
None,
|
||||
None,
|
||||
path);
|
||||
path,
|
||||
id);
|
||||
let bounds = match *opt_bounds {
|
||||
None => {
|
||||
conv_existential_bounds(this,
|
||||
@ -771,7 +779,12 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
||||
trait_did,
|
||||
None,
|
||||
Some(for_type),
|
||||
trait_path);
|
||||
trait_path,
|
||||
ast::DUMMY_NODE_ID); // *see below
|
||||
|
||||
// * The trait in a qualified path cannot be "higher-ranked" and
|
||||
// hence cannot use the parenthetical sugar, so the binder-id is
|
||||
// irrelevant.
|
||||
|
||||
debug!("associated_ty_to_ty(trait_ref={})",
|
||||
trait_ref.repr(this.tcx()));
|
||||
@ -894,11 +907,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
|
||||
ty::mk_closure(tcx, fn_decl)
|
||||
}
|
||||
ast::TyUnboxedFn(..) => {
|
||||
tcx.sess.span_err(ast_ty.span,
|
||||
"cannot use unboxed functions here");
|
||||
ty::mk_err()
|
||||
}
|
||||
ast::TyPath(ref path, ref bounds, id) => {
|
||||
let a_def = match tcx.def_map.borrow().get(&id) {
|
||||
None => {
|
||||
@ -925,7 +933,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
trait_def_id,
|
||||
None,
|
||||
None,
|
||||
path);
|
||||
path,
|
||||
id);
|
||||
let empty_bounds: &[ast::TyParamBound] = &[];
|
||||
let ast_bounds = match *bounds {
|
||||
Some(ref b) => b.as_slice(),
|
||||
@ -942,7 +951,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
bounds)
|
||||
}
|
||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||
ast_path_to_ty(this, rscope, did, path).ty
|
||||
ast_path_to_ty(this, rscope, did, path, id).ty
|
||||
}
|
||||
def::DefTyParam(space, id, n) => {
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
@ -1377,8 +1386,7 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
|
||||
|
||||
let PartitionedBounds { builtin_bounds,
|
||||
trait_bounds,
|
||||
region_bounds,
|
||||
unboxed_fn_ty_bounds } =
|
||||
region_bounds } =
|
||||
partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
|
||||
|
||||
if !trait_bounds.is_empty() {
|
||||
@ -1389,13 +1397,6 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
|
||||
as closure or object bounds").as_slice());
|
||||
}
|
||||
|
||||
if !unboxed_fn_ty_bounds.is_empty() {
|
||||
this.tcx().sess.span_err(
|
||||
span,
|
||||
format!("only the builtin traits can be used \
|
||||
as closure or object bounds").as_slice());
|
||||
}
|
||||
|
||||
// The "main trait refs", rather annoyingly, have no type
|
||||
// specified for the `Self` parameter of the trait. The reason for
|
||||
// this is that they are, after all, *existential* types, and
|
||||
@ -1524,7 +1525,6 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
|
||||
pub struct PartitionedBounds<'a> {
|
||||
pub builtin_bounds: ty::BuiltinBounds,
|
||||
pub trait_bounds: Vec<&'a ast::TraitRef>,
|
||||
pub unboxed_fn_ty_bounds: Vec<&'a ast::UnboxedFnBound>,
|
||||
pub region_bounds: Vec<&'a ast::Lifetime>,
|
||||
}
|
||||
|
||||
@ -1542,7 +1542,6 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
|
||||
let mut builtin_bounds = ty::empty_builtin_bounds();
|
||||
let mut region_bounds = Vec::new();
|
||||
let mut trait_bounds = Vec::new();
|
||||
let mut unboxed_fn_ty_bounds = Vec::new();
|
||||
let mut trait_def_ids = HashMap::new();
|
||||
for &ast_bound in ast_bounds.iter() {
|
||||
match *ast_bound {
|
||||
@ -1587,9 +1586,6 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
|
||||
ast::RegionTyParamBound(ref l) => {
|
||||
region_bounds.push(l);
|
||||
}
|
||||
ast::UnboxedFnTyParamBound(ref unboxed_function) => {
|
||||
unboxed_fn_ty_bounds.push(&**unboxed_function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1597,7 +1593,6 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
|
||||
builtin_bounds: builtin_bounds,
|
||||
trait_bounds: trait_bounds,
|
||||
region_bounds: region_bounds,
|
||||
unboxed_fn_ty_bounds: unboxed_fn_ty_bounds
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3481,11 +3481,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
|
||||
// Tuple up the arguments and insert the resulting function type into
|
||||
// the `unboxed_closures` table.
|
||||
fn_ty.sig.inputs = if fn_ty.sig.inputs.len() == 0 {
|
||||
vec![ty::mk_nil()]
|
||||
} else {
|
||||
vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)]
|
||||
};
|
||||
fn_ty.sig.inputs = vec![ty::mk_tup_or_nil(fcx.tcx(), fn_ty.sig.inputs)];
|
||||
|
||||
let kind = match kind {
|
||||
ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
|
||||
@ -4478,7 +4474,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
|
||||
fcx.infcx(),
|
||||
struct_id,
|
||||
path);
|
||||
path,
|
||||
expr.id);
|
||||
match fcx.mk_subty(false,
|
||||
infer::Misc(path.span),
|
||||
actual_structure_type,
|
||||
@ -5339,6 +5336,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
Some(space) => {
|
||||
push_explicit_parameters_from_segment_to_substs(fcx,
|
||||
space,
|
||||
path.span,
|
||||
type_defs,
|
||||
region_defs,
|
||||
segment,
|
||||
@ -5374,13 +5372,13 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
fcx: &FnCtxt,
|
||||
segment: &ast::PathSegment)
|
||||
{
|
||||
for typ in segment.types.iter() {
|
||||
for typ in segment.parameters.types().iter() {
|
||||
span_err!(fcx.tcx().sess, typ.span, E0085,
|
||||
"type parameters may not appear here");
|
||||
break;
|
||||
}
|
||||
|
||||
for lifetime in segment.lifetimes.iter() {
|
||||
for lifetime in segment.parameters.lifetimes().iter() {
|
||||
span_err!(fcx.tcx().sess, lifetime.span, E0086,
|
||||
"lifetime parameters may not appear here");
|
||||
break;
|
||||
@ -5390,6 +5388,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
fn push_explicit_parameters_from_segment_to_substs(
|
||||
fcx: &FnCtxt,
|
||||
space: subst::ParamSpace,
|
||||
span: Span,
|
||||
type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
|
||||
region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
|
||||
segment: &ast::PathSegment,
|
||||
@ -5412,10 +5411,31 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
* span of the N+1'th parameter.
|
||||
*/
|
||||
|
||||
match segment.parameters {
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
push_explicit_angle_bracketed_parameters_from_segment_to_substs(
|
||||
fcx, space, type_defs, region_defs, data, substs);
|
||||
}
|
||||
|
||||
ast::ParenthesizedParameters(ref data) => {
|
||||
push_explicit_parenthesized_parameters_from_segment_to_substs(
|
||||
fcx, space, span, type_defs, data, substs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(
|
||||
fcx: &FnCtxt,
|
||||
space: subst::ParamSpace,
|
||||
type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
|
||||
region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
|
||||
data: &ast::AngleBracketedParameterData,
|
||||
substs: &mut Substs)
|
||||
{
|
||||
{
|
||||
let type_count = type_defs.len(space);
|
||||
assert_eq!(substs.types.len(space), 0);
|
||||
for (i, typ) in segment.types.iter().enumerate() {
|
||||
for (i, typ) in data.types.iter().enumerate() {
|
||||
let t = fcx.to_ty(&**typ);
|
||||
if i < type_count {
|
||||
substs.types.push(space, t);
|
||||
@ -5424,7 +5444,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
"too many type parameters provided: \
|
||||
expected at most {} parameter(s), \
|
||||
found {} parameter(s)",
|
||||
type_count, segment.types.len());
|
||||
type_count, data.types.len());
|
||||
substs.types.truncate(space, 0);
|
||||
}
|
||||
}
|
||||
@ -5433,7 +5453,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
{
|
||||
let region_count = region_defs.len(space);
|
||||
assert_eq!(substs.regions().len(space), 0);
|
||||
for (i, lifetime) in segment.lifetimes.iter().enumerate() {
|
||||
for (i, lifetime) in data.lifetimes.iter().enumerate() {
|
||||
let r = ast_region_to_region(fcx.tcx(), lifetime);
|
||||
if i < region_count {
|
||||
substs.mut_regions().push(space, r);
|
||||
@ -5442,13 +5462,59 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
"too many lifetime parameters provided: \
|
||||
expected {} parameter(s), found {} parameter(s)",
|
||||
region_count,
|
||||
segment.lifetimes.len());
|
||||
data.lifetimes.len());
|
||||
substs.mut_regions().truncate(space, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn push_explicit_parenthesized_parameters_from_segment_to_substs(
|
||||
fcx: &FnCtxt,
|
||||
space: subst::ParamSpace,
|
||||
span: Span,
|
||||
type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
|
||||
data: &ast::ParenthesizedParameterData,
|
||||
substs: &mut Substs)
|
||||
{
|
||||
/*!
|
||||
* 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).
|
||||
*/
|
||||
|
||||
let type_count = type_defs.len(space);
|
||||
if type_count < 2 {
|
||||
span_err!(fcx.tcx().sess, span, E0167,
|
||||
"parenthesized form always supplies 2 type parameters, \
|
||||
but only {} parameter(s) were expected",
|
||||
type_count);
|
||||
}
|
||||
|
||||
let input_tys: Vec<ty::t> =
|
||||
data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
|
||||
|
||||
let tuple_ty =
|
||||
ty::mk_tup_or_nil(fcx.tcx(), input_tys);
|
||||
|
||||
if type_count >= 1 {
|
||||
substs.types.push(space, tuple_ty);
|
||||
}
|
||||
|
||||
let output_ty: Option<ty::t> =
|
||||
data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
|
||||
|
||||
let output_ty =
|
||||
output_ty.unwrap_or(ty::mk_nil());
|
||||
|
||||
if type_count >= 2 {
|
||||
substs.types.push(space, output_ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_type_parameters(
|
||||
fcx: &FnCtxt,
|
||||
span: Span,
|
||||
|
@ -638,7 +638,7 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
|
||||
let mut bounds = bounds.chain(ty_param.unbound.iter());
|
||||
for bound in bounds {
|
||||
match *bound {
|
||||
ast::TraitTyParamBound(..) | ast::UnboxedFnTyParamBound(..) => {
|
||||
ast::TraitTyParamBound(..) => {
|
||||
// According to accepted RFC #XXX, we should
|
||||
// eventually accept these, but it will not be
|
||||
// part of this PR. Still, convert to warning to
|
||||
@ -1340,7 +1340,8 @@ pub fn instantiate_trait_ref<'tcx,AC>(this: &AC,
|
||||
trait_did,
|
||||
Some(self_ty),
|
||||
associated_type,
|
||||
&ast_trait_ref.path);
|
||||
&ast_trait_ref.path,
|
||||
ast_trait_ref.ref_id);
|
||||
|
||||
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
|
||||
trait_ref.clone());
|
||||
@ -1355,20 +1356,6 @@ pub fn instantiate_trait_ref<'tcx,AC>(this: &AC,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instantiate_unboxed_fn_ty<'tcx,AC>(this: &AC,
|
||||
unboxed_function: &ast::UnboxedFnTy,
|
||||
param_ty: ty::ParamTy)
|
||||
-> Rc<ty::TraitRef>
|
||||
where AC: AstConv<'tcx> {
|
||||
let rscope = ExplicitRscope;
|
||||
let param_ty = param_ty.to_ty(this.tcx());
|
||||
Rc::new(astconv::trait_ref_for_unboxed_function(this,
|
||||
&rscope,
|
||||
unboxed_function.kind,
|
||||
&*unboxed_function.decl,
|
||||
Some(param_ty)))
|
||||
}
|
||||
|
||||
fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
|
||||
if trait_id.krate != ast::LOCAL_CRATE {
|
||||
return ty::lookup_trait_def(ccx.tcx, trait_id)
|
||||
@ -1878,7 +1865,6 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
// In the above example, `ast_trait_ref` is `Iterator`.
|
||||
let ast_trait_ref = match *bound {
|
||||
ast::TraitTyParamBound(ref r) => r,
|
||||
ast::UnboxedFnTyParamBound(..) => { continue; }
|
||||
ast::RegionTyParamBound(..) => { continue; }
|
||||
};
|
||||
|
||||
@ -2056,45 +2042,8 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
merge_param_bounds(this.tcx(), param_ty, ast_bounds, where_clause);
|
||||
let astconv::PartitionedBounds { builtin_bounds,
|
||||
trait_bounds,
|
||||
region_bounds,
|
||||
unboxed_fn_ty_bounds } =
|
||||
region_bounds } =
|
||||
astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice());
|
||||
|
||||
let unboxed_fn_ty_bounds = unboxed_fn_ty_bounds.into_iter().map(|b| {
|
||||
let trait_id = (*this.tcx().def_map.borrow())[b.ref_id].def_id();
|
||||
let mut kind = None;
|
||||
for &(lang_item, this_kind) in [
|
||||
(this.tcx().lang_items.fn_trait(), ast::FnUnboxedClosureKind),
|
||||
(this.tcx().lang_items.fn_mut_trait(),
|
||||
ast::FnMutUnboxedClosureKind),
|
||||
(this.tcx().lang_items.fn_once_trait(),
|
||||
ast::FnOnceUnboxedClosureKind)
|
||||
].iter() {
|
||||
if Some(trait_id) == lang_item {
|
||||
kind = Some(this_kind);
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let kind = match kind {
|
||||
Some(kind) => kind,
|
||||
None => {
|
||||
this.tcx().sess.span_err(b.path.span,
|
||||
"unboxed function trait must be one \
|
||||
of `Fn`, `FnMut`, or `FnOnce`");
|
||||
ast::FnMutUnboxedClosureKind
|
||||
}
|
||||
};
|
||||
|
||||
let rscope = ExplicitRscope;
|
||||
let param_ty = param_ty.to_ty(this.tcx());
|
||||
Rc::new(astconv::trait_ref_for_unboxed_function(this,
|
||||
&rscope,
|
||||
kind,
|
||||
&*b.decl,
|
||||
Some(param_ty)))
|
||||
});
|
||||
|
||||
let trait_bounds: Vec<Rc<ty::TraitRef>> =
|
||||
trait_bounds.into_iter()
|
||||
.map(|b| {
|
||||
@ -2103,7 +2052,6 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
param_ty.to_ty(this.tcx()),
|
||||
Some(param_ty.to_ty(this.tcx())))
|
||||
})
|
||||
.chain(unboxed_fn_ty_bounds)
|
||||
.collect();
|
||||
let region_bounds: Vec<ty::Region> =
|
||||
region_bounds.into_iter()
|
||||
|
@ -1102,13 +1102,11 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||
// be passing down a map.
|
||||
ast::RegionTyParamBound(lt)
|
||||
}
|
||||
&ast::UnboxedFnTyParamBound(ref unboxed_function_type) => {
|
||||
ast::UnboxedFnTyParamBound((*unboxed_function_type).clone())
|
||||
}
|
||||
&ast::TraitTyParamBound(ref tr) => {
|
||||
let last_seg = tr.path.segments.last().unwrap();
|
||||
let mut insert = Vec::new();
|
||||
for (i, lt) in last_seg.lifetimes.iter().enumerate() {
|
||||
let lifetimes = last_seg.parameters.lifetimes();
|
||||
for (i, lt) in lifetimes.iter().enumerate() {
|
||||
if region_names.contains(<.name) {
|
||||
insert.push(i);
|
||||
}
|
||||
@ -1116,7 +1114,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||
let rebuild_info = RebuildPathInfo {
|
||||
path: &tr.path,
|
||||
indexes: insert,
|
||||
expected: last_seg.lifetimes.len(),
|
||||
expected: lifetimes.len(),
|
||||
anon_nums: &HashSet::new(),
|
||||
region_names: region_names
|
||||
};
|
||||
@ -1257,7 +1255,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||
let expected =
|
||||
generics.regions.len(subst::TypeSpace);
|
||||
let lifetimes =
|
||||
&path.segments.last().unwrap().lifetimes;
|
||||
path.segments.last().unwrap().parameters.lifetimes();
|
||||
let mut insert = Vec::new();
|
||||
if lifetimes.len() == 0 {
|
||||
let anon = self.cur_anon.get();
|
||||
@ -1357,7 +1355,8 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||
fn rebuild_path(&self,
|
||||
rebuild_info: RebuildPathInfo,
|
||||
lifetime: ast::Lifetime)
|
||||
-> ast::Path {
|
||||
-> ast::Path
|
||||
{
|
||||
let RebuildPathInfo {
|
||||
path,
|
||||
indexes,
|
||||
@ -1367,37 +1366,48 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||
} = rebuild_info;
|
||||
|
||||
let last_seg = path.segments.last().unwrap();
|
||||
let mut new_lts = Vec::new();
|
||||
if last_seg.lifetimes.len() == 0 {
|
||||
// traverse once to see if there's a need to insert lifetime
|
||||
let need_insert = range(0, expected).any(|i| {
|
||||
indexes.contains(&i)
|
||||
});
|
||||
if need_insert {
|
||||
for i in range(0, expected) {
|
||||
if indexes.contains(&i) {
|
||||
new_lts.push(lifetime);
|
||||
} else {
|
||||
new_lts.push(self.life_giver.give_lifetime());
|
||||
let new_parameters = match last_seg.parameters {
|
||||
ast::ParenthesizedParameters(..) => {
|
||||
last_seg.parameters.clone()
|
||||
}
|
||||
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
let mut new_lts = Vec::new();
|
||||
if data.lifetimes.len() == 0 {
|
||||
// traverse once to see if there's a need to insert lifetime
|
||||
let need_insert = range(0, expected).any(|i| {
|
||||
indexes.contains(&i)
|
||||
});
|
||||
if need_insert {
|
||||
for i in range(0, expected) {
|
||||
if indexes.contains(&i) {
|
||||
new_lts.push(lifetime);
|
||||
} else {
|
||||
new_lts.push(self.life_giver.give_lifetime());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i, lt) in data.lifetimes.iter().enumerate() {
|
||||
if indexes.contains(&i) {
|
||||
new_lts.push(lifetime);
|
||||
} else {
|
||||
new_lts.push(*lt);
|
||||
}
|
||||
}
|
||||
}
|
||||
let new_types = data.types.map(|t| {
|
||||
self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
|
||||
});
|
||||
ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: new_lts,
|
||||
types: new_types
|
||||
})
|
||||
}
|
||||
} else {
|
||||
for (i, lt) in last_seg.lifetimes.iter().enumerate() {
|
||||
if indexes.contains(&i) {
|
||||
new_lts.push(lifetime);
|
||||
} else {
|
||||
new_lts.push(*lt);
|
||||
}
|
||||
}
|
||||
}
|
||||
let new_types = last_seg.types.map(|t| {
|
||||
self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
|
||||
});
|
||||
};
|
||||
let new_seg = ast::PathSegment {
|
||||
identifier: last_seg.identifier,
|
||||
lifetimes: new_lts,
|
||||
types: new_types,
|
||||
parameters: new_parameters
|
||||
};
|
||||
let mut new_segs = Vec::new();
|
||||
new_segs.push_all(path.segments.init());
|
||||
|
@ -323,7 +323,6 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
|
||||
trait_: associated_trait.clean(cx).map(|bound| {
|
||||
match bound {
|
||||
clean::TraitBound(ty) => ty,
|
||||
clean::UnboxedFnBound(..) |
|
||||
clean::RegionBound(..) => unreachable!(),
|
||||
}
|
||||
}),
|
||||
|
@ -476,7 +476,6 @@ impl Clean<TyParam> for ty::TypeParameterDef {
|
||||
#[deriving(Clone, Encodable, Decodable, PartialEq)]
|
||||
pub enum TyParamBound {
|
||||
RegionBound(Lifetime),
|
||||
UnboxedFnBound(UnboxedFnType),
|
||||
TraitBound(Type)
|
||||
}
|
||||
|
||||
@ -484,7 +483,6 @@ impl Clean<TyParamBound> for ast::TyParamBound {
|
||||
fn clean(&self, cx: &DocContext) -> TyParamBound {
|
||||
match *self {
|
||||
ast::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
|
||||
ast::UnboxedFnTyParamBound(ref ty) => { UnboxedFnBound(ty.clean(cx)) },
|
||||
ast::TraitTyParamBound(ref t) => TraitBound(t.clean(cx)),
|
||||
}
|
||||
}
|
||||
@ -599,21 +597,6 @@ impl Clean<Option<Vec<TyParamBound>>> for subst::Substs {
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable, PartialEq)]
|
||||
pub struct UnboxedFnType {
|
||||
pub path: Path,
|
||||
pub decl: FnDecl
|
||||
}
|
||||
|
||||
impl Clean<UnboxedFnType> for ast::UnboxedFnBound {
|
||||
fn clean(&self, cx: &DocContext) -> UnboxedFnType {
|
||||
UnboxedFnType {
|
||||
path: self.path.clean(cx),
|
||||
decl: self.decl.clean(cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable, PartialEq)]
|
||||
pub struct Lifetime(String);
|
||||
|
||||
@ -1641,10 +1624,23 @@ pub struct PathSegment {
|
||||
|
||||
impl Clean<PathSegment> for ast::PathSegment {
|
||||
fn clean(&self, cx: &DocContext) -> PathSegment {
|
||||
let (lifetimes, types) = match self.parameters {
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
(data.lifetimes.clean(cx), data.types.clean(cx))
|
||||
}
|
||||
|
||||
ast::ParenthesizedParameters(ref data) => {
|
||||
// FIXME -- rustdoc should be taught about Foo() notation
|
||||
let inputs = Tuple(data.inputs.clean(cx));
|
||||
let output = data.output.as_ref().map(|t| t.clean(cx)).unwrap_or(Tuple(Vec::new()));
|
||||
(Vec::new(), vec![inputs, output])
|
||||
}
|
||||
};
|
||||
|
||||
PathSegment {
|
||||
name: self.identifier.clean(cx),
|
||||
lifetimes: self.lifetimes.clean(cx),
|
||||
types: self.types.clean(cx),
|
||||
lifetimes: lifetimes,
|
||||
types: types,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,9 +143,6 @@ impl fmt::Show for clean::TyParamBound {
|
||||
clean::RegionBound(ref lt) => {
|
||||
write!(f, "{}", *lt)
|
||||
}
|
||||
clean::UnboxedFnBound(ref ty) => {
|
||||
write!(f, "{}{}", ty.path, ty.decl)
|
||||
}
|
||||
clean::TraitBound(ref ty) => {
|
||||
write!(f, "{}", *ty)
|
||||
}
|
||||
@ -404,8 +401,7 @@ impl fmt::Show for clean::Type {
|
||||
let mut ret = String::new();
|
||||
for bound in decl.bounds.iter() {
|
||||
match *bound {
|
||||
clean::RegionBound(..) |
|
||||
clean::UnboxedFnBound(..) => {}
|
||||
clean::RegionBound(..) => {}
|
||||
clean::TraitBound(ref t) => {
|
||||
if ret.len() == 0 {
|
||||
ret.push_str(": ");
|
||||
|
@ -171,7 +171,7 @@ pub struct Path {
|
||||
/// module (like paths in an import).
|
||||
pub global: bool,
|
||||
/// The segments in the path: the things separated by `::`.
|
||||
pub segments: Vec<PathSegment> ,
|
||||
pub segments: Vec<PathSegment>,
|
||||
}
|
||||
|
||||
/// A segment of a path: an identifier, an optional lifetime, and a set of
|
||||
@ -180,12 +180,107 @@ pub struct Path {
|
||||
pub struct PathSegment {
|
||||
/// The identifier portion of this path segment.
|
||||
pub identifier: Ident,
|
||||
|
||||
/// Type/lifetime parameters attached to this path. They come in
|
||||
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
|
||||
/// this is more than just simple syntactic sugar; the use of
|
||||
/// parens affects the region binding rules, so we preserve the
|
||||
/// distinction.
|
||||
pub parameters: PathParameters,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum PathParameters {
|
||||
AngleBracketedParameters(AngleBracketedParameterData),
|
||||
ParenthesizedParameters(ParenthesizedParameterData),
|
||||
}
|
||||
|
||||
impl PathParameters {
|
||||
pub fn none() -> PathParameters {
|
||||
AngleBracketedParameters(AngleBracketedParameterData {
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => data.is_empty(),
|
||||
|
||||
// Even if the user supplied no types, something like
|
||||
// `X()` is equivalent to `X<(),()>`.
|
||||
ParenthesizedParameters(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_lifetimes(&self) -> bool {
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => !data.lifetimes.is_empty(),
|
||||
ParenthesizedParameters(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_types(&self) -> bool {
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => !data.types.is_empty(),
|
||||
ParenthesizedParameters(..) => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn types(&self) -> Vec<&P<Ty>> {
|
||||
/*!
|
||||
* Returns the types that the user wrote. Note that these do not
|
||||
* necessarily map to the type parameters in the parenthesized case.
|
||||
*/
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => {
|
||||
data.types.iter().collect()
|
||||
}
|
||||
ParenthesizedParameters(ref data) => {
|
||||
data.inputs.iter()
|
||||
.chain(data.output.iter())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lifetimes(&self) -> Vec<&Lifetime> {
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => {
|
||||
data.lifetimes.iter().collect()
|
||||
}
|
||||
ParenthesizedParameters(_) => {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A path like `Foo<'a, T>`
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct AngleBracketedParameterData {
|
||||
/// The lifetime parameters for this path segment.
|
||||
pub lifetimes: Vec<Lifetime>,
|
||||
/// The type parameters for this path segment, if present.
|
||||
pub types: OwnedSlice<P<Ty>>,
|
||||
}
|
||||
|
||||
impl AngleBracketedParameterData {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.lifetimes.is_empty() && self.types.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// A path like `Foo(A,B) -> C`
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct ParenthesizedParameterData {
|
||||
/// `(A,B)`
|
||||
pub inputs: Vec<P<Ty>>,
|
||||
|
||||
/// `C`
|
||||
pub output: Option<P<Ty>>,
|
||||
}
|
||||
|
||||
pub type CrateNum = u32;
|
||||
|
||||
pub type NodeId = u32;
|
||||
@ -213,20 +308,11 @@ pub const DUMMY_NODE_ID: NodeId = -1;
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum TyParamBound {
|
||||
TraitTyParamBound(TraitRef),
|
||||
UnboxedFnTyParamBound(P<UnboxedFnBound>),
|
||||
RegionTyParamBound(Lifetime)
|
||||
}
|
||||
|
||||
pub type TyParamBounds = OwnedSlice<TyParamBound>;
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct UnboxedFnBound {
|
||||
pub path: Path,
|
||||
pub decl: P<FnDecl>,
|
||||
pub lifetimes: Vec<LifetimeDef>,
|
||||
pub ref_id: NodeId,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct TyParam {
|
||||
pub ident: Ident,
|
||||
@ -994,12 +1080,6 @@ pub struct BareFnTy {
|
||||
pub decl: P<FnDecl>
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct UnboxedFnTy {
|
||||
pub kind: UnboxedClosureKind,
|
||||
pub decl: P<FnDecl>,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum Ty_ {
|
||||
TyNil,
|
||||
@ -1012,7 +1092,6 @@ pub enum Ty_ {
|
||||
TyClosure(P<ClosureTy>),
|
||||
TyProc(P<ClosureTy>),
|
||||
TyBareFn(P<BareFnTy>),
|
||||
TyUnboxedFn(P<UnboxedFnTy>),
|
||||
TyTup(Vec<P<Ty>> ),
|
||||
TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
|
||||
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
|
||||
|
@ -848,9 +848,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
TyBareFn(ref fd) => {
|
||||
self.visit_fn_decl(&*fd.decl);
|
||||
}
|
||||
TyUnboxedFn(ref fd) => {
|
||||
self.visit_fn_decl(&*fd.decl);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_ty(self, ty);
|
||||
|
@ -171,8 +171,10 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
})
|
||||
}
|
||||
),
|
||||
}
|
||||
@ -681,11 +683,11 @@ pub fn segments_name_eq(a : &[ast::PathSegment], b : &[ast::PathSegment]) -> boo
|
||||
false
|
||||
} else {
|
||||
for (idx,seg) in a.iter().enumerate() {
|
||||
if (seg.identifier.name != b[idx].identifier.name)
|
||||
if seg.identifier.name != b[idx].identifier.name
|
||||
// FIXME #7743: ident -> name problems in lifetime comparison?
|
||||
|| (seg.lifetimes != b[idx].lifetimes)
|
||||
// can types contain idents?
|
||||
|| (seg.types != b[idx].types) {
|
||||
|| seg.parameters != b[idx].parameters
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -747,12 +749,10 @@ impl PostExpansionMethod for Method {
|
||||
mod test {
|
||||
use ast::*;
|
||||
use super::*;
|
||||
use owned_slice::OwnedSlice;
|
||||
|
||||
fn ident_to_segment(id : &Ident) -> PathSegment {
|
||||
PathSegment {identifier:id.clone(),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty()}
|
||||
PathSegment {identifier: id.clone(),
|
||||
parameters: PathParameters::none()}
|
||||
}
|
||||
|
||||
#[test] fn idents_name_eq_test() {
|
||||
|
@ -313,14 +313,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
.map(|ident| {
|
||||
ast::PathSegment {
|
||||
identifier: ident,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect();
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: last_identifier,
|
||||
lifetimes: lifetimes,
|
||||
types: OwnedSlice::from_vec(types),
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: OwnedSlice::from_vec(types),
|
||||
})
|
||||
});
|
||||
ast::Path {
|
||||
span: sp,
|
||||
|
@ -12,7 +12,6 @@ use ast;
|
||||
use codemap::Span;
|
||||
use ext::base::*;
|
||||
use ext::base;
|
||||
use owned_slice::OwnedSlice;
|
||||
use parse::token;
|
||||
use parse::token::{str_to_ident};
|
||||
use ptr::P;
|
||||
@ -52,8 +51,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: res,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -313,11 +313,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
|
||||
experimental and likely to be removed");
|
||||
|
||||
},
|
||||
ast::TyUnboxedFn(..) => {
|
||||
self.gate_feature("unboxed_closure_sugar",
|
||||
t.span,
|
||||
"unboxed closure trait sugar is experimental");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,22 @@ pub trait Folder {
|
||||
noop_fold_path(p, self)
|
||||
}
|
||||
|
||||
fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters {
|
||||
noop_fold_path_parameters(p, self)
|
||||
}
|
||||
|
||||
fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData)
|
||||
-> AngleBracketedParameterData
|
||||
{
|
||||
noop_fold_angle_bracketed_parameter_data(p, self)
|
||||
}
|
||||
|
||||
fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData)
|
||||
-> ParenthesizedParameterData
|
||||
{
|
||||
noop_fold_parenthesized_parameter_data(p, self)
|
||||
}
|
||||
|
||||
fn fold_local(&mut self, l: P<Local>) -> P<Local> {
|
||||
noop_fold_local(l, self)
|
||||
}
|
||||
@ -408,12 +424,6 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||
decl: fld.fold_fn_decl(decl)
|
||||
}))
|
||||
}
|
||||
TyUnboxedFn(f) => {
|
||||
TyUnboxedFn(f.map(|UnboxedFnTy {decl, kind}| UnboxedFnTy {
|
||||
decl: fld.fold_fn_decl(decl),
|
||||
kind: kind,
|
||||
}))
|
||||
}
|
||||
TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
|
||||
TyParen(ty) => TyParen(fld.fold_ty(ty)),
|
||||
TyPath(path, bounds, id) => {
|
||||
@ -480,15 +490,43 @@ pub fn noop_fold_uint<T: Folder>(i: uint, _: &mut T) -> uint {
|
||||
pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut T) -> Path {
|
||||
Path {
|
||||
global: global,
|
||||
segments: segments.move_map(|PathSegment {identifier, lifetimes, types}| PathSegment {
|
||||
segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
|
||||
identifier: fld.fold_ident(identifier),
|
||||
lifetimes: fld.fold_lifetimes(lifetimes),
|
||||
types: types.move_map(|typ| fld.fold_ty(typ)),
|
||||
parameters: fld.fold_path_parameters(parameters),
|
||||
}),
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T)
|
||||
-> PathParameters
|
||||
{
|
||||
match path_parameters {
|
||||
AngleBracketedParameters(data) =>
|
||||
AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)),
|
||||
ParenthesizedParameters(data) =>
|
||||
ParenthesizedParameters(fld.fold_parenthesized_parameter_data(data)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData,
|
||||
fld: &mut T)
|
||||
-> AngleBracketedParameterData
|
||||
{
|
||||
let AngleBracketedParameterData { lifetimes, types } = data;
|
||||
AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes),
|
||||
types: types.move_map(|ty| fld.fold_ty(ty)) }
|
||||
}
|
||||
|
||||
pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
|
||||
fld: &mut T)
|
||||
-> ParenthesizedParameterData
|
||||
{
|
||||
let ParenthesizedParameterData { inputs, output } = data;
|
||||
ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
|
||||
output: output.map(|ty| fld.fold_ty(ty)) }
|
||||
}
|
||||
|
||||
pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
|
||||
l.map(|Local {id, pat, ty, init, source, span}| Local {
|
||||
id: fld.new_id(id),
|
||||
@ -671,23 +709,6 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
|
||||
match tpb {
|
||||
TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_trait_ref(ty)),
|
||||
RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
|
||||
UnboxedFnTyParamBound(bound) => {
|
||||
match *bound {
|
||||
UnboxedFnBound {
|
||||
ref path,
|
||||
ref decl,
|
||||
ref lifetimes,
|
||||
ref_id
|
||||
} => {
|
||||
UnboxedFnTyParamBound(P(UnboxedFnBound {
|
||||
path: fld.fold_path(path.clone()),
|
||||
decl: fld.fold_fn_decl(decl.clone()),
|
||||
lifetimes: fld.fold_lifetime_defs(lifetimes.clone()),
|
||||
ref_id: fld.new_id(ref_id),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -749,8 +749,7 @@ mod test {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("a"),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
),
|
||||
}),
|
||||
@ -768,13 +767,11 @@ mod test {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("a"),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
},
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("b"),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
)
|
||||
}),
|
||||
@ -952,8 +949,7 @@ mod test {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("d"),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
),
|
||||
}),
|
||||
@ -974,8 +970,7 @@ mod test {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("b"),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
),
|
||||
}),
|
||||
@ -1022,8 +1017,7 @@ mod test {
|
||||
ast::PathSegment {
|
||||
identifier:
|
||||
str_to_ident("int"),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
),
|
||||
}, None, ast::DUMMY_NODE_ID),
|
||||
@ -1072,10 +1066,8 @@ mod test {
|
||||
identifier:
|
||||
str_to_ident(
|
||||
"b"),
|
||||
lifetimes:
|
||||
Vec::new(),
|
||||
types:
|
||||
OwnedSlice::empty()
|
||||
parameters:
|
||||
ast::PathParameters::none(),
|
||||
}
|
||||
),
|
||||
}),
|
||||
|
@ -53,9 +53,8 @@ use ast::{TtNonterminal, TupleVariantKind, Ty, Ty_, TyBot};
|
||||
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
|
||||
use ast::{TyTypeof, TyInfer, TypeMethod};
|
||||
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath};
|
||||
use ast::{TyRptr, TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
|
||||
use ast::{TyRptr, TyTup, TyU32, TyUniq, TyVec, UnUniq};
|
||||
use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
|
||||
use ast::{UnboxedFnBound, UnboxedFnTy, UnboxedFnTyParamBound};
|
||||
use ast::{UnnamedField, UnsafeBlock};
|
||||
use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
|
||||
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
@ -1127,19 +1126,16 @@ impl<'a> Parser<'a> {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let (optional_unboxed_closure_kind, inputs) = if self.eat(&token::OrOr) {
|
||||
(None, Vec::new())
|
||||
let inputs = if self.eat(&token::OrOr) {
|
||||
Vec::new()
|
||||
} else {
|
||||
self.expect_or();
|
||||
|
||||
let optional_unboxed_closure_kind =
|
||||
self.parse_optional_unboxed_closure_kind();
|
||||
|
||||
let inputs = self.parse_seq_to_before_or(
|
||||
&token::Comma,
|
||||
|p| p.parse_arg_general(false));
|
||||
self.expect_or();
|
||||
(optional_unboxed_closure_kind, inputs)
|
||||
inputs
|
||||
};
|
||||
|
||||
let bounds = self.parse_colon_then_ty_param_bounds();
|
||||
@ -1152,23 +1148,13 @@ impl<'a> Parser<'a> {
|
||||
variadic: false
|
||||
});
|
||||
|
||||
match optional_unboxed_closure_kind {
|
||||
Some(unboxed_closure_kind) => {
|
||||
TyUnboxedFn(P(UnboxedFnTy {
|
||||
kind: unboxed_closure_kind,
|
||||
decl: decl,
|
||||
}))
|
||||
}
|
||||
None => {
|
||||
TyClosure(P(ClosureTy {
|
||||
fn_style: fn_style,
|
||||
onceness: onceness,
|
||||
bounds: bounds,
|
||||
decl: decl,
|
||||
lifetimes: lifetime_defs,
|
||||
}))
|
||||
}
|
||||
}
|
||||
TyClosure(P(ClosureTy {
|
||||
fn_style: fn_style,
|
||||
onceness: onceness,
|
||||
bounds: bounds,
|
||||
decl: decl,
|
||||
lifetimes: lifetime_defs,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn parse_unsafety(&mut self) -> FnStyle {
|
||||
@ -1487,9 +1473,9 @@ impl<'a> Parser<'a> {
|
||||
trait_name: trait_name.path,
|
||||
item_name: item_name,
|
||||
}))
|
||||
} else if self.token == token::ModSep
|
||||
|| self.token.is_ident()
|
||||
|| self.token.is_path() {
|
||||
} else if self.token == token::ModSep ||
|
||||
self.token.is_ident() ||
|
||||
self.token.is_path() {
|
||||
// NAMED TYPE
|
||||
let mode = if plus_allowed {
|
||||
LifetimeAndTypesAndBounds
|
||||
@ -1706,50 +1692,18 @@ impl<'a> Parser<'a> {
|
||||
// Parse any number of segments and bound sets. A segment is an
|
||||
// identifier followed by an optional lifetime and a set of types.
|
||||
// A bound set is a set of type parameter bounds.
|
||||
let mut segments = Vec::new();
|
||||
loop {
|
||||
// First, parse an identifier.
|
||||
let identifier = self.parse_ident();
|
||||
|
||||
// Parse the '::' before type parameters if it's required. If
|
||||
// it is required and wasn't present, then we're done.
|
||||
if mode == LifetimeAndTypesWithColons &&
|
||||
!self.eat(&token::ModSep) {
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
});
|
||||
break
|
||||
let segments = match mode {
|
||||
LifetimeAndTypesWithoutColons |
|
||||
LifetimeAndTypesAndBounds => {
|
||||
self.parse_path_segments_without_colons()
|
||||
}
|
||||
|
||||
// Parse the `<` before the lifetime and types, if applicable.
|
||||
let (any_lifetime_or_types, lifetimes, types) = {
|
||||
if mode != NoTypesAllowed && self.eat_lt(false) {
|
||||
let (lifetimes, types) =
|
||||
self.parse_generic_values_after_lt();
|
||||
(true, lifetimes, OwnedSlice::from_vec(types))
|
||||
} else {
|
||||
(false, Vec::new(), OwnedSlice::empty())
|
||||
}
|
||||
};
|
||||
|
||||
// Assemble and push the result.
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: lifetimes,
|
||||
types: types,
|
||||
});
|
||||
|
||||
// We're done if we don't see a '::', unless the mode required
|
||||
// a double colon to get here in the first place.
|
||||
if !(mode == LifetimeAndTypesWithColons &&
|
||||
!any_lifetime_or_types) {
|
||||
if !self.eat(&token::ModSep) {
|
||||
break
|
||||
}
|
||||
LifetimeAndTypesWithColons => {
|
||||
self.parse_path_segments_with_colons()
|
||||
}
|
||||
}
|
||||
NoTypesAllowed => {
|
||||
self.parse_path_segments_without_types()
|
||||
}
|
||||
};
|
||||
|
||||
// Next, parse a plus and bounded type parameters, if
|
||||
// applicable. We need to remember whether the separate was
|
||||
@ -1792,6 +1746,123 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Examples:
|
||||
/// - `a::b<T,U>::c<V,W>`
|
||||
/// - `a::b<T,U>::c(V) -> W`
|
||||
/// - `a::b<T,U>::c(V)`
|
||||
pub fn parse_path_segments_without_colons(&mut self) -> Vec<ast::PathSegment> {
|
||||
let mut segments = Vec::new();
|
||||
loop {
|
||||
// First, parse an identifier.
|
||||
let identifier = self.parse_ident();
|
||||
|
||||
// Parse types, optionally.
|
||||
let parameters = if self.eat_lt(false) {
|
||||
let (lifetimes, types) = self.parse_generic_values_after_lt();
|
||||
|
||||
ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: OwnedSlice::from_vec(types),
|
||||
})
|
||||
} else if self.eat(&token::OpenDelim(token::Paren)) {
|
||||
let inputs = self.parse_seq_to_end(
|
||||
&token::CloseDelim(token::Paren),
|
||||
seq_sep_trailing_allowed(token::Comma),
|
||||
|p| p.parse_ty(true));
|
||||
|
||||
let output_ty = if self.eat(&token::RArrow) {
|
||||
Some(self.parse_ty(true))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
ast::ParenthesizedParameters(ast::ParenthesizedParameterData {
|
||||
inputs: inputs,
|
||||
output: output_ty
|
||||
})
|
||||
} else {
|
||||
ast::PathParameters::none()
|
||||
};
|
||||
|
||||
// Assemble and push the result.
|
||||
segments.push(ast::PathSegment { identifier: identifier,
|
||||
parameters: parameters });
|
||||
|
||||
// Continue only if we see a `::`
|
||||
if !self.eat(&token::ModSep) {
|
||||
return segments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Examples:
|
||||
/// - `a::b::<T,U>::c`
|
||||
pub fn parse_path_segments_with_colons(&mut self) -> Vec<ast::PathSegment> {
|
||||
let mut segments = Vec::new();
|
||||
loop {
|
||||
// First, parse an identifier.
|
||||
let identifier = self.parse_ident();
|
||||
|
||||
// If we do not see a `::`, stop.
|
||||
if !self.eat(&token::ModSep) {
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
})
|
||||
});
|
||||
return segments;
|
||||
}
|
||||
|
||||
// Check for a type segment.
|
||||
if self.eat_lt(false) {
|
||||
// Consumed `a::b::<`, go look for types
|
||||
let (lifetimes, types) = self.parse_generic_values_after_lt();
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: OwnedSlice::from_vec(types),
|
||||
}),
|
||||
});
|
||||
|
||||
// Consumed `a::b::<T,U>`, check for `::` before proceeding
|
||||
if !self.eat(&token::ModSep) {
|
||||
return segments;
|
||||
}
|
||||
} else {
|
||||
// Consumed `a::`, go look for `b`
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Examples:
|
||||
/// - `a::b::c`
|
||||
pub fn parse_path_segments_without_types(&mut self) -> Vec<ast::PathSegment> {
|
||||
let mut segments = Vec::new();
|
||||
loop {
|
||||
// First, parse an identifier.
|
||||
let identifier = self.parse_ident();
|
||||
|
||||
// Assemble and push the result.
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none()
|
||||
});
|
||||
|
||||
// If we do not see a `::`, stop.
|
||||
if !self.eat(&token::ModSep) {
|
||||
return segments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// parses 0 or 1 lifetime
|
||||
pub fn parse_opt_lifetime(&mut self) -> Option<ast::Lifetime> {
|
||||
match self.token {
|
||||
@ -3389,13 +3460,9 @@ impl<'a> Parser<'a> {
|
||||
},
|
||||
_ => {
|
||||
if !enum_path.global &&
|
||||
enum_path.segments.len() == 1 &&
|
||||
enum_path.segments[0]
|
||||
.lifetimes
|
||||
.len() == 0 &&
|
||||
enum_path.segments[0]
|
||||
.types
|
||||
.len() == 0 {
|
||||
enum_path.segments.len() == 1 &&
|
||||
enum_path.segments[0].parameters.is_empty()
|
||||
{
|
||||
// it could still be either an enum
|
||||
// or an identifier pattern, resolve
|
||||
// will sort it out:
|
||||
@ -3854,31 +3921,11 @@ impl<'a> Parser<'a> {
|
||||
token::ModSep | token::Ident(..) => {
|
||||
let path =
|
||||
self.parse_path(LifetimeAndTypesWithoutColons).path;
|
||||
if self.token == token::OpenDelim(token::Paren) {
|
||||
self.bump();
|
||||
let inputs = self.parse_seq_to_end(
|
||||
&token::CloseDelim(token::Paren),
|
||||
seq_sep_trailing_allowed(token::Comma),
|
||||
|p| p.parse_arg_general(false));
|
||||
let (return_style, output) = self.parse_ret_ty();
|
||||
result.push(UnboxedFnTyParamBound(P(UnboxedFnBound {
|
||||
path: path,
|
||||
decl: P(FnDecl {
|
||||
inputs: inputs,
|
||||
output: output,
|
||||
cf: return_style,
|
||||
variadic: false,
|
||||
}),
|
||||
lifetimes: lifetime_defs,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
})));
|
||||
} else {
|
||||
result.push(TraitTyParamBound(ast::TraitRef {
|
||||
path: path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
lifetimes: lifetime_defs,
|
||||
}))
|
||||
}
|
||||
result.push(TraitTyParamBound(ast::TraitRef {
|
||||
path: path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
lifetimes: lifetime_defs,
|
||||
}))
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
@ -3894,8 +3941,7 @@ impl<'a> Parser<'a> {
|
||||
fn trait_ref_from_ident(ident: Ident, span: Span) -> ast::TraitRef {
|
||||
let segment = ast::PathSegment {
|
||||
identifier: ident,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none()
|
||||
};
|
||||
let path = ast::Path {
|
||||
span: span,
|
||||
@ -5611,8 +5657,7 @@ impl<'a> Parser<'a> {
|
||||
segments: path.into_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
@ -5646,8 +5691,7 @@ impl<'a> Parser<'a> {
|
||||
segments: path.into_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
@ -5664,8 +5708,7 @@ impl<'a> Parser<'a> {
|
||||
segments: path.into_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
@ -5686,8 +5729,7 @@ impl<'a> Parser<'a> {
|
||||
segments: path.into_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
|
@ -13,7 +13,7 @@ use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
|
||||
use ast::{FnOnceUnboxedClosureKind};
|
||||
use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound};
|
||||
use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem};
|
||||
use ast::{UnboxedClosureKind, UnboxedFnTyParamBound};
|
||||
use ast::{UnboxedClosureKind};
|
||||
use ast;
|
||||
use ast_util;
|
||||
use owned_slice::OwnedSlice;
|
||||
@ -699,7 +699,6 @@ impl<'a> State<'a> {
|
||||
None,
|
||||
&OwnedSlice::empty(),
|
||||
Some(&generics),
|
||||
None,
|
||||
None));
|
||||
}
|
||||
ast::TyClosure(ref f) => {
|
||||
@ -719,7 +718,6 @@ impl<'a> State<'a> {
|
||||
None,
|
||||
&f.bounds,
|
||||
Some(&generics),
|
||||
None,
|
||||
None));
|
||||
}
|
||||
ast::TyProc(ref f) => {
|
||||
@ -739,21 +737,8 @@ impl<'a> State<'a> {
|
||||
None,
|
||||
&f.bounds,
|
||||
Some(&generics),
|
||||
None,
|
||||
None));
|
||||
}
|
||||
ast::TyUnboxedFn(ref f) => {
|
||||
try!(self.print_ty_fn(None,
|
||||
None,
|
||||
ast::NormalFn,
|
||||
ast::Many,
|
||||
&*f.decl,
|
||||
None,
|
||||
&OwnedSlice::empty(),
|
||||
None,
|
||||
None,
|
||||
Some(f.kind)));
|
||||
}
|
||||
ast::TyPath(ref path, ref bounds, _) => {
|
||||
try!(self.print_bounded_path(path, bounds));
|
||||
}
|
||||
@ -1212,8 +1197,7 @@ impl<'a> State<'a> {
|
||||
Some(m.ident),
|
||||
&OwnedSlice::empty(),
|
||||
Some(&m.generics),
|
||||
Some(&m.explicit_self.node),
|
||||
None));
|
||||
Some(&m.explicit_self.node)));
|
||||
word(&mut self.s, ";")
|
||||
}
|
||||
|
||||
@ -1995,14 +1979,34 @@ impl<'a> State<'a> {
|
||||
|
||||
try!(self.print_ident(segment.identifier));
|
||||
|
||||
if !segment.lifetimes.is_empty() || !segment.types.is_empty() {
|
||||
if colons_before_params {
|
||||
try!(word(&mut self.s, "::"))
|
||||
}
|
||||
try!(self.print_path_parameters(&segment.parameters, colons_before_params));
|
||||
}
|
||||
|
||||
match *opt_bounds {
|
||||
None => Ok(()),
|
||||
Some(ref bounds) => self.print_bounds("+", bounds)
|
||||
}
|
||||
}
|
||||
|
||||
fn print_path_parameters(&mut self,
|
||||
parameters: &ast::PathParameters,
|
||||
colons_before_params: bool)
|
||||
-> IoResult<()>
|
||||
{
|
||||
if parameters.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if colons_before_params {
|
||||
try!(word(&mut self.s, "::"))
|
||||
}
|
||||
|
||||
match *parameters {
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
try!(word(&mut self.s, "<"));
|
||||
|
||||
let mut comma = false;
|
||||
for lifetime in segment.lifetimes.iter() {
|
||||
for lifetime in data.lifetimes.iter() {
|
||||
if comma {
|
||||
try!(self.word_space(","))
|
||||
}
|
||||
@ -2010,24 +2014,38 @@ impl<'a> State<'a> {
|
||||
comma = true;
|
||||
}
|
||||
|
||||
if !segment.types.is_empty() {
|
||||
if !data.types.is_empty() {
|
||||
if comma {
|
||||
try!(self.word_space(","))
|
||||
}
|
||||
try!(self.commasep(
|
||||
Inconsistent,
|
||||
segment.types.as_slice(),
|
||||
data.types.as_slice(),
|
||||
|s, ty| s.print_type(&**ty)));
|
||||
}
|
||||
|
||||
try!(word(&mut self.s, ">"))
|
||||
}
|
||||
|
||||
ast::ParenthesizedParameters(ref data) => {
|
||||
try!(word(&mut self.s, "("));
|
||||
try!(self.commasep(
|
||||
Inconsistent,
|
||||
data.inputs.as_slice(),
|
||||
|s, ty| s.print_type(&**ty)));
|
||||
try!(word(&mut self.s, ")"));
|
||||
|
||||
match data.output {
|
||||
None => { }
|
||||
Some(ref ty) => {
|
||||
try!(self.word_space("->"));
|
||||
try!(self.print_type(&**ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match *opt_bounds {
|
||||
None => Ok(()),
|
||||
Some(ref bounds) => self.print_bounds("+", bounds)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_path(&mut self, path: &ast::Path,
|
||||
@ -2373,15 +2391,6 @@ impl<'a> State<'a> {
|
||||
RegionTyParamBound(ref lt) => {
|
||||
self.print_lifetime(lt)
|
||||
}
|
||||
UnboxedFnTyParamBound(ref unboxed_function_type) => {
|
||||
try!(self.print_path(&unboxed_function_type.path,
|
||||
false));
|
||||
try!(self.popen());
|
||||
try!(self.print_fn_args(&*unboxed_function_type.decl,
|
||||
None));
|
||||
try!(self.pclose());
|
||||
self.print_fn_output(&*unboxed_function_type.decl)
|
||||
}
|
||||
})
|
||||
}
|
||||
Ok(())
|
||||
@ -2641,9 +2650,7 @@ impl<'a> State<'a> {
|
||||
id: Option<ast::Ident>,
|
||||
bounds: &OwnedSlice<ast::TyParamBound>,
|
||||
generics: Option<&ast::Generics>,
|
||||
opt_explicit_self: Option<&ast::ExplicitSelf_>,
|
||||
opt_unboxed_closure_kind:
|
||||
Option<ast::UnboxedClosureKind>)
|
||||
opt_explicit_self: Option<&ast::ExplicitSelf_>)
|
||||
-> IoResult<()> {
|
||||
try!(self.ibox(indent_unit));
|
||||
|
||||
@ -2660,9 +2667,7 @@ impl<'a> State<'a> {
|
||||
try!(self.print_fn_style(fn_style));
|
||||
try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi));
|
||||
try!(self.print_onceness(onceness));
|
||||
if opt_unboxed_closure_kind.is_none() {
|
||||
try!(word(&mut self.s, "fn"));
|
||||
}
|
||||
try!(word(&mut self.s, "fn"));
|
||||
}
|
||||
|
||||
match id {
|
||||
@ -2676,30 +2681,15 @@ impl<'a> State<'a> {
|
||||
match generics { Some(g) => try!(self.print_generics(g)), _ => () }
|
||||
try!(zerobreak(&mut self.s));
|
||||
|
||||
if opt_unboxed_closure_kind.is_some() || opt_sigil == Some('&') {
|
||||
if opt_sigil == Some('&') {
|
||||
try!(word(&mut self.s, "|"));
|
||||
} else {
|
||||
try!(self.popen());
|
||||
}
|
||||
|
||||
match opt_unboxed_closure_kind {
|
||||
Some(ast::FnUnboxedClosureKind) => {
|
||||
try!(word(&mut self.s, "&"));
|
||||
try!(self.word_space(":"));
|
||||
}
|
||||
Some(ast::FnMutUnboxedClosureKind) => {
|
||||
try!(word(&mut self.s, "&mut"));
|
||||
try!(self.word_space(":"));
|
||||
}
|
||||
Some(ast::FnOnceUnboxedClosureKind) => {
|
||||
try!(self.word_space(":"));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
try!(self.print_fn_args(decl, opt_explicit_self));
|
||||
|
||||
if opt_unboxed_closure_kind.is_some() || opt_sigil == Some('&') {
|
||||
if opt_sigil == Some('&') {
|
||||
try!(word(&mut self.s, "|"));
|
||||
} else {
|
||||
if decl.variadic {
|
||||
|
@ -14,7 +14,6 @@ use codemap::DUMMY_SP;
|
||||
use codemap;
|
||||
use fold::Folder;
|
||||
use fold;
|
||||
use owned_slice::OwnedSlice;
|
||||
use parse::token::InternedString;
|
||||
use parse::token::special_idents;
|
||||
use parse::token;
|
||||
@ -181,13 +180,11 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: token::str_to_ident("std"),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
},
|
||||
ast::PathSegment {
|
||||
identifier: token::str_to_ident("prelude"),
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -453,8 +453,7 @@ fn path_node(ids: Vec<ast::Ident> ) -> ast::Path {
|
||||
global: false,
|
||||
segments: ids.into_iter().map(|identifier| ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
@ -365,12 +365,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||
visitor.visit_ty(&*function_declaration.decl.output);
|
||||
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
|
||||
}
|
||||
TyUnboxedFn(ref function_declaration) => {
|
||||
for argument in function_declaration.decl.inputs.iter() {
|
||||
visitor.visit_ty(&*argument.ty)
|
||||
}
|
||||
visitor.visit_ty(&*function_declaration.decl.output);
|
||||
}
|
||||
TyPath(ref path, ref opt_bounds, id) => {
|
||||
visitor.visit_path(path, id);
|
||||
match *opt_bounds {
|
||||
@ -407,11 +401,23 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
|
||||
for segment in path.segments.iter() {
|
||||
visitor.visit_ident(path.span, segment.identifier);
|
||||
|
||||
for typ in segment.types.iter() {
|
||||
visitor.visit_ty(&**typ);
|
||||
}
|
||||
for lifetime in segment.lifetimes.iter() {
|
||||
visitor.visit_lifetime_ref(lifetime);
|
||||
match segment.parameters {
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
for typ in data.types.iter() {
|
||||
visitor.visit_ty(&**typ);
|
||||
}
|
||||
for lifetime in data.lifetimes.iter() {
|
||||
visitor.visit_lifetime_ref(lifetime);
|
||||
}
|
||||
}
|
||||
ast::ParenthesizedParameters(ref data) => {
|
||||
for typ in data.inputs.iter() {
|
||||
visitor.visit_ty(&**typ);
|
||||
}
|
||||
for typ in data.output.iter() {
|
||||
visitor.visit_ty(&**typ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -493,13 +499,6 @@ pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
TraitTyParamBound(ref typ) => {
|
||||
walk_trait_ref_helper(visitor, typ)
|
||||
}
|
||||
UnboxedFnTyParamBound(ref function_declaration) => {
|
||||
for argument in function_declaration.decl.inputs.iter() {
|
||||
visitor.visit_ty(&*argument.ty)
|
||||
}
|
||||
visitor.visit_ty(&*function_declaration.decl.output);
|
||||
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
|
||||
}
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
visitor.visit_lifetime_ref(lifetime);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn fn1(0: Box) {} //~ ERROR: not enough type parameters supplied to `Box<T>`
|
||||
fn fn1(0: Box) {} //~ ERROR: wrong number of type arguments: expected 1, found 0
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
18
src/test/compile-fail/issue-18423.rs
Normal file
18
src/test/compile-fail/issue-18423.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that `Box` cannot be used with a lifetime parameter.
|
||||
|
||||
struct Foo<'a> {
|
||||
x: Box<'a, int> //~ ERROR wrong number of lifetime parameters
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
}
|
37
src/test/compile-fail/unboxed-closure-sugar-default.rs
Normal file
37
src/test/compile-fail/unboxed-closure-sugar-default.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test interaction between unboxed closure sugar and default type
|
||||
// parameters (should be exactly as if angle brackets were used).
|
||||
|
||||
#![feature(default_type_params)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct Foo<T,U,V=T> {
|
||||
t: T, u: U
|
||||
}
|
||||
|
||||
trait Eq<X> { }
|
||||
impl<X> Eq<X> for X { }
|
||||
fn eq<A,B:Eq<A>>() { }
|
||||
|
||||
fn test<'a,'b>() {
|
||||
// Parens are equivalent to omitting default in angle.
|
||||
eq::< Foo<(int,),()>, Foo(int) >();
|
||||
|
||||
// In angle version, we supply something other than the default
|
||||
eq::< Foo<(int,),(),int>, Foo(int) >();
|
||||
//~^ ERROR not implemented
|
||||
|
||||
// Supply default explicitly.
|
||||
eq::< Foo<(int,),(),(int,)>, Foo(int) >();
|
||||
}
|
||||
|
||||
fn main() { }
|
39
src/test/compile-fail/unboxed-closure-sugar-equiv.rs
Normal file
39
src/test/compile-fail/unboxed-closure-sugar-equiv.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that the unboxed closure sugar can be used with an arbitrary
|
||||
// struct type and that it is equivalent to the same syntax using
|
||||
// angle brackets. This test covers only simple types and in
|
||||
// particular doesn't test bound regions.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct Foo<T,U> {
|
||||
t: T, u: U
|
||||
}
|
||||
|
||||
trait Eq<X> { }
|
||||
impl<X> Eq<X> for X { }
|
||||
fn eq<A,B:Eq<A>>() { }
|
||||
|
||||
fn test<'a,'b>() {
|
||||
// No errors expected:
|
||||
eq::< Foo<(),()>, Foo() >();
|
||||
eq::< Foo<(int,),()>, Foo(int) >();
|
||||
eq::< Foo<(int,uint),()>, Foo(int,uint) >();
|
||||
eq::< Foo<(int,uint),uint>, Foo(int,uint) -> uint >();
|
||||
eq::< Foo<(&'a int,&'b uint),uint>, Foo(&'a int,&'b uint) -> uint >();
|
||||
|
||||
// Errors expected:
|
||||
eq::< Foo<(),()>, Foo(char) >();
|
||||
//~^ ERROR not implemented
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn f<F:Nonexist(int) -> int>(x: F) {} //~ ERROR unresolved trait
|
||||
fn f<F:Nonexist(int) -> int>(x: F) {} //~ ERROR nonexistent trait `Nonexist`
|
||||
|
||||
type Typedef = int;
|
||||
|
||||
|
45
src/test/compile-fail/unboxed-closure-sugar-region.rs
Normal file
45
src/test/compile-fail/unboxed-closure-sugar-region.rs
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test interaction between unboxed closure sugar and region
|
||||
// parameters (should be exactly as if angle brackets were used
|
||||
// and regions omitted).
|
||||
|
||||
#![feature(default_type_params)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::kinds::marker;
|
||||
|
||||
struct Foo<'a,T,U> {
|
||||
t: T,
|
||||
u: U,
|
||||
m: marker::InvariantLifetime<'a>
|
||||
}
|
||||
|
||||
trait Eq<X> { }
|
||||
impl<X> Eq<X> for X { }
|
||||
fn eq<A,B:Eq<A>>() { }
|
||||
fn same_type<A,B:Eq<A>>(a: A, b: B) { }
|
||||
|
||||
fn test<'a,'b>() {
|
||||
// Parens are equivalent to omitting default in angle.
|
||||
eq::< Foo<(int,),()>, Foo(int) >();
|
||||
|
||||
// Here we specify 'static explicitly in angle-bracket version.
|
||||
// Parenthesized winds up getting inferred.
|
||||
eq::< Foo<'static, (int,),()>, Foo(int) >();
|
||||
}
|
||||
|
||||
fn test2(x: Foo<(int,),()>, y: Foo(int)) {
|
||||
// Here, the omitted lifetimes are expanded to distinct things.
|
||||
same_type(x, y) //~ ERROR cannot infer
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,16 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct One<A>;
|
||||
|
||||
fn foo(_: One()) //~ ERROR wrong number of type arguments
|
||||
{}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,16 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct Three<A,B,C>;
|
||||
|
||||
fn foo(_: Three()) //~ ERROR wrong number of type arguments
|
||||
{}
|
||||
|
||||
fn main() { }
|
@ -0,0 +1,16 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct Zero;
|
||||
|
||||
fn foo(_: Zero()) //~ ERROR wrong number of type arguments
|
||||
{}
|
||||
|
||||
fn main() { }
|
@ -11,7 +11,7 @@
|
||||
trait Trait {}
|
||||
|
||||
fn f<F:Trait(int) -> int>(x: F) {}
|
||||
//~^ ERROR unboxed function trait must be one of `Fn`, `FnMut`, or `FnOnce`
|
||||
//~^ ERROR wrong number of type arguments: expected 0, found 2
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
@ -25,7 +25,7 @@ fn call_it<F:FnMut(int)->int>(mut f: F, x: int) -> int {
|
||||
f.call_mut((x,)) + 3
|
||||
}
|
||||
|
||||
fn call_box(f: &mut |&mut: int|->int, x: int) -> int {
|
||||
fn call_box(f: &mut FnMut(int) -> int, x: int) -> int {
|
||||
f.call_mut((x,)) + 3
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
#![feature(unboxed_closures, unboxed_closure_sugar)]
|
||||
|
||||
fn main() {
|
||||
let task: Box<|: int| -> int> = box |: x| x;
|
||||
let task: Box<FnOnce(int) -> int> = box |: x| x;
|
||||
task.call_once((0i, ));
|
||||
}
|
||||
|
||||
|
34
src/test/run-pass/unboxed-closures-sugar-1.rs
Normal file
34
src/test/run-pass/unboxed-closures-sugar-1.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that the unboxed closure sugar can be used with an arbitrary
|
||||
// struct type and that it is equivalent to the same syntax using
|
||||
// angle brackets. This test covers only simple types and in
|
||||
// particular doesn't test bound regions.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct Foo<T,U> {
|
||||
t: T, u: U
|
||||
}
|
||||
|
||||
trait Eq<X> { }
|
||||
impl<X> Eq<X> for X { }
|
||||
fn eq<A,B:Eq<A>>() { }
|
||||
|
||||
fn test<'a,'b>() {
|
||||
eq::< Foo<(),()>, Foo() >();
|
||||
eq::< Foo<(int,),()>, Foo(int) >();
|
||||
eq::< Foo<(int,uint),()>, Foo(int,uint) >();
|
||||
eq::< Foo<(int,uint),uint>, Foo(int,uint) -> uint >();
|
||||
eq::< Foo<(&'a int,&'b uint),uint>, Foo(&'a int,&'b uint) -> uint >();
|
||||
}
|
||||
|
||||
fn main() { }
|
34
src/test/run-pass/unboxed-closures-sugar-object.rs
Normal file
34
src/test/run-pass/unboxed-closures-sugar-object.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test unboxed closure sugar used in object types.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct Foo<T,U> {
|
||||
t: T, u: U
|
||||
}
|
||||
|
||||
trait Getter<A,R> {
|
||||
fn get(&self, arg: A) -> R;
|
||||
}
|
||||
|
||||
struct Identity;
|
||||
impl<X> Getter<X,X> for Identity {
|
||||
fn get(&self, arg: X) -> X {
|
||||
arg
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: &Getter(int) -> (int,) = &Identity;
|
||||
let (y,) = x.get((22,));
|
||||
assert_eq!(y, 22);
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
use std::ops::FnOnce;
|
||||
|
||||
fn main() {
|
||||
let task: Box<|: int| -> int> = box |: x| x;
|
||||
let task: Box<FnOnce(int) -> int> = box |: x| x;
|
||||
assert!(task.call_once((1234i,)) == 1234i);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user