about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-04-21 01:26:56 +0000
committerbors <bors@rust-lang.org>2020-04-21 01:26:56 +0000
commit073744f554cf170942aa43893f292199ad44e3d4 (patch)
tree7460d5414cb1ed93377e6effe1f8d724c8c4d7dd
parent20fc02f836f3035b86b56a7cedb97c5cd4ed9612 (diff)
parent9a0e7029062fb74a71a200b1f7ce0c212c9ea3a6 (diff)
downloadrust-073744f554cf170942aa43893f292199ad44e3d4.tar.gz
rust-073744f554cf170942aa43893f292199ad44e3d4.zip
Auto merge of #71367 - Dylan-DPC:rollup-ysj4olr, r=Dylan-DPC
Rollup of 4 pull requests

Successful merges:

 - #69362 (Stabilize most common subset of alloc_layout_extras)
 - #71174 (Check that main/start is not async)
 - #71285 (MIR: use HirId instead of NodeId to avoid cycles while inlining)
 - #71346 (Do not build tools if user do not want them)

Failed merges:

r? @ghost
-rw-r--r--src/bootstrap/tool.rs10
-rw-r--r--src/libcore/alloc/layout.rs56
-rw-r--r--src/librustc_error_codes/error_codes.rs1
-rw-r--r--src/librustc_error_codes/error_codes/E0752.md11
-rw-r--r--src/librustc_mir/transform/inline.rs12
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs14
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/suggestions.rs5
-rw-r--r--src/librustc_typeck/lib.rs28
-rw-r--r--src/test/ui/async-await/issue-68523-start.rs9
-rw-r--r--src/test/ui/async-await/issue-68523-start.stderr9
-rw-r--r--src/test/ui/async-await/issue-68523.rs7
-rw-r--r--src/test/ui/async-await/issue-68523.stderr18
12 files changed, 145 insertions, 35 deletions
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 52f750f448e..f756b1235ab 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -607,7 +607,15 @@ macro_rules! tool_extended {
 
             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
                 let builder = run.builder;
-                run.path($path).default_condition(builder.config.extended)
+                run.path($path).default_condition(
+                    builder.config.extended
+                        && builder.config.tools.as_ref().map_or(true, |tools| {
+                            tools.iter().any(|tool| match tool.as_ref() {
+                                "clippy" => $tool_name == "clippy-driver",
+                                x => $tool_name == x,
+                            })
+                        }),
+                )
             }
 
             fn make_run(run: RunConfig<'_>) {
diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs
index fa644cfe99e..6200cd24266 100644
--- a/src/libcore/alloc/layout.rs
+++ b/src/libcore/alloc/layout.rs
@@ -162,7 +162,7 @@ impl Layout {
     /// Returns an error if the combination of `self.size()` and the given
     /// `align` violates the conditions listed in
     /// [`Layout::from_size_align`](#method.from_size_align).
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
     #[inline]
     pub fn align_to(&self, align: usize) -> Result<Self, LayoutErr> {
         Layout::from_size_align(self.size(), cmp::max(self.align(), align))
@@ -218,7 +218,7 @@ impl Layout {
     ///
     /// This is equivalent to adding the result of `padding_needed_for`
     /// to the layout's current size.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
     #[inline]
     pub fn pad_to_align(&self) -> Layout {
         let pad = self.padding_needed_for(self.align());
@@ -258,19 +258,50 @@ impl Layout {
 
     /// Creates a layout describing the record for `self` followed by
     /// `next`, including any necessary padding to ensure that `next`
-    /// will be properly aligned. Note that the resulting layout will
-    /// satisfy the alignment properties of both `self` and `next`.
+    /// will be properly aligned, but *no trailing padding*.
     ///
-    /// The resulting layout will be the same as that of a C struct containing
-    /// two fields with the layouts of `self` and `next`, in that order.
+    /// In order to match C representation layout `repr(C)`, you should
+    /// call `pad_to_align` after extending the layout with all fields.
+    /// (There is no way to match the default Rust representation
+    /// layout `repr(Rust)`, as it is unspecified.)
     ///
-    /// Returns `Some((k, offset))`, where `k` is layout of the concatenated
+    /// Note that the alignment of the resulting layout will be the maximum of
+    /// those of `self` and `next`, in order to ensure alignment of both parts.
+    ///
+    /// Returns `Ok((k, offset))`, where `k` is layout of the concatenated
     /// record and `offset` is the relative location, in bytes, of the
     /// start of the `next` embedded within the concatenated record
     /// (assuming that the record itself starts at offset 0).
     ///
     /// On arithmetic overflow, returns `LayoutErr`.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    ///
+    /// # Examples
+    ///
+    /// To calculate the layout of a `#[repr(C)]` structure and the offsets of
+    /// the fields from its fields' layouts:
+    ///
+    /// ```rust
+    /// # use std::alloc::{Layout, LayoutErr};
+    /// pub fn repr_c(fields: &[Layout]) -> Result<(Layout, Vec<usize>), LayoutErr> {
+    ///     let mut offsets = Vec::new();
+    ///     let mut layout = Layout::from_size_align(0, 1)?;
+    ///     for &field in fields {
+    ///         let (new_layout, offset) = layout.extend(field)?;
+    ///         layout = new_layout;
+    ///         offsets.push(offset);
+    ///     }
+    ///     // Remember to finalize with `pad_to_align`!
+    ///     Ok((layout.pad_to_align(), offsets))
+    /// }
+    /// # // test that it works
+    /// # #[repr(C)] struct S { a: u64, b: u32, c: u16, d: u32 }
+    /// # let s = Layout::new::<S>();
+    /// # let u16 = Layout::new::<u16>();
+    /// # let u32 = Layout::new::<u32>();
+    /// # let u64 = Layout::new::<u64>();
+    /// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16])));
+    /// ```
+    #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
     #[inline]
     pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
         let new_align = cmp::max(self.align(), next.align());
@@ -318,13 +349,12 @@ impl Layout {
     /// Creates a layout describing the record for a `[T; n]`.
     ///
     /// On arithmetic overflow, returns `LayoutErr`.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
     #[inline]
     pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
-        Layout::new::<T>().repeat(n).map(|(k, offs)| {
-            debug_assert!(offs == mem::size_of::<T>());
-            k
-        })
+        let (layout, offset) = Layout::new::<T>().repeat(n)?;
+        debug_assert_eq!(offset, mem::size_of::<T>());
+        Ok(layout.pad_to_align())
     }
 }
 
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 225ede851b4..bc04809eaa1 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -431,6 +431,7 @@ E0748: include_str!("./error_codes/E0748.md"),
 E0749: include_str!("./error_codes/E0749.md"),
 E0750: include_str!("./error_codes/E0750.md"),
 E0751: include_str!("./error_codes/E0751.md"),
+E0752: include_str!("./error_codes/E0752.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/src/librustc_error_codes/error_codes/E0752.md b/src/librustc_error_codes/error_codes/E0752.md
new file mode 100644
index 00000000000..86945f83b55
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0752.md
@@ -0,0 +1,11 @@
+`fn main()` or the specified start function is not allowed to be
+async. You might be seeing this error because your async runtime
+library is not set up correctly.
+
+Erroneous code example:
+
+```compile_fail,E0752
+async fn main() -> Result<i32, ()> {
+    Ok(1)
+}
+```
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index bfa13abb871..173c2a3f1d8 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -94,17 +94,15 @@ impl Inliner<'tcx> {
                     continue;
                 }
 
-                let self_node_id = self.tcx.hir().as_local_node_id(self.source.def_id()).unwrap();
-                let callee_node_id = self.tcx.hir().as_local_node_id(callsite.callee);
+                let callee_hir_id = self.tcx.hir().as_local_hir_id(callsite.callee);
 
-                let callee_body = if let Some(callee_node_id) = callee_node_id {
+                let callee_body = if let Some(callee_hir_id) = callee_hir_id {
+                    let self_hir_id = self.tcx.hir().as_local_hir_id(self.source.def_id()).unwrap();
                     // Avoid a cycle here by only using `optimized_mir` only if we have
-                    // a lower node id than the callee. This ensures that the callee will
+                    // a lower `HirId` than the callee. This ensures that the callee will
                     // not inline us. This trick only works without incremental compilation.
                     // So don't do it if that is enabled.
-                    if !self.tcx.dep_graph.is_fully_enabled()
-                        && self_node_id.as_u32() < callee_node_id.as_u32()
-                    {
+                    if !self.tcx.dep_graph.is_fully_enabled() && self_hir_id < callee_hir_id {
                         self.tcx.optimized_mir(callsite.callee)
                     } else {
                         continue;
diff --git a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
index e9f55c24256..fd87759a762 100644
--- a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
@@ -82,10 +82,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         match &node {
             hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
                 self.describe_generator(*body_id).or_else(|| {
-                    Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                        "an async function"
-                    } else {
-                        "a function"
+                    Some(match sig.header {
+                        hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async function",
+                        _ => "a function",
                     })
                 })
             }
@@ -97,10 +96,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 kind: hir::ImplItemKind::Fn(sig, body_id),
                 ..
             }) => self.describe_generator(*body_id).or_else(|| {
-                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                    "an async method"
-                } else {
-                    "a method"
+                Some(match sig.header {
+                    hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async method",
+                    _ => "a method",
                 })
             }),
             hir::Node::Expr(hir::Expr {
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index 2b19699d6ec..331c8f3be84 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -1318,10 +1318,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         let is_async = inner_generator_body
             .and_then(|body| body.generator_kind())
-            .map(|generator_kind| match generator_kind {
-                hir::GeneratorKind::Async(..) => true,
-                _ => false,
-            })
+            .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
             .unwrap_or(false);
         let (await_or_yield, an_await_or_yield) =
             if is_async { ("await", "an await") } else { ("yield", "a yield") };
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index df8290fd018..cd76184c9bf 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -159,7 +159,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
     match main_t.kind {
         ty::FnDef(..) => {
             if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
-                if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
+                if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
                     let mut error = false;
                     if !generics.params.is_empty() {
                         let msg = "`main` function is not allowed to have generic \
@@ -182,6 +182,18 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
                         .emit();
                         error = true;
                     }
+                    if let hir::IsAsync::Async = sig.header.asyncness {
+                        let span = tcx.sess.source_map().guess_head_span(it.span);
+                        struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0752,
+                            "`main` function is not allowed to be `async`"
+                        )
+                        .span_label(span, "`main` function is not allowed to be `async`")
+                        .emit();
+                        error = true;
+                    }
                     if error {
                         return;
                     }
@@ -226,7 +238,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
     match start_t.kind {
         ty::FnDef(..) => {
             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
-                if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
+                if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
                     let mut error = false;
                     if !generics.params.is_empty() {
                         struct_span_err!(
@@ -250,6 +262,18 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
                         .emit();
                         error = true;
                     }
+                    if let hir::IsAsync::Async = sig.header.asyncness {
+                        let span = tcx.sess.source_map().guess_head_span(it.span);
+                        struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0752,
+                            "start is not allowed to be `async`"
+                        )
+                        .span_label(span, "start is not allowed to be `async`")
+                        .emit();
+                        error = true;
+                    }
                     if error {
                         return;
                     }
diff --git a/src/test/ui/async-await/issue-68523-start.rs b/src/test/ui/async-await/issue-68523-start.rs
new file mode 100644
index 00000000000..5988dffd68f
--- /dev/null
+++ b/src/test/ui/async-await/issue-68523-start.rs
@@ -0,0 +1,9 @@
+// edition:2018
+
+#![feature(start)]
+
+#[start]
+pub async fn start(_: isize, _: *const *const u8) -> isize {
+//~^ ERROR start is not allowed to be `async`
+    0
+}
diff --git a/src/test/ui/async-await/issue-68523-start.stderr b/src/test/ui/async-await/issue-68523-start.stderr
new file mode 100644
index 00000000000..e471945900e
--- /dev/null
+++ b/src/test/ui/async-await/issue-68523-start.stderr
@@ -0,0 +1,9 @@
+error[E0752]: start is not allowed to be `async`
+  --> $DIR/issue-68523-start.rs:6:1
+   |
+LL | pub async fn start(_: isize, _: *const *const u8) -> isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ start is not allowed to be `async`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0752`.
diff --git a/src/test/ui/async-await/issue-68523.rs b/src/test/ui/async-await/issue-68523.rs
new file mode 100644
index 00000000000..e6250c40c71
--- /dev/null
+++ b/src/test/ui/async-await/issue-68523.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+async fn main() -> Result<i32, ()> {
+//~^ ERROR `main` function is not allowed to be `async`
+//~^^ ERROR `main` has invalid return type `impl std::future::Future`
+    Ok(1)
+}
diff --git a/src/test/ui/async-await/issue-68523.stderr b/src/test/ui/async-await/issue-68523.stderr
new file mode 100644
index 00000000000..62e37cf2629
--- /dev/null
+++ b/src/test/ui/async-await/issue-68523.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `main` has invalid return type `impl std::future::Future`
+  --> $DIR/issue-68523.rs:3:20
+   |
+LL | async fn main() -> Result<i32, ()> {
+   |                    ^^^^^^^^^^^^^^^ `main` can only return types that implement `std::process::Termination`
+   |
+   = help: consider using `()`, or a `Result`
+
+error[E0752]: `main` function is not allowed to be `async`
+  --> $DIR/issue-68523.rs:3:1
+   |
+LL | async fn main() -> Result<i32, ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0752.
+For more information about an error, try `rustc --explain E0277`.