Skip to content

Commit 66131d2

Browse files
committed
---
yaml --- r: 227623 b: refs/heads/try c: 9cc0b22 h: refs/heads/master i: 227621: 9e6f382 227619: 964df45 227615: e46848f v: v3
1 parent b2623f2 commit 66131d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+611
-269
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: aca2057ed5fb7af3f8905b2bc01f72fa001c35c8
33
refs/heads/snap-stage3: 1af31d4974e33027a68126fa5a5a3c2c6491824f
4-
refs/heads/try: ec333380e03eb1fb94c4938db888d5bed40b8fd6
4+
refs/heads/try: 9cc0b2247509d61d6a246a5c5ad67f84b9a2d8b6
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
66
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
77
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try/src/doc/reference.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -944,9 +944,20 @@ fn foo<T>(x: T) where T: Debug {
944944
```
945945

946946
When a generic function is referenced, its type is instantiated based on the
947-
context of the reference. For example, calling the `iter` function defined
948-
above on `[1, 2]` will instantiate type parameter `T` with `i32`, and require
949-
the closure parameter to have type `Fn(i32)`.
947+
context of the reference. For example, calling the `foo` function here:
948+
949+
```
950+
use std::fmt::Debug;
951+
952+
fn foo<T>(x: &[T]) where T: Debug {
953+
// details elided
954+
# ()
955+
}
956+
957+
foo(&[1, 2]);
958+
```
959+
960+
will instantiate type parameter `T` with `i32`.
950961

951962
The type parameters can also be explicitly supplied in a trailing
952963
[path](#paths) component after the function name. This might be necessary if
@@ -2768,22 +2779,24 @@ meaning of the operators on standard types is given here.
27682779
Like the [arithmetic operators](#arithmetic-operators), bitwise operators are
27692780
syntactic sugar for calls to methods of built-in traits. This means that
27702781
bitwise operators can be overridden for user-defined types. The default
2771-
meaning of the operators on standard types is given here.
2782+
meaning of the operators on standard types is given here. Bitwise `&`, `|` and
2783+
`^` applied to boolean arguments are equivalent to logical `&&`, `||` and `!=`
2784+
evaluated in non-lazy fashion.
27722785

27732786
* `&`
2774-
: And.
2787+
: Bitwise AND.
27752788
Calls the `bitand` method of the `std::ops::BitAnd` trait.
27762789
* `|`
2777-
: Inclusive or.
2790+
: Bitwise inclusive OR.
27782791
Calls the `bitor` method of the `std::ops::BitOr` trait.
27792792
* `^`
2780-
: Exclusive or.
2793+
: Bitwise exclusive OR.
27812794
Calls the `bitxor` method of the `std::ops::BitXor` trait.
27822795
* `<<`
27832796
: Left shift.
27842797
Calls the `shl` method of the `std::ops::Shl` trait.
27852798
* `>>`
2786-
: Right shift.
2799+
: Right shift (arithmetic).
27872800
Calls the `shr` method of the `std::ops::Shr` trait.
27882801

27892802
#### Lazy boolean operators

branches/try/src/doc/trpl/traits.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ fn normal<T: ConvertTo<i64>>(x: &T) -> i64 {
332332
fn inverse<T>() -> T
333333
// this is using ConvertTo as if it were "ConvertFrom<i32>"
334334
where i32: ConvertTo<T> {
335-
1i32.convert()
335+
42.convert()
336336
}
337337
```
338338

branches/try/src/librustc/middle/check_const.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
285285
fn check_static_type(&self, e: &ast::Expr) {
286286
let ty = ty::node_id_to_type(self.tcx, e.id);
287287
let infcx = infer::new_infer_ctxt(self.tcx);
288-
let mut fulfill_cx = traits::FulfillmentContext::new();
288+
let mut fulfill_cx = traits::FulfillmentContext::new(false);
289289
let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
290290
fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
291291
let env = ty::empty_parameter_environment(self.tcx);

branches/try/src/librustc/middle/mem_categorization.rs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ pub use self::InteriorKind::*;
6565
pub use self::FieldName::*;
6666
pub use self::ElementKind::*;
6767
pub use self::MutabilityCategory::*;
68-
pub use self::InteriorSafety::*;
6968
pub use self::AliasableReason::*;
7069
pub use self::Note::*;
7170
pub use self::deref_kind::*;
@@ -1385,12 +1384,6 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
13851384
}
13861385
}
13871386

1388-
#[derive(Copy, Clone, Debug)]
1389-
pub enum InteriorSafety {
1390-
InteriorUnsafe,
1391-
InteriorSafe
1392-
}
1393-
13941387
#[derive(Clone, Debug)]
13951388
pub enum Aliasability {
13961389
FreelyAliasable(AliasableReason),
@@ -1404,8 +1397,8 @@ pub enum AliasableReason {
14041397
AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env
14051398
AliasableOther,
14061399
UnaliasableImmutable, // Created as needed upon seeing ImmutableUnique
1407-
AliasableStatic(InteriorSafety),
1408-
AliasableStaticMut(InteriorSafety),
1400+
AliasableStatic,
1401+
AliasableStaticMut,
14091402
}
14101403

14111404
impl<'tcx> cmt_<'tcx> {
@@ -1469,16 +1462,10 @@ impl<'tcx> cmt_<'tcx> {
14691462
}
14701463

14711464
cat_static_item(..) => {
1472-
let int_safe = if ty::type_interior_is_unsafe(ctxt, self.ty) {
1473-
InteriorUnsafe
1474-
} else {
1475-
InteriorSafe
1476-
};
1477-
14781465
if self.mutbl.is_mutable() {
1479-
FreelyAliasable(AliasableStaticMut(int_safe))
1466+
FreelyAliasable(AliasableStaticMut)
14801467
} else {
1481-
FreelyAliasable(AliasableStatic(int_safe))
1468+
FreelyAliasable(AliasableStatic)
14821469
}
14831470
}
14841471

branches/try/src/librustc/middle/traits/fulfill.rs

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ use super::select::SelectionContext;
2828
use super::Unimplemented;
2929
use super::util::predicate_for_builtin_bound;
3030

31+
pub struct FulfilledPredicates<'tcx> {
32+
set: HashSet<ty::Predicate<'tcx>>
33+
}
34+
3135
/// The fulfillment context is used to drive trait resolution. It
3236
/// consists of a list of obligations that must be (eventually)
3337
/// satisfied. The job is to track which are satisfied, which yielded
@@ -44,7 +48,7 @@ pub struct FulfillmentContext<'tcx> {
4448
// than the `SelectionCache`: it avoids duplicate errors and
4549
// permits recursive obligations, which are often generated from
4650
// traits like `Send` et al.
47-
duplicate_set: HashSet<ty::Predicate<'tcx>>,
51+
duplicate_set: FulfilledPredicates<'tcx>,
4852

4953
// A list of all obligations that have been registered with this
5054
// fulfillment context.
@@ -80,6 +84,8 @@ pub struct FulfillmentContext<'tcx> {
8084
// obligations (otherwise, it's easy to fail to walk to a
8185
// particular node-id).
8286
region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
87+
88+
errors_will_be_reported: bool,
8389
}
8490

8591
#[derive(Clone)]
@@ -90,12 +96,30 @@ pub struct RegionObligation<'tcx> {
9096
}
9197

9298
impl<'tcx> FulfillmentContext<'tcx> {
93-
pub fn new() -> FulfillmentContext<'tcx> {
99+
/// Creates a new fulfillment context.
100+
///
101+
/// `errors_will_be_reported` indicates whether ALL errors that
102+
/// are generated by this fulfillment context will be reported to
103+
/// the end user. This is used to inform caching, because it
104+
/// allows us to conclude that traits that resolve successfully
105+
/// will in fact always resolve successfully (in particular, it
106+
/// guarantees that if some dependent obligation encounters a
107+
/// problem, compilation will be aborted). If you're not sure of
108+
/// the right value here, pass `false`, as that is the more
109+
/// conservative option.
110+
///
111+
/// FIXME -- a better option would be to hold back on modifying
112+
/// the global cache until we know that all dependent obligations
113+
/// are also satisfied. In that case, we could actually remove
114+
/// this boolean flag, and we'd also avoid the problem of squelching
115+
/// duplicate errors that occur across fns.
116+
pub fn new(errors_will_be_reported: bool) -> FulfillmentContext<'tcx> {
94117
FulfillmentContext {
95-
duplicate_set: HashSet::new(),
118+
duplicate_set: FulfilledPredicates::new(),
96119
predicates: Vec::new(),
97120
attempted_mark: 0,
98121
region_obligations: NodeMap(),
122+
errors_will_be_reported: errors_will_be_reported,
99123
}
100124
}
101125

@@ -165,7 +189,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
165189

166190
assert!(!obligation.has_escaping_regions());
167191

168-
if !self.duplicate_set.insert(obligation.predicate.clone()) {
192+
if self.is_duplicate_or_add(infcx.tcx, &obligation.predicate) {
169193
debug!("register_predicate({}) -- already seen, skip", obligation.repr(infcx.tcx));
170194
return;
171195
}
@@ -231,6 +255,28 @@ impl<'tcx> FulfillmentContext<'tcx> {
231255
&self.predicates
232256
}
233257

258+
fn is_duplicate_or_add(&mut self, tcx: &ty::ctxt<'tcx>,
259+
predicate: &ty::Predicate<'tcx>)
260+
-> bool {
261+
// This is a kind of dirty hack to allow us to avoid "rederiving"
262+
// things that we have already proven in other methods.
263+
//
264+
// The idea is that any predicate that doesn't involve type
265+
// parameters and which only involves the 'static region (and
266+
// no other regions) is universally solvable, since impls are global.
267+
//
268+
// This is particularly important since even if we have a
269+
// cache hit in the selection context, we still wind up
270+
// evaluating the 'nested obligations'. This cache lets us
271+
// skip those.
272+
273+
if self.errors_will_be_reported && predicate.is_global() {
274+
tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(predicate)
275+
} else {
276+
self.duplicate_set.is_duplicate_or_add(predicate)
277+
}
278+
}
279+
234280
/// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
235281
/// only attempts to select obligations that haven't been seen before.
236282
fn select<'a>(&mut self,
@@ -442,3 +488,21 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
442488
.push(region_obligation);
443489

444490
}
491+
492+
impl<'tcx> FulfilledPredicates<'tcx> {
493+
pub fn new() -> FulfilledPredicates<'tcx> {
494+
FulfilledPredicates {
495+
set: HashSet::new()
496+
}
497+
}
498+
499+
pub fn is_duplicate(&self, p: &ty::Predicate<'tcx>) -> bool {
500+
self.set.contains(p)
501+
}
502+
503+
fn is_duplicate_or_add(&mut self, p: &ty::Predicate<'tcx>) -> bool {
504+
!self.set.insert(p.clone())
505+
}
506+
}
507+
508+

branches/try/src/librustc/middle/traits/mod.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub use self::error_reporting::suggest_new_overflow_limit;
3232
pub use self::coherence::orphan_check;
3333
pub use self::coherence::overlapping_impls;
3434
pub use self::coherence::OrphanCheckErr;
35-
pub use self::fulfill::{FulfillmentContext, RegionObligation};
35+
pub use self::fulfill::{FulfillmentContext, FulfilledPredicates, RegionObligation};
3636
pub use self::project::MismatchedProjectionTypes;
3737
pub use self::project::normalize;
3838
pub use self::project::Normalized;
@@ -315,7 +315,7 @@ pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
315315
ty.repr(infcx.tcx),
316316
bound);
317317

318-
let mut fulfill_cx = FulfillmentContext::new();
318+
let mut fulfill_cx = FulfillmentContext::new(false);
319319

320320
// We can use a dummy node-id here because we won't pay any mind
321321
// to region obligations that arise (there shouldn't really be any
@@ -414,9 +414,27 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
414414
debug!("normalize_param_env_or_error(unnormalized_env={})",
415415
unnormalized_env.repr(tcx));
416416

417+
let predicates: Vec<_> =
418+
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.clone())
419+
.filter(|p| !p.is_global()) // (*)
420+
.collect();
421+
422+
// (*) Any predicate like `i32: Trait<u32>` or whatever doesn't
423+
// need to be in the *environment* to be proven, so screen those
424+
// out. This is important for the soundness of inter-fn
425+
// caching. Note though that we should probably check that these
426+
// predicates hold at the point where the environment is
427+
// constructed, but I am not currently doing so out of laziness.
428+
// -nmatsakis
429+
430+
debug!("normalize_param_env_or_error: elaborated-predicates={}",
431+
predicates.repr(tcx));
432+
433+
let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
434+
417435
let infcx = infer::new_infer_ctxt(tcx);
418-
let predicates = match fully_normalize(&infcx, &unnormalized_env, cause,
419-
&unnormalized_env.caller_bounds) {
436+
let predicates = match fully_normalize(&infcx, &elaborated_env, cause,
437+
&elaborated_env.caller_bounds) {
420438
Ok(predicates) => predicates,
421439
Err(errors) => {
422440
report_fulfillment_errors(&infcx, &errors);
@@ -438,14 +456,11 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
438456
// all things considered.
439457
let err_msg = fixup_err_to_string(fixup_err);
440458
tcx.sess.span_err(span, &err_msg);
441-
return unnormalized_env; // an unnormalized env is better than nothing
459+
return elaborated_env; // an unnormalized env is better than nothing
442460
}
443461
};
444462

445-
debug!("normalize_param_env_or_error: predicates={}",
446-
predicates.repr(tcx));
447-
448-
unnormalized_env.with_caller_bounds(predicates)
463+
elaborated_env.with_caller_bounds(predicates)
449464
}
450465

451466
pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
@@ -460,7 +475,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
460475
debug!("normalize_param_env(value={})", value.repr(tcx));
461476

462477
let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
463-
let mut fulfill_cx = FulfillmentContext::new();
478+
let mut fulfill_cx = FulfillmentContext::new(false);
464479
let Normalized { value: normalized_value, obligations } =
465480
project::normalize(selcx, cause, value);
466481
debug!("normalize_param_env: normalized_value={} obligations={}",

branches/try/src/librustc/middle/traits/project.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
535535
obligation_trait_ref: &ty::TraitRef<'tcx>,
536536
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
537537
{
538-
let env_predicates = selcx.param_env().caller_bounds.clone();
538+
let env_predicates = selcx.param_env().caller_bounds.iter().cloned();
539539
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
540540
candidate_set, env_predicates);
541541
}
@@ -571,22 +571,25 @@ fn assemble_candidates_from_trait_def<'cx,'tcx>(
571571
// If so, extract what we know from the trait and try to come up with a good answer.
572572
let trait_predicates = ty::lookup_predicates(selcx.tcx(), trait_ref.def_id);
573573
let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs);
574+
let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec());
574575
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
575-
candidate_set, bounds.predicates.into_vec());
576+
candidate_set, bounds)
576577
}
577578

578-
fn assemble_candidates_from_predicates<'cx,'tcx>(
579+
fn assemble_candidates_from_predicates<'cx,'tcx,I>(
579580
selcx: &mut SelectionContext<'cx,'tcx>,
580581
obligation: &ProjectionTyObligation<'tcx>,
581582
obligation_trait_ref: &ty::TraitRef<'tcx>,
582583
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
583-
env_predicates: Vec<ty::Predicate<'tcx>>)
584+
env_predicates: I)
585+
where I: Iterator<Item=ty::Predicate<'tcx>>
584586
{
585-
debug!("assemble_candidates_from_predicates(obligation={}, env_predicates={})",
586-
obligation.repr(selcx.tcx()),
587-
env_predicates.repr(selcx.tcx()));
587+
debug!("assemble_candidates_from_predicates(obligation={})",
588+
obligation.repr(selcx.tcx()));
588589
let infcx = selcx.infcx();
589-
for predicate in elaborate_predicates(selcx.tcx(), env_predicates) {
590+
for predicate in env_predicates {
591+
debug!("assemble_candidates_from_predicates: predicate={}",
592+
predicate.repr(selcx.tcx()));
590593
match predicate {
591594
ty::Predicate::Projection(ref data) => {
592595
let same_name = data.item_name() == obligation.predicate.item_name;
@@ -641,6 +644,7 @@ fn assemble_candidates_from_object_type<'cx,'tcx>(
641644
let env_predicates = projection_bounds.iter()
642645
.map(|p| p.as_predicate())
643646
.collect();
647+
let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
644648
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
645649
candidate_set, env_predicates)
646650
}

0 commit comments

Comments
 (0)