diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index e95087fa84689..a090e4f24ce1d 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -758,7 +758,9 @@ mod test { 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 d482888e3bc8c..0e99a2c9c3e1b 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -1117,29 +1117,33 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T { #[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 @@ impl FnMut for F } } +#[cfg(stage0)] impl FnOnce for F where F : FnMut { @@ -1155,3 +1160,61 @@ impl FnOnce for F 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 5b94733ea6fd6..101d349c35170 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -461,6 +461,7 @@ delegate_iter!{exact u8 : Bytes<'a>} #[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 @@ impl<'a> Fn(&'a u8) -> u8 for BytesDeref { } } +#[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/astencode.rs b/src/librustc/middle/astencode.rs index 091ef9d52eb40..af41844b2df12 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -904,8 +904,8 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { try!(this.emit_struct_field("method_num", 0, |this| { this.emit_uint(o.method_num) })); - try!(this.emit_struct_field("real_index", 0, |this| { - this.emit_uint(o.real_index) + try!(this.emit_struct_field("vtable_index", 0, |this| { + this.emit_uint(o.vtable_index) })); Ok(()) }) @@ -1492,8 +1492,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { this.read_uint() }).unwrap() }, - real_index: { - this.read_struct_field("real_index", 3, |this| { + vtable_index: { + this.read_struct_field("vtable_index", 3, |this| { this.read_uint() }).unwrap() }, diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index 7ccb5e6e71160..5e7168b67358e 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -408,7 +408,7 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, } ObligationCauseCode::CompareImplMethodObligation => { span_note!(tcx.sess, cause_span, - "the requirement `{}` appears on the impl method\ + "the requirement `{}` appears on the impl method \ but not on the corresponding trait method", predicate.user_string(infcx.tcx)); } diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 8d3888fcfdbb5..82a4a60cebbf7 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -18,7 +18,7 @@ pub use self::ObligationCauseCode::*; use middle::mem_categorization::Typer; use middle::subst; use middle::ty::{self, Ty}; -use middle::infer::InferCtxt; +use middle::infer::{self, InferCtxt}; use std::slice::Iter; use std::rc::Rc; use syntax::ast; @@ -392,6 +392,65 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, } } +pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>, + cause: ObligationCause<'tcx>) + -> ty::ParameterEnvironment<'a,'tcx> +{ + match normalize_param_env(&unnormalized_env, cause) { + Ok(p) => p, + Err(errors) => { + // I'm not wild about reporting errors here; I'd prefer to + // have the errors get reported at a defined place (e.g., + // during typeck). Instead I have all parameter + // environments, in effect, going through this function + // and hence potentially reporting errors. This ensurse of + // course that we never forget to normalize (the + // alternative seemed like it would involve a lot of + // manual invocations of this fn -- and then we'd have to + // deal with the errors at each of those sites). + // + // In any case, in practice, typeck constructs all the + // parameter environments once for every fn as it goes, + // and errors will get reported then; so after typeck we + // can be sure that no errors should occur. + let infcx = infer::new_infer_ctxt(unnormalized_env.tcx); + report_fulfillment_errors(&infcx, &errors); + + // Normalized failed? use what they gave us, it's better than nothing. + unnormalized_env + } + } +} + +pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>, + cause: ObligationCause<'tcx>) + -> Result, + Vec>> +{ + let tcx = param_env.tcx; + + debug!("normalize_param_env(param_env={})", + param_env.repr(tcx)); + + let predicates: Vec> = { + let infcx = infer::new_infer_ctxt(tcx); + let mut selcx = &mut SelectionContext::new(&infcx, param_env); + let mut fulfill_cx = FulfillmentContext::new(); + let Normalized { value: predicates, obligations } = + project::normalize(selcx, cause, ¶m_env.caller_bounds); + for obligation in obligations.into_iter() { + fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation); + } + try!(fulfill_cx.select_all_or_error(selcx.infcx(), param_env)); + predicates.iter().map(|p| infcx.resolve_type_vars_if_possible(p)).collect() + }; + + debug!("normalize_param_env: predicates={}", + predicates.repr(tcx)); + + Ok(param_env.with_caller_bounds(predicates)) +} + impl<'tcx,O> Obligation<'tcx,O> { pub fn new(cause: ObligationCause<'tcx>, trait_ref: O) diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index c0399112c33a9..56c1419502fd0 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -122,17 +122,15 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>, trait_def_id: ast::DefId) -> bool { - let trait_def = ty::lookup_trait_def(tcx, trait_def_id); - let param_env = ty::construct_parameter_environment(tcx, - &trait_def.generics, - ast::DUMMY_NODE_ID); - let predicates = param_env.caller_bounds.predicates.as_slice().to_vec(); let sized_def_id = match tcx.lang_items.sized_trait() { Some(def_id) => def_id, None => { return false; /* No Sized trait, can't require it! */ } }; // Search for a predicate like `Self : Sized` amongst the trait bounds. + let trait_def = ty::lookup_trait_def(tcx, trait_def_id); + let free_substs = ty::construct_free_substs(tcx, &trait_def.generics, ast::DUMMY_NODE_ID); + let predicates = trait_def.generics.to_bounds(tcx, &free_substs).predicates.into_vec(); elaborate_predicates(tcx, predicates) .any(|predicate| { match predicate { diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index c179153dbde0a..d1dd086a5a342 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -18,13 +18,17 @@ use super::PredicateObligation; 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> { @@ -60,6 +66,11 @@ struct ProjectionTyCandidateSet<'tcx> { ambiguous: bool } +/// Evaluates constraints of the form: +/// +/// for<...> ::U == V +/// +/// If successful, this may result in additional obligations. pub fn poly_project_and_unify_type<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, obligation: &PolyProjectionObligation<'tcx>) @@ -102,8 +113,11 @@ pub fn poly_project_and_unify_type<'cx,'tcx>( } } -/// Compute result of projecting an associated type and unify it with -/// `obligation.predicate.ty` (if we can). +/// Evaluates constraints of the form: +/// +/// ::U == V +/// +/// If successful, this may result in additional obligations. fn project_and_unify_type<'cx,'tcx>( selcx: &mut SelectionContext<'cx,'tcx>, obligation: &ProjectionObligation<'tcx>) @@ -133,6 +147,10 @@ fn project_and_unify_type<'cx,'tcx>( } } +/// Normalizes any associated type projections in `value`, replacing +/// them with a fully resolved type where possible. The return value +/// combines the normalized result and any additional obligations that +/// were incurred as result. pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>, cause: ObligationCause<'tcx>, value: &T) @@ -142,6 +160,7 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>, normalize_with_depth(selcx, cause, 0, value) } +/// As `normalize`, but with a custom depth. pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>, cause: ObligationCause<'tcx>, depth: uint, @@ -251,6 +270,12 @@ impl<'tcx,T> Normalized<'tcx,T> { } } +/// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly +/// additional obligations). If ambiguity arises, which implies that +/// there are unresolved type variables in the projection, we will +/// substitute a fresh type variable `$X` and generate a new +/// obligation `::Item == $X` for later. pub fn normalize_projection_type<'a,'b,'tcx>( selcx: &'a mut SelectionContext<'b,'tcx>, projection_ty: ty::ProjectionTy<'tcx>, @@ -277,6 +302,10 @@ pub fn normalize_projection_type<'a,'b,'tcx>( }) } +/// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly +/// additional obligations). Returns `None` in the case of ambiguity, +/// which indicates that there are unbound type variables. fn opt_normalize_projection_type<'a,'b,'tcx>( selcx: &'a mut SelectionContext<'b,'tcx>, projection_ty: ty::ProjectionTy<'tcx>, @@ -440,8 +469,7 @@ fn assemble_candidates_from_param_env<'cx,'tcx>( obligation_trait_ref: &Rc>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>) { - let env_predicates = selcx.param_env().caller_bounds.predicates.clone(); - let env_predicates = env_predicates.iter().cloned().collect(); + let env_predicates = selcx.param_env().caller_bounds.clone(); assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, candidate_set, env_predicates); } @@ -464,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())); } @@ -551,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: @@ -578,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, @@ -606,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!()) } } } @@ -688,7 +807,11 @@ impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> { 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 b18cb86a2f4c3..4d5f3d925b09a 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -214,6 +214,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.closure_typer.param_env() } + pub fn closure_typer(&self) -> &'cx (ty::ClosureTyper<'tcx>+'cx) { + self.closure_typer + } + /////////////////////////////////////////////////////////////////////////// // Selection // @@ -951,7 +955,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack.obligation.repr(self.tcx())); let caller_trait_refs: Vec<_> = - self.param_env().caller_bounds.predicates.iter() + self.param_env().caller_bounds.iter() .filter_map(|o| o.to_opt_poly_trait_ref()) .collect(); @@ -1913,33 +1917,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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()), @@ -2157,16 +2128,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { where_clause_trait_ref: ty::PolyTraitRef<'tcx>) -> Result>,()> { - let where_clause_trait_ref = - project::normalize_with_depth(self, - obligation.cause.clone(), - obligation.recursion_depth+1, - &where_clause_trait_ref); - let () = - try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref.value.clone())); + try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref)); - Ok(where_clause_trait_ref.obligations) + Ok(Vec::new()) } /// Returns `Ok` if `poly_trait_ref` being true implies that the @@ -2286,6 +2251,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + 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 beb28260834ac..edeca83d5697f 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -329,28 +329,67 @@ pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>, pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>, object_trait_ref: ty::PolyTraitRef<'tcx>, trait_def_id: ast::DefId, - method_index_in_trait: uint) -> uint { + method_offset_in_trait: uint) -> uint { // We need to figure the "real index" of the method in a // listing of all the methods of an object. We do this by // iterating down the supertraits of the object's trait until // we find the trait the method came from, counting up the // methods from them. let mut method_count = 0; - ty::each_bound_trait_and_supertraits(tcx, &[object_trait_ref], |bound_ref| { + + for bound_ref in transitive_bounds(tcx, &[object_trait_ref]) { if bound_ref.def_id() == trait_def_id { - false - } else { - let trait_items = ty::trait_items(tcx, bound_ref.def_id()); - for trait_item in trait_items.iter() { - match *trait_item { - ty::MethodTraitItem(_) => method_count += 1, - ty::TypeTraitItem(_) => {} - } + break; + } + + let trait_items = ty::trait_items(tcx, bound_ref.def_id()); + for trait_item in trait_items.iter() { + match *trait_item { + ty::MethodTraitItem(_) => method_count += 1, + ty::TypeTraitItem(_) => {} } - true } + } + + // count number of methods preceding the one we are selecting and + // add them to the total offset; skip over associated types. + let trait_items = ty::trait_items(tcx, trait_def_id); + for trait_item in trait_items.iter().take(method_offset_in_trait) { + match *trait_item { + ty::MethodTraitItem(_) => method_count += 1, + ty::TypeTraitItem(_) => {} + } + } + + // the item at the offset we were given really ought to be a method + assert!(match trait_items[method_offset_in_trait] { + ty::MethodTraitItem(_) => true, + ty::TypeTraitItem(_) => false + }); + + method_count +} + +pub enum TupleArgumentsFlag { Yes, No } + +pub fn closure_trait_ref_and_return_type<'tcx>( + tcx: &ty::ctxt<'tcx>, + fn_trait_def_id: ast::DefId, + self_ty: Ty<'tcx>, + sig: &ty::PolyFnSig<'tcx>, + tuple_arguments: TupleArgumentsFlag) + -> ty::Binder<(Rc>, Ty<'tcx>)> +{ + let arguments_tuple = match tuple_arguments { + TupleArgumentsFlag::No => sig.0.inputs[0], + TupleArgumentsFlag::Yes => ty::mk_tup(tcx, sig.0.inputs.to_vec()), + }; + 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), }); - method_count + method_index_in_trait + ty::Binder((trait_ref, sig.0.output.unwrap())) } impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 86cf030c8288a..062ddd23d9de9 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -452,7 +452,10 @@ pub struct MethodParam<'tcx> { // never contains bound regions; those regions should have been // instantiated with fresh variables at this point. pub trait_ref: Rc>, - // index of uint in the list of methods for the trait + + // index of uint in the list of trait items. Note that this is NOT + // the index into the vtable, because the list of trait items + // includes associated types. pub method_num: uint, /// The impl for the trait from which the method comes. This @@ -471,14 +474,14 @@ pub struct MethodObject<'tcx> { // the actual base trait id of the object pub object_trait_id: ast::DefId, - // index of the method to be invoked amongst the trait's methods + // index of the method to be invoked amongst the trait's items pub method_num: uint, // index into the actual runtime vtable. // the vtable is formed by concatenating together the method lists of - // the base object trait and all supertraits; this is the index into + // the base object trait and all supertraits; this is the index into // that vtable - pub real_index: uint, + pub vtable_index: uint, } #[derive(Clone)] @@ -2084,11 +2087,7 @@ impl<'tcx> TraitRef<'tcx> { pub struct ParameterEnvironment<'a, 'tcx:'a> { pub tcx: &'a ctxt<'tcx>, - /// A substitution that can be applied to move from - /// the "outer" view of a type or method to the "inner" view. - /// In general, this means converting from bound parameters to - /// free parameters. Since we currently represent bound/free type - /// parameters in the same way, this only has an effect on regions. + /// See `construct_free_substs` for details. pub free_substs: Substs<'tcx>, /// Each type parameter has an implicit region bound that @@ -2100,7 +2099,7 @@ pub struct ParameterEnvironment<'a, 'tcx:'a> { /// Obligations that the caller must satisfy. This is basically /// the set of bounds on the in-scope type parameters, translated /// into Obligations. - pub caller_bounds: ty::GenericBounds<'tcx>, + pub caller_bounds: Vec>, /// Caches the results of trait selection. This cache is used /// for things that have to do with the parameters in scope. @@ -2108,6 +2107,19 @@ pub struct ParameterEnvironment<'a, 'tcx:'a> { } impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { + pub fn with_caller_bounds(&self, + caller_bounds: Vec>) + -> ParameterEnvironment<'a,'tcx> + { + ParameterEnvironment { + tcx: self.tcx, + free_substs: self.free_substs.clone(), + implicit_region_bound: self.implicit_region_bound, + caller_bounds: caller_bounds, + selection_cache: traits::SelectionCache::new(), + } + } + pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx> { match cx.map.find(id) { Some(ast_map::NodeImplItem(ref impl_item)) => { @@ -2119,6 +2131,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let method_generics = &method_ty.generics; construct_parameter_environment( cx, + method.span, method_generics, method.pe_body().id) } @@ -2153,6 +2166,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let method_generics = &method_ty.generics; construct_parameter_environment( cx, + method.span, method_generics, method.pe_body().id) } @@ -2179,6 +2193,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let fn_pty = ty::lookup_item_type(cx, fn_def_id); construct_parameter_environment(cx, + item.span, &fn_pty.generics, body.id) } @@ -2189,7 +2204,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { ast::ItemStatic(..) => { let def_id = ast_util::local_def(id); let pty = ty::lookup_item_type(cx, def_id); - construct_parameter_environment(cx, &pty.generics, id) + construct_parameter_environment(cx, item.span, &pty.generics, id) } _ => { cx.sess.span_bug(item.span, @@ -6258,23 +6273,22 @@ impl Variance { pub fn empty_parameter_environment<'a,'tcx>(cx: &'a ctxt<'tcx>) -> ParameterEnvironment<'a,'tcx> { ty::ParameterEnvironment { tcx: cx, free_substs: Substs::empty(), - caller_bounds: GenericBounds::empty(), + caller_bounds: Vec::new(), implicit_region_bound: ty::ReEmpty, selection_cache: traits::SelectionCache::new(), } } -/// See `ParameterEnvironment` struct def'n for details -pub fn construct_parameter_environment<'a,'tcx>( +/// Constructs and returns a substitution that can be applied to move from +/// the "outer" view of a type or method to the "inner" view. +/// In general, this means converting from bound parameters to +/// free parameters. Since we currently represent bound/free type +/// parameters in the same way, this only has an effect on regions. +pub fn construct_free_substs<'a,'tcx>( tcx: &'a ctxt<'tcx>, generics: &ty::Generics<'tcx>, free_id: ast::NodeId) - -> ParameterEnvironment<'a, 'tcx> + -> Substs<'tcx> { - - // - // Construct the free substs. - // - // map T => T let mut types = VecPerParamSpace::empty(); push_types_from_defs(tcx, &mut types, generics.types.as_slice()); @@ -6283,11 +6297,45 @@ pub fn construct_parameter_environment<'a,'tcx>( let mut regions = VecPerParamSpace::empty(); push_region_params(&mut regions, free_id, generics.regions.as_slice()); - let free_substs = Substs { + return Substs { types: types, regions: subst::NonerasedRegions(regions) }; + fn push_region_params(regions: &mut VecPerParamSpace, + free_id: ast::NodeId, + region_params: &[RegionParameterDef]) + { + for r in region_params.iter() { + regions.push(r.space, ty::free_region_from_def(free_id, r)); + } + } + + fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>, + types: &mut VecPerParamSpace>, + defs: &[TypeParameterDef<'tcx>]) { + for def in defs.iter() { + debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", + def.repr(tcx)); + let ty = ty::mk_param_from_def(tcx, def); + types.push(def.space, ty); + } + } +} + +/// See `ParameterEnvironment` struct def'n for details +pub fn construct_parameter_environment<'a,'tcx>( + tcx: &'a ctxt<'tcx>, + span: Span, + generics: &ty::Generics<'tcx>, + free_id: ast::NodeId) + -> ParameterEnvironment<'a, 'tcx> +{ + // + // Construct the free substs. + // + + let free_substs = construct_free_substs(tcx, generics, free_id); let free_id_scope = region::CodeExtent::from_node_id(free_id); // @@ -6296,6 +6344,7 @@ pub fn construct_parameter_environment<'a,'tcx>( let bounds = generics.to_bounds(tcx, &free_substs); let bounds = liberate_late_bound_regions(tcx, free_id_scope, &ty::Binder(bounds)); + let predicates = bounds.predicates.into_vec(); // // Compute region bounds. For now, these relations are stored in a @@ -6303,45 +6352,42 @@ pub fn construct_parameter_environment<'a,'tcx>( // crazy about this scheme, but it's convenient, at least. // - record_region_bounds(tcx, &bounds); + record_region_bounds(tcx, &*predicates); - debug!("construct_parameter_environment: free_id={:?} free_subst={:?} bounds={:?}", + debug!("construct_parameter_environment: free_id={:?} free_subst={:?} predicates={:?}", free_id, free_substs.repr(tcx), - bounds.repr(tcx)); + predicates.repr(tcx)); + + // + // Finally, we have to normalize the bounds in the environment, in + // case they contain any associated type projections. This process + // can yield errors if the put in illegal associated types, like + // `::Bar` where `i32` does not implement `Foo`. We + // report these errors right here; this doesn't actually feel + // right to me, because constructing the environment feels like a + // kind of a "idempotent" action, but I'm not sure where would be + // a better place. In practice, we construct environments for + // every fn once during type checking, and we'll abort if there + // are any errors at that point, so after type checking you can be + // sure that this will succeed without errors anyway. + // - return ty::ParameterEnvironment { + let unnormalized_env = ty::ParameterEnvironment { tcx: tcx, free_substs: free_substs, implicit_region_bound: ty::ReScope(free_id_scope), - caller_bounds: bounds, + caller_bounds: predicates, selection_cache: traits::SelectionCache::new(), }; - fn push_region_params(regions: &mut VecPerParamSpace, - free_id: ast::NodeId, - region_params: &[RegionParameterDef]) - { - for r in region_params.iter() { - regions.push(r.space, ty::free_region_from_def(free_id, r)); - } - } - - fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>, - types: &mut VecPerParamSpace>, - defs: &[TypeParameterDef<'tcx>]) { - for def in defs.iter() { - debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", - def.repr(tcx)); - let ty = ty::mk_param_from_def(tcx, def); - types.push(def.space, ty); - } - } + let cause = traits::ObligationCause::misc(span, free_id); + return traits::normalize_param_env_or_error(unnormalized_env, cause); - fn record_region_bounds<'tcx>(tcx: &ty::ctxt<'tcx>, bounds: &GenericBounds<'tcx>) { - debug!("record_region_bounds(bounds={:?})", bounds.repr(tcx)); + fn record_region_bounds<'tcx>(tcx: &ty::ctxt<'tcx>, predicates: &[ty::Predicate<'tcx>]) { + debug!("record_region_bounds(predicates={:?})", predicates.repr(tcx)); - for predicate in bounds.predicates.iter() { + for predicate in predicates.iter() { match *predicate { Predicate::Projection(..) | Predicate::Trait(..) | diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 86552705963c9..69d32c3f5fc33 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -71,7 +71,7 @@ pub trait TypeFolder<'tcx> : Sized { fn exit_region_binder(&mut self) { } fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder - where T : TypeFoldable<'tcx> + Repr<'tcx> + where T : TypeFoldable<'tcx> + Repr<'tcx> + Clone { // FIXME(#20526) this should replace `enter_region_binder`/`exit_region_binder`. super_fold_binder(self, t) @@ -186,7 +186,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { } } -impl<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>> TypeFoldable<'tcx> for ty::Binder { +impl<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>+Clone> TypeFoldable<'tcx> for ty::Binder { fn fold_with>(&self, folder: &mut F) -> ty::Binder { folder.fold_binder(self) } @@ -319,7 +319,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> { trait_ref: object.trait_ref.fold_with(folder), object_trait_id: object.object_trait_id, method_num: object.method_num, - real_index: object.real_index + vtable_index: object.vtable_index, }) } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 8915d55e2063e..bdb6ea22f8b45 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -22,6 +22,9 @@ use syntax::ast; 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 5601898136c79..1be99a8e569f3 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -298,17 +298,9 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String { let mut s = String::new(); - - match cty.unsafety { - ast::Unsafety::Normal => {} - ast::Unsafety::Unsafe => { - s.push_str(cty.unsafety.to_string().as_slice()); - s.push(' '); - } - }; - - push_sig_to_string(cx, &mut s, '|', '|', &cty.sig); - + s.push_str("[closure"); + push_sig_to_string(cx, &mut s, '(', ')', &cty.sig); + s.push(']'); s } @@ -399,18 +391,10 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { ty_enum(did, substs) | ty_struct(did, substs) => { let base = ty::item_path_str(cx, did); let generics = ty::lookup_item_type(cx, did).generics; - parameterized(cx, base.as_slice(), substs, &generics, did) + parameterized(cx, base.as_slice(), substs, &generics, did, &[]) } - ty_trait(box ty::TyTrait { - ref principal, ref bounds - }) => { - let principal = principal.user_string(cx); - let bound_str = bounds.user_string(cx); - let bound_sep = if bound_str.is_empty() { "" } else { " + " }; - format!("{}{}{}", - principal, - bound_sep, - bound_str) + ty_trait(ref data) => { + data.user_string(cx) } ty::ty_projection(ref data) => { format!("<{} as {}>::{}", @@ -420,14 +404,15 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { } ty_str => "str".to_string(), ty_closure(ref did, _, substs) => { - cx.closures.borrow().get(did).map(|cl| { + let closures = cx.closures.borrow(); + closures.get(did).map(|cl| { closure_to_string(cx, &cl.closure_type.subst(cx, substs)) }).unwrap_or_else(|| { if did.krate == ast::LOCAL_CRATE { let span = cx.map.span(did.node); - format!("closure[{}]", span.repr(cx)) + format!("[closure {}]", span.repr(cx)) } else { - format!("closure") + format!("[closure]") } }) } @@ -458,7 +443,8 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>, base: &str, substs: &subst::Substs<'tcx>, generics: &ty::Generics<'tcx>, - did: ast::DefId) + did: ast::DefId, + projections: &[ty::ProjectionPredicate<'tcx>]) -> String { if cx.sess.verbose() { @@ -511,7 +497,20 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>, strs.push(ty_to_string(cx, *t)) } - if cx.lang_items.fn_trait_kind(did).is_some() { + for projection in projections.iter() { + strs.push(format!("{}={}", + projection.projection_ty.item_name.user_string(cx), + projection.ty.user_string(cx))); + } + + if cx.lang_items.fn_trait_kind(did).is_some() && projections.len() == 1 { + let projection_ty = projections[0].ty; + let tail = + if ty::type_is_nil(projection_ty) { + format!("") + } else { + format!(" -> {}", projection_ty.user_string(cx)) + }; format!("{}({}){}", base, if strs[0].starts_with("(") && strs[0].ends_with(",)") { @@ -521,7 +520,7 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>, } else { &strs[0][] }, - if &*strs[1] == "()" { String::new() } else { format!(" -> {}", strs[1]) }) + tail) } else if strs.len() > 0 { format!("{}<{}>", base, strs.connect(", ")) } else { @@ -623,6 +622,65 @@ impl<'tcx> Repr<'tcx> for def::Def { } } +/// This curious type is here to help pretty-print trait objects. In +/// a trait object, the projections are stored separately from the +/// main trait bound, but in fact we want to package them together +/// when printing out; they also have separate binders, but we want +/// them to share a binder when we print them out. (And the binder +/// pretty-printing logic is kind of clever and we don't want to +/// reproduce it.) So we just repackage up the structure somewhat. +/// +/// Right now there is only one trait in an object that can have +/// projection bounds, so we just stuff them altogether. But in +/// reality we should eventually sort things out better. +type TraitAndProjections<'tcx> = + (Rc>, Vec>); + +impl<'tcx> UserString<'tcx> for TraitAndProjections<'tcx> { + fn user_string(&self, tcx: &ctxt<'tcx>) -> String { + let &(ref trait_ref, ref projection_bounds) = self; + let base = ty::item_path_str(tcx, trait_ref.def_id); + let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id); + parameterized(tcx, + base.as_slice(), + trait_ref.substs, + &trait_def.generics, + trait_ref.def_id, + &projection_bounds[]) + } +} + +impl<'tcx> UserString<'tcx> for ty::TyTrait<'tcx> { + fn user_string(&self, tcx: &ctxt<'tcx>) -> String { + let &ty::TyTrait { ref principal, ref bounds } = self; + + let mut components = vec![]; + + let tap: ty::Binder> = + ty::Binder((principal.0.clone(), + bounds.projection_bounds.iter().map(|x| x.0.clone()).collect())); + + // Generate the main trait ref, including associated types. + components.push(tap.user_string(tcx)); + + // Builtin bounds. + for bound in bounds.builtin_bounds.iter() { + components.push(bound.user_string(tcx)); + } + + // Region, if not obviously implied by builtin bounds. + if bounds.region_bound != ty::ReStatic || + !bounds.builtin_bounds.contains(&ty::BoundSend) + { // Region bound is implied by builtin bounds: + components.push(bounds.region_bound.user_string(tcx)); + } + + components.retain(|s| !s.is_empty()); + + components.connect(" + ") + } +} + impl<'tcx> Repr<'tcx> for ty::TypeParameterDef<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { format!("TypeParameterDef({:?}, {}, {:?}/{})", @@ -701,12 +759,6 @@ impl<'tcx> Repr<'tcx> for ty::BuiltinBounds { } } -impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> { - fn repr(&self, tcx: &ctxt<'tcx>) -> String { - self.user_string(tcx) - } -} - impl<'tcx> Repr<'tcx> for ty::ParamBounds<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { let mut res = Vec::new(); @@ -727,7 +779,8 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> { let trait_def = ty::lookup_trait_def(tcx, self.def_id); format!("TraitRef({}, {})", self.substs.self_ty().repr(tcx), - parameterized(tcx, base.as_slice(), self.substs, &trait_def.generics, self.def_id)) + parameterized(tcx, base.as_slice(), self.substs, + &trait_def.generics, self.def_id, &[])) } } @@ -1062,7 +1115,7 @@ impl<'tcx> Repr<'tcx> for ty::MethodObject<'tcx> { format!("MethodObject({},{},{})", self.trait_ref.repr(tcx), self.method_num, - self.real_index) + self.vtable_index) } } @@ -1110,14 +1163,8 @@ impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> { } } -impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> { - fn user_string(&self, tcx: &ctxt<'tcx>) -> String { - if self.builtin_bounds.contains(&ty::BoundSend) && - self.region_bound == ty::ReStatic - { // Region bound is implied by builtin bounds: - return self.builtin_bounds.repr(tcx); - } - +impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> { + fn repr(&self, tcx: &ctxt<'tcx>) -> String { let mut res = Vec::new(); let region_str = self.region_bound.user_string(tcx); @@ -1129,6 +1176,10 @@ impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> { res.push(bound.user_string(tcx)); } + for projection_bound in self.projection_bounds.iter() { + res.push(projection_bound.user_string(tcx)); + } + res.connect("+") } } @@ -1184,7 +1235,7 @@ impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> { let path_str = ty::item_path_str(tcx, self.def_id); let trait_def = ty::lookup_trait_def(tcx, self.def_id); parameterized(tcx, path_str.as_slice(), self.substs, - &trait_def.generics, self.def_id) + &trait_def.generics, self.def_id, &[]) } } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 187b73b1b0952..c4240fa9ebae7 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -13,7 +13,7 @@ use back::abi; use back::link; use llvm::{self, ValueRef, get_param}; use metadata::csearch; -use middle::subst::{Subst, Substs}; +use middle::subst::Substs; use middle::subst::VecPerParamSpace; use middle::subst; use middle::traits; @@ -29,6 +29,7 @@ use trans::expr::{SaveIn, Ignore}; use trans::expr; use trans::glue; use trans::machine; +use trans::monomorphize; use trans::type_::Type; use trans::type_of::*; use middle::ty::{self, Ty}; @@ -162,7 +163,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; trans_trait_callee(bcx, monomorphize_type(bcx, method_ty), - mt.real_index, + mt.vtable_index, self_expr, arg_cleanup_scope) } @@ -439,7 +440,7 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// extract the self data and vtable out of the pair. fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, method_ty: Ty<'tcx>, - n_method: uint, + vtable_index: uint, self_expr: &ast::Expr, arg_cleanup_scope: cleanup::ScopeId) -> Callee<'blk, 'tcx> { @@ -469,28 +470,28 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, self_datum.val }; - trans_trait_callee_from_llval(bcx, method_ty, n_method, llval) + trans_trait_callee_from_llval(bcx, method_ty, vtable_index, llval) } /// Same as `trans_trait_callee()` above, except that it is given a by-ref pointer to the object /// pair. pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, callee_ty: Ty<'tcx>, - n_method: uint, + vtable_index: uint, llpair: ValueRef) -> Callee<'blk, 'tcx> { let _icx = push_ctxt("meth::trans_trait_callee"); let ccx = bcx.ccx(); // Load the data pointer from the object. - debug!("(translating trait callee) loading second index from pair"); + debug!("trans_trait_callee_from_llval(callee_ty={}, vtable_index={}, llpair={})", + callee_ty.repr(ccx.tcx()), + vtable_index, + bcx.val_to_string(llpair)); let llboxptr = GEPi(bcx, llpair, &[0u, abi::FAT_PTR_ADDR]); let llbox = Load(bcx, llboxptr); let llself = PointerCast(bcx, llbox, Type::i8p(ccx)); - // Load the function from the vtable and cast it to the expected type. - debug!("(translating trait callee) loading method"); - // Replace the self type (&Self or Box) with an opaque pointer. let llcallee_ty = match callee_ty.sty { ty::ty_bare_fn(_, ref f) if f.abi == Rust || f.abi == RustCall => { @@ -500,10 +501,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, output: f.sig.0.output, variadic: f.sig.0.variadic, }); - type_of_rust_fn(ccx, - Some(Type::i8p(ccx)), - &fake_sig, - f.abi) + type_of_rust_fn(ccx, Some(Type::i8p(ccx)), &fake_sig, f.abi) } _ => { ccx.sess().bug("meth::trans_trait_callee given non-bare-rust-fn"); @@ -514,7 +512,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, GEPi(bcx, llpair, &[0u, abi::FAT_PTR_EXTRA]), Type::vtable(ccx).ptr_to().ptr_to())); - let mptr = Load(bcx, GEPi(bcx, llvtable, &[0u, n_method + VTABLE_OFFSET])); + let mptr = Load(bcx, GEPi(bcx, llvtable, &[0u, vtable_index + VTABLE_OFFSET])); let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to()); return Callee { @@ -558,7 +556,7 @@ pub fn trans_object_shim<'a, 'tcx>( let _icx = push_ctxt("trans_object_shim"); let tcx = ccx.tcx(); - debug!("trans_object_shim(object_ty={}, trait_id={}, n_method={})", + debug!("trans_object_shim(object_ty={}, trait_id={}, method_offset_in_trait={})", object_ty.repr(tcx), trait_id.repr(tcx), method_offset_in_trait); @@ -587,7 +585,7 @@ pub fn trans_object_shim<'a, 'tcx>( tcx.sess.bug("can't create a method shim for an associated type") } }; - let fty = method_ty.fty.subst(tcx, &object_substs); + let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty); let fty = tcx.mk_bare_fn(fty); debug!("trans_object_shim: fty={}", fty.repr(tcx)); diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 61dbb5514353a..6b6ca600a8831 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -103,6 +103,10 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, abi: abi::Abi) -> Type { + debug!("type_of_rust_fn(sig={},abi={:?})", + sig.repr(cx.tcx()), + abi); + let sig = ty::erase_late_bound_regions(cx.tcx(), sig); assert!(!sig.variadic); // rust fns are never variadic diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 921ed505fa3af..6e8dd6b0ae755 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -57,7 +57,7 @@ use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty}; 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/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 2d7a76344721c..bdae34e787850 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -34,7 +34,7 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expected.repr(fcx.tcx())); let expected_sig_and_kind = expected.to_option(fcx).and_then(|ty| { - deduce_closure_expectations_from_expected_type(fcx, ty) + deduce_expectations_from_expected_type(fcx, ty) }); match opt_kind { @@ -137,20 +137,21 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fcx.inh.closures.borrow_mut().insert(expr_def_id, closure); } -fn deduce_closure_expectations_from_expected_type<'a,'tcx>( +fn deduce_expectations_from_expected_type<'a,'tcx>( fcx: &FnCtxt<'a,'tcx>, expected_ty: Ty<'tcx>) -> Option<(ty::FnSig<'tcx>,ty::ClosureKind)> { match expected_ty.sty { ty::ty_trait(ref object_type) => { - let trait_ref = - object_type.principal_trait_ref_with_self_ty(fcx.tcx(), - fcx.tcx().types.err); - deduce_closure_expectations_from_trait_ref(fcx, &trait_ref) + let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(), + fcx.tcx().types.err); + proj_bounds.iter() + .filter_map(|pb| deduce_expectations_from_projection(fcx, pb)) + .next() } ty::ty_infer(ty::TyVar(vid)) => { - deduce_closure_expectations_from_obligations(fcx, vid) + deduce_expectations_from_obligations(fcx, vid) } _ => { None @@ -158,15 +159,51 @@ fn deduce_closure_expectations_from_expected_type<'a,'tcx>( } } -fn deduce_closure_expectations_from_trait_ref<'a,'tcx>( +fn deduce_expectations_from_obligations<'a,'tcx>( fcx: &FnCtxt<'a,'tcx>, - trait_ref: &ty::PolyTraitRef<'tcx>) + expected_vid: ty::TyVid) + -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)> +{ + let fulfillment_cx = fcx.inh.fulfillment_cx.borrow(); + // Here `expected_ty` is known to be a type inference variable. + + fulfillment_cx.pending_obligations() + .iter() + .filter_map(|obligation| { + match obligation.predicate { + ty::Predicate::Projection(ref proj_predicate) => { + let trait_ref = proj_predicate.to_poly_trait_ref(); + let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty()); + match self_ty.sty { + ty::ty_infer(ty::TyVar(v)) if expected_vid == v => { + deduce_expectations_from_projection(fcx, proj_predicate) + } + _ => { + None + } + } + } + _ => { + None + } + } + }) + .next() +} + +/// Given a projection like "::Result == Y", we can deduce +/// everything we need to know about a closure. +fn deduce_expectations_from_projection<'a,'tcx>( + fcx: &FnCtxt<'a,'tcx>, + projection: &ty::PolyProjectionPredicate<'tcx>) -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)> { let tcx = fcx.tcx(); - debug!("deduce_closure_expectations_from_object_type({})", - trait_ref.repr(tcx)); + debug!("deduce_expectations_from_projection({})", + projection.repr(tcx)); + + let trait_ref = projection.to_poly_trait_ref(); let kind = match tcx.lang_items.fn_trait_kind(trait_ref.def_id()) { Some(k) => k, @@ -185,7 +222,7 @@ fn deduce_closure_expectations_from_trait_ref<'a,'tcx>( }; debug!("input_tys {}", input_tys.repr(tcx)); - let ret_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 1); + let ret_param_ty = projection.0.ty; let ret_param_ty = fcx.infcx().resolve_type_vars_if_possible(&ret_param_ty); debug!("ret_param_ty {}", ret_param_ty.repr(tcx)); @@ -199,30 +236,3 @@ fn deduce_closure_expectations_from_trait_ref<'a,'tcx>( return Some((fn_sig, kind)); } -fn deduce_closure_expectations_from_obligations<'a,'tcx>( - fcx: &FnCtxt<'a,'tcx>, - expected_vid: ty::TyVid) - -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)> -{ - // Here `expected_ty` is known to be a type inference variable. - for obligation in fcx.inh.fulfillment_cx.borrow().pending_obligations().iter() { - match obligation.predicate { - ty::Predicate::Trait(ref trait_predicate) => { - let trait_ref = trait_predicate.to_poly_trait_ref(); - let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty()); - match self_ty.sty { - ty::ty_infer(ty::TyVar(v)) if expected_vid == v => { } - _ => { continue; } - } - - match deduce_closure_expectations_from_trait_ref(fcx, &trait_ref) { - Some(e) => { return Some(e); } - None => { } - } - } - _ => { } - } - } - - None -} diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index e3e5d67869fa4..31b14ea3f3dec 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -215,14 +215,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_impl_method: impl_bounds={}", impl_bounds.repr(tcx)); - // // Normalize the associated types in the impl_bounds. - // let traits::Normalized { value: impl_bounds, .. } = - // traits::normalize(&mut selcx, normalize_cause.clone(), &impl_bounds); - // Normalize the associated types in the trait_bounds. let trait_bounds = trait_m.generics.to_bounds(tcx, &trait_to_skol_substs); - // let traits::Normalized { value: trait_bounds, .. } = - // traits::normalize(&mut selcx, normalize_cause, &trait_bounds); // Obtain the predicate split predicate sets for each. let trait_pred = trait_bounds.predicates.split(); @@ -242,19 +236,18 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, ); // Construct trait parameter environment and then shift it into the skolemized viewpoint. - let mut trait_param_env = impl_param_env.clone(); // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. - trait_param_env.caller_bounds.predicates = hybrid_preds; + let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id); + let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.into_vec()); + let trait_param_env = traits::normalize_param_env_or_error(trait_param_env, + normalize_cause.clone()); debug!("compare_impl_method: trait_bounds={}", trait_param_env.caller_bounds.repr(tcx)); let mut selcx = traits::SelectionContext::new(&infcx, &trait_param_env); - let normalize_cause = - traits::ObligationCause::misc(impl_m_span, impl_m_body_id); - for predicate in impl_pred.fns.into_iter() { let traits::Normalized { value: predicate, .. } = traits::normalize(&mut selcx, normalize_cause.clone(), &predicate); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 4aa0a211221ef..67b055ac946cc 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -206,7 +206,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { (impl_polytype.substs, MethodStatic(pick.method_ty.def_id)) } - probe::ObjectPick(trait_def_id, method_num, real_index) => { + probe::ObjectPick(trait_def_id, method_num, vtable_index) => { self.extract_trait_ref(self_ty, |this, object_ty, data| { // The object data has no entry for the Self // Type. For the purposes of this method call, we @@ -233,7 +233,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { trait_ref: upcast_trait_ref, object_trait_id: trait_def_id, method_num: method_num, - real_index: real_index, + vtable_index: vtable_index, }); (substs, origin) }) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 4c5a8144cbd06..6a3554314e215 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -59,7 +59,7 @@ struct Candidate<'tcx> { enum CandidateKind<'tcx> { InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>), - ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint), + ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ uint, /* vtable index */ uint), ExtensionImplCandidate(/* Impl */ ast::DefId, Rc>, subst::Substs<'tcx>, MethodIndex), ClosureCandidate(/* Trait */ ast::DefId, MethodIndex), @@ -318,7 +318,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // itself. Hence, a `&self` method will wind up with an // argument type like `&Trait`. let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty); - self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| { + self.elaborate_bounds(&[trait_ref.clone()], |this, new_trait_ref, m, method_num| { let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref); let vtable_index = @@ -343,7 +343,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // FIXME -- Do we want to commit to this behavior for param bounds? let bounds: Vec<_> = - self.fcx.inh.param_env.caller_bounds.predicates + self.fcx.inh.param_env.caller_bounds .iter() .filter_map(|predicate| { match *predicate { @@ -365,7 +365,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { }) .collect(); - self.elaborate_bounds(bounds.as_slice(), true, |this, poly_trait_ref, m, method_num| { + self.elaborate_bounds(bounds.as_slice(), |this, poly_trait_ref, m, method_num| { let trait_ref = this.erase_late_bound_regions(&poly_trait_ref); @@ -405,7 +405,6 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn elaborate_bounds( &mut self, bounds: &[ty::PolyTraitRef<'tcx>], - num_includes_types: bool, mut mk_cand: F, ) where F: for<'b> FnMut( @@ -427,8 +426,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { let (pos, method) = match trait_method(tcx, bound_trait_ref.def_id(), - self.method_name, - num_includes_types) { + self.method_name) { Some(v) => v, None => { continue; } }; @@ -697,8 +695,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { debug!("assemble_where_clause_candidates(trait_def_id={})", trait_def_id.repr(self.tcx())); - let caller_predicates = - self.fcx.inh.param_env.caller_bounds.predicates.as_slice().to_vec(); + let caller_predicates = self.fcx.inh.param_env.caller_bounds.clone(); for poly_bound in traits::elaborate_predicates(self.tcx(), caller_predicates) .filter_map(|p| p.to_opt_poly_trait_ref()) .filter(|b| b.def_id() == trait_def_id) @@ -1140,19 +1137,13 @@ fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, /// index (or `None`, if no such method). fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, trait_def_id: ast::DefId, - method_name: ast::Name, - num_includes_types: bool) + method_name: ast::Name) -> Option<(uint, Rc>)> { let trait_items = ty::trait_items(tcx, trait_def_id); debug!("trait_method; items: {:?}", trait_items); trait_items .iter() - .filter(|item| - num_includes_types || match *item { - &ty::MethodTraitItem(_) => true, - &ty::TypeTraitItem(_) => false - }) .enumerate() .find(|&(_, ref item)| item.name() == method_name) .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m))) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 09b65bcb1fc25..fe3d9157be48b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -467,7 +467,8 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, body: &ast::Block, id: ast::NodeId, raw_fty: Ty<'tcx>, - param_env: ty::ParameterEnvironment<'a, 'tcx>) { + param_env: ty::ParameterEnvironment<'a, 'tcx>) +{ match raw_fty.sty { ty::ty_bare_fn(_, ref fn_ty) => { let inh = Inherited::new(ccx.tcx, param_env); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index f2a3d6609252f..b039f3ab8e44d 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1482,7 +1482,7 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, let mut param_bounds = ty::required_region_bounds(rcx.tcx(), generic.to_ty(rcx.tcx()), - param_env.caller_bounds.predicates.as_slice().to_vec()); + param_env.caller_bounds.clone()); // In the case of a projection T::Foo, we may be able to extract bounds from the trait def: match *generic { diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 60284433ffe45..db226295cd970 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -127,6 +127,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { reject_non_type_param_bounds(ccx.tcx, item.span, &type_scheme.generics); let param_env = ty::construct_parameter_environment(ccx.tcx, + item.span, &type_scheme.generics, item.id); let inh = Inherited::new(ccx.tcx, param_env); diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index ed8a50110e5ac..63ad47ff31f61 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -818,6 +818,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { trait_def.generics.regions.get_slice(subst::TypeSpace), trait_ref.substs(), variance); + + let projections = data.projection_bounds_with_self_ty(self.tcx(), + self.tcx().types.err); + for projection in projections.iter() { + self.add_constraints_from_ty(generics, projection.0.ty, self.invariant); + } } ty::ty_param(ref data) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c12726c8868ca..d208041946951 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -536,7 +536,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, match (trait_did, cx.tcx_opt()) { // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C (Some(did), Some(ref tcx)) if tcx.lang_items.fn_trait_kind(did).is_some() => { - assert_eq!(types.len(), 2); + assert_eq!(types.len(), 1); let inputs = match types[0].sty { sty::ty_tup(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), _ => { @@ -547,10 +547,12 @@ fn external_path_params(cx: &DocContext, trait_did: Option, } } }; - let output = match types[1].sty { - sty::ty_tup(ref v) if v.is_empty() => None, // -> () - _ => Some(types[1].clean(cx)) - }; + let output = None; + // FIXME(#20299) return type comes from a projection now + // match types[1].sty { + // sty::ty_tup(ref v) if v.is_empty() => None, // -> () + // _ => Some(types[1].clean(cx)) + // }; PathParameters::Parenthesized { inputs: inputs, output: output diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 4f6cd8ad356d7..4dada5bc81ec2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -347,6 +347,9 @@ impl AngleBracketedParameterData { /// 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 bf822599a8864..a1362f5382c97 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 fbea265597c6a..4c1ae532d13cd 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1796,6 +1796,8 @@ impl<'a> Parser<'a> { 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 @@ impl<'a> Parser<'a> { 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() diff --git a/src/test/compile-fail/borrowck-overloaded-call.rs b/src/test/compile-fail/borrowck-overloaded-call.rs index 7d35a27c0ae20..04d73cc36f04c 100644 --- a/src/test/compile-fail/borrowck-overloaded-call.rs +++ b/src/test/compile-fail/borrowck-overloaded-call.rs @@ -17,7 +17,9 @@ struct SFn { y: isize, } -impl Fn<(isize,),isize> for SFn { +impl Fn<(isize,)> for SFn { + type Output = isize; + extern "rust-call" fn call(&self, (z,): (isize,)) -> isize { self.x * self.y * z } @@ -28,7 +30,9 @@ struct SFnMut { y: isize, } -impl FnMut<(isize,),isize> for SFnMut { +impl FnMut<(isize,)> for SFnMut { + type Output = isize; + extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize { self.x * self.y * z } @@ -38,7 +42,9 @@ struct SFnOnce { x: String, } -impl FnOnce<(String,),usize> for SFnOnce { +impl FnOnce<(String,)> for SFnOnce { + type Output = usize; + extern "rust-call" fn call_once(self, (z,): (String,)) -> usize { self.x.len() + z.len() } diff --git a/src/test/compile-fail/extern-wrong-value-type.rs b/src/test/compile-fail/extern-wrong-value-type.rs index d7586af291e86..db3373ea02772 100644 --- a/src/test/compile-fail/extern-wrong-value-type.rs +++ b/src/test/compile-fail/extern-wrong-value-type.rs @@ -16,5 +16,7 @@ fn is_fn(_: F) where F: Fn() {} fn main() { // extern functions are extern "C" fn let _x: extern "C" fn() = f; // OK - is_fn(f); //~ ERROR the trait `core::ops::Fn()` is not implemented for the type `extern "C" fn() + is_fn(f); + //~^ ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn() + //~| ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn() } diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs index cdb207f705f5f..e5e5ddadafccf 100644 --- a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs +++ b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs @@ -8,18 +8,38 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test that manual impls of the `Fn` traits are not possible without +// a feature gate. In fact, the specialized check for these cases +// never triggers (yet), because they encounter other problems around +// angle bracket vs parentheses notation. + #![allow(dead_code)] struct Foo; -impl Fn() for Foo { //~ ERROR manual implementations of `Fn` are experimental +impl Fn<()> for Foo { + //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits + type Output = (); + + extern "rust-call" fn call(&self, args: ()) -> () {} +} +struct Foo1; +impl Fn() for Foo1 { + //~^ ERROR associated type bindings are not allowed here + extern "rust-call" fn call(&self, args: ()) -> () {} } struct Bar; -impl FnMut() for Bar { //~ ERROR manual implementations of `FnMut` are experimental +impl FnMut<()> for Bar { + //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits + type Output = (); + extern "rust-call" fn call_mut(&self, args: ()) -> () {} } struct Baz; -impl FnOnce() for Baz { //~ ERROR manual implementations of `FnOnce` are experimental +impl FnOnce<()> for Baz { + //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits + type Output = (); + extern "rust-call" fn call_once(&self, args: ()) -> () {} } diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs index f19e27640cbc7..460e05c8438cd 100644 --- a/src/test/compile-fail/fn-trait-formatting.rs +++ b/src/test/compile-fail/fn-trait-formatting.rs @@ -34,5 +34,7 @@ fn main() { //~| expected () //~| found box - needs_fn(1is); //~ ERROR `core::ops::Fn(isize) -> isize` + needs_fn(1is); + //~^ ERROR `core::ops::Fn<(isize,)>` + //~| ERROR `core::ops::Fn<(isize,)>` } diff --git a/src/test/compile-fail/issue-15094.rs b/src/test/compile-fail/issue-15094.rs index 2c03a9e07332e..977586483b031 100644 --- a/src/test/compile-fail/issue-15094.rs +++ b/src/test/compile-fail/issue-15094.rs @@ -16,7 +16,9 @@ struct Debuger { x: T } -impl ops::Fn<(), ()> for Debuger { +impl ops::Fn<(),> for Debuger { + type Output = (); + fn call(&self, _args: ()) { //~^ ERROR `call` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn println!("{:?}", self.x); diff --git a/src/test/compile-fail/issue-17545.rs b/src/test/compile-fail/issue-17545.rs index 0501a3013ccd4..84800218efc94 100644 --- a/src/test/compile-fail/issue-17545.rs +++ b/src/test/compile-fail/issue-17545.rs @@ -10,7 +10,7 @@ #![feature(unboxed_closures)] -pub fn foo<'a, F: Fn<(&'a (),), ()>>(bar: F) { +pub fn foo<'a, F: Fn(&'a ())>(bar: F) { bar.call(( &(), //~ ERROR borrowed value does not live long enough )); diff --git a/src/test/compile-fail/overloaded-calls-bad.rs b/src/test/compile-fail/overloaded-calls-bad.rs index d784ba2d0d6bd..61752e62abdef 100644 --- a/src/test/compile-fail/overloaded-calls-bad.rs +++ b/src/test/compile-fail/overloaded-calls-bad.rs @@ -17,7 +17,9 @@ struct S { y: isize, } -impl FnMut<(isize,),isize> for S { +impl FnMut<(isize,)> for S { + type Output = isize; + extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize { self.x * self.y * z } diff --git a/src/test/compile-fail/overloaded-calls-nontuple.rs b/src/test/compile-fail/overloaded-calls-nontuple.rs index c06ab04cd849a..41ecf7146138d 100644 --- a/src/test/compile-fail/overloaded-calls-nontuple.rs +++ b/src/test/compile-fail/overloaded-calls-nontuple.rs @@ -17,7 +17,8 @@ struct S { y: isize, } -impl FnMut for S { +impl FnMut for S { + type Output = isize; extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { self.x + self.y + z } diff --git a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs index 2e634dfe3eb61..2a246124f6f9d 100644 --- a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs +++ b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs @@ -9,15 +9,15 @@ // except according to those terms. -struct invariant<'a> { +struct Invariant<'a> { f: Box FnOnce() -> &'b mut &'a isize + 'static>, } -fn to_same_lifetime<'r>(bi: invariant<'r>) { - let bj: invariant<'r> = bi; +fn to_same_lifetime<'r>(bi: Invariant<'r>) { + let bj: Invariant<'r> = bi; } -fn to_longer_lifetime<'r>(bi: invariant<'r>) -> invariant<'static> { +fn to_longer_lifetime<'r>(bi: Invariant<'r>) -> Invariant<'static> { bi //~ ERROR mismatched types } diff --git a/src/test/compile-fail/unboxed-closure-feature-gate.rs b/src/test/compile-fail/unboxed-closure-feature-gate.rs index 5eb67a9bb71d4..3536244f01165 100644 --- a/src/test/compile-fail/unboxed-closure-feature-gate.rs +++ b/src/test/compile-fail/unboxed-closure-feature-gate.rs @@ -11,7 +11,8 @@ // Check that parenthetical notation is feature-gated except with the // `Fn` traits. -trait Foo { +trait Foo { + type Output; } fn main() { diff --git a/src/test/compile-fail/unboxed-closure-sugar-default.rs b/src/test/compile-fail/unboxed-closure-sugar-default.rs index 0d9e406b0867c..870377bc1add7 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-default.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-default.rs @@ -14,8 +14,9 @@ #![feature(unboxed_closures)] #![allow(dead_code)] -trait Foo { - fn dummy(&self, t: T, u: U, v: V); +trait Foo { + type Output; + fn dummy(&self, t: T, v: V); } trait Eq { } @@ -24,14 +25,14 @@ fn eq() where A : Eq { } fn test<'a,'b>() { // Parens are equivalent to omitting default in angle. - eq::< Foo<(isize,),()>, Foo(isize) >(); + eq::< Foo<(isize,),Output=()>, Foo(isize) >(); // In angle version, we supply something other than the default - eq::< Foo<(isize,),(),isize>, Foo(isize) >(); + eq::< Foo<(isize,),isize,Output=()>, Foo(isize) >(); //~^ ERROR not implemented // Supply default explicitly. - eq::< Foo<(isize,),(),(isize,)>, Foo(isize) >(); + eq::< Foo<(isize,),(isize,),Output=()>, Foo(isize) >(); } fn main() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index 9dff0e9e01e34..dc5576aee650a 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs @@ -16,8 +16,9 @@ #![feature(unboxed_closures)] #![allow(dead_code)] -trait Foo { - fn dummy(&self, t: T, u: U); +trait Foo { + type Output; + fn dummy(&self, t: T, u: Self::Output); } trait Eq { } @@ -26,31 +27,32 @@ fn eq>() { } fn test<'a,'b>() { // No errors expected: - eq::< Foo<(),()>, Foo() >(); - eq::< Foo<(isize,),()>, Foo(isize) >(); - eq::< Foo<(isize,usize),()>, Foo(isize,usize) >(); - eq::< Foo<(isize,usize),usize>, Foo(isize,usize) -> usize >(); - eq::< Foo<(&'a isize,&'b usize),usize>, Foo(&'a isize,&'b usize) -> usize >(); + eq::< Foo<(),Output=()>, Foo() >(); + eq::< Foo<(isize,),Output=()>, Foo(isize) >(); + eq::< Foo<(isize,usize),Output=()>, Foo(isize,usize) >(); + eq::< Foo<(isize,usize),Output=usize>, Foo(isize,usize) -> usize >(); + eq::< Foo<(&'a isize,&'b usize),Output=usize>, Foo(&'a isize,&'b usize) -> usize >(); // Test that anonymous regions in `()` form are equivalent // to fresh bound regions, and that we can intermingle // named and anonymous as we choose: - eq::< for<'x,'y> Foo<(&'x isize,&'y usize),usize>, + eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>, for<'x,'y> Foo(&'x isize,&'y usize) -> usize >(); - eq::< for<'x,'y> Foo<(&'x isize,&'y usize),usize>, + eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>, for<'x> Foo(&'x isize,&usize) -> usize >(); - eq::< for<'x,'y> Foo<(&'x isize,&'y usize),usize>, + eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>, for<'y> Foo(&isize,&'y usize) -> usize >(); - eq::< for<'x,'y> Foo<(&'x isize,&'y usize),usize>, + eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>, Foo(&isize,&usize) -> usize >(); // lifetime elision - eq::< for<'x> Foo<(&'x isize,), &'x isize>, + eq::< for<'x> Foo<(&'x isize,), Output=&'x isize>, Foo(&isize) -> &isize >(); // Errors expected: - eq::< Foo<(),()>, Foo(char) >(); - //~^ ERROR not implemented + eq::< Foo<(),Output=()>, + Foo(char) >(); + //~^^ ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs index 29429c708d255..d2f781bba11ea 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs @@ -16,8 +16,9 @@ #![feature(unboxed_closures)] #![allow(dead_code)] -trait Foo { - fn dummy(&self, t: T, u: U); +trait Foo { + type Output; + fn dummy(&self, t: T); } trait Eq { } @@ -25,9 +26,9 @@ impl Eq for X { } fn eq>() { } fn main() { - eq::< for<'a> Foo<(&'a isize,), &'a isize>, + eq::< for<'a> Foo<(&'a isize,), Output=&'a isize>, Foo(&isize) -> &isize >(); - eq::< for<'a> Foo<(&'a isize,), (&'a isize, &'a isize)>, + eq::< for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>, Foo(&isize) -> (&isize, &isize) >(); let _: Foo(&isize, &usize) -> &usize; //~ ERROR missing lifetime specifier diff --git a/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs b/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs index 21844e5b986c1..1f0d5aae36db5 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs @@ -11,11 +11,11 @@ // Test that the `Fn` traits require `()` form without a feature gate. -fn bar1(x: &Fn<(),()>) { +fn bar1(x: &Fn<()>) { //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family } -fn bar2(x: &T) where T: Fn<(),()> { +fn bar2(x: &T) where T: Fn<()> { //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family } diff --git a/src/test/compile-fail/unboxed-closure-sugar-region.rs b/src/test/compile-fail/unboxed-closure-sugar-region.rs index c8dd33c11fd3b..75688e44e8076 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-region.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-region.rs @@ -17,8 +17,9 @@ use std::marker; -trait Foo<'a,T,U> { - fn dummy(&'a self) -> &'a (T,U); +trait Foo<'a,T> { + type Output; + fn dummy(&'a self) -> &'a (T,Self::Output); } trait Eq { } @@ -29,16 +30,17 @@ fn same_type>(a: A, b: B) { } fn test<'a,'b>() { // Parens are equivalent to omitting default in angle. - eq::< Foo<(isize,),()>, Foo(isize) >(); + eq::< Foo<(isize,),Output=()>, Foo(isize) >(); // Here we specify 'static explicitly in angle-bracket version. // Parenthesized winds up getting inferred. - eq::< Foo<'static, (isize,),()>, Foo(isize) >(); + eq::< Foo<'static, (isize,),Output=()>, Foo(isize) >(); } -fn test2(x: &Foo<(isize,),()>, y: &Foo(isize)) { +fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) { // Here, the omitted lifetimes are expanded to distinct things. same_type(x, y) //~ ERROR cannot infer + //~^ ERROR cannot infer } fn main() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs index a6184caf68b1f..a3991a87b78f8 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs @@ -11,13 +11,14 @@ // Test that parentheses form doesn't work with struct types appearing in local variables. -struct Bar { - f: A, r: R +struct Bar { + f: A } fn bar() { let x: Box = panic!(); //~^ ERROR parenthesized parameters may only be used with a trait + //~^^ ERROR associated type bindings are not allowed here } fn main() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs index d5fb505715e90..ad85cdcaa03a1 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs @@ -10,12 +10,13 @@ // Test that parentheses form doesn't work with struct types appearing in argument types. -struct Bar { - f: A, r: R +struct Bar { + f: A } fn foo(b: Box) { //~^ ERROR parenthesized parameters may only be used with a trait + //~^^ ERROR associated type bindings are not allowed here } fn main() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs b/src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs index d9efab974d83f..c9837da58e75a 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs @@ -12,7 +12,7 @@ trait One { fn foo(&self) -> A; } -fn foo(_: &One()) //~ ERROR wrong number of type arguments +fn foo(_: &One()) //~ ERROR no associated type `Output` defined in `One<()>` {} fn main() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs index b58e08355c118..e63f510b890d7 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs @@ -13,7 +13,7 @@ trait Trait {} fn f isize>(x: F) {} -//~^ ERROR wrong number of type arguments: expected 0, found 2 +//~^ ERROR wrong number of type arguments: expected 0, found 1 fn main() {} diff --git a/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs b/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs index fc87ec9f9598c..bbafd5109edff 100644 --- a/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs +++ b/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs @@ -18,7 +18,9 @@ use std::ops::{Fn,FnMut,FnOnce}; struct S; -impl FnMut<(isize,),isize> for S { +impl FnMut<(isize,)> for S { + type Output = isize; + extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize { x * x } @@ -29,6 +31,8 @@ fn call_itisize>(f: &F, x: isize) -> isize { } fn main() { - let x = call_it(&S, 22); //~ ERROR not implemented + let x = call_it(&S, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs index ab909717cab65..23f7ee2b0101d 100644 --- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs @@ -21,7 +21,9 @@ fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { - let x = call_it(&square, 22); //~ ERROR not implemented + let x = call_it(&square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn b() { diff --git a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs index 95673a513190b..305dd33e5a05a 100644 --- a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs +++ b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs @@ -12,13 +12,15 @@ use std::ops::FnMut; -fn call_it>(y: isize, mut f: F) -> isize { +fn call_itisize>(y: isize, mut f: F) -> isize { f(2, y) } pub fn main() { let f = |&mut: x: usize, y: isize| -> isize { (x as isize) + y }; - let z = call_it(3, f); //~ ERROR type mismatch + let z = call_it(3, f); + //~^ ERROR type mismatch + //~| ERROR type mismatch println!("{}", z); } diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs index 4a0b55558c049..96619bef36fd5 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs @@ -21,7 +21,9 @@ fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { - let x = call_it(&square, 22); //~ ERROR not implemented + let x = call_it(&square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn b() { diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs index b2fdf79263019..ebcbdbbc006df 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -22,7 +22,9 @@ fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { - let x = call_it(&square, 22); //~ ERROR not implemented + let x = call_it(&square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn b() { diff --git a/src/test/compile-fail/unboxed-closures-wrong-trait.rs b/src/test/compile-fail/unboxed-closures-wrong-trait.rs index e4255d0024feb..2ada0dd22e75f 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-trait.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-trait.rs @@ -18,5 +18,6 @@ fn main() { let z: isize = 7; assert_eq!(c(|&mut: x: isize, y| x + y + z), 10); //~^ ERROR not implemented + //~| ERROR not implemented } diff --git a/src/test/compile-fail/variance-object-types.rs b/src/test/compile-fail/variance-object-types.rs new file mode 100644 index 0000000000000..972ec96f5f27b --- /dev/null +++ b/src/test/compile-fail/variance-object-types.rs @@ -0,0 +1,24 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that Cell is considered invariant with respect to its +// type. + +use std::cell::Cell; + +// For better or worse, associated types are invariant, and hence we +// get an invariant result for `'a`. +#[rustc_variance] +struct Foo<'a> { //~ ERROR regions=[[o];[];[]] + x: Box &'a i32 + 'static> +} + +fn main() { +} diff --git a/src/test/run-pass/associated-types-issue-21212.rs b/src/test/run-pass/associated-types-issue-21212.rs new file mode 100644 index 0000000000000..ced44250e4d39 --- /dev/null +++ b/src/test/run-pass/associated-types-issue-21212.rs @@ -0,0 +1,28 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #21212: an overflow occurred during trait +// checking where normalizing `Self::Input` led to normalizing the +// where clauses in the environment which in turn required normalizing +// `Self::Input`. + +pub trait Parser { + type Input; + + fn parse(input: ::Input) { + panic!() + } +} +impl

Parser for P { + type Input = (); +} + +fn main() { +} diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs new file mode 100644 index 0000000000000..dd5814f875b08 --- /dev/null +++ b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs @@ -0,0 +1,42 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we normalize associated types that appear in a bound that +// contains a binding. Issue #21664. + +#![allow(dead_code)] + +pub trait Integral { + type Opposite; +} + +impl Integral for i32 { + type Opposite = u32; +} + +impl Integral for u32 { + type Opposite = i32; +} + +pub trait FnLike { + type R; +} + +fn foo() + where T : FnLike<::Opposite, R=bool> +{ + bar::(); +} + +fn bar() + where T : FnLike +{} + +fn main() { } diff --git a/src/test/run-pass/bare-fn-implements-fn-mut.rs b/src/test/run-pass/bare-fn-implements-fn-mut.rs index 9d104afd6464e..fae83d4aa6563 100644 --- a/src/test/run-pass/bare-fn-implements-fn-mut.rs +++ b/src/test/run-pass/bare-fn-implements-fn-mut.rs @@ -12,7 +12,7 @@ use std::ops::FnMut; -fn call_f>(mut f: F) { +fn call_f(mut f: F) { f(); } @@ -20,7 +20,7 @@ fn f() { println!("hello"); } -fn call_g>(mut g: G, x: String, y: String) +fn call_g String>(mut g: G, x: String, y: String) -> String { g(x, y) } diff --git a/src/test/run-pass/hrtb-parse.rs b/src/test/run-pass/hrtb-parse.rs index 41b7c0fae0746..d5307c09103a1 100644 --- a/src/test/run-pass/hrtb-parse.rs +++ b/src/test/run-pass/hrtb-parse.rs @@ -22,23 +22,23 @@ trait Get { // Parse HRTB with explicit `for` in a where-clause: fn foo00(t: T) - where T : for<'a> Get<&'a int, &'a int> + where T : for<'a> Get<&'a i32, &'a i32> { } -fn foo01 Get<&'a int, &'a int>>(t: T) +fn foo01 Get<&'a i32, &'a i32>>(t: T) { } // Parse HRTB with explicit `for` in various sorts of types: -fn foo10(t: Box Get>) { } -fn foo11(t: Box Get(int) -> int>) { } +fn foo10(t: Box Get>) { } +fn foo11(t: Box Fn(i32) -> i32>) { } -fn foo20(t: for<'a> fn(int) -> int) { } -fn foo21(t: for<'a> unsafe fn(int) -> int) { } -fn foo22(t: for<'a> extern "C" fn(int) -> int) { } -fn foo23(t: for<'a> unsafe extern "C" fn(int) -> int) { } +fn foo20(t: for<'a> fn(i32) -> i32) { } +fn foo21(t: for<'a> unsafe fn(i32) -> i32) { } +fn foo22(t: for<'a> extern "C" fn(i32) -> i32) { } +fn foo23(t: for<'a> unsafe extern "C" fn(i32) -> i32) { } fn main() { } diff --git a/src/test/run-pass/hrtb-trait-object-paren-notation.rs b/src/test/run-pass/hrtb-trait-object-paren-notation.rs index e17e0ae2189d3..1b62a8e809c89 100644 --- a/src/test/run-pass/hrtb-trait-object-paren-notation.rs +++ b/src/test/run-pass/hrtb-trait-object-paren-notation.rs @@ -16,7 +16,7 @@ trait FnLike { fn call(&self, arg: A) -> R; } -type FnObject<'b> = for<'a> FnLike(&'a int) -> (&'a int) + 'b; +type FnObject<'b> = for<'a> FnLike<(&'a i32,), &'a i32> + 'b; struct Identity; diff --git a/src/test/run-pass/issue-13655.rs b/src/test/run-pass/issue-13655.rs index 6fdaac992047f..81a8b29461c78 100644 --- a/src/test/run-pass/issue-13655.rs +++ b/src/test/run-pass/issue-13655.rs @@ -13,7 +13,8 @@ use std::ops::Fn; struct Foo(T); -impl Fn<(), T> for Foo { +impl Fn<()> for Foo { + type Output = T; extern "rust-call" fn call(&self, _: ()) -> T { match *self { Foo(t) => t diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs index 1ffd349a65385..814a743648d3f 100644 --- a/src/test/run-pass/issue-14958.rs +++ b/src/test/run-pass/issue-14958.rs @@ -14,7 +14,8 @@ trait Foo {} struct Bar; -impl<'a> std::ops::Fn<(&'a (Foo+'a),), ()> for Bar { +impl<'a> std::ops::Fn<(&'a (Foo+'a),)> for Bar { + type Output = (); extern "rust-call" fn call(&self, _: (&'a Foo,)) {} } diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs index 99472bb3610f8..33281d7d78ffb 100644 --- a/src/test/run-pass/issue-14959.rs +++ b/src/test/run-pass/issue-14959.rs @@ -33,7 +33,9 @@ impl Alloy { } } -impl<'a, 'b> Fn<(&'b mut (Response+'b),),()> for SendFile<'a> { +impl<'a, 'b> Fn<(&'b mut (Response+'b),)> for SendFile<'a> { + type Output = (); + extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {} } diff --git a/src/test/run-pass/issue-16668.rs b/src/test/run-pass/issue-16668.rs index 75b1e11ddc1e6..e82add61aa3bb 100644 --- a/src/test/run-pass/issue-16668.rs +++ b/src/test/run-pass/issue-16668.rs @@ -15,7 +15,7 @@ #![feature(unboxed_closures)] struct Parser<'a, I, O> { - parse: Box> + 'a> + parse: Box Result + 'a> } impl<'a, I, O: 'a> Parser<'a, I, O> { diff --git a/src/test/run-pass/issue-16739.rs b/src/test/run-pass/issue-16739.rs index cb6f068cf45b8..389baecafd144 100644 --- a/src/test/run-pass/issue-16739.rs +++ b/src/test/run-pass/issue-16739.rs @@ -15,27 +15,30 @@ // Test that unboxing shim for calling rust-call ABI methods through a // trait box works and does not cause an ICE. -struct Foo { foo: uint } +struct Foo { foo: u32 } -impl FnMut<(), uint> for Foo { - extern "rust-call" fn call_mut(&mut self, _: ()) -> uint { self.foo } +impl FnMut<()> for Foo { + type Output = u32; + extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { self.foo } } -impl FnMut<(uint,), uint> for Foo { - extern "rust-call" fn call_mut(&mut self, (x,): (uint,)) -> uint { self.foo + x } +impl FnMut<(u32,)> for Foo { + type Output = u32; + extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x } } -impl FnMut<(uint, uint), uint> for Foo { - extern "rust-call" fn call_mut(&mut self, (x, y): (uint, uint)) -> uint { self.foo + x + y } +impl FnMut<(u32,u32)> for Foo { + type Output = u32; + extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y } } fn main() { - let mut f = box Foo { foo: 42 } as Box>; + let mut f = box Foo { foo: 42 } as Box u32>; assert_eq!(f.call_mut(()), 42); - let mut f = box Foo { foo: 40 } as Box>; + let mut f = box Foo { foo: 40 } as Box u32>; assert_eq!(f.call_mut((2,)), 42); - let mut f = box Foo { foo: 40 } as Box>; + let mut f = box Foo { foo: 40 } as Box u32>; assert_eq!(f.call_mut((1, 1)), 42); } diff --git a/src/test/run-pass/object-method-numbering.rs b/src/test/run-pass/object-method-numbering.rs new file mode 100644 index 0000000000000..8da753acb966e --- /dev/null +++ b/src/test/run-pass/object-method-numbering.rs @@ -0,0 +1,36 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test for using an object with an associated type binding as the +// instantiation for a generic type with a bound. + +trait SomeTrait { + type SomeType; + + fn get(&self) -> Self::SomeType; +} + +fn get_int+?Sized>(x: &T) -> i32 { + x.get() +} + +impl SomeTrait for i32 { + type SomeType = i32; + fn get(&self) -> i32 { + *self + } +} + +fn main() { + let x = 22_i32; + let x1: &SomeTrait = &x; + let y = get_int(x1); + assert_eq!(x, y); +} diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index 56887636d5dfb..2838909c1be62 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -17,13 +17,15 @@ use std::ops::Add; struct G; -impl<'a, A: Add> Fn<(A,), int> for G { - extern "rust-call" fn call(&self, (arg,): (A,)) -> int { +impl<'a, A: Add> Fn<(A,)> for G { + type Output = i32; + + extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 { arg.add(1) } } fn main() { // ICE trigger - G(1i); + G(1_i32); } diff --git a/src/test/run-pass/overloaded-calls-simple.rs b/src/test/run-pass/overloaded-calls-simple.rs index bb5b88d3674a1..f9e838d9b3d34 100644 --- a/src/test/run-pass/overloaded-calls-simple.rs +++ b/src/test/run-pass/overloaded-calls-simple.rs @@ -13,34 +13,37 @@ use std::ops::{Fn, FnMut, FnOnce}; struct S1 { - x: int, - y: int, + x: i32, + y: i32, } -impl FnMut<(int,),int> for S1 { - extern "rust-call" fn call_mut(&mut self, (z,): (int,)) -> int { +impl FnMut<(i32,)> for S1 { + type Output = i32; + extern "rust-call" fn call_mut(&mut self, (z,): (i32,)) -> i32 { self.x * self.y * z } } struct S2 { - x: int, - y: int, + x: i32, + y: i32, } -impl Fn<(int,),int> for S2 { - extern "rust-call" fn call(&self, (z,): (int,)) -> int { +impl Fn<(i32,)> for S2 { + type Output = i32; + extern "rust-call" fn call(&self, (z,): (i32,)) -> i32 { self.x * self.y * z } } struct S3 { - x: int, - y: int, + x: i32, + y: i32, } -impl FnOnce<(int,int),int> for S3 { - extern "rust-call" fn call_once(self, (z,zz): (int,int)) -> int { +impl FnOnce<(i32,i32)> for S3 { + type Output = i32; + extern "rust-call" fn call_once(self, (z,zz): (i32,i32)) -> i32 { self.x * self.y * z * zz } } diff --git a/src/test/run-pass/overloaded-calls-zero-args.rs b/src/test/run-pass/overloaded-calls-zero-args.rs index 809a251fe8059..ce7395673b390 100644 --- a/src/test/run-pass/overloaded-calls-zero-args.rs +++ b/src/test/run-pass/overloaded-calls-zero-args.rs @@ -13,12 +13,13 @@ use std::ops::{FnMut}; struct S { - x: int, - y: int, + x: i32, + y: i32, } -impl FnMut<(),int> for S { - extern "rust-call" fn call_mut(&mut self, (): ()) -> int { +impl FnMut<()> for S { + type Output = i32; + extern "rust-call" fn call_mut(&mut self, (): ()) -> i32 { self.x * self.y } } diff --git a/src/test/run-pass/unboxed-closures-boxed.rs b/src/test/run-pass/unboxed-closures-boxed.rs index dc35d5bf2caca..27528ca5d5663 100644 --- a/src/test/run-pass/unboxed-closures-boxed.rs +++ b/src/test/run-pass/unboxed-closures-boxed.rs @@ -14,9 +14,9 @@ use std::ops::FnMut; - fn make_adder(x: int) -> Box+'static> { - (box move |&mut: y: int| -> int { x + y }) as - Box+'static> + fn make_adder(x: i32) -> Boxi32+'static> { + (box move |&mut: y: i32| -> i32 { x + y }) as + Boxi32+'static> } pub fn main() { diff --git a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs index 8af0547e5e57f..5d6029e703b82 100644 --- a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs @@ -18,21 +18,22 @@ use std::ops::{Fn,FnMut,FnOnce}; struct S; -impl Fn<(int,),int> for S { - extern "rust-call" fn call(&self, (x,): (int,)) -> int { +impl Fn<(i32,)> for S { + type Output = i32; + extern "rust-call" fn call(&self, (x,): (i32,)) -> i32 { x * x } } -fn call_itint>(f: &F, x: int) -> int { +fn call_iti32>(f: &F, x: i32) -> i32 { f(x) } -fn call_it_mutint>(f: &mut F, x: int) -> int { +fn call_it_muti32>(f: &mut F, x: i32) -> i32 { f(x) } -fn call_it_onceint>(f: F, x: int) -> int { +fn call_it_oncei32>(f: F, x: i32) -> i32 { f(x) } diff --git a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs index 068080e256dba..95dae41c6840e 100644 --- a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs @@ -18,17 +18,19 @@ use std::ops::{FnMut,FnOnce}; struct S; -impl FnMut<(int,),int> for S { - extern "rust-call" fn call_mut(&mut self, (x,): (int,)) -> int { +impl FnMut<(i32,)> for S { + type Output = i32; + + extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 { x * x } } -fn call_it_mutint>(f: &mut F, x: int) -> int { +fn call_it_muti32>(f: &mut F, x: i32) -> i32 { f(x) } -fn call_it_onceint>(f: F, x: int) -> int { +fn call_it_oncei32>(f: F, x: i32) -> i32 { f(x) } diff --git a/src/test/run-pass/unboxed-closures-generic.rs b/src/test/run-pass/unboxed-closures-generic.rs index 0edeeb8d198da..04c124946c9a1 100644 --- a/src/test/run-pass/unboxed-closures-generic.rs +++ b/src/test/run-pass/unboxed-closures-generic.rs @@ -12,12 +12,12 @@ use std::ops::FnMut; -fn call_it>(y: int, mut f: F) -> int { +fn call_iti32>(y: i32, mut f: F) -> i32 { f(2, y) } pub fn main() { - let f = |&mut: x: int, y: int| -> int { x + y }; + let f = |&mut: x: i32, y: i32| -> i32 { x + y }; let z = call_it(3, f); println!("{}", z); assert_eq!(z, 5); diff --git a/src/test/run-pass/unboxed-closures-manual-impl.rs b/src/test/run-pass/unboxed-closures-manual-impl.rs index 88c9ceae4a124..37075de0405ad 100644 --- a/src/test/run-pass/unboxed-closures-manual-impl.rs +++ b/src/test/run-pass/unboxed-closures-manual-impl.rs @@ -15,17 +15,19 @@ use std::ops::FnMut; struct S; -impl FnMut<(int,),int> for S { - extern "rust-call" fn call_mut(&mut self, (x,): (int,)) -> int { +impl FnMut<(i32,)> for S { + type Output = i32; + + extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 { x * x } } -fn call_itint>(mut f: F, x: int) -> int { +fn call_iti32>(mut f: F, x: i32) -> i32 { f(x) + 3 } -fn call_box(f: &mut FnMut(int) -> int, x: int) -> int { +fn call_box(f: &mut FnMut(i32) -> i32, x: i32) -> i32 { f(x) + 3 } diff --git a/src/test/run-pass/unboxed-closures-monomorphization.rs b/src/test/run-pass/unboxed-closures-monomorphization.rs index 6701f879e4f2b..6dfa4c124e24e 100644 --- a/src/test/run-pass/unboxed-closures-monomorphization.rs +++ b/src/test/run-pass/unboxed-closures-monomorphization.rs @@ -16,17 +16,17 @@ #![feature(unboxed_closures)] fn main(){ - fn bar<'a, T:Clone+'a> (t: T) -> Box + 'a> { + fn bar<'a, T:Clone+'a> (t: T) -> BoxT + 'a> { box move |&mut:| t.clone() } - let mut f = bar(42u); + let mut f = bar(42_u32); assert_eq!(f.call_mut(()), 42); let mut f = bar("forty-two"); assert_eq!(f.call_mut(()), "forty-two"); - let x = 42u; + let x = 42_u32; let mut f = bar(&x); assert_eq!(f.call_mut(()), &x); diff --git a/src/test/run-pass/unboxed-closures-sugar-object.rs b/src/test/run-pass/unboxed-closures-sugar-object.rs index d65de438514f5..fff841a2f052d 100644 --- a/src/test/run-pass/unboxed-closures-sugar-object.rs +++ b/src/test/run-pass/unboxed-closures-sugar-object.rs @@ -29,7 +29,7 @@ impl Getter for Identity { } fn main() { - let x: &Getter(int) -> (int,) = &Identity; + let x: &Getter<(i32,), (i32,)> = &Identity; let (y,) = x.get((22,)); assert_eq!(y, 22); }