diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index e95087fa84689409eb6d4baed25336b5a44b7869..a090e4f24ce1d35ba16d7827e1f270fb8e6c2f0d 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -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; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index d482888e3bc8ca9608e526a566cfc6b50eb20f23..0e99a2c9c3e1b2e8fc20683ade769707d79ccbd9 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -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 { +#[cfg(stage0)] +pub trait Fn { /// 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 { +#[cfg(stage0)] +pub trait FnMut { /// 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 { +#[cfg(stage0)] +pub trait FnOnce { /// 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 FnMut for F where F : Fn { @@ -1148,6 +1152,7 @@ extern "rust-call" fn call_mut(&mut self, args: A) -> R { } } +#[cfg(stage0)] impl FnOnce for F where F : FnMut { @@ -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 { + 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 { + 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 { + 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 FnMut for F + where F : Fn +{ + type Output = >::Output; + + extern "rust-call" fn call_mut(&mut self, args: A) -> >::Output { + self.call(args) + } +} + +#[cfg(not(stage0))] +impl FnOnce for F + where F : FnMut +{ + type Output = >::Output; + + extern "rust-call" fn call_once(mut self, args: A) -> >::Output { + self.call_mut(args) + } +} diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 5b94733ea6fd6d3ca5f4e31396c40380b9c2c27c..101d349c3517084896bf207c22c8df28e055a539 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -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> { diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 0011603d3fa24c71adca1a87f3e3dda6156f69d7..d1dd086a5a342b0adface7779e15ca9f60ff452f 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -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>) +{ + 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>) +{ + 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>) +{ + 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>) +{ + 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>) +{ + // 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)), } } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 12ad56d316abacd4585c64f633104b0c5b72ccd3..2ad6f63a341d63bd18881f05c05d9595473ba4f0 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -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 { } } + 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, diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index beb28260834acf4e8e46bae3828a1645ba5665b3..f8c184896513c324d6d26fc53005ab637a00977c 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -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<'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={})", diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 8915d55e2063e7b5fa7ce1c4ffee26bfaedbff3e..bdb6ea22f8b457fa2c779ac945bef9804e64407b 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -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)] diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 5601898136c79d629773ed2c93d649322a3cd252..c10ce686f08c1fbee22986c8da93c30776893068 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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 { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 921ed505fa3af3517fadc1d4ba1818a23748c865..6e8dd6b0ae7551740ba5410cd594cce8dd1a960e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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> + -> (Vec, + Vec>, + Vec>) { 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) } }; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 4f6cd8ad356d70750266ec2e892c9439b051ba9e..4dada5bc81ec23f96fb65529c23d9652236c63c8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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>, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index bf822599a8864347a29e06157bb3b75f9eb7d08b..a1362f5382c979b4f3864039181f5e7e2fd5e434 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -536,9 +536,10 @@ pub fn noop_fold_parenthesized_parameter_data(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(l: P, fld: &mut T) -> P { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fbea265597c6a5b7a531b1c94c0690f1864b458d..4c1ae532d13cdb151064ff0eabfe4400fb92f8e8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1796,6 +1796,8 @@ pub fn parse_path_segments_without_colons(&mut self) -> Vec { 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 { 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()