Skip to content

Commit ba98683

Browse files
committed
---
yaml --- r: 155555 b: refs/heads/try2 c: 2f15dcd h: refs/heads/master i: 155553: 3bb7dd9 155551: a71f871 v: v3
1 parent 6dd56bf commit ba98683

38 files changed

+470
-52
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 416144b8279fbffceacea6d0fd90e0fd1f8ce53d
8+
refs/heads/try2: 2f15dcd4d3865f9cc466637027eb02d5607b2bb7
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/doc/reference.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,8 @@ The currently implemented features of the reference compiler are:
24412441
* `default_type_params` - Allows use of default type parameters. The future of
24422442
this feature is uncertain.
24432443

2444+
* `if_let` - Allows use of the `if let` syntax.
2445+
24442446
* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
24452447
are inherently unstable and no promise about them is made.
24462448

@@ -3229,7 +3231,7 @@ for i in range(0u, 256) {
32293231
if_expr : "if" no_struct_literal_expr '{' block '}'
32303232
else_tail ? ;
32313233
3232-
else_tail : "else" [ if_expr
3234+
else_tail : "else" [ if_expr | if_let_expr
32333235
| '{' block '}' ] ;
32343236
```
32353237

@@ -3434,6 +3436,19 @@ let message = match maybe_digit {
34343436
};
34353437
```
34363438

3439+
### If let expressions
3440+
3441+
```{.ebnf .gram}
3442+
if_let_expr : "if" "let" pat '=' expr '{' block '}'
3443+
else_tail ? ;
3444+
else_tail : "else" [ if_expr | if_let_expr | '{' block '}' ] ;
3445+
```
3446+
3447+
An `if let` expression is semantically identical to an `if` expression but in place
3448+
of a condition expression it expects a refutable let statement. If the value of the
3449+
expression on the right hand side of the let statement matches the pattern, the corresponding
3450+
block will execute, otherwise flow proceeds to the first `else` block that follows.
3451+
34373452
### Return expressions
34383453

34393454
```{.ebnf .gram}

branches/try2/src/etc/emacs/rust-mode-tests.el

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ Convert the line-column information from that list into a buffer position value.
623623
(move-to-column column)
624624
(point))))
625625

626-
;;; TODO: Maybe add an ERT explainer function (something that shows the
626+
;;; FIXME: Maybe add an ERT explainer function (something that shows the
627627
;;; surrounding code of the final point, not just the position).
628628
(defun rust-test-motion (source-code init-pos final-pos manip-func &optional &rest args)
629629
"Test that MANIP-FUNC moves point from INIT-POS to FINAL-POS.

branches/try2/src/etc/kate/rust.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE language SYSTEM "language.dtd"
33
[
4-
<!-- TODO: Kate's regex engine has very limited support for
4+
<!-- FIXME: Kate's regex engine has very limited support for
55
predefined char classes, so making rustIdent consistent with actual
66
Rust identifiers will be a bit difficult -->
77
<!ENTITY rustIdent "[a-zA-Z_][a-zA-Z_0-9]*">

branches/try2/src/etc/vim/syntax/rust.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ syn keyword rustTodo contained TODO FIXME XXX NB NOTE
216216

217217
" Folding rules {{{2
218218
" Trivial folding rules to begin with.
219-
" TODO: use the AST to make really good folding
219+
" FIXME: use the AST to make really good folding
220220
syn region rustFoldBraces start="{" end="}" transparent fold
221221

222222
" Default highlighting {{{1

branches/try2/src/librustc/diagnostics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,6 @@ register_diagnostics!(
151151
E0157,
152152
E0158,
153153
E0159,
154-
E0161
154+
E0161,
155+
E0162
155156
)

branches/try2/src/librustc/lint/builtin.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ impl LintPass for UnusedAttribute {
593593
"static_assert",
594594
"thread_local",
595595
"no_debug",
596+
"unsafe_no_drop_flag",
596597

597598
// used in resolve
598599
"prelude_import",
@@ -1091,7 +1092,10 @@ impl LintPass for UnnecessaryParens {
10911092
let (value, msg, struct_lit_needs_parens) = match e.node {
10921093
ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
10931094
ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
1094-
ast::ExprMatch(ref head, _) => (head, "`match` head expression", true),
1095+
ast::ExprMatch(ref head, _, source) => match source {
1096+
ast::MatchNormal => (head, "`match` head expression", true),
1097+
ast::MatchIfLetDesugar => (head, "`if let` head expression", true)
1098+
},
10951099
ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
10961100
ast::ExprAssign(_, ref value) => (value, "assigned value", false),
10971101
ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),
@@ -1241,7 +1245,7 @@ impl LintPass for UnusedMut {
12411245

12421246
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
12431247
match e.node {
1244-
ast::ExprMatch(_, ref arms) => {
1248+
ast::ExprMatch(_, ref arms, _) => {
12451249
for a in arms.iter() {
12461250
self.check_unused_mut_pat(cx, a.pats.as_slice())
12471251
}

branches/try2/src/librustc/metadata/common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ pub static tag_reachable_extern_fn_id: uint = 0x91;
214214

215215
pub static tag_items_data_item_stability: uint = 0x92;
216216

217+
pub static tag_items_data_item_repr: uint = 0x93;
218+
217219
#[deriving(Clone, Show)]
218220
pub struct LinkMeta {
219221
pub crate_name: String,

branches/try2/src/librustc/metadata/csearch.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,12 @@ pub fn get_stability(cstore: &cstore::CStore,
350350
decoder::get_stability(&*cdata, def.node)
351351
}
352352

353+
pub fn get_repr_attrs(cstore: &cstore::CStore, def: ast::DefId)
354+
-> Vec<attr::ReprAttr> {
355+
let cdata = cstore.get_crate_data(def.krate);
356+
decoder::get_repr_attrs(&*cdata, def.node)
357+
}
358+
353359
pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool {
354360
let cdata = cstore.get_crate_data(def.krate);
355361
decoder::is_associated_type(&*cdata, def.node)

branches/try2/src/librustc/metadata/decoder.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,17 @@ pub fn get_stability(cdata: Cmd, id: ast::NodeId) -> Option<attr::Stability> {
384384
})
385385
}
386386

387+
pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
388+
let item = lookup_item(id, cdata.data());
389+
match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {
390+
let mut decoder = reader::Decoder::new(doc);
391+
Decodable::decode(&mut decoder).unwrap()
392+
}) {
393+
Some(attrs) => attrs,
394+
None => Vec::new(),
395+
}
396+
}
397+
387398
pub fn get_impl_trait(cdata: Cmd,
388399
id: ast::NodeId,
389400
tcx: &ty::ctxt) -> Option<Rc<ty::TraitRef>>

branches/try2/src/librustc/metadata/encoder.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
332332
encode_parent_item(rbml_w, local_def(id));
333333
encode_visibility(rbml_w, variant.node.vis);
334334
encode_attributes(rbml_w, variant.node.attrs.as_slice());
335+
encode_repr_attrs(rbml_w, ecx, variant.node.attrs.as_slice());
335336

336337
let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
337338
encode_stability(rbml_w, stab);
@@ -948,6 +949,19 @@ fn encode_method_argument_names(rbml_w: &mut Encoder,
948949
rbml_w.end_tag();
949950
}
950951

952+
fn encode_repr_attrs(rbml_w: &mut Encoder,
953+
ecx: &EncodeContext,
954+
attrs: &[Attribute]) {
955+
let mut repr_attrs = Vec::new();
956+
for attr in attrs.iter() {
957+
repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
958+
attr).into_iter());
959+
}
960+
rbml_w.start_tag(tag_items_data_item_repr);
961+
repr_attrs.encode(rbml_w);
962+
rbml_w.end_tag();
963+
}
964+
951965
fn encode_inlined_item(ecx: &EncodeContext,
952966
rbml_w: &mut Encoder,
953967
ii: InlinedItemRef) {
@@ -1137,6 +1151,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
11371151
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
11381152
encode_name(rbml_w, item.ident.name);
11391153
encode_attributes(rbml_w, item.attrs.as_slice());
1154+
encode_repr_attrs(rbml_w, ecx, item.attrs.as_slice());
11401155
for v in (*enum_definition).variants.iter() {
11411156
encode_variant_id(rbml_w, local_def(v.node.id));
11421157
}
@@ -1183,6 +1198,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
11831198
encode_path(rbml_w, path.clone());
11841199
encode_stability(rbml_w, stab);
11851200
encode_visibility(rbml_w, vis);
1201+
encode_repr_attrs(rbml_w, ecx, item.attrs.as_slice());
11861202

11871203
/* Encode def_ids for each field and method
11881204
for methods, write all the stuff get_trait_method

branches/try2/src/librustc/middle/cfg/construct.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
222222
self.add_node(expr.id, [then_exit, else_exit]) // 4, 5
223223
}
224224

225+
ast::ExprIfLet(..) => {
226+
self.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
227+
}
228+
225229
ast::ExprWhile(ref cond, ref body, _) => {
226230
//
227231
// [pred]
@@ -322,7 +326,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
322326
expr_exit
323327
}
324328

325-
ast::ExprMatch(ref discr, ref arms) => {
329+
ast::ExprMatch(ref discr, ref arms, _) => {
326330
//
327331
// [pred]
328332
// |

branches/try2/src/librustc/middle/check_match.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ pub fn check_crate(tcx: &ty::ctxt) {
147147
fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
148148
visit::walk_expr(cx, ex);
149149
match ex.node {
150-
ExprMatch(ref scrut, ref arms) => {
150+
ExprMatch(ref scrut, ref arms, source) => {
151151
// First, check legality of move bindings.
152152
for arm in arms.iter() {
153153
check_legality_of_move_bindings(cx,
@@ -184,7 +184,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
184184
}
185185

186186
// Fourth, check for unreachable arms.
187-
check_arms(cx, inlined_arms.as_slice());
187+
check_arms(cx, inlined_arms.as_slice(), source);
188188

189189
// Finally, check if the whole match expression is exhaustive.
190190
// Check for empty enum, because is_useful only works on inhabited types.
@@ -252,13 +252,31 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pats: &[P<Pat>]) {
252252
}
253253

254254
// Check for unreachable patterns
255-
fn check_arms(cx: &MatchCheckCtxt, arms: &[(Vec<P<Pat>>, Option<&Expr>)]) {
255+
fn check_arms(cx: &MatchCheckCtxt, arms: &[(Vec<P<Pat>>, Option<&Expr>)], source: MatchSource) {
256256
let mut seen = Matrix(vec![]);
257+
let mut printed_if_let_err = false;
257258
for &(ref pats, guard) in arms.iter() {
258259
for pat in pats.iter() {
259260
let v = vec![&**pat];
261+
260262
match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
261-
NotUseful => span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern"),
263+
NotUseful => {
264+
if source == MatchIfLetDesugar {
265+
if printed_if_let_err {
266+
// we already printed an irrefutable if-let pattern error.
267+
// We don't want two, that's just confusing.
268+
} else {
269+
// find the first arm pattern so we can use its span
270+
let &(ref first_arm_pats, _) = &arms[0];
271+
let first_pat = first_arm_pats.get(0);
272+
let span = first_pat.span;
273+
span_err!(cx.tcx.sess, span, E0162, "irrefutable if-let pattern");
274+
printed_if_let_err = true;
275+
}
276+
} else {
277+
span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern");
278+
}
279+
}
262280
Useful => (),
263281
UsefulWithWitness(_) => unreachable!()
264282
}

branches/try2/src/librustc/middle/expr_use_visitor.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
374374
}
375375
}
376376

377-
ast::ExprMatch(ref discr, ref arms) => {
377+
ast::ExprIfLet(..) => {
378+
self.tcx().sess.span_bug(expr.span, "non-desugared ExprIfLet");
379+
}
380+
381+
ast::ExprMatch(ref discr, ref arms, _) => {
378382
let discr_cmt = return_if_err!(self.mc.cat_expr(&**discr));
379383
self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow, MatchDiscriminant);
380384

branches/try2/src/librustc/middle/liveness.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,9 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
481481
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
482482
visit::walk_expr(ir, expr);
483483
}
484+
ExprIfLet(..) => {
485+
ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
486+
}
484487
ExprForLoop(ref pat, _, _, _) => {
485488
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
486489
debug!("adding local variable {} from for loop with bm {:?}",
@@ -1011,6 +1014,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
10111014
self.propagate_through_expr(&**cond, ln)
10121015
}
10131016

1017+
ExprIfLet(..) => {
1018+
self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
1019+
}
1020+
10141021
ExprWhile(ref cond, ref blk, _) => {
10151022
self.propagate_through_loop(expr, WhileLoop(&**cond), &**blk, succ)
10161023
}
@@ -1026,7 +1033,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
10261033
self.propagate_through_loop(expr, LoopLoop, &**blk, succ)
10271034
}
10281035

1029-
ExprMatch(ref e, ref arms) => {
1036+
ExprMatch(ref e, ref arms, _) => {
10301037
//
10311038
// (e)
10321039
// |
@@ -1470,6 +1477,9 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
14701477
ExprPath(..) | ExprBox(..) => {
14711478
visit::walk_expr(this, expr);
14721479
}
1480+
ExprIfLet(..) => {
1481+
this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
1482+
}
14731483
}
14741484
}
14751485

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
505505
ast::ExprForLoop(..) => {
506506
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
507507
}
508+
509+
ast::ExprIfLet(..) => {
510+
self.tcx().sess.span_bug(expr.span, "non-desugared ExprIfLet");
511+
}
508512
}
509513
}
510514

branches/try2/src/librustc/middle/trans/debuginfo.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3576,6 +3576,11 @@ fn populate_scope_map(cx: &CrateContext,
35763576
}
35773577
}
35783578

3579+
ast::ExprIfLet(..) => {
3580+
cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
3581+
Found unexpanded if-let.");
3582+
}
3583+
35793584
ast::ExprWhile(ref cond_exp, ref loop_body, _) => {
35803585
walk_expr(cx, &**cond_exp, scope_stack, scope_map);
35813586

@@ -3654,7 +3659,7 @@ fn populate_scope_map(cx: &CrateContext,
36543659
}
36553660
}
36563661

3657-
ast::ExprMatch(ref discriminant_exp, ref arms) => {
3662+
ast::ExprMatch(ref discriminant_exp, ref arms, _) => {
36583663
walk_expr(cx, &**discriminant_exp, scope_stack, scope_map);
36593664

36603665
// For each arm we have to first walk the pattern as these might

branches/try2/src/librustc/middle/trans/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
10131013
ast::ExprIf(ref cond, ref thn, ref els) => {
10141014
controlflow::trans_if(bcx, expr.id, &**cond, &**thn, els.as_ref().map(|e| &**e), dest)
10151015
}
1016-
ast::ExprMatch(ref discr, ref arms) => {
1016+
ast::ExprMatch(ref discr, ref arms, _) => {
10171017
_match::trans_match(bcx, expr, &**discr, arms.as_slice(), dest)
10181018
}
10191019
ast::ExprBlock(ref blk) => {

0 commit comments

Comments
 (0)