提交 07cdb853 编写于 作者: N Niko Matsakis

Move return type an associated type of the `Fn*` traits. Mostly this involves tweaking things in

the compiler that assumed two input types to assume two ouputs; we also have to teach `project.rs`
to project `Output` from the unboxed closure and fn traits.
上级 c61d7889
......@@ -758,7 +758,9 @@ struct Counter<'a, 'b> {
expected: &'b [int],
}
impl<'a, 'b, 'c> FnMut(&'c int) -> bool for Counter<'a, 'b> {
impl<'a, 'b, 'c> FnMut<(&'c int,)> for Counter<'a, 'b> {
type Output = bool;
extern "rust-call" fn call_mut(&mut self, (&x,): (&'c int,)) -> bool {
assert_eq!(x, self.expected[*self.i]);
*self.i += 1;
......
......@@ -1117,29 +1117,33 @@ fn deref_mut(&mut self) -> &mut T { *self }
#[lang="fn"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
pub trait Fn<Args,Result> {
#[cfg(stage0)]
pub trait Fn<Args,Output> {
/// This is called when the call operator is used.
extern "rust-call" fn call(&self, args: Args) -> Result;
extern "rust-call" fn call(&self, args: Args) -> Output;
}
/// A version of the call operator that takes a mutable receiver.
#[lang="fn_mut"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
pub trait FnMut<Args,Result> {
#[cfg(stage0)]
pub trait FnMut<Args,Output> {
/// This is called when the call operator is used.
extern "rust-call" fn call_mut(&mut self, args: Args) -> Result;
extern "rust-call" fn call_mut(&mut self, args: Args) -> Output;
}
/// A version of the call operator that takes a by-value receiver.
#[lang="fn_once"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
pub trait FnOnce<Args,Result> {
#[cfg(stage0)]
pub trait FnOnce<Args,Output> {
/// This is called when the call operator is used.
extern "rust-call" fn call_once(self, args: Args) -> Result;
extern "rust-call" fn call_once(self, args: Args) -> Output;
}
#[cfg(stage0)]
impl<F: ?Sized, A, R> FnMut<A, R> for F
where F : Fn<A, R>
{
......@@ -1148,6 +1152,7 @@ extern "rust-call" fn call_mut(&mut self, args: A) -> R {
}
}
#[cfg(stage0)]
impl<F,A,R> FnOnce<A,R> for F
where F : FnMut<A,R>
{
......@@ -1155,3 +1160,61 @@ extern "rust-call" fn call_once(mut self, args: A) -> R {
self.call_mut(args)
}
}
/// A version of the call operator that takes an immutable receiver.
#[lang="fn"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
pub trait Fn<Args> {
type Output;
/// This is called when the call operator is used.
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
/// A version of the call operator that takes a mutable receiver.
#[lang="fn_mut"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
pub trait FnMut<Args> {
type Output;
/// This is called when the call operator is used.
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
/// A version of the call operator that takes a by-value receiver.
#[lang="fn_once"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
pub trait FnOnce<Args> {
type Output;
/// This is called when the call operator is used.
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
#[cfg(not(stage0))]
impl<F: ?Sized, A> FnMut<A> for F
where F : Fn<A>
{
type Output = <F as Fn<A>>::Output;
extern "rust-call" fn call_mut(&mut self, args: A) -> <F as Fn<A>>::Output {
self.call(args)
}
}
#[cfg(not(stage0))]
impl<F,A> FnOnce<A> for F
where F : FnMut<A>
{
type Output = <F as FnMut<A>>::Output;
extern "rust-call" fn call_once(mut self, args: A) -> <F as FnMut<A>>::Output {
self.call_mut(args)
}
}
......@@ -461,6 +461,7 @@ fn next_back(&mut self) -> Option<(uint, char)> {
#[derive(Copy, Clone)]
struct BytesDeref;
#[cfg(stage0)]
impl<'a> Fn(&'a u8) -> u8 for BytesDeref {
#[inline]
extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
......@@ -468,6 +469,16 @@ extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
}
}
#[cfg(not(stage0))]
impl<'a> Fn<(&'a u8,)> for BytesDeref {
type Output = u8;
#[inline]
extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
*ptr
}
}
/// An iterator over the substrings of a string, separated by `sep`.
#[derive(Clone)]
struct CharSplits<'a, Sep> {
......
......@@ -18,13 +18,17 @@
use super::SelectionContext;
use super::SelectionError;
use super::VtableImplData;
use super::util;
use middle::infer;
use middle::subst::Subst;
use middle::subst::{Subst, Substs};
use middle::ty::{self, AsPredicate, ReferencesError, RegionEscape,
HasProjectionTypes, ToPolyTraitRef, Ty};
use middle::ty_fold::{self, TypeFoldable, TypeFolder};
use std::rc::Rc;
use syntax::ast;
use syntax::parse::token;
use util::common::FN_OUTPUT_NAME;
use util::ppaux::Repr;
pub type PolyProjectionObligation<'tcx> =
......@@ -53,6 +57,8 @@ pub struct MismatchedProjectionTypes<'tcx> {
enum ProjectionTyCandidate<'tcx> {
ParamEnv(ty::PolyProjectionPredicate<'tcx>),
Impl(VtableImplData<'tcx, PredicateObligation<'tcx>>),
Closure(ast::DefId, Substs<'tcx>),
FnPointer(Ty<'tcx>),
}
struct ProjectionTyCandidateSet<'tcx> {
......@@ -486,20 +492,22 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
let is_match = same_name && infcx.probe(|_| {
let origin = infer::Misc(obligation.cause.span);
let obligation_poly_trait_ref =
obligation_trait_ref.to_poly_trait_ref();
let data_poly_trait_ref =
data.to_poly_trait_ref();
let obligation_poly_trait_ref =
obligation_trait_ref.to_poly_trait_ref();
infcx.sub_poly_trait_refs(false,
origin,
obligation_poly_trait_ref,
data_poly_trait_ref).is_ok()
data_poly_trait_ref,
obligation_poly_trait_ref).is_ok()
});
if is_match {
debug!("assemble_candidates_from_predicates: candidate {}",
data.repr(selcx.tcx()));
debug!("assemble_candidates_from_predicates: candidate {} is_match {} same_name {}",
data.repr(selcx.tcx()),
is_match,
same_name);
if is_match {
candidate_set.vec.push(
ProjectionTyCandidate::ParamEnv(data.clone()));
}
......@@ -573,6 +581,14 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
selcx, obligation, obligation_trait_ref, candidate_set,
data.object_ty);
}
super::VtableClosure(closure_def_id, substs) => {
candidate_set.vec.push(
ProjectionTyCandidate::Closure(closure_def_id, substs));
}
super::VtableFnPointer(fn_type) => {
candidate_set.vec.push(
ProjectionTyCandidate::FnPointer(fn_type));
}
super::VtableParam(..) => {
// This case tell us nothing about the value of an
// associated type. Consider:
......@@ -600,9 +616,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
// projection. And the projection where clause is handled
// in `assemble_candidates_from_param_env`.
}
super::VtableBuiltin(..) |
super::VtableClosure(..) |
super::VtableFnPointer(..) => {
super::VtableBuiltin(..) => {
// These traits have no associated types.
selcx.tcx().sess.span_bug(
obligation.cause.span,
......@@ -628,67 +642,150 @@ fn confirm_candidate<'cx,'tcx>(
match candidate {
ProjectionTyCandidate::ParamEnv(poly_projection) => {
let projection =
infcx.replace_late_bound_regions_with_fresh_var(
obligation.cause.span,
infer::LateBoundRegionConversionTime::HigherRankedType,
&poly_projection).0;
assert_eq!(projection.projection_ty.item_name,
obligation.predicate.item_name);
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
match infcx.sub_trait_refs(false,
origin,
obligation.predicate.trait_ref.clone(),
projection.projection_ty.trait_ref.clone()) {
Ok(()) => { }
Err(e) => {
selcx.tcx().sess.span_bug(
obligation.cause.span,
format!("Failed to unify `{}` and `{}` in projection: {}",
obligation.repr(selcx.tcx()),
projection.repr(selcx.tcx()),
ty::type_err_to_str(selcx.tcx(), &e)).as_slice());
}
}
(projection.ty, vec!())
confirm_param_env_candidate(selcx, obligation, poly_projection)
}
ProjectionTyCandidate::Impl(impl_vtable) => {
// there don't seem to be nicer accessors to these:
let impl_items_map = selcx.tcx().impl_items.borrow();
let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow();
let impl_items = &impl_items_map[impl_vtable.impl_def_id];
let mut impl_ty = None;
for impl_item in impl_items.iter() {
let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] {
ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
ty::MethodTraitItem(..) => { continue; }
};
if assoc_type.name != obligation.predicate.item_name {
continue;
}
confirm_impl_candidate(selcx, obligation, impl_vtable)
}
let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id);
impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs));
break;
}
ProjectionTyCandidate::Closure(def_id, substs) => {
confirm_closure_candidate(selcx, obligation, def_id, &substs)
}
match impl_ty {
Some(ty) => (ty, impl_vtable.nested.into_vec()),
None => {
// This means that the impl is missing a
// definition for the associated type. This error
// ought to be reported by the type checker method
// `check_impl_items_against_trait`, so here we
// just return ty_err.
(selcx.tcx().types.err, vec!())
}
}
ProjectionTyCandidate::FnPointer(fn_type) => {
confirm_fn_pointer_candidate(selcx, obligation, fn_type)
}
}
}
fn confirm_fn_pointer_candidate<'cx,'tcx>(
selcx: &mut SelectionContext<'cx,'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
fn_type: Ty<'tcx>)
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
{
let fn_type = selcx.infcx().shallow_resolve(fn_type);
let sig = ty::ty_fn_sig(fn_type);
confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
}
fn confirm_closure_candidate<'cx,'tcx>(
selcx: &mut SelectionContext<'cx,'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
closure_def_id: ast::DefId,
substs: &Substs<'tcx>)
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
{
let closure_typer = selcx.closure_typer();
let closure_type = closure_typer.closure_type(closure_def_id, substs);
confirm_callable_candidate(selcx, obligation, &closure_type.sig, util::TupleArgumentsFlag::No)
}
fn confirm_callable_candidate<'cx,'tcx>(
selcx: &mut SelectionContext<'cx,'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
fn_sig: &ty::PolyFnSig<'tcx>,
flag: util::TupleArgumentsFlag)
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
{
let tcx = selcx.tcx();
debug!("confirm_closure_candidate({},{})",
obligation.repr(tcx),
fn_sig.repr(tcx));
// Note: we unwrap the binder here but re-create it below (1)
let ty::Binder((trait_ref, ret_type)) =
util::closure_trait_ref_and_return_type(tcx,
obligation.predicate.trait_ref.def_id,
obligation.predicate.trait_ref.self_ty(),
fn_sig,
flag);
let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here
projection_ty: ty::ProjectionTy {
trait_ref: trait_ref,
item_name: token::intern(FN_OUTPUT_NAME),
},
ty: ret_type
});
confirm_param_env_candidate(selcx, obligation, predicate)
}
fn confirm_param_env_candidate<'cx,'tcx>(
selcx: &mut SelectionContext<'cx,'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
poly_projection: ty::PolyProjectionPredicate<'tcx>)
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
{
let infcx = selcx.infcx();
let projection =
infcx.replace_late_bound_regions_with_fresh_var(
obligation.cause.span,
infer::LateBoundRegionConversionTime::HigherRankedType,
&poly_projection).0;
assert_eq!(projection.projection_ty.item_name,
obligation.predicate.item_name);
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
match infcx.sub_trait_refs(false,
origin,
obligation.predicate.trait_ref.clone(),
projection.projection_ty.trait_ref.clone()) {
Ok(()) => { }
Err(e) => {
selcx.tcx().sess.span_bug(
obligation.cause.span,
format!("Failed to unify `{}` and `{}` in projection: {}",
obligation.repr(selcx.tcx()),
projection.repr(selcx.tcx()),
ty::type_err_to_str(selcx.tcx(), &e)).as_slice());
}
}
(projection.ty, vec!())
}
fn confirm_impl_candidate<'cx,'tcx>(
selcx: &mut SelectionContext<'cx,'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>)
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
{
// there don't seem to be nicer accessors to these:
let impl_items_map = selcx.tcx().impl_items.borrow();
let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow();
let impl_items = &impl_items_map[impl_vtable.impl_def_id];
let mut impl_ty = None;
for impl_item in impl_items.iter() {
let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] {
ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
ty::MethodTraitItem(..) => { continue; }
};
if assoc_type.name != obligation.predicate.item_name {
continue;
}
let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id);
impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs));
break;
}
match impl_ty {
Some(ty) => (ty, impl_vtable.nested.into_vec()),
None => {
// This means that the impl is missing a
// definition for the associated type. This error
// ought to be reported by the type checker method
// `check_impl_items_against_trait`, so here we
// just return ty_err.
(selcx.tcx().types.err, vec!())
}
}
}
......@@ -710,7 +807,11 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
ProjectionTyCandidate::ParamEnv(ref data) =>
format!("ParamEnv({})", data.repr(tcx)),
ProjectionTyCandidate::Impl(ref data) =>
format!("Impl({})", data.repr(tcx))
format!("Impl({})", data.repr(tcx)),
ProjectionTyCandidate::Closure(ref a, ref b) =>
format!("Closure(({},{}))", a.repr(tcx), b.repr(tcx)),
ProjectionTyCandidate::FnPointer(a) =>
format!("FnPointer(({}))", a.repr(tcx)),
}
}
}
......
......@@ -214,6 +214,10 @@ pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'cx, 'tcx> {
self.closure_typer.param_env()
}
pub fn closure_typer(&self) -> &'cx (ty::UnboxedClosureTyper<'tcx>+'cx) {
self.closure_typer
}
///////////////////////////////////////////////////////////////////////////
// Selection
//
......@@ -1913,33 +1917,14 @@ fn confirm_fn_pointer_candidate(&mut self,
obligation.repr(self.tcx()));
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
let sig = match self_ty.sty {
ty::ty_bare_fn(_, &ty::BareFnTy {
unsafety: ast::Unsafety::Normal,
abi: abi::Rust,
ref sig
}) => {
sig
}
_ => {
self.tcx().sess.span_bug(
obligation.cause.span,
&format!("Fn pointer candidate for inappropriate self type: {}",
self_ty.repr(self.tcx()))[]);
}
};
let arguments_tuple = ty::mk_tup(self.tcx(), sig.0.inputs.to_vec());
let output_type = sig.0.output.unwrap();
let substs =
Substs::new_trait(
vec![arguments_tuple, output_type],
vec![],
self_ty);
let trait_ref = ty::Binder(Rc::new(ty::TraitRef {
def_id: obligation.predicate.def_id(),
substs: self.tcx().mk_substs(substs),
}));
let sig = ty::ty_fn_sig(self_ty);
let ty::Binder((trait_ref, _)) =
util::closure_trait_ref_and_return_type(self.tcx(),
obligation.predicate.def_id(),
self_ty,
sig,
util::TupleArgumentsFlag::Yes);
let trait_ref = ty::Binder(trait_ref);
try!(self.confirm_poly_trait_refs(obligation.cause.clone(),
obligation.predicate.to_poly_trait_ref(),
......@@ -1958,23 +1943,9 @@ fn confirm_closure_candidate(&mut self,
closure_def_id.repr(self.tcx()),
substs.repr(self.tcx()));
let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
debug!("confirm_closure_candidate: closure_def_id={} closure_type={}",
closure_def_id.repr(self.tcx()),
closure_type.repr(self.tcx()));
let closure_sig = &closure_type.sig;
let arguments_tuple = closure_sig.0.inputs[0];
let trait_substs =
Substs::new_trait(
vec![arguments_tuple, closure_sig.0.output.unwrap()],
vec![],
obligation.self_ty());
let trait_ref = ty::Binder(Rc::new(ty::TraitRef {
def_id: obligation.predicate.def_id(),
substs: self.tcx().mk_substs(trait_substs),
}));
let trait_ref = self.closure_trait_ref(obligation,
closure_def_id,
substs);
debug!("confirm_closure_candidate(closure_def_id={}, trait_ref={})",
closure_def_id.repr(self.tcx()),
......@@ -2280,6 +2251,29 @@ fn all_impls(&self, trait_def_id: ast::DefId) -> Vec<ast::DefId> {
}
}
fn closure_trait_ref(&self,
obligation: &TraitObligation<'tcx>,
closure_def_id: ast::DefId,
substs: &Substs<'tcx>)
-> ty::PolyTraitRef<'tcx>
{
let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
let ty::Binder((trait_ref, _)) =
util::closure_trait_ref_and_return_type(self.tcx(),
obligation.predicate.def_id(),
obligation.predicate.0.self_ty(), // (1)
&closure_type.sig,
util::TupleArgumentsFlag::No);
// (1) Feels icky to skip the binder here, but OTOH we know
// that the self-type is an unboxed closure type and hence is
// in fact unparameterized (or at least does not reference any
// regions bound in the obligation). Still probably some
// refactoring could make this nicer.
ty::Binder(trait_ref)
}
fn impl_obligations(&mut self,
cause: ObligationCause<'tcx>,
recursion_depth: uint,
......
......@@ -353,6 +353,36 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
method_count + method_index_in_trait
}
pub fn unboxed_closure_trait_ref_and_return_type<'tcx>(
closure_typer: &ty::UnboxedClosureTyper<'tcx>,
fn_trait_def_id: ast::DefId,
self_ty: Ty<'tcx>,
closure_def_id: ast::DefId,
substs: &Substs<'tcx>)
-> ty::Binder<(Rc<ty::TraitRef<'tcx>>, Ty<'tcx>)>
{
let tcx = closure_typer.param_env().tcx;
let closure_type = closure_typer.unboxed_closure_type(closure_def_id, substs);
debug!("unboxed_closure_trait_ref: closure_def_id={} closure_type={}",
closure_def_id.repr(tcx),
closure_type.repr(tcx));
let closure_sig = &closure_type.sig;
let arguments_tuple = closure_sig.0.inputs[0];
let trait_substs =
Substs::new_trait(
vec![arguments_tuple],
vec![],
self_ty);
let trait_ref = Rc::new(ty::TraitRef {
def_id: fn_trait_def_id,
substs: tcx.mk_substs(trait_substs),
});
ty::Binder((trait_ref, closure_sig.0.output.unwrap()))
}
impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
format!("Obligation(predicate={},depth={})",
......
......@@ -22,6 +22,9 @@
use syntax::visit;
use syntax::visit::Visitor;
// The name of the associated type for `Fn` return types
pub const FN_OUTPUT_NAME: &'static str = "Output";
// Useful type to use with `Result<>` indicate that an error has already
// been reported to the user, so no need to continue checking.
#[derive(Clone, Copy, Show)]
......
......@@ -512,7 +512,7 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
}
if cx.lang_items.fn_trait_kind(did).is_some() {
format!("{}({}){}",
format!("{}({})", // TODO
base,
if strs[0].starts_with("(") && strs[0].ends_with(",)") {
&strs[0][1 .. strs[0].len() - 2] // Remove '(' and ',)'
......@@ -520,8 +520,7 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
&strs[0][1 .. strs[0].len() - 1] // Remove '(' and ')'
} else {
&strs[0][]
},
if &*strs[1] == "()" { String::new() } else { format!(" -> {}", strs[1]) })
})
} else if strs.len() > 0 {
format!("{}<{}>", base, strs.connect(", "))
} else {
......
......@@ -57,7 +57,7 @@
use rscope::{self, UnelidableRscope, RegionScope, SpecificRscope,
ShiftedRscope, BindingRscope};
use TypeAndSubsts;
use util::common::ErrorReported;
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::DefIdMap;
use util::ppaux::{self, Repr, UserString};
......@@ -268,7 +268,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
ast::ParenthesizedParameters(ref data) => {
span_err!(tcx.sess, path.span, E0214,
"parenthesized parameters may only be used with a trait");
(Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
convert_parenthesized_parameters(this, data)
}
};
......@@ -479,7 +479,9 @@ fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>,
fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
data: &ast::ParenthesizedParameterData)
-> Vec<Ty<'tcx>>
-> (Vec<ty::Region>,
Vec<Ty<'tcx>>,
Vec<ConvertedBinding<'tcx>>)
{
let binding_rscope = BindingRscope::new();
let inputs = data.inputs.iter()
......@@ -492,15 +494,26 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
let input_ty = ty::mk_tup(this.tcx(), inputs);
let output = match data.output {
Some(ref output_ty) => convert_ty_with_lifetime_elision(this,
implied_output_region,
params_lifetimes,
&**output_ty),
None => ty::mk_nil(this.tcx()),
let (output, output_span) = match data.output {
Some(ref output_ty) => {
(convert_ty_with_lifetime_elision(this,
implied_output_region,
params_lifetimes,
&**output_ty),
output_ty.span)
}
None => {
(ty::mk_nil(this.tcx()), data.span)
}
};
let output_binding = ConvertedBinding {
item_name: token::intern(FN_OUTPUT_NAME),
ty: output,
span: output_span
};
vec![input_ty, output]
(vec![], vec![input_ty], vec![output_binding])
}
pub fn instantiate_poly_trait_ref<'tcx>(
......@@ -630,7 +643,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
the crate attributes to enable");
}
(Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
convert_parenthesized_parameters(this, data)
}
};
......
......@@ -347,6 +347,9 @@ fn is_empty(&self) -> bool {
/// A path like `Foo(A,B) -> C`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub struct ParenthesizedParameterData {
/// Overall span
pub span: Span,
/// `(A,B)`
pub inputs: Vec<P<Ty>>,
......
......@@ -536,9 +536,10 @@ pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedPara
fld: &mut T)
-> ParenthesizedParameterData
{
let ParenthesizedParameterData { inputs, output } = data;
let ParenthesizedParameterData { inputs, output, span } = data;
ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
output: output.map(|ty| fld.fold_ty(ty)) }
output: output.map(|ty| fld.fold_ty(ty)),
span: fld.new_span(span) }
}
pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
......
......@@ -1796,6 +1796,8 @@ pub fn parse_path_segments_without_colons(&mut self) -> Vec<ast::PathSegment> {
bindings: OwnedSlice::from_vec(bindings),
})
} else if self.eat(&token::OpenDelim(token::Paren)) {
let lo = self.last_span.lo;
let inputs = self.parse_seq_to_end(
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
......@@ -1807,9 +1809,12 @@ pub fn parse_path_segments_without_colons(&mut self) -> Vec<ast::PathSegment> {
None
};
let hi = self.last_span.hi;
ast::ParenthesizedParameters(ast::ParenthesizedParameterData {
span: mk_sp(lo, hi),
inputs: inputs,
output: output_ty
output: output_ty,
})
} else {
ast::PathParameters::none()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册