]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #60969 - Centril:rollup-3j71mqj, r=Centril
authorbors <bors@rust-lang.org>
Mon, 20 May 2019 00:37:48 +0000 (00:37 +0000)
committerbors <bors@rust-lang.org>
Mon, 20 May 2019 00:37:48 +0000 (00:37 +0000)
Rollup of 6 pull requests

Successful merges:

 - #60590 (Test interaction of unions with non-zero/niche-filling optimization)
 - #60745 (Perform constant propagation into terminators)
 - #60895 (Enable thumbv7a-pc-windows-msvc target build end to end in rust/master)
 - #60908 (Fix lints handling in rustdoc)
 - #60960 (Stop using gensyms in HIR lowering)
 - #60962 (Fix data types indication)

Failed merges:

r? @ghost

23 files changed:
src/bootstrap/test.rs
src/libcore/fmt/mod.rs
src/librustc/hir/lowering.rs
src/librustc/lint/mod.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_ssa/back/write.rs
src/librustc_mir/transform/const_prop.rs
src/librustdoc/clean/mod.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/mod.rs
src/libsyntax_pos/symbol.rs
src/libtest/lib.rs
src/test/mir-opt/const_prop/array_index.rs
src/test/mir-opt/const_prop/checked_add.rs
src/test/mir-opt/const_prop/switch_int.rs [new file with mode: 0644]
src/test/mir-opt/simplify_if.rs
src/test/run-pass/union/union-nonzero.rs [new file with mode: 0644]
src/test/rustdoc-ui/doc-without-codeblock.rs
src/test/rustdoc-ui/doc-without-codeblock.stderr
src/test/rustdoc-ui/lint-missing-doc-code-example.rs [new file with mode: 0644]
src/test/rustdoc-ui/lint-missing-doc-code-example.stderr [new file with mode: 0644]
src/test/ui/print_type_sizes/niche-filling.rs
src/test/ui/print_type_sizes/niche-filling.stdout

index 7826ac9471806043c1b00505e13cbe9ffab424c6..be0af8be7b272bc615aab84985faa07db286c449 100644 (file)
@@ -683,7 +683,7 @@ fn run(self, builder: &Builder<'_>) {
             target: self.target,
             mode: "ui",
             suite: "rustdoc-ui",
-            path: None,
+            path: Some("src/test/rustdoc-ui"),
             compare_mode: None,
         })
     }
