Skip to content

Commit 5c069b0

Browse files
committed
---
yaml --- r: 212970 b: refs/heads/master c: 81024d9 h: refs/heads/master v: v3
1 parent ec108dc commit 5c069b0

Some content is hidden

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

41 files changed

+580
-211
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 8e969dee689ecdb588434080a614a11fca0ecde7
2+
refs/heads/master: 81024d9931ef63316995294fc41accb641646c4f
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: ba0e1cd8147d452c356aacb29fb87568ca26f111
55
refs/heads/try: 1864973ae17213c5a58c4dd3f9af6d1b6c7d2e05

trunk/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

trunk/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

trunk/src/libcore/char.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,8 @@ pub const MAX: char = '\u{10ffff}';
7474
/// ```
7575
/// use std::char;
7676
///
77-
/// let c = char::from_u32(10084); // produces `Some(❤)`
78-
/// assert_eq!(c, Some('❤'));
79-
/// ```
80-
///
81-
/// An invalid character:
82-
///
83-
/// ```
84-
/// use std::char;
85-
///
86-
/// let none = char::from_u32(1114112);
87-
/// assert_eq!(none, None);
77+
/// assert_eq!(char::from_u32(0x2764), Some('❤'));
78+
/// assert_eq!(char::from_u32(0x110000), None); // invalid character
8879
/// ```
8980
#[inline]
9081
#[stable(feature = "rust1", since = "1.0.0")]

trunk/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);

trunk/src/librustc/middle/dead.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
4848
struct_has_extern_repr: bool,
4949
ignore_non_const_paths: bool,
5050
inherited_pub_visibility: bool,
51+
ignore_variant_stack: Vec<ast::NodeId>,
5152
}
5253

5354
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
@@ -60,6 +61,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
6061
struct_has_extern_repr: false,
6162
ignore_non_const_paths: false,
6263
inherited_pub_visibility: false,
64+
ignore_variant_stack: vec![],
6365
}
6466
}
6567

@@ -80,7 +82,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
8082
def::DefPrimTy(_) => (),
8183
def::DefVariant(enum_id, variant_id, _) => {
8284
self.check_def_id(enum_id);
83-
self.check_def_id(variant_id);
85+
if !self.ignore_variant_stack.contains(&variant_id.node) {
86+
self.check_def_id(variant_id);
87+
}
8488
}
8589
_ => {
8690
self.check_def_id(def.def_id());
@@ -272,6 +276,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
272276
visit::walk_expr(self, expr);
273277
}
274278

279+
fn visit_arm(&mut self, arm: &ast::Arm) {
280+
if arm.pats.len() == 1 {
281+
let pat = &*arm.pats[0];
282+
let variants = pat_util::necessary_variants(&self.tcx.def_map, pat);
283+
284+
// Inside the body, ignore constructions of variants
285+
// necessary for the pattern to match. Those construction sites
286+
// can't be reached unless the variant is constructed elsewhere.
287+
let len = self.ignore_variant_stack.len();
288+
self.ignore_variant_stack.push_all(&*variants);
289+
visit::walk_arm(self, arm);
290+
self.ignore_variant_stack.truncate(len);
291+
} else {
292+
visit::walk_arm(self, arm);
293+
}
294+
}
295+
275296
fn visit_pat(&mut self, pat: &ast::Pat) {
276297
let def_map = &self.tcx.def_map;
277298
match pat.node {
@@ -393,6 +414,11 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
393414
worklist.push(*id);
394415
}
395416
for id in reachable_symbols {
417+
// Reachable variants can be dead, because we warn about
418+
// variants never constructed, not variants never used.
419+
if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) {
420+
continue;
421+
}
396422
worklist.push(*id);
397423
}
398424

trunk/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

trunk/src/librustc/middle/pat_util.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,27 @@ pub fn def_to_path(tcx: &ty::ctxt, id: ast::DefId) -> ast::Path {
201201
span: DUMMY_SP,
202202
})
203203
}
204+
205+
/// Return variants that are necessary to exist for the pattern to match.
206+
pub fn necessary_variants(dm: &DefMap, pat: &ast::Pat) -> Vec<ast::NodeId> {
207+
let mut variants = vec![];
208+
walk_pat(pat, |p| {
209+
match p.node {
210+
ast::PatEnum(_, _) |
211+
ast::PatIdent(_, _, None) |
212+
ast::PatStruct(..) => {
213+
match dm.borrow().get(&p.id) {
214+
Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
215+
variants.push(id.node);
216+
}
217+
_ => ()
218+
}
219+
}
220+
_ => ()
221+
}
222+
true
223+
});
224+
variants.sort();
225+
variants.dedup();
226+
variants
227+
}

trunk/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+

0 commit comments

Comments
 (0)