]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #51580 - cramertj:async-await, r=eddyb
authorbors <bors@rust-lang.org>
Sat, 23 Jun 2018 09:02:45 +0000 (09:02 +0000)
committerbors <bors@rust-lang.org>
Sat, 23 Jun 2018 09:02:45 +0000 (09:02 +0000)
async/await

This PR implements `async`/`await` syntax for `async fn` in Rust 2015 and `async` closures and `async` blocks in Rust 2018 (tracking issue: https://github.com/rust-lang/rust/issues/50547). Limitations: non-`move` async closures with arguments are currently not supported, nor are `async fn` with multiple different input lifetimes. These limitations are not fundamental and will be removed in the future, however I'd like to go ahead and get this PR merged so we can start experimenting with this in combination with futures 0.3.

Based on https://github.com/rust-lang/rust/pull/51414.
cc @petrochenkov for parsing changes.
r? @eddyb

38 files changed:
src/bootstrap/builder.rs
src/bootstrap/test.rs
src/doc/rustdoc/src/documentation-tests.md
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc_codegen_llvm/attributes.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/used_muts.rs [new file with mode: 0644]
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/util/collect_writes.rs
src/librustc_typeck/check/method/suggest.rs
src/librustdoc/html/static/rustdoc.css
src/libstd/sys/unix/rand.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/test/compile-fail/auxiliary/lint_stability.rs
src/test/compile-fail/lint-stability.rs
src/test/ui/borrowck/issue-51415.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-51415.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-51415.stderr [new file with mode: 0644]
src/test/ui/issue-50585.rs [new file with mode: 0644]
src/test/ui/issue-50585.stderr [new file with mode: 0644]
src/test/ui/single-use-lifetime/fn-types.stderr
src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
src/test/ui/single-use-lifetime/one-use-in-fn-argument.stderr
src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr
src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr
src/test/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr
src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr
src/test/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr
src/test/ui/struct-duplicate-comma.rs [new file with mode: 0644]
src/test/ui/struct-duplicate-comma.stderr [new file with mode: 0644]
src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs [new file with mode: 0644]
src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
src/tools/build-manifest/src/main.rs

index 08bdff364f84be0315e7e10e100bc717eb46dbc5..fa2440e27d06aba4f8125f480e619420a33e04be 100644 (file)
@@ -218,6 +218,12 @@ fn run(v: &[StepDescription], builder: &Builder, paths: &[PathBuf]) {
             }
         } else {
             for path in paths {
+                // strip CurDir prefix if present
+                let path = match path.strip_prefix(".") {
+                    Ok(p) => p,
+                    Err(_) => path,
+                };
+
                 let mut attempted_run = false;
                 for (desc, should_run) in v.iter().zip(&should_runs) {
                     if let Some(suite) = should_run.is_suite_path(path) {
index d2fd798723dabbf0c6abf809eb50f56b32c11c18..90688b1c0e181e095aa73c6ff814879e1fcf8f53 100644 (file)
@@ -1074,6 +1074,12 @@ fn run(self, builder: &Builder) {
         // Get test-args by striping suite path
         let mut test_args: Vec<&str> = paths
             .iter()
+            .map(|p| {
+                match p.strip_prefix(".") {
+                    Ok(path) => path,
+                    Err(_) => p,
+                }
+            })
             .filter(|p| p.starts_with(suite_path) && p.is_file())
             .map(|p| p.strip_prefix(suite_path).unwrap().to_str().unwrap())
             .collect();
index cb233cc84cbed8fd95ddbce645dcabfe35a0cd45..7639537fc553539055e976c897388d278221fce1 100644 (file)
@@ -305,3 +305,27 @@ environment that has no network access.
 compiles, then the test will fail. However please note that code failing
 with the current Rust release may work in a future release, as new features
 are added.
+
+## Syntax reference
+
+The *exact* syntax for code blocks, including the edge cases, can be found
+in the [Fenced Code Blocks](https://spec.commonmark.org/0.28/#fenced-code-blocks)
+section of the CommonMark specification.
+
+Rustdoc also accepts *indented* code blocks as an alternative to fenced
+code blocks: instead of surrounding your code with three backticks, you
+can indent each line by four or more spaces.
+
+``````markdown
+    let foo = "foo";
+    assert_eq!(foo, "foo");
+``````
+
+These, too, are documented in the CommonMark specification, in the
+[Indented Code Blocks](https://spec.commonmark.org/0.28/#indented-code-blocks)
+section.
+
+However, it's preferable to use fenced code blocks over indented code blocks.
+Not only are fenced code blocks considered more idiomatic for Rust code,
+but there is no way to use directives such as `ignore` or `should_panic` with
+indented code blocks.
index 9fb7d31ed6f75d178128989b8ed8f643da5afc47..8ef45a966da85647992a661820e2af1c2aeb6a23 100644 (file)
@@ -313,7 +313,8 @@ pub fn consume_body(&mut self, body: &hir::Body) {
         debug!("consume_body(body={:?})", body);
 
         for arg in &body.arguments {
-            let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.hir_id));
+            let arg_ty = return_if_err!(self.mc.pat_ty_adjusted(&arg.pat));
+            debug!("consume_body: arg_ty = {:?}", arg_ty);
 
             let fn_body_scope_r =
                 self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id)));
index 959dda69e30ed81d69ab2f88b9ab4e35adb45339..597872ef45de047aade45f0ca805cbe8b5104acc 100644 (file)
@@ -517,7 +517,7 @@ pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
     ///   implicit deref patterns attached (e.g., it is really
     ///   `&Some(x)`). In that case, we return the "outermost" type
     ///   (e.g., `&Option<T>).
-    fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
+    pub fn pat_ty_adjusted(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
         // Check for implicit `&` types wrapping the pattern; note
         // that these are never attached to binding patterns, so
         // actually this is somewhat "disjoint" from the code below
@@ -1300,7 +1300,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
             };
 
             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
-                let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
+                let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
                 let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
                 let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
                 self.cat_pattern_(subcmt, &subpat, op)?;
@@ -1323,7 +1323,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
             };
 
             for fp in field_pats {
-                let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2)
+                let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2)
                 let f_index = self.tcx.field_index(fp.node.id, self.tables);
                 let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index,
                                                        fp.node.ident, field_ty));
@@ -1342,7 +1342,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
                 ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
-                let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
+                let subpat_ty = self.pat_ty_unadjusted(&subpat)?; // see (*2)
                 let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
                 let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
                 self.cat_pattern_(subcmt, &subpat, op)?;
index c2623f403567e8ee3b0a5645069fc23a6443901f..efb3eecd691f2dc47d3930af098c0b49166ff05b 100644 (file)
@@ -1395,7 +1395,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                 lifetimeuseset
             );
             match lifetimeuseset {
-                Some(LifetimeUseSet::One(_)) => {
+                Some(LifetimeUseSet::One(lifetime)) => {
                     let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
                     debug!("node id first={:?}", node_id);
                     if let Some((id, span, name)) = match self.tcx.hir.get(node_id) {
@@ -1408,12 +1408,15 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                         _ => None,
                     } {
                         debug!("id = {:?} span = {:?} name = {:?}", node_id, span, name);
-                        self.tcx.struct_span_lint_node(
+                        let mut err = self.tcx.struct_span_lint_node(
                             lint::builtin::SINGLE_USE_LIFETIMES,
                             id,
                             span,
                             &format!("lifetime parameter `{}` only used once", name),
-                        ).emit();
+                        );
+                        err.span_label(span, "this lifetime...");
+                        err.span_label(lifetime.span, "...is used only here");
+                        err.emit();
                     }
                 }
                 Some(LifetimeUseSet::Many) => {
index d6a7d5e8472ac086dab3b6dec23b6cc37664f8cd..4cdc9fdddbf80b1176de05bdd44b9a26ab91315a 100644 (file)
@@ -614,10 +614,12 @@ pub fn eval_stability(self, def_id: DefId, id: Option<NodeId>, span: Span) -> Ev
         debug!("stability: \
                 inspecting def_id={:?} span={:?} of stability={:?}", def_id, span, stability);
 
-        if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, .. }), ..})
+        if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, since }), ..})
                 = stability {
             if let Some(id) = id {
-                lint_deprecated(def_id, id, Some(reason));
+                if deprecation_in_effect(&since.as_str()) {
+                    lint_deprecated(def_id, id, Some(reason));
+                }
             }
         }
 
index a5d04c5c576b22e3c2d89e0c611ec58da7f88372..429acbbe0c2cb1cb428447c55e22845378bcfa14 100644 (file)
@@ -98,6 +98,11 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
         return;
     }
 
+    // probestack doesn't play nice either with gcov profiling.
+    if cx.sess().opts.debugging_opts.profile {
+        return;
+    }
+
     // Flag our internal `__rust_probestack` function as the stack probe symbol.
     // This is defined in the `compiler-builtins` crate for each architecture.
     llvm::AddFunctionAttrStringValue(
index 3d3275a6b171485ae18cbd47e75ef9a69f16b782..115f36c149b64907ce33fa3974f5c9088803efbf 100644 (file)
@@ -61,6 +61,7 @@
 crate mod place_ext;
 mod prefixes;
 mod path_utils;
+mod used_muts;
 
 pub(crate) mod nll;
 
@@ -281,20 +282,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
             .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
             .cloned()
             .collect();
-
-    for local in temporary_used_locals {
-        for location in mbcx.mir.find_assignments(local) {
-            for moi in &mbcx.move_data.loc_map[location] {
-                let mpi = &mbcx.move_data.moves[*moi].path;
-                let path = &mbcx.move_data.move_paths[*mpi];
-                debug!("assignment of {:?} to {:?}, adding {:?} to used mutable set",
-                       path.place, local, path.place);
-                if let Place::Local(user_local) = path.place {
-                    mbcx.used_mut.insert(user_local);
-                }
-            }
-        }
-    }
+    mbcx.gather_used_muts(temporary_used_locals);
 
     debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
 
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
new file mode 100644 (file)
index 0000000..dbe19bc
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::mir::visit::{PlaceContext, Visitor};
+use rustc::mir::{Local, Location, Place};
+
+use rustc_data_structures::fx::FxHashSet;
+
+use borrow_check::MirBorrowckCtxt;
+use util::collect_writes::is_place_assignment;
+
+impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
+    /// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable
+    /// local variables lint, to update the context's `used_mut` in a single walk.
+    crate fn gather_used_muts(&mut self, locals: FxHashSet<Local>) {
+        let mut visitor = GatherUsedMutsVisitor {
+            needles: locals,
+            mbcx: self,
+        };
+        visitor.visit_mir(visitor.mbcx.mir);
+    }
+}
+
+/// MIR visitor gathering the assignments to a set of locals, in a single walk.
+/// 'visit = the duration of the MIR walk
+struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> {
+    needles: FxHashSet<Local>,
+    mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
+}
+
+impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> {
+    fn visit_local(
+        &mut self,
+        local: &Local,
+        place_context: PlaceContext<'tcx>,
+        location: Location,
+    ) {
+        if !self.needles.contains(local) {
+            return;
+        }
+
+        if is_place_assignment(&place_context) {
+            // Propagate the Local assigned at this Location as a used mutable local variable
+            for moi in &self.mbcx.move_data.loc_map[location] {
+                let mpi = &self.mbcx.move_data.moves[*moi].path;
+                let path = &self.mbcx.move_data.move_paths[*mpi];
+                debug!(
+                    "assignment of {:?} to {:?}, adding {:?} to used mutable set",
+                    path.place, local, path.place
+                );
+                if let Place::Local(user_local) = path.place {
+                    self.mbcx.used_mut.insert(user_local);
+                }
+            }
+        }
+    }
+}
index 7dae79530c488d6a8abba1111479e831729fe9c4..2b1422773c117a2d8f67a724d35ae19d16257ed6 100644 (file)
@@ -505,7 +505,16 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                 let def = self.tables.qpath_def(qpath, pat.hir_id);
                 let adt_def = match ty.sty {
                     ty::TyAdt(adt_def, _) => adt_def,
-                    _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
+                    ty::TyError => {  // Avoid ICE (#50585)
+                        return Pattern {
+                            span: pat.span,
+                            ty,
+                            kind: Box::new(PatternKind::Wild),
+                        };
+                    }
+                    _ => span_bug!(pat.span,
+                                   "tuple struct pattern not applied to an ADT {:?}",
+                                   ty.sty),
                 };
                 let variant_def = adt_def.variant_of_def(def);
 
@@ -637,6 +646,9 @@ fn lower_variant_or_leaf(
                     let substs = match ty.sty {
                         ty::TyAdt(_, substs) |
                         ty::TyFnDef(_, substs) => substs,
+                        ty::TyError => {  // Avoid ICE (#50585)
+                            return PatternKind::Wild;
+                        }
                         _ => bug!("inappropriate type for def: {:?}", ty.sty),
                     };
                     PatternKind::Variant {
index f04f9233447c3d83761a34836fa913182de3aa0c..23f753f8569bb780170cb0118e6c61a453106f48 100644 (file)
@@ -43,25 +43,24 @@ fn visit_local(&mut self,
             return;
         }
 
-        match place_context {
-            PlaceContext::Store | PlaceContext::Call => {
-                self.locations.push(location);
-            }
-            PlaceContext::AsmOutput |
-            PlaceContext::Drop |
-            PlaceContext::Inspect |
-            PlaceContext::Borrow { .. } |
-            PlaceContext::Projection(..) |
-            PlaceContext::Copy |
-            PlaceContext::Move |
-            PlaceContext::StorageLive |
-            PlaceContext::StorageDead |
-            PlaceContext::Validate => {
-                // TO-DO
-                // self.super_local(local)
-            }
+        if is_place_assignment(&place_context) {
+            self.locations.push(location);
         }
     }
-    // TO-DO
-    // fn super_local()
+}
+
+/// Returns true if this place context represents an assignment statement
+crate fn is_place_assignment(place_context: &PlaceContext) -> bool {
+    match *place_context {
+        PlaceContext::Store | PlaceContext::Call | PlaceContext::AsmOutput => true,
+        PlaceContext::Drop
+        | PlaceContext::Inspect
+        | PlaceContext::Borrow { .. }
+        | PlaceContext::Projection(..)
+        | PlaceContext::Copy
+        | PlaceContext::Move
+        | PlaceContext::StorageLive
+        | PlaceContext::StorageDead
+        | PlaceContext::Validate => false,
+    }
 }
index 90680b4156e7a825693bc6399eb9ebd360e2de21..546ce34fe12ae864a7e8300565513e796ab8f323 100644 (file)
@@ -25,7 +25,8 @@
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 use errors::DiagnosticBuilder;
-use syntax_pos::Span;
+use syntax_pos::{Span, FileName};
+
 
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir;
@@ -187,7 +188,6 @@ pub fn report_method_error(&self,
                 out_of_scope_traits,
                 lev_candidate,
                 mode,
-                ..
             }) => {
                 let tcx = self.tcx;
 
@@ -264,13 +264,35 @@ pub fn report_method_error(&self,
                                         let span = tcx.hir.span(node_id);
                                         let snippet = tcx.sess.codemap().span_to_snippet(span)
                                             .unwrap();
-                                        err.span_suggestion(span,
-                                                            &format!("you must specify a type for \
-                                                                      this binding, like `{}`",
-                                                                     concrete_type),
-                                                            format!("{}: {}",
-                                                                    snippet,
-                                                                    concrete_type));
+                                        let filename = tcx.sess.codemap().span_to_filename(span);
+
+                                        let parent_node = self.tcx.hir.get(
+                                            self.tcx.hir.get_parent_node(node_id),
+                                        );
+                                        let msg = format!(
+                                            "you must specify a type for this binding, like `{}`",
+                                            concrete_type,
+                                        );
+
+                                        match (filename, parent_node) {
+                                            (FileName::Real(_), hir_map::NodeLocal(hir::Local {
+                                                source: hir::LocalSource::Normal,
+                                                ty,
+                                                ..
+                                            })) => {
+                                                err.span_suggestion(
+                                                    // account for `let x: _ = 42;`
+                                                    //                  ^^^^
+                                                    span.to(ty.as_ref().map(|ty| ty.span)
+                                                        .unwrap_or(span)),
+                                                    &msg,
+                                                    format!("{}: {}", snippet, concrete_type),
+                                                );
+                                            }
+                                            _ => {
+                                                err.span_label(span, msg);
+                                            }
+                                        }
                                     }
                                 }
                             }
index d684db152df0129aff972b2570da44eb8a0555fd..575a7ea27921f0e9581e4276f30ce6ec2311a1ae 100644 (file)
@@ -407,31 +407,27 @@ h4 > code, h3 > code, .invisible > code {
 
 .content table:not(.table-display) {
        border-spacing: 0 5px;
-       border-collapse: separate;
 }
 .content td { vertical-align: top; }
 .content td:first-child { padding-right: 20px; }
 .content td p:first-child { margin-top: 0; }
 .content td h1, .content td h2 { margin-left: 0; font-size: 1.1em; }
+.content tr:first-child td { border-top: 0; }
 
 .docblock table {
-       border: 1px solid;
        margin: .5em 0;
-       border-collapse: collapse;
        width: 100%;
 }
 
 .docblock table td {
        padding: .5em;
-       border-top: 1px dashed;
-       border-bottom: 1px dashed;
+       border: 1px dashed;
 }
 
 .docblock table th {
        padding: .5em;
        text-align: left;
-       border-top: 1px solid;
-       border-bottom: 1px solid;
+       border: 1px solid;
 }
 
 .fields + table {
index caa189457655230e1a47094fe73b054a308cdf2f..3f7f06714908428ee990b89fe15c483fe890d8ec 100644 (file)
@@ -183,15 +183,14 @@ pub fn fill_bytes(v: &mut [u8]) {
 mod imp {
     #[link(name = "zircon")]
     extern {
-        fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
+        fn zx_cprng_draw_new(buffer: *mut u8, len: usize) -> i32;
     }
 
     fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
         unsafe {
-            let mut actual = 0;
-            let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
+            let status = zx_cprng_draw_new(buf.as_mut_ptr(), buf.len());
             if status == 0 {
-                Ok(actual)
+                Ok(buf.len())
             } else {
                 Err(status)
             }
index 61f88f3a250d3ce567f3c0390a9d9beb0899f520..cce8da1dcbd53f9291aa08bab5d6e032920e9938 100644 (file)
@@ -294,7 +294,7 @@ fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) {
 
 /// Parse a string representing a string literal into its final form. Does
 /// unescaping.
-fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
+pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
     debug!("str_lit: given {}", lit.escape_default());
     let mut res = String::with_capacity(lit.len());
 
index 0be149d7a034eb158ef57cafd04a2c735df06294..5970f94b97d52f12f4cfc9737033c8703900875a 100644 (file)
@@ -776,6 +776,9 @@ fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
             err.span_label(self.span, format!("expected identifier, found {}", token_descr));
         } else {
             err.span_label(self.span, "expected identifier");
+            if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
+                err.span_suggestion(self.span, "remove this comma", "".into());
+            }
         }
         err
     }
@@ -1057,7 +1060,7 @@ pub fn parse_seq_to_end<T, F>(&mut self,
     /// Parse a sequence, not including the closing delimiter. The function
     /// f must consume tokens until reaching the next separator or
     /// closing bracket.
-    fn parse_seq_to_before_end<T, F>(&mut self,
+    pub fn parse_seq_to_before_end<T, F>(&mut self,
                                          ket: &token::Token,
                                          sep: SeqSep,
                                          f: F)
@@ -2129,7 +2132,7 @@ fn mk_assign_op(&mut self, binop: ast::BinOp,
         ExprKind::AssignOp(binop, lhs, rhs)
     }
 
-    fn mk_mac_expr(&mut self, span: Span, m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> {
+    pub fn mk_mac_expr(&mut self, span: Span, m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> {
         P(Expr {
             id: ast::DUMMY_NODE_ID,
             node: ExprKind::Mac(codemap::Spanned {node: m, span: span}),
@@ -2467,8 +2470,14 @@ fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Att
                 Err(mut e) => {
                     e.span_label(struct_sp, "while parsing this struct");
                     e.emit();
-                    self.recover_stmt();
-                    break;
+
+                    // If the next token is a comma, then try to parse
+                    // what comes next as additional fields, rather than
+                    // bailing out until next `}`.
+                    if self.token != token::Comma {
+                        self.recover_stmt();
+                        break;
+                    }
                 }
             }
 
@@ -4767,7 +4776,7 @@ fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Blo
                 if macro_legacy_warnings && self.token != token::Semi {
                     self.warn_missing_semicolon();
                 } else {
-                    self.expect_one_of(&[token::Semi], &[])?;
+                    self.expect_one_of(&[], &[token::Semi])?;
                 }
             }
             _ => {}
@@ -5461,7 +5470,7 @@ fn parse_fn_front_matter(&mut self)
     }
 
     /// Parse an impl item.
-    crate fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> {
+    pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> {
         maybe_whole!(self, NtImplItem, |x| x);
         let attrs = self.parse_outer_attributes()?;
         let (mut item, tokens) = self.collect_tokens(|this| {
@@ -7325,7 +7334,7 @@ pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
         })
     }
 
-    fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
+    pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
         let ret = match self.token {
             token::Literal(token::Str_(s), suf) => (s, ast::StrStyle::Cooked, suf),
             token::Literal(token::StrRaw(s, n), suf) => (s, ast::StrStyle::Raw(n), suf),
index 5e3cb606ce0371f258c77d2ec1576f398f29addd..07e80b61cd0a69cc764a016b88c15c940a9efe3d 100644 (file)
@@ -7,6 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+
 #![crate_name="lint_stability"]
 #![crate_type = "lib"]
 #![feature(staged_api)]
@@ -20,6 +21,10 @@ pub fn deprecated() {}
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_text() {}
 
+#[stable(feature = "test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "99.99.99", reason = "text")]
+pub fn deprecated_future() {}
+
 #[unstable(feature = "test_feature", issue = "0")]
 #[rustc_deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_unstable() {}
index 49a52204295e505aa3e6b8762c6c7a8ce02974fe..bd390108bd8f3c40468fc1e122bae926a345f8c3 100644 (file)
@@ -50,6 +50,8 @@ fn test() {
         <Foo>::trait_deprecated_text(&foo);
         <Foo as Trait>::trait_deprecated_text(&foo);
 
+        deprecated_future(); // Fine; no error.
+
         deprecated_unstable();
         //~^ ERROR use of unstable library feature
         Trait::trait_deprecated_unstable(&foo);
@@ -218,6 +220,10 @@ pub fn deprecated() {}
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated_text() {}
 
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(since = "99.99.99", reason = "text")]
+    pub fn deprecated_future() {}
+
     #[unstable(feature = "test_feature", issue = "0")]
     pub fn unstable() {}
     #[unstable(feature = "test_feature", reason = "text", issue = "0")]
@@ -338,6 +344,8 @@ fn test() {
         <Foo>::trait_deprecated_text(&foo);
         <Foo as Trait>::trait_deprecated_text(&foo);
 
+        deprecated_future();
+
         unstable();
         foo.method_unstable();
         Foo::method_unstable(&foo);
diff --git a/src/test/ui/borrowck/issue-51415.nll.stderr b/src/test/ui/borrowck/issue-51415.nll.stderr
new file mode 100644 (file)
index 0000000..79454b6
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-51415.rs:16:47
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
+   |                                               ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-51415.rs b/src/test/ui/borrowck/issue-51415.rs
new file mode 100644 (file)
index 0000000..9067a50
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #51415: match default bindings were failing to
+// see the "move out" implied by `&s` below.
+
+fn main() {
+    let a = vec![String::from("a")];
+    let opt = a.iter().enumerate().find(|(_, &s)| {
+        //~^ ERROR cannot move out
+        *s == String::from("d")
+    }).map(|(i, _)| i);
+    println!("{:?}", opt);
+}
diff --git a/src/test/ui/borrowck/issue-51415.stderr b/src/test/ui/borrowck/issue-51415.stderr
new file mode 100644 (file)
index 0000000..b4b0bc7
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-51415.rs:16:46
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
+   |                                              ^-
+   |                                              ||
+   |                                              |hint: to prevent move, use `ref s` or `ref mut s`
+   |                                              cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issue-50585.rs b/src/test/ui/issue-50585.rs
new file mode 100644 (file)
index 0000000..0c063d4
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    |y: Vec<[(); for x in 0..2 {}]>| {};
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/issue-50585.stderr b/src/test/ui/issue-50585.stderr
new file mode 100644 (file)
index 0000000..3f9328d
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-50585.rs:12:18
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+LL |     |y: Vec<[(); for x in 0..2 {}]>| {};
+   |                  ^^^^^^^^^^^^^^^^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index 6b8417bf9db6d8b131ff6479fdb787b195f20f2e..6fd2b320472f3cd5c623906ff208d2cbf995ec49 100644 (file)
@@ -2,7 +2,9 @@ error: lifetime parameter `'a` only used once
   --> $DIR/fn-types.rs:19:10
    |
 LL |   a: for<'a> fn(&'a u32), //~ ERROR `'a` only used once
-   |          ^^
+   |          ^^      -- ...is used only here
+   |          |
+   |          this lifetime...
    |
 note: lint level defined here
   --> $DIR/fn-types.rs:11:9
index 3694c2452f34c0ecb810728cea63d099a5a2c4fe..3dd2675646cde0918112259118a93d20b61ee72f 100644 (file)
@@ -3,6 +3,9 @@ error: lifetime parameter `'b` only used once
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
    |                      ^^
+   |                      |
+   |                      this lifetime...
+   |                      ...is used only here
    |
 note: lint level defined here
   --> $DIR/one-use-in-fn-argument-in-band.rs:12:9
@@ -15,6 +18,9 @@ error: lifetime parameter `'a` only used once
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
    |          ^^
+   |          |
+   |          this lifetime...
+   |          ...is used only here
 
 error: aborting due to 2 previous errors
 
index f1304568fe72cb6a32b32642191eb77cd8cc3ab4..4c13133581bb4d156433031f8ce36404b257a6d1 100644 (file)
@@ -2,7 +2,9 @@ error: lifetime parameter `'a` only used once
   --> $DIR/one-use-in-fn-argument.rs:18:6
    |
 LL | fn a<'a>(x: &'a u32) { //~ ERROR `'a` only used once
-   |      ^^
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
    |
 note: lint level defined here
   --> $DIR/one-use-in-fn-argument.rs:11:9
index 8f91ca0ce54c32a27899ea479c1725c7c614faa2..2509366f9696fb080dbe1d2b21b5740c89d51e9b 100644 (file)
@@ -2,7 +2,9 @@ error: lifetime parameter `'f` only used once
   --> $DIR/one-use-in-inherent-impl-header.rs:24:6
    |
 LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
-   |      ^^
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
    |
 note: lint level defined here
   --> $DIR/one-use-in-inherent-impl-header.rs:11:9
index 4811a65ced91975849b5ffc96f30fd4cfb301f4a..cfc8dbf18dc01d02c07045acf6eeacad050a748e 100644 (file)
@@ -2,7 +2,9 @@ error: lifetime parameter `'a` only used once
   --> $DIR/one-use-in-inherent-method-argument.rs:22:19
    |
 LL |     fn inherent_a<'a>(&self, data: &'a u32) { //~ ERROR `'a` only used once
-   |                   ^^
+   |                   ^^                -- ...is used only here
+   |                   |
+   |                   this lifetime...
    |
 note: lint level defined here
   --> $DIR/one-use-in-inherent-method-argument.rs:11:9
@@ -14,7 +16,9 @@ error: lifetime parameter `'f` only used once
   --> $DIR/one-use-in-inherent-method-argument.rs:21:6
    |
 LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
-   |      ^^
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
 
 error: aborting due to 2 previous errors
 
index b552c8475d8900800ddabc0a77f1581c6277325e..8aa19d4e3ee916e7c1e9c463ea16e9ab6b30ad56 100644 (file)
@@ -2,7 +2,9 @@ error: lifetime parameter `'f` only used once
   --> $DIR/one-use-in-inherent-method-return.rs:22:6
    |
 LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
-   |      ^^
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
    |
 note: lint level defined here
   --> $DIR/one-use-in-inherent-method-return.rs:11:9
index de74800ff60140a2aa97b15e241d6f804dd27b0e..4a796d83242fd91570718d2a72c8e77b8ecf5bae 100644 (file)
@@ -2,7 +2,9 @@ error: lifetime parameter `'g` only used once
   --> $DIR/one-use-in-trait-method-argument.rs:25:13
    |
 LL |     fn next<'g>(&'g mut self) -> Option<Self::Item> { //~ ERROR `'g` only used once
-   |             ^^
+   |             ^^   -- ...is used only here
+   |             |
+   |             this lifetime...
    |
 note: lint level defined here
   --> $DIR/one-use-in-trait-method-argument.rs:14:9
index ca0b050b696793dca7c44879adc245fcf3ed885a..b4b370d6e976b81645c8b8c409da752da3579674 100644 (file)
@@ -2,7 +2,9 @@ error: lifetime parameter `'f` only used once
   --> $DIR/two-uses-in-inherent-method-argument-and-return.rs:22:6
    |
 LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
-   |      ^^
+   |      ^^      -- ...is used only here
+   |      |
+   |      this lifetime...
    |
 note: lint level defined here
   --> $DIR/two-uses-in-inherent-method-argument-and-return.rs:14:9
diff --git a/src/test/ui/struct-duplicate-comma.rs b/src/test/ui/struct-duplicate-comma.rs
new file mode 100644 (file)
index 0000000..d7ee2f2
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only
+
+// Issue #50974
+
+struct Foo {
+    a: u8,
+    b: u8
+}
+
+fn main() {
+    let bar = Foo {
+        a: 0,,
+          //~^ ERROR expected identifier
+        b: 42
+    };
+}
+
diff --git a/src/test/ui/struct-duplicate-comma.stderr b/src/test/ui/struct-duplicate-comma.stderr
new file mode 100644 (file)
index 0000000..06e3b95
--- /dev/null
@@ -0,0 +1,13 @@
+error: expected identifier, found `,`
+  --> $DIR/struct-duplicate-comma.rs:22:14
+   |
+LL |     let bar = Foo {
+   |               --- while parsing this struct
+LL |         a: 0,,
+   |              ^
+   |              |
+   |              expected identifier
+   |              help: remove this comma
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs b/src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs
new file mode 100644 (file)
index 0000000..01282f2
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_export]
+macro_rules! mac {
+    ($ident:ident) => { let $ident = 42; }
+}
index 9bf74c3875fed5f379d35372a1baea0db62d2ec2..2b6e830ec59622f871a177d317dea34d461aa2e9 100644 (file)
@@ -8,11 +8,35 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// aux-build:macro-in-other-crate.rs
+
+#[macro_use] extern crate macro_in_other_crate;
+
+macro_rules! local_mac {
+    ($ident:ident) => { let $ident = 42; }
+}
+
 fn main() {
     let x = 2.0.neg();
     //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+
     let y = 2.0;
     let x = y.neg();
     //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
     println!("{:?}", x);
+
+    for i in 0..100 {
+        println!("{}", i.pow(2));
+        //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+    }
+
+    local_mac!(local_bar);
+    local_bar.pow(2);
+    //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+}
+
+fn qux() {
+    mac!(bar);
+    bar.pow(2);
+    //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
 }
index 68c8be7dff8c941de2164d31a72574735a55e3b6..796520e0ec71ba3849cb37fba9c756d9ff5d9c29 100644 (file)
@@ -1,5 +1,5 @@
 error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
-  --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
+  --> $DIR/method-on-ambiguous-numeric-type.rs:20:17
    |
 LL |     let x = 2.0.neg();
    |                 ^^^
@@ -9,7 +9,7 @@ LL |     let x = 2.0_f32.neg();
    |             ^^^^^^^
 
 error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
-  --> $DIR/method-on-ambiguous-numeric-type.rs:15:15
+  --> $DIR/method-on-ambiguous-numeric-type.rs:24:15
    |
 LL |     let x = y.neg();
    |               ^^^
@@ -18,6 +18,34 @@ help: you must specify a type for this binding, like `f32`
 LL |     let y: f32 = 2.0;
    |         ^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:29:26
+   |
+LL |     for i in 0..100 {
+   |         - you must specify a type for this binding, like `i32`
+LL |         println!("{}", i.pow(2));
+   |                          ^^^
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:34:15
+   |
+LL |     local_bar.pow(2);
+   |               ^^^
+help: you must specify a type for this binding, like `i32`
+   |
+LL |     ($ident:ident) => { let $ident: i32 = 42; }
+   |                             ^^^^^^^^^^^
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+  --> $DIR/method-on-ambiguous-numeric-type.rs:40:9
+   |
+LL |     mac!(bar);
+   |     ---------- you must specify a type for this binding, like `i32`
+LL |     bar.pow(2);
+   |         ^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0689`.
index 91a44fdd424fb12ff34b2298ce7a8b1e12828293..db30e649a7e6b5b4f0ee8b6e73ea946549ba765b 100644 (file)
@@ -212,6 +212,7 @@ fn main() {
     let cargo_release = args.next().unwrap();
     let rls_release = args.next().unwrap();
     let rustfmt_release = args.next().unwrap();
+    let _llvm_tools_vers = args.next().unwrap(); // FIXME do something with it?
     let s3_address = args.next().unwrap();
     let mut passphrase = String::new();
     t!(io::stdin().read_to_string(&mut passphrase));