Skip to content

Commit 2ed8e5b

Browse files
committed
---
yaml --- r: 157571 b: refs/heads/snap-stage3 c: 1da73ff h: refs/heads/master i: 157569: bd99e84 157567: bcc719a v: v3
1 parent 384a252 commit 2ed8e5b

File tree

6 files changed

+131
-50
lines changed

6 files changed

+131
-50
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: 065caf34f5ff29e04605f95d9c5d511af219439a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 9a778bc550c22c50117ee42ef5cf7510622fb036
4+
refs/heads/snap-stage3: 1da73ff12642182c9049630c3625f44f718c6c2f
55
refs/heads/try: 0ee4d8b0b112c608646fa75463ab4dc59132efd9
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/libcollections/vec.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -636,18 +636,13 @@ impl<T> Vec<T> {
636636
}
637637
}
638638

639-
/// Shrinks the capacity of the vector as much as possible. It will drop
640-
/// down as close as possible to the length but the allocator may still
641-
/// inform the vector that there is space for a few more elements.
639+
/// Shrinks the capacity of the vector as much as possible.
642640
///
643641
/// # Example
644642
///
645643
/// ```
646-
/// let mut vec: Vec<int> = Vec::with_capacity(10);
647-
/// vec.push_all([1, 2, 3]);
648-
/// assert_eq!(vec.capacity(), 10);
644+
/// let mut vec = vec![1i, 2, 3];
649645
/// vec.shrink_to_fit();
650-
/// assert!(vec.capacity() >= 3);
651646
/// ```
652647
#[stable]
653648
pub fn shrink_to_fit(&mut self) {
@@ -835,7 +830,6 @@ impl<T> Vec<T> {
835830
/// for num in vec.iter_mut() {
836831
/// *num = 0;
837832
/// }
838-
/// assert_eq!(vec, vec![0i, 0, 0]);
839833
/// ```
840834
#[inline]
841835
pub fn iter_mut<'a>(&'a mut self) -> MutItems<'a,T> {

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

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,18 @@ pub struct FulfillmentContext {
3535
// A list of all obligations that have been registered with this
3636
// fulfillment context.
3737
trait_obligations: Vec<Obligation>,
38+
39+
// Remembers the count of trait obligations that we have already
40+
// attempted to select. This is used to avoid repeating work
41+
// when `select_new_obligations` is called.
42+
attempted_mark: uint,
3843
}
3944

4045
impl FulfillmentContext {
4146
pub fn new() -> FulfillmentContext {
4247
FulfillmentContext {
4348
trait_obligations: Vec::new(),
49+
attempted_mark: 0,
4450
}
4551
}
4652

@@ -74,18 +80,49 @@ impl FulfillmentContext {
7480
}
7581
}
7682

83+
pub fn select_new_obligations<'a,'tcx>(&mut self,
84+
infcx: &InferCtxt<'a,'tcx>,
85+
param_env: &ty::ParameterEnvironment,
86+
typer: &Typer<'tcx>)
87+
-> Result<(),Vec<FulfillmentError>>
88+
{
89+
/*!
90+
* Attempts to select obligations that were registered since
91+
* the call to a selection routine. This is used by the type checker
92+
* to eagerly attempt to resolve obligations in hopes of gaining
93+
* type information. It'd be equally valid to use `select_where_possible`
94+
* but it results in `O(n^2)` performance (#18208).
95+
*/
96+
97+
let mut selcx = SelectionContext::new(infcx, param_env, typer);
98+
self.select(&mut selcx, true)
99+
}
100+
77101
pub fn select_where_possible<'a,'tcx>(&mut self,
78102
infcx: &InferCtxt<'a,'tcx>,
79103
param_env: &ty::ParameterEnvironment,
80104
typer: &Typer<'tcx>)
81105
-> Result<(),Vec<FulfillmentError>>
82106
{
83-
let tcx = infcx.tcx;
84107
let mut selcx = SelectionContext::new(infcx, param_env, typer);
108+
self.select(&mut selcx, false)
109+
}
85110

86-
debug!("select_where_possible({} obligations) start",
87-
self.trait_obligations.len());
111+
fn select(&mut self,
112+
selcx: &mut SelectionContext,
113+
only_new_obligations: bool)
114+
-> Result<(),Vec<FulfillmentError>>
115+
{
116+
/*!
117+
* Attempts to select obligations using `selcx`. If
118+
* `only_new_obligations` is true, then it only attempts to
119+
* select obligations that haven't been seen before.
120+
*/
121+
debug!("select({} obligations, only_new_obligations={}) start",
122+
self.trait_obligations.len(),
123+
only_new_obligations);
88124

125+
let tcx = selcx.tcx();
89126
let mut errors = Vec::new();
90127

91128
loop {
@@ -96,30 +133,47 @@ impl FulfillmentContext {
96133

97134
let mut selections = Vec::new();
98135

136+
// If we are only attempting obligations we haven't seen yet,
137+
// then set `skip` to the number of obligations we've already
138+
// seen.
139+
let mut skip = if only_new_obligations {
140+
self.attempted_mark
141+
} else {
142+
0
143+
};
144+
99145
// First pass: walk each obligation, retaining
100146
// only those that we cannot yet process.
101147
self.trait_obligations.retain(|obligation| {
102-
match selcx.select(obligation) {
103-
Ok(None) => {
104-
true
105-
}
106-
Ok(Some(s)) => {
107-
selections.push(s);
108-
false
109-
}
110-
Err(selection_err) => {
111-
debug!("obligation: {} error: {}",
112-
obligation.repr(tcx),
113-
selection_err.repr(tcx));
114-
115-
errors.push(FulfillmentError::new(
116-
(*obligation).clone(),
117-
CodeSelectionError(selection_err)));
118-
false
148+
// Hack: Retain does not pass in the index, but we want
149+
// to avoid processing the first `start_count` entries.
150+
if skip > 0 {
151+
skip -= 1;
152+
true
153+
} else {
154+
match selcx.select(obligation) {
155+
Ok(None) => {
156+
true
157+
}
158+
Ok(Some(s)) => {
159+
selections.push(s);
160+
false
161+
}
162+
Err(selection_err) => {
163+
debug!("obligation: {} error: {}",
164+
obligation.repr(tcx),
165+
selection_err.repr(tcx));
166+
errors.push(FulfillmentError::new(
167+
(*obligation).clone(),
168+
CodeSelectionError(selection_err)));
169+
false
170+
}
119171
}
120172
}
121173
});
122174

175+
self.attempted_mark = self.trait_obligations.len();
176+
123177
if self.trait_obligations.len() == count {
124178
// Nothing changed.
125179
break;
@@ -133,7 +187,7 @@ impl FulfillmentContext {
133187
}
134188
}
135189

136-
debug!("select_where_possible({} obligations, {} errors) done",
190+
debug!("select({} obligations, {} errors) done",
137191
self.trait_obligations.len(),
138192
errors.len());
139193

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ use middle::ty;
8888
use middle::typeck::astconv::AstConv;
8989
use middle::typeck::check::{FnCtxt, NoPreference, PreferMutLvalue};
9090
use middle::typeck::check::{impl_self_ty};
91-
use middle::typeck::check::vtable::select_fcx_obligations_where_possible;
91+
use middle::typeck::check::vtable::select_new_fcx_obligations;
9292
use middle::typeck::check;
9393
use middle::typeck::infer;
9494
use middle::typeck::{MethodCall, MethodCallee};
@@ -1302,7 +1302,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
13021302
// the `Self` trait).
13031303
let callee = self.confirm_candidate(rcvr_ty, &candidate);
13041304

1305-
select_fcx_obligations_where_possible(self.fcx);
1305+
select_new_fcx_obligations(self.fcx);
13061306

13071307
Some(Ok(callee))
13081308
}

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

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ use middle::typeck::check::method::{AutoderefReceiver};
101101
use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
102102
use middle::typeck::check::regionmanip::replace_late_bound_regions;
103103
use middle::typeck::CrateCtxt;
104-
use middle::typeck::infer::{resolve_type, force_tvar};
105104
use middle::typeck::infer;
106105
use middle::typeck::rscope::RegionScope;
107106
use middle::typeck::{lookup_def_ccx};
@@ -1412,7 +1411,7 @@ fn check_cast(fcx: &FnCtxt,
14121411
}
14131412
// casts from C-like enums are allowed
14141413
} else if t_1_is_char {
1415-
let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1414+
let t_e = fcx.infcx().shallow_resolve(t_e);
14161415
if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
14171416
fcx.type_error_message(span, |actual| {
14181417
format!("only `u8` can be cast as \
@@ -2564,7 +2563,7 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
25642563
// an "opportunistic" vtable resolution of any trait
25652564
// bounds on the call.
25662565
if check_blocks {
2567-
vtable::select_fcx_obligations_where_possible(fcx);
2566+
vtable::select_new_fcx_obligations(fcx);
25682567
}
25692568

25702569
// For variadic functions, we don't have a declared type for all of
@@ -2988,9 +2987,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
29882987
// 'else' branch.
29892988
let expected = match expected.only_has_type() {
29902989
ExpectHasType(ety) => {
2991-
match infer::resolve_type(fcx.infcx(), Some(sp), ety, force_tvar) {
2992-
Ok(rty) if !ty::type_is_ty_var(rty) => ExpectHasType(rty),
2993-
_ => NoExpectation
2990+
let ety = fcx.infcx().shallow_resolve(ety);
2991+
if !ty::type_is_ty_var(ety) {
2992+
ExpectHasType(ety)
2993+
} else {
2994+
NoExpectation
29942995
}
29952996
}
29962997
_ => NoExpectation
@@ -4037,7 +4038,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
40374038
ast::ExprForLoop(ref pat, ref head, ref block, _) => {
40384039
check_expr(fcx, &**head);
40394040
let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
4040-
vtable::select_fcx_obligations_where_possible(fcx);
4041+
vtable::select_new_fcx_obligations(fcx);
40414042

40424043
let pcx = pat_ctxt {
40434044
fcx: fcx,
@@ -5393,18 +5394,32 @@ pub fn instantiate_path(fcx: &FnCtxt,
53935394

53945395
// Resolves `typ` by a single level if `typ` is a type variable. If no
53955396
// resolution is possible, then an error is reported.
5396-
pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
5397-
match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
5398-
Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
5399-
_ => {
5400-
fcx.type_error_message(sp, |_actual| {
5401-
"the type of this value must be known in this \
5402-
context".to_string()
5403-
}, tp, None);
5404-
demand::suptype(fcx, sp, ty::mk_err(), tp);
5405-
tp
5406-
}
5397+
pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, mut ty: ty::t) -> ty::t {
5398+
// If `ty` is a type variable, see whether we already know what it is.
5399+
ty = fcx.infcx().shallow_resolve(ty);
5400+
5401+
// If not, try resolve pending fcx obligations. Those can shed light.
5402+
//
5403+
// FIXME(#18391) -- This current strategy can lead to bad performance in
5404+
// extreme cases. We probably ought to smarter in general about
5405+
// only resolving when we need help and only resolving obligations
5406+
// will actually help.
5407+
if ty::type_is_ty_var(ty) {
5408+
vtable::select_fcx_obligations_where_possible(fcx);
5409+
ty = fcx.infcx().shallow_resolve(ty);
54075410
}
5411+
5412+
// If not, error.
5413+
if ty::type_is_ty_var(ty) {
5414+
fcx.type_error_message(sp, |_actual| {
5415+
"the type of this value must be known in this \
5416+
context".to_string()
5417+
}, ty, None);
5418+
demand::suptype(fcx, sp, ty::mk_err(), ty);
5419+
ty = ty::mk_err();
5420+
}
5421+
5422+
ty
54085423
}
54095424

54105425
// Returns the one-level-deep structure of the given type.

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,24 @@ pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) {
339339
}
340340
}
341341

342+
pub fn select_new_fcx_obligations(fcx: &FnCtxt) {
343+
/*!
344+
* Try to select any fcx obligation that we haven't tried yet,
345+
* in an effort to improve inference. You could just call
346+
* `select_fcx_obligations_where_possible` except that it leads
347+
* to repeated work.
348+
*/
349+
350+
match
351+
fcx.inh.fulfillment_cx
352+
.borrow_mut()
353+
.select_new_obligations(fcx.infcx(), &fcx.inh.param_env, fcx)
354+
{
355+
Ok(()) => { }
356+
Err(errors) => { report_fulfillment_errors(fcx, &errors); }
357+
}
358+
}
359+
342360
fn note_obligation_cause(fcx: &FnCtxt,
343361
obligation: &Obligation) {
344362
let tcx = fcx.tcx();

0 commit comments

Comments
 (0)