index 43c1a3b7767ab647838c9f4f3702e0a29271a881..2f6d745d146d647d3fd5716e57db7dc020964b39 100644 (file)
@@ -886,7 +886,7 @@ pub trait Pointer {
 ///
 /// # Examples
 ///
-/// Basic usage with `i32`:
+/// Basic usage with `f64`:
 ///
 /// ```
 /// let x = 42.0; // 42.0 is '4.2e1' in scientific notation
@@ -929,7 +929,7 @@ pub trait LowerExp {
 ///
 /// # Examples
 ///
-/// Basic usage with `f32`:
+/// Basic usage with `f64`:
 ///
 /// ```
 /// let x = 42.0; // 42.0 is '4.2E1' in scientific notation
index 970f6ba01773557ebc8d94203fba55f4160b52f8..3ec4d4e8cc8f68350eba397be435676d2c89fc91 100644 (file)
@@ -855,10 +855,6 @@ fn diagnostic(&self) -> &errors::Handler {
         self.sess.diagnostic()
     }
 
-    fn str_to_ident(&self, s: &'static str) -> Ident {
-        Ident::with_empty_ctxt(Symbol::gensym(s))
-    }
-
     fn with_anonymous_lifetime_mode<R>(
         &mut self,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
@@ -4621,18 +4617,18 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 );
                 head.span = desugared_span;
 
-                let iter = self.str_to_ident("iter");
+                let iter = Ident::with_empty_ctxt(sym::iter);
 
-                let next_ident = self.str_to_ident("__next");
+                let next_ident = Ident::with_empty_ctxt(sym::__next);
                 let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
                     desugared_span,
                     next_ident,
                     hir::BindingAnnotation::Mutable,
                 );
 
-                // `::std::option::Option::Some(val) => next = val`
+                // `::std::option::Option::Some(val) => __next = val`
                 let pat_arm = {
-                    let val_ident = self.str_to_ident("val");
+                    let val_ident = Ident::with_empty_ctxt(sym::val);
                     let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
                     let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
                     let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
@@ -4771,17 +4767,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let unstable_span = self.sess.source_map().mark_span_with_reason(
                     CompilerDesugaringKind::QuestionMark,
                     e.span,
-                    Some(vec![
-                        Symbol::intern("try_trait")
-                    ].into()),
+                    Some(vec![sym::try_trait].into()),
                 );
                 let try_span = self.sess.source_map().end_point(e.span);
                 let try_span = self.sess.source_map().mark_span_with_reason(
                     CompilerDesugaringKind::QuestionMark,
                     try_span,
-                    Some(vec![
-                        Symbol::intern("try_trait")
-                    ].into()),
+                    Some(vec![sym::try_trait].into()),
                 );
 
                 // `Try::into_result(<expr>)`
@@ -4802,7 +4794,8 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     // `allow(unreachable_code)`
                     let allow = {
                         let allow_ident = Ident::with_empty_ctxt(sym::allow).with_span_pos(e.span);
-                        let uc_ident = Ident::from_str("unreachable_code").with_span_pos(e.span);
+                        let uc_ident = Ident::with_empty_ctxt(sym::unreachable_code)
+                            .with_span_pos(e.span);
                         let uc_nested = attr::mk_nested_word_item(uc_ident);
                         attr::mk_list_item(e.span, allow_ident, vec![uc_nested])
                     };
@@ -4812,7 +4805,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
                 // `Ok(val) => #[allow(unreachable_code)] val,`
                 let ok_arm = {
-                    let val_ident = self.str_to_ident("val");
+                    let val_ident = Ident::with_empty_ctxt(sym::val);
                     let (val_pat, val_pat_nid) = self.pat_ident(e.span, val_ident);
                     let val_expr = P(self.expr_ident_with_attrs(
                         e.span,
@@ -4828,7 +4821,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 // `Err(err) => #[allow(unreachable_code)]
                 //              return Try::from_error(From::from(err)),`
                 let err_arm = {
-                    let err_ident = self.str_to_ident("err");
+                    let err_ident = Ident::with_empty_ctxt(sym::err);
                     let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
                     let from_expr = {
                         let from_path = &[sym::convert, sym::From, sym::from];
@@ -5552,7 +5545,7 @@ fn lower_await(
         //         match ::std::future::poll_with_tls_context(unsafe {
         //             ::std::pin::Pin::new_unchecked(&mut pinned)
         //         }) {
-        //             ::std::task::Poll::Ready(x) => break x,
+        //             ::std::task::Poll::Ready(result) => break result,
         //             ::std::task::Poll::Pending => {},
         //         }
         //         yield ();
@@ -5580,12 +5573,12 @@ fn lower_await(
         let gen_future_span = self.sess.source_map().mark_span_with_reason(
             CompilerDesugaringKind::Await,
             await_span,
-            Some(vec![Symbol::intern("gen_future")].into()),
+            Some(vec![sym::gen_future].into()),
         );
 
         // let mut pinned = <expr>;
         let expr = P(self.lower_expr(expr));
-        let pinned_ident = self.str_to_ident("pinned");
+        let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
         let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
             span,
             pinned_ident,
@@ -5621,11 +5614,11 @@ fn lower_await(
             ))
         };
 
-        // `::std::task::Poll::Ready(x) => break x`
+        // `::std::task::Poll::Ready(result) => break result`
         let loop_node_id = self.sess.next_node_id();
         let loop_hir_id = self.lower_node_id(loop_node_id);
         let ready_arm = {
-            let x_ident = self.str_to_ident("x");
+            let x_ident = Ident::with_empty_ctxt(sym::result);
             let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
             let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
             let ready_pat = self.pat_std_enum(
index 68b65f9b4a1ccfa9c948d76a4f1b8310e209f9a3..9c4683e094634eea384d348ff8c2b9785a6c6dfe 100644 (file)
@@ -778,6 +778,9 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
 
     let push = builder.levels.push(&krate.attrs);
     builder.levels.register_id(hir::CRATE_HIR_ID);
+    for macro_def in &krate.exported_macros {
+       builder.levels.register_id(macro_def.hir_id);
+    }
     intravisit::walk_crate(&mut builder, krate);
     builder.levels.pop(push);
 
index cb59cf41a3ca531a8adeecac42debee4d6279ed1..66ba95810a62516a109462f740955fed5c54afb8 100644 (file)
@@ -795,10 +795,10 @@ fn create_msvc_imps(
         return
     }
     // The x86 ABI seems to require that leading underscores are added to symbol
-    // names, so we need an extra underscore on 32-bit. There's also a leading
+    // names, so we need an extra underscore on x86. There's also a leading
     // '\x01' here which disables LLVM's symbol mangling (e.g., no extra
     // underscores added in front).
-    let prefix = if cgcx.target_pointer_width == "32" {
+    let prefix = if cgcx.target_arch == "x86" {
         "\x01__imp__"
     } else {
         "\x01__imp_"
index 6320d8a671ddbfd66f87de8060b86e9641839956..1c793996c83db65cc1cc2960546f358197812253 100644 (file)
@@ -248,6 +248,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub tm_factory: TargetMachineFactory<B>,
     pub msvc_imps_needed: bool,
     pub target_pointer_width: String,
+    pub target_arch: String,
     pub debuginfo: config::DebugInfo,
 
     // Number of cgus excluding the allocator/metadata modules
@@ -1103,6 +1104,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         total_cgus,
         msvc_imps_needed: msvc_imps_needed(tcx),
         target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
+        target_arch: tcx.sess.target.target.arch.clone(),
         debuginfo: tcx.sess.opts.debuginfo,
         assembler_cmd,
     };
index 4e214c3c7253ee71d8455d5e0cf5d6367a895041..8f3dd72c4f2450a82ca151b53d8ebbe9128b72d6 100644 (file)
@@ -546,6 +546,10 @@ fn replace_with_const(&self, rval: &mut Rvalue<'tcx>, value: Const<'tcx>, span:
             }
         }
     }
+
+    fn should_const_prop(&self) -> bool {
+        self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2
+    }
 }
 
 fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -639,7 +643,7 @@ fn visit_statement(
                             assert!(self.places[local].is_none());
                             self.places[local] = Some(value);
 
-                            if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
+                            if self.should_const_prop() {
                                 self.replace_with_const(rval, value, statement.source_info.span);
                             }
                         }
@@ -656,75 +660,112 @@ fn visit_terminator(
         location: Location,
     ) {
         self.super_terminator(terminator, location);
-        let source_info = terminator.source_info;;
-        if let TerminatorKind::Assert { expected, msg, cond, .. } = &terminator.kind {
-            if let Some(value) = self.eval_operand(&cond, source_info) {
-                trace!("assertion on {:?} should be {:?}", value, expected);
-                let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
-                if expected != self.ecx.read_scalar(value).unwrap() {
-                    // poison all places this operand references so that further code
-                    // doesn't use the invalid value
-                    match cond {
-                        Operand::Move(ref place) | Operand::Copy(ref place) => {
-                            let mut place = place;
-                            while let Place::Projection(ref proj) = *place {
-                                place = &proj.base;
-                            }
-                            if let Place::Base(PlaceBase::Local(local)) = *place {
-                                self.places[local] = None;
+        let source_info = terminator.source_info;
+        match &mut terminator.kind {
+            TerminatorKind::Assert { expected, msg, ref mut cond, .. } => {
+                if let Some(value) = self.eval_operand(&cond, source_info) {
+                    trace!("assertion on {:?} should be {:?}", value, expected);
+                    let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
+                    let value_const = self.ecx.read_scalar(value).unwrap();
+                    if expected != value_const {
+                        // poison all places this operand references so that further code
+                        // doesn't use the invalid value
+                        match cond {
+                            Operand::Move(ref place) | Operand::Copy(ref place) => {
+                                let mut place = place;
+                                while let Place::Projection(ref proj) = *place {
+                                    place = &proj.base;
+                                }
+                                if let Place::Base(PlaceBase::Local(local)) = *place {
+                                    self.places[local] = None;
+                                }
+                            },
+                            Operand::Constant(_) => {}
+                        }
+                        let span = terminator.source_info.span;
+                        let hir_id = self
+                            .tcx
+                            .hir()
+                            .as_local_hir_id(self.source.def_id())
+                            .expect("some part of a failing const eval must be local");
+                        use rustc::mir::interpret::InterpError::*;
+                        let msg = match msg {
+                            Overflow(_) |
+                            OverflowNeg |
+                            DivisionByZero |
+                            RemainderByZero => msg.description().to_owned(),
+                            BoundsCheck { ref len, ref index } => {
+                                let len = self
+                                    .eval_operand(len, source_info)
+                                    .expect("len must be const");
+                                let len = match self.ecx.read_scalar(len) {
+                                    Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
+                                        bits, ..
+                                    })) => bits,
+                                    other => bug!("const len not primitive: {:?}", other),
+                                };
+                                let index = self
+                                    .eval_operand(index, source_info)
+                                    .expect("index must be const");
+                                let index = match self.ecx.read_scalar(index) {
+                                    Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
+                                        bits, ..
+                                    })) => bits,
+                                    other => bug!("const index not primitive: {:?}", other),
+                                };
+                                format!(
+                                    "index out of bounds: \
+                                    the len is {} but the index is {}",
+                                    len,
+                                    index,
+                                )
+                            },
+                            // Need proper const propagator for these
+                            _ => return,
+                        };
+                        self.tcx.lint_hir(
+                            ::rustc::lint::builtin::CONST_ERR,
+                            hir_id,
+                            span,
+                            &msg,
+                        );
+                    } else {
+                        if self.should_const_prop() {
+                            if let ScalarMaybeUndef::Scalar(scalar) = value_const {
+                                *cond = self.operand_from_scalar(
+                                    scalar,
+                                    self.tcx.types.bool,
+                                    source_info.span,
+                                );
                             }
-                        },
-                        Operand::Constant(_) => {}
+                        }
                     }
-                    let span = terminator.source_info.span;
-                    let hir_id = self
-                        .tcx
-                        .hir()
-                        .as_local_hir_id(self.source.def_id())
-                        .expect("some part of a failing const eval must be local");
-                    use rustc::mir::interpret::InterpError::*;
-                    let msg = match msg {
-                        Overflow(_) |
-                        OverflowNeg |
-                        DivisionByZero |
-                        RemainderByZero => msg.description().to_owned(),
-                        BoundsCheck { ref len, ref index } => {
-                            let len = self
-                                .eval_operand(len, source_info)
-                                .expect("len must be const");
-                            let len = match self.ecx.read_scalar(len) {
-                                Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
-                                    bits, ..
-                                })) => bits,
-                                other => bug!("const len not primitive: {:?}", other),
-                            };
-                            let index = self
-                                .eval_operand(index, source_info)
-                                .expect("index must be const");
-                            let index = match self.ecx.read_scalar(index) {
-                                Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
-                                    bits, ..
-                                })) => bits,
-                                other => bug!("const index not primitive: {:?}", other),
-                            };
-                            format!(
-                                "index out of bounds: \
-                                the len is {} but the index is {}",
-                                len,
-                                index,
-                            )
-                        },
-                        // Need proper const propagator for these
-                        _ => return,
-                    };
-                    self.tcx.lint_hir(
-                        ::rustc::lint::builtin::CONST_ERR,
-                        hir_id,
-                        span,
-                        &msg,
-                    );
                 }
-            }
+            },
+            TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => {
+                if self.should_const_prop() {
+                    if let Some(value) = self.eval_operand(&discr, source_info) {
+                        if let ScalarMaybeUndef::Scalar(scalar) =
+                                self.ecx.read_scalar(value).unwrap() {
+                            *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span);
+                        }
+                    }
+                }
+            },
+            //none of these have Operands to const-propagate
+            TerminatorKind::Goto { .. } |
+            TerminatorKind::Resume |
+            TerminatorKind::Abort |
+            TerminatorKind::Return |
+            TerminatorKind::Unreachable |
+            TerminatorKind::Drop { .. } |
+            TerminatorKind::DropAndReplace { .. } |
+            TerminatorKind::Yield { .. } |
+            TerminatorKind::GeneratorDrop |
+            TerminatorKind::FalseEdges { .. } |
+            TerminatorKind::FalseUnwind { .. } => { }
+            //FIXME(wesleywiser) Call does have Operands that could be const-propagated
+            TerminatorKind::Call { .. } => { }
         }
     }
 }
index f91cb469e462992755890455c1501e86d64a266c..e434623d4a12759fe3f1bb82cef4fa0cd11fca18 100644 (file)
@@ -3408,6 +3408,7 @@ pub struct Span {
     pub locol: usize,
     pub hiline: usize,
     pub hicol: usize,
+    pub original: syntax_pos::Span,
 }
 
 impl Span {
@@ -3416,8 +3417,13 @@ pub fn empty() -> Span {
             filename: FileName::Anon(0),
             loline: 0, locol: 0,
             hiline: 0, hicol: 0,
+            original: syntax_pos::DUMMY_SP,
         }
     }
+
+    pub fn span(&self) -> syntax_pos::Span {
+        self.original
+    }
 }
 
 impl Clean<Span> for syntax_pos::Span {
@@ -3436,6 +3442,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Span {
             locol: lo.col.to_usize(),
             hiline: hi.line,
             hicol: hi.col.to_usize(),
+            original: *self,
         }
     }
 }
index 9e108e605c8bba9fc42a9f57cb2a22a519fe911d..2c382a1c1759632806bb316f621aa582564b9fe0 100644 (file)
@@ -321,7 +321,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) {
                             res
                         } else {
-                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            resolution_failure(cx, &item, path_str, &dox, link_range);
                             // This could just be a normal link or a broken link
                             // we could potentially check if something is
                             // "intra-doc-link-like" and warn in that case.
@@ -332,7 +332,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) {
                             res
                         } else {
-                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            resolution_failure(cx, &item, path_str, &dox, link_range);
                             // This could just be a normal link.
                             continue;
                         }
