Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the return type of Fn trait an associated type #21019

Merged
merged 14 commits into from
Jan 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/libcollections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
75 changes: 69 additions & 6 deletions src/libcore/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Args,Result> {
#[cfg(stage0)]
pub trait Fn<Args,Output> {
/// This is called when the call operator is used.
extern "rust-call" fn call(&self, args: Args) -> Result;
extern "rust-call" fn call(&self, args: Args) -> Output;
}

/// A version of the call operator that takes a mutable receiver.
#[lang="fn_mut"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
pub trait FnMut<Args,Result> {
#[cfg(stage0)]
pub trait FnMut<Args,Output> {
/// This is called when the call operator is used.
extern "rust-call" fn call_mut(&mut self, args: Args) -> Result;
extern "rust-call" fn call_mut(&mut self, args: Args) -> Output;
}

/// A version of the call operator that takes a by-value receiver.
#[lang="fn_once"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
pub trait FnOnce<Args,Result> {
#[cfg(stage0)]
pub trait FnOnce<Args,Output> {
/// This is called when the call operator is used.
extern "rust-call" fn call_once(self, args: Args) -> Result;
extern "rust-call" fn call_once(self, args: Args) -> Output;
}

#[cfg(stage0)]
impl<F: ?Sized, A, R> FnMut<A, R> for F
where F : Fn<A, R>
{
Expand All @@ -1148,10 +1152,69 @@ impl<F: ?Sized, A, R> FnMut<A, R> for F
}
}

#[cfg(stage0)]
impl<F,A,R> FnOnce<A,R> for F
where F : FnMut<A,R>
{
extern "rust-call" fn call_once(mut self, args: A) -> R {
self.call_mut(args)
}
}

/// A version of the call operator that takes an immutable receiver.
#[lang="fn"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
pub trait Fn<Args> {
type Output;

/// This is called when the call operator is used.
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}

/// A version of the call operator that takes a mutable receiver.
#[lang="fn_mut"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
pub trait FnMut<Args> {
type Output;

/// This is called when the call operator is used.
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}

/// A version of the call operator that takes a by-value receiver.
#[lang="fn_once"]
#[unstable(feature = "core",
reason = "uncertain about variadic generics, input versus associated types")]
#[cfg(not(stage0))]
pub trait FnOnce<Args> {
type Output;

/// This is called when the call operator is used.
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

#[cfg(not(stage0))]
impl<F: ?Sized, A> FnMut<A> for F
where F : Fn<A>
{
type Output = <F as Fn<A>>::Output;

extern "rust-call" fn call_mut(&mut self, args: A) -> <F as Fn<A>>::Output {
self.call(args)
}
}

#[cfg(not(stage0))]
impl<F,A> FnOnce<A> for F
where F : FnMut<A>
{
type Output = <F as FnMut<A>>::Output;

extern "rust-call" fn call_once(mut self, args: A) -> <F as FnMut<A>>::Output {
self.call_mut(args)
}
}
11 changes: 11 additions & 0 deletions src/libcore/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,13 +461,24 @@ 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 {
*ptr
}
}

#[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> {
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
})
Expand Down Expand Up @@ -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()
},
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
61 changes: 60 additions & 1 deletion src/librustc/middle/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<ty::ParameterEnvironment<'a,'tcx>,
Vec<FulfillmentError<'tcx>>>
{
let tcx = param_env.tcx;

debug!("normalize_param_env(param_env={})",
param_env.repr(tcx));

let predicates: Vec<ty::Predicate<'tcx>> = {
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, &param_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)
Expand Down
8 changes: 3 additions & 5 deletions src/librustc/middle/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading