Skip to content

Commit f8d4f4a

Browse files
author
Jorge Aparicio
committed
---
yaml --- r: 158719 b: refs/heads/snap-stage3 c: 88ed2d1 h: refs/heads/master i: 158717: 218ad47 158715: d7c7423 158711: 6f53504 158703: ddfd100 158687: 595726a 158655: 59805a6 158591: 479aabf 158463: 05c499d 158207: dec4c6a 157695: be32bab v: v3
1 parent 394ed71 commit f8d4f4a

17 files changed

+126
-319
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 0b48001c28329392b26961eaf1c3ed293a352d6f
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 0e2f9b948564708085373fc28d91b4524c821fa3
4+
refs/heads/snap-stage3: 88ed2d1c41a0a80c98cb84be076e6447eeed3f36
55
refs/heads/try: f58aad6dce273570fb130b4df008ef9acd5a5be2
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d

branches/snap-stage3/src/libcore/ops.rs

Lines changed: 20 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -866,64 +866,34 @@ pub trait FnOnce<Args,Result> {
866866
extern "rust-call" fn call_once(self, args: Args) -> Result;
867867
}
868868

869-
impl<F,A,R> FnMut<A,R> for F
870-
where F : Fn<A,R>
871-
{
872-
extern "rust-call" fn call_mut(&mut self, args: A) -> R {
873-
self.call(args)
874-
}
875-
}
876-
877-
impl<F,A,R> FnOnce<A,R> for F
878-
where F : FnMut<A,R>
879-
{
880-
extern "rust-call" fn call_once(mut self, args: A) -> R {
881-
self.call_mut(args)
882-
}
883-
}
884-
885-
886-
impl<Result> Fn<(),Result> for extern "Rust" fn() -> Result {
887-
#[allow(non_snake_case)]
888-
extern "rust-call" fn call(&self, _args: ()) -> Result {
889-
(*self)()
890-
}
891-
}
892-
893-
impl<Result,A0> Fn<(A0,),Result> for extern "Rust" fn(A0) -> Result {
894-
#[allow(non_snake_case)]
895-
extern "rust-call" fn call(&self, args: (A0,)) -> Result {
896-
let (a0,) = args;
897-
(*self)(a0)
898-
}
899-
}
900-
901-
macro_rules! def_fn(
869+
macro_rules! def_fn_mut(
902870
($($args:ident)*) => (
903871
impl<Result$(,$args)*>
904-
Fn<($($args,)*),Result>
872+
FnMut<($($args,)*),Result>
905873
for extern "Rust" fn($($args: $args,)*) -> Result {
906874
#[allow(non_snake_case)]
907-
extern "rust-call" fn call(&self, args: ($($args,)*)) -> Result {
875+
extern "rust-call" fn call_mut(&mut self, args: ($($args,)*)) -> Result {
908876
let ($($args,)*) = args;
909877
(*self)($($args,)*)
910878
}
911879
}
912880
)
913881
)
914882

915-
def_fn!(A0 A1)
916-
def_fn!(A0 A1 A2)
917-
def_fn!(A0 A1 A2 A3)
918-
def_fn!(A0 A1 A2 A3 A4)
919-
def_fn!(A0 A1 A2 A3 A4 A5)
920-
def_fn!(A0 A1 A2 A3 A4 A5 A6)
921-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7)
922-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8)
923-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9)
924-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10)
925-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11)
926-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12)
927-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13)
928-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14)
929-
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15)
883+
def_fn_mut!()
884+
def_fn_mut!(A0)
885+
def_fn_mut!(A0 A1)
886+
def_fn_mut!(A0 A1 A2)
887+
def_fn_mut!(A0 A1 A2 A3)
888+
def_fn_mut!(A0 A1 A2 A3 A4)
889+
def_fn_mut!(A0 A1 A2 A3 A4 A5)
890+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6)
891+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7)
892+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8)
893+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9)
894+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10)
895+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11)
896+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12)
897+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13)
898+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14)
899+
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15)

branches/snap-stage3/src/librustc/middle/traits/coherence.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
4343
// Determine whether `impl2` can provide an implementation for those
4444
// same types.
4545
let param_env = ty::empty_parameter_environment();
46-
let mut selcx = SelectionContext::intercrate(infcx, &param_env, infcx.tcx);
46+
let mut selcx = SelectionContext::new(infcx, &param_env, infcx.tcx);
4747
let obligation = Obligation::misc(DUMMY_SP, impl1_trait_ref);
4848
debug!("impl_can_satisfy obligation={}", obligation.repr(infcx.tcx));
4949
selcx.evaluate_impl(impl2_def_id, &obligation)

branches/snap-stage3/src/librustc/middle/traits/select.rs

Lines changed: 62 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,6 @@ pub struct SelectionContext<'cx, 'tcx:'cx> {
4545
/// which is important for checking for trait bounds that
4646
/// recursively require themselves.
4747
skolemizer: TypeSkolemizer<'cx, 'tcx>,
48-
49-
/// If true, indicates that the evaluation should be conservative
50-
/// and consider the possibility of types outside this crate.
51-
/// This comes up primarily when resolving ambiguity. Imagine
52-
/// there is some trait reference `$0 : Bar` where `$0` is an
53-
/// inference variable. If `intercrate` is true, then we can never
54-
/// say for sure that this reference is not implemented, even if
55-
/// there are *no impls at all for `Bar`*, because `$0` could be
56-
/// bound to some type that in a downstream crate that implements
57-
/// `Bar`. This is the suitable mode for coherence. Elsewhere,
58-
/// though, we set this to false, because we are only interested
59-
/// in types that the user could actually have written --- in
60-
/// other words, we consider `$0 : Bar` to be unimplemented if
61-
/// there is no type that the user could *actually name* that
62-
/// would satisfy it. This avoids crippling inference, basically.
63-
intercrate: bool,
6448
}
6549

6650
// A stack that walks back up the stack frame.
@@ -158,20 +142,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
158142
param_env: param_env,
159143
typer: typer,
160144
skolemizer: infcx.skolemizer(),
161-
intercrate: false,
162-
}
163-
}
164-
165-
pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>,
166-
param_env: &'cx ty::ParameterEnvironment,
167-
typer: &'cx Typer<'tcx>)
168-
-> SelectionContext<'cx, 'tcx> {
169-
SelectionContext {
170-
infcx: infcx,
171-
param_env: param_env,
172-
typer: typer,
173-
skolemizer: infcx.skolemizer(),
174-
intercrate: true,
175145
}
176146
}
177147

@@ -244,20 +214,44 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
244214
// The result is "true" if the obligation *may* hold and "false" if
245215
// we can be sure it does not.
246216

247-
pub fn evaluate_obligation(&mut self,
248-
obligation: &Obligation)
249-
-> bool
217+
pub fn evaluate_obligation_intercrate(&mut self,
218+
obligation: &Obligation)
219+
-> bool
250220
{
251221
/*!
252222
* Evaluates whether the obligation `obligation` can be
253-
* satisfied (by any means).
223+
* satisfied (by any means). This "intercrate" version allows
224+
* for the possibility that unbound type variables may be
225+
* instantiated with types from another crate. This is
226+
* important for coherence. In practice this means that
227+
* unbound type variables must always be considered ambiguous.
254228
*/
255229

256-
debug!("evaluate_obligation({})",
230+
debug!("evaluate_obligation_intercrate({})",
257231
obligation.repr(self.tcx()));
258232

259233
let stack = self.push_stack(None, obligation);
260-
self.evaluate_stack(&stack).may_apply()
234+
self.evaluate_stack_intercrate(&stack).may_apply()
235+
}
236+
237+
pub fn evaluate_obligation_intracrate(&mut self,
238+
obligation: &Obligation)
239+
-> bool
240+
{
241+
/*!
242+
* Evaluates whether the obligation `obligation` can be
243+
* satisfied (by any means). This "intracrate" version does
244+
* not allow for the possibility that unbound type variables
245+
* may be instantiated with types from another crate; hence,
246+
* if there are unbound inputs but no crates locally visible,
247+
* it considers the result to be unimplemented.
248+
*/
249+
250+
debug!("evaluate_obligation_intracrate({})",
251+
obligation.repr(self.tcx()));
252+
253+
let stack = self.push_stack(None, obligation);
254+
self.evaluate_stack_intracrate(&stack).may_apply()
261255
}
262256

263257
fn evaluate_builtin_bound_recursively(&mut self,
@@ -294,53 +288,46 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
294288

295289
let stack = self.push_stack(previous_stack.map(|x| x), obligation);
296290

297-
let result = self.evaluate_stack(&stack);
291+
// FIXME(#17901) -- Intercrate vs intracrate resolution is a
292+
// tricky question here. For coherence, we want
293+
// intercrate. Also, there was a nasty cycle around impls like
294+
// `impl<T:Eq> Eq for Vec<T>` (which would wind up checking
295+
// whether `$0:Eq`, where $0 was the value substituted for
296+
// `T`, which could then be checked against the very same
297+
// impl). This problem is avoided by the stricter rules around
298+
// unbound type variables by intercrate. I suspect that in the
299+
// latter case a more fine-grained rule would suffice (i.e.,
300+
// consider it ambiguous if even 1 impl matches, no need to
301+
// figure out which one, but call it unimplemented if 0 impls
302+
// match).
303+
let result = self.evaluate_stack_intercrate(&stack);
298304

299305
debug!("result: {}", result);
300306
result
301307
}
302308

303-
fn evaluate_stack(&mut self,
309+
fn evaluate_stack_intercrate(&mut self,
304310
stack: &ObligationStack)
305311
-> EvaluationResult
306312
{
307-
// In intercrate mode, whenever any of the types are unbound,
308-
// there can always be an impl. Even if there are no impls in
309-
// this crate, perhaps the type would be unified with
310-
// something from another crate that does provide an impl.
311-
//
312-
// In intracrate mode, we must still be conservative. The reason is
313-
// that we want to avoid cycles. Imagine an impl like:
314-
//
315-
// impl<T:Eq> Eq for Vec<T>
316-
//
317-
// and a trait reference like `$0 : Eq` where `$0` is an
318-
// unbound variable. When we evaluate this trait-reference, we
319-
// will unify `$0` with `Vec<$1>` (for some fresh variable
320-
// `$1`), on the condition that `$1 : Eq`. We will then wind
321-
// up with many candidates (since that are other `Eq` impls
322-
// that apply) and try to winnow things down. This results in
323-
// a recurssive evaluation that `$1 : Eq` -- as you can
324-
// imagine, this is just where we started. To avoid that, we
325-
// check for unbound variables and return an ambiguous (hence possible)
326-
// match if we've seen this trait before.
327-
//
328-
// This suffices to allow chains like `FnMut` implemented in
329-
// terms of `Fn` etc, but we could probably make this more
330-
// precise still.
313+
// Whenever any of the types are unbound, there can always be
314+
// an impl. Even if there are no impls in this crate, perhaps
315+
// the type would be unified with something from another crate
316+
// that does provide an impl.
331317
let input_types = stack.skol_trait_ref.input_types();
332-
let unbound_input_types = input_types.iter().any(|&t| ty::type_is_skolemized(t));
333-
if
334-
unbound_input_types &&
335-
(self.intercrate ||
336-
stack.iter().skip(1).any(
337-
|prev| stack.skol_trait_ref.def_id == prev.skol_trait_ref.def_id))
338-
{
339-
debug!("evaluate_stack_intracrate({}) --> unbound argument, recursion --> ambiguous",
318+
if input_types.iter().any(|&t| ty::type_is_skolemized(t)) {
319+
debug!("evaluate_stack_intercrate({}) --> unbound argument, must be ambiguous",
340320
stack.skol_trait_ref.repr(self.tcx()));
341321
return EvaluatedToAmbig;
342322
}
343323

324+
self.evaluate_stack_intracrate(stack)
325+
}
326+
327+
fn evaluate_stack_intracrate(&mut self,
328+
stack: &ObligationStack)
329+
-> EvaluationResult
330+
{
344331
// If there is any previous entry on the stack that precisely
345332
// matches this obligation, then we can assume that the
346333
// obligation is satisfied for now (still all other conditions
@@ -605,7 +592,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
605592
Err(_) => { return Err(()); }
606593
}
607594

608-
if self.evaluate_obligation(obligation) {
595+
if self.evaluate_obligation_intracrate(obligation) {
609596
Ok(())
610597
} else {
611598
Err(())
@@ -817,12 +804,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
817804
&candidates[i],
818805
&candidates[j]));
819806
if is_dup {
820-
debug!("Dropping candidate #{}/{}: {}",
807+
debug!("Dropping candidate #{}/#{}: {}",
821808
i, candidates.len(), candidates[i].repr(self.tcx()));
822809
candidates.swap_remove(i);
823810
} else {
824-
debug!("Retaining candidate #{}/{}: {}",
825-
i, candidates.len(), candidates[i].repr(self.tcx()));
811+
debug!("Retaining candidate #{}/#{}",
812+
i, candidates.len());
826813
i += 1;
827814
}
828815
}
@@ -841,7 +828,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
841828
// be the case that you could still satisfy the obligation
842829
// from another crate by instantiating the type variables with
843830
// a type from another crate that does have an impl. This case
844-
// is checked for in `evaluate_stack` (and hence users
831+
// is checked for in `evaluate_obligation` (and hence users
845832
// who might care about this case, like coherence, should use
846833
// that function).
847834
if candidates.len() == 0 {
@@ -862,17 +849,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
862849
// global cache. We want the cache that is specific to this
863850
// scope whenever where clauses might affect the result.
864851

865-
// Avoid using the master cache during coherence and just rely
866-
// on the local cache. This effectively disables caching
867-
// during coherence. It is really just a simplification to
868-
// avoid us having to fear that coherence results "pollute"
869-
// the master cache. Since coherence executes pretty quickly,
870-
// it's not worth going to more trouble to increase the
871-
// hit-rate I don't think.
872-
if self.intercrate {
873-
return &self.param_env.selection_cache;
874-
}
875-
876852
// If the trait refers to any parameters in scope, then use
877853
// the cache of the param-environment.
878854
if

branches/snap-stage3/src/librustc/middle/typeck/check/method.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(
235235
let mut selcx = traits::SelectionContext::new(fcx.infcx(),
236236
&fcx.inh.param_env,
237237
fcx);
238-
if !selcx.evaluate_obligation(&obligation) {
238+
if !selcx.evaluate_obligation_intracrate(&obligation) {
239239
debug!("--> Cannot match obligation");
240240
return None; // Cannot be matched, no such method resolution is possible.
241241
}

branches/snap-stage3/src/librustc/middle/typeck/check/mod.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,11 +2147,11 @@ fn try_overloaded_call<'a>(fcx: &FnCtxt,
21472147
_ => {}
21482148
}
21492149

2150-
// Try the options that are least restrictive on the caller first.
2150+
// Try `FnOnce`, then `FnMut`, then `Fn`.
21512151
for &(maybe_function_trait, method_name) in [
2152-
(fcx.tcx().lang_items.fn_trait(), token::intern("call")),
2153-
(fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
21542152
(fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
2153+
(fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
2154+
(fcx.tcx().lang_items.fn_trait(), token::intern("call"))
21552155
].iter() {
21562156
let function_trait = match maybe_function_trait {
21572157
None => continue,
@@ -3493,11 +3493,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
34933493
ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
34943494
};
34953495

3496-
debug!("unboxed_closure for {} --> sig={} kind={}",
3497-
local_def(expr.id).repr(fcx.tcx()),
3498-
fn_ty.sig.repr(fcx.tcx()),
3499-
kind);
3500-
35013496
let unboxed_closure = ty::UnboxedClosure {
35023497
closure_type: fn_ty,
35033498
kind: kind,

0 commit comments

Comments
 (0)