@@ -357,7 +357,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         };
 
                         if candidates.is_empty() {
-                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            resolution_failure(cx, &item, path_str, &dox, link_range);
                             // this could just be a normal link
                             continue;
                         }
@@ -368,7 +368,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         } else {
                             ambiguity_error(
                                 cx,
-                                &item.attrs,
+                                &item,
                                 path_str,
                                 &dox,
                                 link_range,
@@ -381,7 +381,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         if let Some(res) = macro_resolve(cx, path_str) {
                             (res, None)
                         } else {
-                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            resolution_failure(cx, &item, path_str, &dox, link_range);
                             continue
                         }
                     }
@@ -452,16 +452,24 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
 /// line containing the failure as a note as well.
 fn resolution_failure(
     cx: &DocContext<'_>,
-    attrs: &Attributes,
+    item: &Item,
     path_str: &str,
     dox: &str,
     link_range: Option<Range<usize>>,
 ) {
+    let hir_id = match cx.as_local_hir_id(item.def_id) {
+        Some(hir_id) => hir_id,
+        None => {
+            // If non-local, no need to check anything.
+            return;
+        }
+    };
+    let attrs = &item.attrs;
     let sp = span_of_attrs(attrs);
 
     let mut diag = cx.tcx.struct_span_lint_hir(
         lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-        hir::CRATE_HIR_ID,
+        hir_id,
         sp,
         &format!("`[{}]` cannot be resolved, ignoring it...", path_str),
     );
@@ -495,12 +503,20 @@ fn resolution_failure(
 
 fn ambiguity_error(
     cx: &DocContext<'_>,
-    attrs: &Attributes,
+    item: &Item,
     path_str: &str,
     dox: &str,
     link_range: Option<Range<usize>>,
     candidates: PerNS<Option<Res>>,
 ) {
+    let hir_id = match cx.as_local_hir_id(item.def_id) {
+        Some(hir_id) => hir_id,
+        None => {
+            // If non-local, no need to check anything.
+            return;
+        }
+    };
+    let attrs = &item.attrs;
     let sp = span_of_attrs(attrs);
 
     let mut msg = format!("`{}` is ", path_str);
@@ -532,7 +548,7 @@ fn ambiguity_error(
 
     let mut diag = cx.tcx.struct_span_lint_hir(
         lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-        hir::CRATE_HIR_ID,
+        hir_id,
         sp,
         &msg,
     );
index 99aca0634710fdc88ac688cf1ffb45bac9ce7cba..d9af33ac5b622a39f288c14b3eca760c02900245 100644 (file)
@@ -1,7 +1,6 @@
 //! Contains information about "passes", used to modify crate information during the documentation
 //! process.
 
-use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::lint as lint;
 use rustc::middle::privacy::AccessLevels;
@@ -314,10 +313,13 @@ pub fn look_for_tests<'tcx>(
     item: &Item,
     check_missing_code: bool,
 ) {
-    if cx.as_local_hir_id(item.def_id).is_none() {
-        // If non-local, no need to check anything.
-        return;
-    }
+    let hir_id = match cx.as_local_hir_id(item.def_id) {
+        Some(hir_id) => hir_id,
+        None => {
+            // If non-local, no need to check anything.
+            return;
+        }
+    };
 
     struct Tests {
         found_tests: usize,
@@ -336,10 +338,11 @@ fn add_test(&mut self, _: String, _: LangString, _: usize) {
     find_testable_code(&dox, &mut tests, ErrorCodes::No);
 
     if check_missing_code == true && tests.found_tests == 0 {
+        let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span());
         let mut diag = cx.tcx.struct_span_lint_hir(
             lint::builtin::MISSING_DOC_CODE_EXAMPLES,
-            hir::CRATE_HIR_ID,
-            span_of_attrs(&item.attrs),
+            hir_id,
+            sp,
             "Missing code example in this documentation");
         diag.emit();
     } else if check_missing_code == false &&
@@ -347,7 +350,7 @@ fn add_test(&mut self, _: String, _: LangString, _: usize) {
               !cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) {
         let mut diag = cx.tcx.struct_span_lint_hir(
             lint::builtin::PRIVATE_DOC_TESTS,
-            hir::CRATE_HIR_ID,
+            hir_id,
             span_of_attrs(&item.attrs),
             "Documentation test in private item");
         diag.emit();
index 01b126f48b327151c0e988deec216b1a8372295e..97b22282668ad1b77d27e00391d49b0e5cb4fba4 100644 (file)
         eh_personality,
         eh_unwind_resume,
         enable,
+        err,
         Err,
         except,
         exclusive_range_pattern,
         fundamental,
         future,
         Future,
+        gen_future,
         generators,
         generic_associated_types,
         generic_param_attrs,
         never,
         never_type,
         next,
+        __next,
         nll,
         no_builtins,
         no_core,
         Pending,
         pin,
         Pin,
+        pinned,
         platform_intrinsics,
         plugin,
         plugin_registrar,
         trivial_bounds,
         Try,
         try_blocks,
+        try_trait,
         tuple_indexing,
         ty,
         type_alias_enum_variants,
         uniform_paths,
         universal_impl_trait,
         unmarked_api,
+        unreachable_code,
         unrestricted_attribute_tokens,
         unsafe_destructor_blind_to_params,
         unsafe_no_drop_flag,
         use_nested_groups,
         usize,
         v1,
+        val,
         vis,
         visible_private_types,
         volatile,
index c6afa90e4ee614d5c85d2961c8b1bff7424d955f..7f7db2a21251ac8864bcc07faf4a30001c2d6634 100644 (file)
 use term;
 
 // FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind
-//                on aarch64-pc-windows-msvc, so we don't link libtest against
-//                libunwind (for the time being), even though it means that
-//                libtest won't be fully functional on this platform.
+//                on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc
+//                so we don't link libtest against libunwind (for the time being)
+//                even though it means that libtest won't be fully functional on
+//                these platforms.
 //
 // See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437
-#[cfg(not(all(windows, target_arch = "aarch64")))]
+#[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))]
 extern crate panic_unwind;
 
 pub use self::ColorConfig::*;
index 4b97af68ff08af727a4f923e58c95e9ed4e4bedf..dd22eb5d604ea51b84d8586ebfc26c6e16bcb038 100644 (file)
@@ -23,7 +23,7 @@ fn main() {
 //  bb0: {
 //      ...
 //      _5 = const true;
-//      assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
+//      assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
 //  }
 //  bb1: {
 //      _1 = _2[_3];
index 0718316307c5edbb5dda0f88983a9c33196079d8..fe98cf24eec009ecc6416033e5b7a38e787a6dae 100644 (file)
@@ -16,6 +16,6 @@ fn main() {
 //  bb0: {
 //      ...
 //      _2 = (const 2u32, const false);
-//      assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1;
+//      assert(!const false, "attempt to add with overflow") -> bb1;
 //  }
 // END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/switch_int.rs b/src/test/mir-opt/const_prop/switch_int.rs
new file mode 100644 (file)
index 0000000..0df1112
--- /dev/null
@@ -0,0 +1,38 @@
+#[inline(never)]
+fn foo(_: i32) { }
+
+fn main() {
+    match 1 {
+        1 => foo(0),
+        _ => foo(-1),
+    }
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _1 = const 1i32;
+//      switchInt(_1) -> [1i32: bb1, otherwise: bb2];
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2];
+//  }
+// END rustc.main.ConstProp.after.mir
+// START rustc.main.SimplifyBranches-after-const-prop.before.mir
+//  bb0: {
+//      ...
+//      _1 = const 1i32;
+//      switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2];
+//  }
+// END rustc.main.SimplifyBranches-after-const-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.after.mir
+//  bb0: {
+//      ...
+//      _1 = const 1i32;
+//      goto -> bb1;
+//  }
+// END rustc.main.SimplifyBranches-after-const-prop.after.mir
index b2a99a6d446bbfe113c245ef2c0a33462371e38e..35512b94c0c8cf8f96c87db6ab2350ae51118525 100644 (file)
@@ -5,15 +5,15 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.main.SimplifyBranches-after-copy-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.before.mir
 // bb0: {
 //     ...
 //     switchInt(const false) -> [false: bb3, otherwise: bb1];
 // }
-// END rustc.main.SimplifyBranches-after-copy-prop.before.mir
-// START rustc.main.SimplifyBranches-after-copy-prop.after.mir
+// END rustc.main.SimplifyBranches-after-const-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.after.mir
 // bb0: {
 //     ...
 //     goto -> bb3;
 // }
-// END rustc.main.SimplifyBranches-after-copy-prop.after.mir
+// END rustc.main.SimplifyBranches-after-const-prop.after.mir
diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs
new file mode 100644 (file)
index 0000000..bd84b46
--- /dev/null
@@ -0,0 +1,51 @@
+// run-pass
+#![allow(dead_code)]
+
+// Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations.
+//
+// For example, if a union `U` can contain both a `&T` and a `*const T`, there's definitely no
+// bit-value that an `Option<U>` could reuse as `None`; this test makes sure that isn't done.
+//
+// Secondly, this tests the status quo (not a guarantee; subject to change!) to not apply such
+// optimizations to types containing unions even if they're theoretically possible. (discussion:
+// https://github.com/rust-lang/rust/issues/36394)
+//
+// Notably this nails down part of the behavior that `MaybeUninit` assumes: that a
+// `Option<MaybeUninit<&u8>>` does not take advantage of non-zero optimization, and thus is a safe
+// construct.
+
+use std::mem::{size_of, transmute};
+
+union U1<A: Copy> {
+    a: A,
+}
+
+union U2<A: Copy, B: Copy> {
+    a: A,
+    b: B,
+}
+
+// Option<E> uses a value other than 0 and 1 as None
+#[derive(Clone,Copy)]
+enum E {
+    A = 0,
+    B = 1,
+}
+
+fn main() {
+    // Unions do not participate in niche-filling/non-zero optimization...
+    assert!(size_of::<Option<U2<&u8, u8>>>() > size_of::<U2<&u8, u8>>());
+    assert!(size_of::<Option<U2<&u8, ()>>>() > size_of::<U2<&u8, ()>>());
+    assert!(size_of::<Option<U2<u8, E>>>() > size_of::<U2<u8, E>>());
+
+    // ...even when theoretically possible:
+    assert!(size_of::<Option<U1<&u8>>>() > size_of::<U1<&u8>>());
+    assert!(size_of::<Option<U2<&u8, &u8>>>() > size_of::<U2<&u8, &u8>>());
+
+    // The unused bits of the () variant can have any value.
+    let zeroed: U2<&u8, ()> = unsafe { transmute(std::ptr::null::<u8>()) };
+
+    if let None = Some(zeroed) {
+        panic!()
+    }
+}
index aa3f539ba32a314c3961181b4e54fabbbf807e67..4b2a91e9c812722f4a6f66beb1692e8ea56037a6 100644 (file)
@@ -1,6 +1,4 @@
-//~ ERROR Missing code example in this documentation
-
-#![deny(missing_doc_code_examples)]
+#![deny(missing_doc_code_examples)] //~ ERROR Missing code example in this documentation
 
 /// Some docs.
 //~^ ERROR Missing code example in this documentation
index 208bdedf24ddb6b10aebd044bdfc6b5118fb770e..23c07c4d32d64359d43a4a4ead40dbac4ba40050 100644 (file)
@@ -1,25 +1,35 @@
 error: Missing code example in this documentation
+  --> $DIR/doc-without-codeblock.rs:1:1
+   |
+LL | / #![deny(missing_doc_code_examples)]
+LL | |
+LL | | /// Some docs.
+LL | |
+...  |
+LL | |     pub fn bar() {}
+LL | | }
+   | |_^
    |
 note: lint level defined here
-  --> $DIR/doc-without-codeblock.rs:3:9
+  --> $DIR/doc-without-codeblock.rs:1:9
    |
 LL | #![deny(missing_doc_code_examples)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Missing code example in this documentation
-  --> $DIR/doc-without-codeblock.rs:5:1
+  --> $DIR/doc-without-codeblock.rs:3:1
    |
 LL | /// Some docs.
    | ^^^^^^^^^^^^^^
 
 error: Missing code example in this documentation
-  --> $DIR/doc-without-codeblock.rs:9:1
+  --> $DIR/doc-without-codeblock.rs:7:1
    |
 LL | /// And then, the princess died.
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Missing code example in this documentation
-  --> $DIR/doc-without-codeblock.rs:12:5
+  --> $DIR/doc-without-codeblock.rs:10:5
    |
 LL |     /// Or maybe not because she saved herself!
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs
new file mode 100644 (file)
index 0000000..ffe0ddc
--- /dev/null
@@ -0,0 +1,40 @@
+#![deny(missing_docs)]
+#![deny(missing_doc_code_examples)]
+
+//! crate level doc
+//! ```
+//! println!("hello"):
+//! ```
+
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+fn test() {
+}
+
+#[allow(missing_docs)]
+mod module1 { //~ ERROR
+}
+
+#[allow(missing_doc_code_examples)]
+/// doc
+mod module2 {
+
+  /// doc
+  pub fn test() {}
+}
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+pub mod module3 {
+
+  /// doc
+  //~^ ERROR
+  pub fn test() {}
+}
diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
new file mode 100644 (file)
index 0000000..97a52a1
--- /dev/null
@@ -0,0 +1,21 @@
+error: Missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:19:1
+   |
+LL | / mod module1 {
+LL | | }
+   | |_^
+   |
+note: lint level defined here
+  --> $DIR/lint-missing-doc-code-example.rs:2:9
+   |
+LL | #![deny(missing_doc_code_examples)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:37:3
+   |
+LL |   /// doc
+   |   ^^^^^^^
+
+error: aborting due to 2 previous errors
+
index bed1e32a60158110c5182368ac219abdaf61c402..0127261b2b7d0a6111f68b71c1af2690c5c7819b 100644 (file)
@@ -57,6 +57,15 @@ pub enum Enum4<A, B, C, D> {
     Four(D)
 }
 
+pub union Union1<A: Copy> {
+    a: A,
+}
+
+pub union Union2<A: Copy, B: Copy> {
+    a: A,
+    b: B,
+}
+
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
     let _x: MyOption<NonZeroU32> = Default::default();
@@ -69,5 +78,13 @@ fn start(_: isize, _: *const *const u8) -> isize {
     let _e: Enum4<(), char, (), ()> = Enum4::One(());
     let _f: Enum4<(), (), bool, ()> = Enum4::One(());
     let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
+
+    // Unions do not currently participate in niche filling.
+    let _h: MyOption<Union2<NonZeroU32, u32>> = Default::default();
+
+    // ...even when theoretically possible.
+    let _i: MyOption<Union1<NonZeroU32>> = Default::default();
+    let _j: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
+
     0
 }
index 9cdb2ae4f57e0aeb99097f211545210d8c75f1c2..301edc0d086b11fee1b251fd47b5ab7ebba36190 100644 (file)
@@ -14,6 +14,21 @@ print-type-size         field `.post`: 2 bytes
 print-type-size         field `.pre`: 1 bytes
 print-type-size     variant `None`: 0 bytes
 print-type-size     end padding: 1 bytes
+print-type-size type: `MyOption<Union1<std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `Some`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZeroU32, std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `Some`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZeroU32, u32>>`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `Some`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes
 print-type-size     field `.val`: 4 bytes
 print-type-size     field `.post`: 2 bytes
@@ -36,6 +51,17 @@ print-type-size type: `MyOption<std::num::NonZeroU32>`: 4 bytes, alignment: 4 by
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
 print-type-size     variant `None`: 0 bytes
+print-type-size type: `Union1<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Union1`: 4 bytes
+print-type-size         field `.a`: 4 bytes
+print-type-size type: `Union2<std::num::NonZeroU32, std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Union2`: 4 bytes
+print-type-size         field `.a`: 4 bytes
+print-type-size         field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
+print-type-size type: `Union2<std::num::NonZeroU32, u32>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Union2`: 4 bytes
+print-type-size         field `.a`: 4 bytes
+print-type-size         field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
 print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes
 print-type-size     field `.0`: 4 bytes
 print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes