]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #52196 - ollie27:rustdoc_ctor_imports, r=QuietMisdreavus
authorbors <bors@rust-lang.org>
Tue, 10 Jul 2018 17:29:30 +0000 (17:29 +0000)
committerbors <bors@rust-lang.org>
Tue, 10 Jul 2018 17:29:30 +0000 (17:29 +0000)
rustdoc: Hide struct and enum variant constructor imports

This is fallout from #51425. The duplicate variant imports can be seen [here](https://doc.rust-lang.org/nightly/std/prelude/v1/index.html) for example.

This is fixing a regression so could be backported to beta.

r? @QuietMisdreavus

79 files changed:
.travis.yml
src/bootstrap/dist.rs
src/bootstrap/native.rs
src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile [deleted file]
src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile [new file with mode: 0644]
src/libcore/alloc.rs
src/librustc/hir/mod.rs
src/librustc/lint/levels.rs
src/librustc/middle/dead.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/session/mod.rs
src/librustc/ty/layout.rs
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/mir/mod.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_codegen_llvm/mir/place.rs
src/librustc_codegen_llvm/mir/rvalue.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_driver/lib.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_resolve/lib.rs
src/librustc_traits/lowering.rs
src/librustc_typeck/check/mod.rs
src/librustdoc/core.rs
src/libstd/alloc.rs
src/libstd/lib.rs
src/libsyntax/codemap.rs
src/libsyntax/feature_gate.rs
src/rustllvm/RustWrapper.cpp
src/test/codegen/call-metadata.rs
src/test/codegen/function-arguments.rs
src/test/codegen/issue-37945.rs
src/test/codegen/issue-45466.rs
src/test/codegen/mainsubprogram.rs
src/test/codegen/mainsubprogramstart.rs
src/test/codegen/noreturnflag.rs
src/test/codegen/scalar-pair-bool.rs [new file with mode: 0644]
src/test/codegen/stack-probes.rs
src/test/codegen/vtabletype.rs
src/test/compile-fail/alloc-error-handler-bad-signature-1.rs [new file with mode: 0644]
src/test/compile-fail/alloc-error-handler-bad-signature-2.rs [new file with mode: 0644]
src/test/compile-fail/alloc-error-handler-bad-signature-3.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-alloc-error-handler.rs [new file with mode: 0644]
src/test/compile-fail/simd-intrinsic-generic-reduction.rs
src/test/mir-opt/lower_128bit_test.rs
src/test/run-make-fulldeps/cross-lang-lto/Makefile
src/test/run-make-fulldeps/issue-51671/app.rs
src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc
src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc
src/test/run-pass/default-alloc-error-hook.rs [new file with mode: 0644]
src/test/run-pass/issue-40883.rs
src/test/run-pass/simd-intrinsic-generic-reduction.rs
src/test/run-pass/stack-probes-lto.rs
src/test/run-pass/stack-probes.rs
src/test/run-pass/thin-lto-global-allocator.rs
src/test/run-pass/thinlto/all-crates.rs
src/test/run-pass/thinlto/dylib-works.rs
src/test/run-pass/thinlto/msvc-imp-present.rs
src/test/run-pass/thinlto/thin-lto-inlines.rs
src/test/run-pass/thinlto/thin-lto-inlines2.rs
src/test/run-pass/thinlto/weak-works.rs
src/test/rustdoc-ui/unused.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-7573.nll.stderr
src/test/ui/chalkify/lower_env1.stderr
src/test/ui/chalkify/lower_trait.stderr
src/test/ui/chalkify/lower_trait_higher_rank.stderr
src/test/ui/chalkify/lower_trait_where_clause.stderr
src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr
src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
src/test/ui/missing-alloc_error_handler.rs [new file with mode: 0644]
src/test/ui/missing-alloc_error_handler.stderr [new file with mode: 0644]
src/test/ui/missing-allocator.rs
src/test/ui/rust-2018/issue-52202-use-suggestions.rs [new file with mode: 0644]
src/test/ui/rust-2018/issue-52202-use-suggestions.stderr [new file with mode: 0644]
src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr

index ba8a39f355c4ba0544643f7dd9900471bd98f81e..2cf10d76098011b87ecfc17d49f45339195bd91f 100644 (file)
@@ -12,7 +12,7 @@ matrix:
   fast_finish: true
   include:
     # Images used in testing PR and try-build should be run first.
-    - env: IMAGE=x86_64-gnu-llvm-3.9 RUST_BACKTRACE=1
+    - env: IMAGE=x86_64-gnu-llvm-5.0 RUST_BACKTRACE=1
       if: type = pull_request OR branch = auto
 
     - env: IMAGE=dist-x86_64-linux DEPLOY=1
index 0587dc8896d15a34546e21e34d19e1dbacf51a1e..e4fbabdf2318f527d63c97d950928f00e71458a9 100644 (file)
@@ -308,6 +308,14 @@ fn make_win_dist(
         builder.copy_to_folder(&src, &target_bin_dir);
     }
 
+    // Warn windows-gnu users that the bundled GCC cannot compile C files
+    builder.create(
+        &target_bin_dir.join("GCC-WARNING.txt"),
+        "gcc.exe contained in this folder cannot be used for compiling C files - it is only\
+         used as a linker. In order to be able to compile projects containing C code use\
+         the GCC provided by MinGW or Cygwin."
+    );
+
     //Copy platform libs to platform-specific lib directory
     let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
     fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
index 93b8880a900ef5539378d457d8f51fe73666f8dc..264acfacee6b0f45eaa87a8969f5f93fb6d0c86c 100644 (file)
@@ -256,12 +256,12 @@ fn check_llvm_version(builder: &Builder, llvm_config: &Path) {
     let version = output(cmd.arg("--version"));
     let mut parts = version.split('.').take(2)
         .filter_map(|s| s.parse::<u32>().ok());
-    if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
-        if major > 3 || (major == 3 && minor >= 9) {
+    if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
+        if major >= 5 {
             return
         }
     }
-    panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version)
+    panic!("\n\nbad LLVM version: {}, need >=5.0\n\n", version)
 }
 
 fn configure_cmake(builder: &Builder,
diff --git a/src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile
deleted file mode 100644 (file)
index 6b81860..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  file \
-  curl \
-  ca-certificates \
-  python2.7 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  llvm-3.9-tools \
-  libedit-dev \
-  zlib1g-dev \
-  xz-utils
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-# using llvm-link-shared due to libffi issues -- see #34486
-ENV RUST_CONFIGURE_ARGS \
-      --build=x86_64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-3.9 \
-      --enable-llvm-link-shared
-ENV RUST_CHECK_TARGET check
diff --git a/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-5.0/Dockerfile
new file mode 100644 (file)
index 0000000..4f90c50
--- /dev/null
@@ -0,0 +1,27 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  llvm-5.0-tools \
+  libedit-dev \
+  zlib1g-dev \
+  xz-utils
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+      --build=x86_64-unknown-linux-gnu \
+      --llvm-root=/usr/lib/llvm-5.0 \
+      --enable-llvm-link-shared
+ENV RUST_CHECK_TARGET check
index 01221aecb6284651aee6a4bf9189b90ec5ca0281..b6ac248b79f8666331ab77c82d7aa9d311b188ff 100644 (file)
@@ -48,6 +48,7 @@ fn size_align<T>() -> (usize, usize) {
 /// use specific allocators with looser requirements.)
 #[stable(feature = "alloc_layout", since = "1.28.0")]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[cfg_attr(not(stage0), lang = "alloc_layout")]
 pub struct Layout {
     // size of the requested block of memory, measured in bytes.
     size_: usize,
index 8d83dd3279c64d4b690c33608b3258128856e7b6..f18846b8574df4ae347fc2f821dc0ae28027dd66 100644 (file)
@@ -402,6 +402,15 @@ pub enum GenericArg {
     Type(Ty),
 }
 
+impl GenericArg {
+    pub fn span(&self) -> Span {
+        match self {
+            GenericArg::Lifetime(l) => l.span,
+            GenericArg::Type(t) => t.span,
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct GenericArgs {
     /// The generic arguments for this path segment.
index 5bf15b10715c4a68ddeb7fc76b1b6410ee61b550..a1b84a7b716efdf4d4c9ea750bb34da9db858911 100644 (file)
@@ -119,6 +119,11 @@ fn get_lint_level(&self,
         // Ensure that we never exceed the `--cap-lints` argument.
         level = cmp::min(level, self.lint_cap);
 
+        if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
+            // Ensure that we never exceed driver level.
+            level = cmp::min(*driver_level, level);
+        }
+
         return (level, src)
     }
 
index 226d19a91240f3d081670b1f7661e9a90445394b..42775e3a1837ff4f63d1e62fb2185efec8afd8d8 100644 (file)
@@ -288,7 +288,17 @@ fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) {
 fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt,
                                     id: ast::NodeId,
                                     attrs: &[ast::Attribute]) -> bool {
-    if attr::contains_name(attrs, "lang") || attr::contains_name(attrs, "panic_implementation") {
+    if attr::contains_name(attrs, "lang") {
+        return true;
+    }
+
+    // (To be) stable attribute for #[lang = "panic_impl"]
+    if attr::contains_name(attrs, "panic_implementation") {
+        return true;
+    }
+
+    // (To be) stable attribute for #[lang = "oom"]
+    if attr::contains_name(attrs, "alloc_error_handler") {
         return true;
     }
 
index fe676919a7d14d23aa08e0050e01869bcfdfb7e2..6c1ef851cbeca6fe4e2abac010e76a84c9602571 100644 (file)
@@ -187,6 +187,8 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
             }
         } else if attribute.check_name("panic_implementation") {
             return Some((Symbol::intern("panic_impl"), attribute.span))
+        } else if attribute.check_name("alloc_error_handler") {
+            return Some((Symbol::intern("oom"), attribute.span))
         }
     }
 
@@ -308,6 +310,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     BoxFreeFnLangItem,               "box_free",                box_free_fn;
     DropInPlaceFnLangItem,           "drop_in_place",           drop_in_place_fn;
     OomLangItem,                     "oom",                     oom;
+    AllocLayoutLangItem,             "alloc_layout",            alloc_layout;
 
     StartFnLangItem,                 "start",                   start_fn;
 
index 180e75df1a66ec55545fbae6c6f97807c020a132..d8570b43fbe276dc32d86cf4baaa582cb0915da7 100644 (file)
@@ -115,6 +115,9 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             if lang_items::$item == lang_items::PanicImplLangItem {
                 tcx.sess.err(&format!("`#[panic_implementation]` function required, \
                                         but not found"));
+            } else if lang_items::$item == lang_items::OomLangItem {
+                tcx.sess.err(&format!("`#[alloc_error_handler]` function required, \
+                                        but not found"));
             } else {
                 tcx.sess.err(&format!("language item required, but not found: `{}`",
                                         stringify!($name)));
index 076d56fb80842cab1c4efbe9677086fae7af1cf7..180c5867e93d8bd9c359d6db2ca26f5faed706f5 100644 (file)
@@ -22,7 +22,7 @@
 use session::search_paths::PathKind;
 use session::config::{OutputType};
 use ty::tls;
-use util::nodemap::{FxHashSet};
+use util::nodemap::{FxHashMap, FxHashSet};
 use util::common::{duration_to_secs_str, ErrorReported};
 use util::common::ProfileQueriesMsg;
 
@@ -160,6 +160,9 @@ pub struct Session {
 
     /// Metadata about the allocators for the current crate being compiled
     pub has_global_allocator: Once<bool>,
+
+    /// Cap lint level specified by a driver specifically.
+    pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
 }
 
 pub struct PerfStats {
@@ -1164,6 +1167,7 @@ pub fn build_session_(
             (*GLOBAL_JOBSERVER).clone()
         },
         has_global_allocator: Once::new(),
+        driver_lint_caps: FxHashMap(),
     };
 
     sess
index a32fdbb285d12cdae128c30dcf4a80077589893b..faad32a5d994ec3402fa659295787672457ce82b 100644 (file)
@@ -1020,13 +1020,8 @@ enum StructKind {
                 let mut abi = Abi::Aggregate { sized: true };
                 if tag.value.size(dl) == size {
                     abi = Abi::Scalar(tag.clone());
-                } else if !tag.is_bool() {
-                    // HACK(nox): Blindly using ScalarPair for all tagged enums
-                    // where applicable leads to Option<u8> being handled as {i1, i8},
-                    // which later confuses SROA and some loop optimisations,
-                    // ultimately leading to the repeat-trusted-len test
-                    // failing. We make the trade-off of using ScalarPair only
-                    // for types where the tag isn't a boolean.
+                } else {
+                    // Try to use a ScalarPair for all tagged enums.
                     let mut common_prim = None;
                     for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) {
                         let offsets = match layout_variant.fields {
index 6b5baa402b4ab88642e0821004e65e2a6bd2efbe..a4fb0378e57a3cae99398546cd2458db873c9b45 100644 (file)
@@ -582,8 +582,8 @@ fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
                 PassMode::Ignore => continue,
                 PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx),
                 PassMode::Pair(..) => {
-                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0));
-                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1));
+                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0, true));
+                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true));
                     continue;
                 }
                 PassMode::Cast(cast) => cast.llvm_type(cx),
@@ -666,11 +666,7 @@ fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) {
                 layout::Int(..) if !scalar.is_bool() => {
                     let range = scalar.valid_range_exclusive(bx.cx);
                     if range.start != range.end {
-                        // FIXME(nox): This causes very weird type errors about
-                        // SHL operators in constants in stage 2 with LLVM 3.9.
-                        if unsafe { llvm::LLVMRustVersionMajor() >= 4 } {
-                            bx.range_metadata(callsite, range);
-                        }
+                        bx.range_metadata(callsite, range);
                     }
                 }
                 _ => {}
index f9d8431943378225d7cc25aa3099ff8861da899b..2598e7c86f9dac67de3048754a2e773ca2df896b 100644 (file)
@@ -266,8 +266,8 @@ pub fn unsize_thin_ptr<'a, 'tcx>(
             }
             let (lldata, llextra) = result.unwrap();
             // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
-            (bx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bx.cx, 0)),
-             bx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bx.cx, 1)))
+            (bx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bx.cx, 0, true)),
+             bx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bx.cx, 1, true)))
         }
         _ => bug!("unsize_thin_ptr: called on bad types"),
     }
@@ -397,9 +397,14 @@ pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef {
 
 pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef {
     if let layout::Abi::Scalar(ref scalar) = layout.abi {
-        if scalar.is_bool() {
-            return bx.trunc(val, Type::i1(bx.cx));
-        }
+        return to_immediate_scalar(bx, val, scalar);
+    }
+    val
+}
+
+pub fn to_immediate_scalar(bx: &Builder, val: ValueRef, scalar: &layout::Scalar) -> ValueRef {
+    if scalar.is_bool() {
+        return bx.trunc(val, Type::i1(bx.cx));
     }
     val
 }
index f9be91b4f3f13d93d2ae1ad16f66b31c1e03cbc0..608539dd3fa7e3367915bd748a12f07a03789759 100644 (file)
@@ -22,7 +22,7 @@
 use common::{CodegenCx, Funclet};
 use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
 use monomorphize::Instance;
-use abi::{ArgAttribute, ArgTypeExt, FnType, FnTypeExt, PassMode};
+use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode};
 use type_::Type;
 
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
@@ -430,10 +430,6 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
         None
     };
 
-    let deref_op = unsafe {
-        [llvm::LLVMRustDIBuilderCreateOpDeref()]
-    };
-
     mir.args_iter().enumerate().map(|(arg_index, local)| {
         let arg_decl = &mir.local_decls[local];
 
@@ -543,21 +539,11 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             if arg_index > 0 || mir.upvar_decls.is_empty() {
                 // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
                 // need to insert a deref here, but the C ABI uses a pointer and a copy using the
-                // byval attribute, for which LLVM does the deref itself, so we must not add it.
-                // Starting with D31439 in LLVM 5, it *always* does the deref itself.
-                let mut variable_access = VariableAccess::DirectVariable {
+                // byval attribute, for which LLVM always does the deref itself,
+                // so we must not add it.
+                let variable_access = VariableAccess::DirectVariable {
                     alloca: place.llval
                 };
-                if unsafe { llvm::LLVMRustVersionMajor() < 5 } {
-                    if let PassMode::Indirect(ref attrs) = arg.mode {
-                        if !attrs.contains(ArgAttribute::ByVal) {
-                            variable_access = VariableAccess::IndirectVariable {
-                                alloca: place.llval,
-                                address_operations: &deref_op,
-                            };
-                        }
-                    }
-                }
 
                 declare_local(
                     bx,
index 3d3a4400bd8108abca11973e5693f839dbc5fc32..5d36eef99af2d393c8124c84a2fb31b49dd0552b 100644 (file)
@@ -18,7 +18,7 @@
 use rustc_data_structures::sync::Lrc;
 
 use base;
-use common::{self, CodegenCx, C_null, C_undef, C_usize};
+use common::{CodegenCx, C_null, C_undef, C_usize};
 use builder::{Builder, MemFlags};
 use value::Value;
 use type_of::LayoutLlvmExt;
@@ -128,13 +128,13 @@ pub fn from_const(bx: &Builder<'a, 'tcx>,
                     bx.cx,
                     a,
                     a_scalar,
-                    layout.scalar_pair_element_llvm_type(bx.cx, 0),
+                    layout.scalar_pair_element_llvm_type(bx.cx, 0, true),
                 );
                 let b_llval = scalar_to_llvm(
                     bx.cx,
                     b,
                     b_scalar,
-                    layout.scalar_pair_element_llvm_type(bx.cx, 1),
+                    layout.scalar_pair_element_llvm_type(bx.cx, 1, true),
                 );
                 OperandValue::Pair(a_llval, b_llval)
             },
@@ -193,8 +193,8 @@ pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'tcx>) -> ValueRef {
                    self, llty);
             // Reconstruct the immediate aggregate.
             let mut llpair = C_undef(llty);
-            llpair = bx.insert_value(llpair, a, 0);
-            llpair = bx.insert_value(llpair, b, 1);
+            llpair = bx.insert_value(llpair, base::from_immediate(bx, a), 0);
+            llpair = bx.insert_value(llpair, base::from_immediate(bx, b), 1);
             llpair
         } else {
             self.immediate()
@@ -206,13 +206,14 @@ pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'tcx>,
                                          llval: ValueRef,
                                          layout: TyLayout<'tcx>)
                                          -> OperandRef<'tcx> {
-        let val = if layout.is_llvm_scalar_pair() {
+        let val = if let layout::Abi::ScalarPair(ref a, ref b) = layout.abi {
             debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}",
                     llval, layout);
 
             // Deconstruct the immediate aggregate.
-            OperandValue::Pair(bx.extract_value(llval, 0),
-                               bx.extract_value(llval, 1))
+            let a_llval = base::to_immediate_scalar(bx, bx.extract_value(llval, 0), a);
+            let b_llval = base::to_immediate_scalar(bx, bx.extract_value(llval, 1), b);
+            OperandValue::Pair(a_llval, b_llval)
         } else {
             OperandValue::Immediate(llval)
         };
@@ -264,8 +265,8 @@ pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx
                 *llval = bx.bitcast(*llval, field.immediate_llvm_type(bx.cx));
             }
             OperandValue::Pair(ref mut a, ref mut b) => {
-                *a = bx.bitcast(*a, field.scalar_pair_element_llvm_type(bx.cx, 0));
-                *b = bx.bitcast(*b, field.scalar_pair_element_llvm_type(bx.cx, 1));
+                *a = bx.bitcast(*a, field.scalar_pair_element_llvm_type(bx.cx, 0, true));
+                *b = bx.bitcast(*b, field.scalar_pair_element_llvm_type(bx.cx, 1, true));
             }
             OperandValue::Ref(..) => bug!()
         }
@@ -308,11 +309,7 @@ fn store_with_flags(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, flags: M
             }
             OperandValue::Pair(a, b) => {
                 for (i, &x) in [a, b].iter().enumerate() {
-                    let mut llptr = bx.struct_gep(dest.llval, i as u64);
-                    // Make sure to always store i1 as i8.
-                    if common::val_ty(x) == Type::i1(bx.cx) {
-                        llptr = bx.pointercast(llptr, Type::i8p(bx.cx));
-                    }
+                    let llptr = bx.struct_gep(dest.llval, i as u64);
                     let val = base::from_immediate(bx, x);
                     bx.store_with_flags(val, llptr, dest.align, flags);
                 }
index 2a1e3980adbcfaa58ee83880d10818127ce5d8cb..e7f9457a6a1cac2ed4868790a3b81f736e9fd55a 100644 (file)
@@ -127,11 +127,7 @@ pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
             OperandValue::Immediate(base::to_immediate(bx, llval, self.layout))
         } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi {
             let load = |i, scalar: &layout::Scalar| {
-                let mut llptr = bx.struct_gep(self.llval, i as u64);
-                // Make sure to always load i1 as i8.
-                if scalar.is_bool() {
-                    llptr = bx.pointercast(llptr, Type::i8p(bx.cx));
-                }
+                let llptr = bx.struct_gep(self.llval, i as u64);
                 let load = bx.load(llptr, self.align);
                 scalar_load_metadata(load, scalar);
                 if scalar.is_bool() {
index 0fd81c6074e48e87012ee895350119966bc5ff29..2e81fc16a58388d935024ac40d25b4ff1cb59b32 100644 (file)
@@ -232,7 +232,7 @@ pub fn codegen_rvalue_operand(&mut self,
                                 // HACK(eddyb) have to bitcast pointers
                                 // until LLVM removes pointee types.
                                 let lldata = bx.pointercast(lldata,
-                                    cast.scalar_pair_element_llvm_type(bx.cx, 0));
+                                    cast.scalar_pair_element_llvm_type(bx.cx, 0, true));
                                 OperandValue::Pair(lldata, llextra)
                             }
                             OperandValue::Immediate(lldata) => {
@@ -251,7 +251,7 @@ pub fn codegen_rvalue_operand(&mut self,
                         if let OperandValue::Pair(data_ptr, meta) = operand.val {
                             if cast.is_llvm_scalar_pair() {
                                 let data_cast = bx.pointercast(data_ptr,
-                                    cast.scalar_pair_element_llvm_type(bx.cx, 0));
+                                    cast.scalar_pair_element_llvm_type(bx.cx, 0, true));
                                 OperandValue::Pair(data_cast, meta)
                             } else { // cast to thin-ptr
                                 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
index bfabf65dfd850976feda8a1798137181bb3be246..4728d7717a1e1d3f874ee69660a8c9c357c848db 100644 (file)
@@ -47,8 +47,8 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         }
         layout::Abi::ScalarPair(..) => {
             return Type::struct_(cx, &[
-                layout.scalar_pair_element_llvm_type(cx, 0),
-                layout.scalar_pair_element_llvm_type(cx, 1),
+                layout.scalar_pair_element_llvm_type(cx, 0, false),
+                layout.scalar_pair_element_llvm_type(cx, 1, false),
             ], false);
         }
         layout::Abi::Uninhabited |
@@ -206,7 +206,7 @@ pub trait LayoutLlvmExt<'tcx> {
     fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
                                scalar: &layout::Scalar, offset: Size) -> Type;
     fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                                         index: usize) -> Type;
+                                         index: usize, immediate: bool) -> Type;
     fn llvm_field_index(&self, index: usize) -> u64;
     fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
                            -> Option<PointeeInfo>;
@@ -340,7 +340,7 @@ fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
     }
 
     fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                                         index: usize) -> Type {
+                                         index: usize, immediate: bool) -> Type {
         // HACK(eddyb) special-case fat pointers until LLVM removes
         // pointee types, to avoid bitcasting every `OperandRef::deref`.
         match self.ty.sty {
@@ -350,7 +350,7 @@ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
             }
             ty::TyAdt(def, _) if def.is_box() => {
                 let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
-                return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index);
+                return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
             }
             _ => {}
         }
@@ -361,14 +361,13 @@ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
         };
         let scalar = [a, b][index];
 
-        // Make sure to return the same type `immediate_llvm_type` would,
-        // to avoid dealing with two types and the associated conversions.
-        // This means that `(bool, bool)` is represented as `{i1, i1}`,
-        // both in memory and as an immediate, while `bool` is typically
-        // `i8` in memory and only `i1` when immediate. While we need to
-        // load/store `bool` as `i8` to avoid crippling LLVM optimizations,
-        // `i1` in a LLVM aggregate is valid and mostly equivalent to `i8`.
-        if scalar.is_bool() {
+        // Make sure to return the same type `immediate_llvm_type` would when
+        // dealing with an immediate pair.  This means that `(bool, bool)` is
+        // effectively represented as `{i8, i8}` in memory and two `i1`s as an
+        // immediate, just like `bool` is typically `i8` in memory and only `i1`
+        // when immediate.  We need to load/store `bool` as `i8` to avoid
+        // crippling LLVM optimizations or triggering other LLVM bugs with `i1`.
+        if immediate && scalar.is_bool() {
             return Type::i1(cx);
         }
 
index 84f7b35d21f33c542ba2d01dd37d44bebb7c2557..1078dadce25f596d1d1b6efc26c359d8cad0d8de 100644 (file)
@@ -1493,7 +1493,7 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
     // Temporarily have stack size set to 16MB to deal with nom-using crates failing
     const STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB
 
-    #[cfg(unix)]
+    #[cfg(all(unix,not(target_os = "haiku")))]
     let spawn_thread = unsafe {
         // Fetch the current resource limits
         let mut rlim = libc::rlimit {
@@ -1525,6 +1525,26 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
     #[cfg(windows)]
     let spawn_thread = false;
 
+    #[cfg(target_os = "haiku")]
+    let spawn_thread = unsafe {
+        // Haiku does not have setrlimit implemented for the stack size.
+        // By default it does have the 16 MB stack limit, but we check this in
+        // case the minimum STACK_SIZE changes or Haiku's defaults change.
+        let mut rlim = libc::rlimit {
+            rlim_cur: 0,
+            rlim_max: 0,
+        };
+        if libc::getrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
+            let err = io::Error::last_os_error();
+            error!("in_rustc_thread: error calling getrlimit: {}", err);
+            true
+        } else if rlim.rlim_cur >= STACK_SIZE {
+            false
+        } else {
+            true
+        }
+    };
+
     #[cfg(not(any(windows,unix)))]
     let spawn_thread = true;
 
index c5f3b45950ed7f86faf1e8631a6d65a0a75574fb..d6e5c70b8f7e1b4320788cf5c83e5bfef44849c7 100644 (file)
@@ -280,7 +280,7 @@ fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
 }
 
 declare_lint! {
-    MISSING_DOCS,
+    pub MISSING_DOCS,
     Allow,
     "detects missing documentation for public members"
 }
index adc700506ffc0bc15f271a2b3b365edca9711021..459f496c9fe05f2308cb56d94ae474b6c628d8db 100644 (file)
@@ -56,7 +56,7 @@
 use lint::FutureIncompatibleInfo;
 
 mod bad_style;
-mod builtin;
+pub mod builtin;
 mod types;
 mod unused;
 
index bf8c9c8c3bef43053f2fe419da4f97fdd2603c34..16dec2725ff0436d7eac0fac222c6ab591ff19d7 100644 (file)
 
 use borrow_check::nll::region_infer::RegionInferenceContext;
 use borrow_check::nll::ToRegionVid;
+use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::mir::{Local, Mir};
-use rustc::ty::{self, RegionVid, TyCtxt};
+use rustc::ty::subst::{Substs, UnpackedKind};
+use rustc::ty::{self, RegionVid, Ty, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_errors::DiagnosticBuilder;
 use syntax::ast::Name;
@@ -60,7 +62,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         self.give_name_from_error_region(tcx, mir_def_id, fr, counter, diag)
             .or_else(|| {
-                self.give_name_if_anonymous_region_appears_in_arguments(tcx, mir, fr, counter, diag)
+                self.give_name_if_anonymous_region_appears_in_arguments(
+                    tcx, mir, mir_def_id, fr, counter, diag,
+                )
             })
             .or_else(|| {
                 self.give_name_if_anonymous_region_appears_in_upvars(tcx, mir, fr, counter, diag)
@@ -129,20 +133,24 @@ fn give_name_if_anonymous_region_appears_in_arguments(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
         mir: &Mir<'tcx>,
+        mir_def_id: DefId,
         fr: RegionVid,
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
     ) -> Option<InternedString> {
         let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
-        let argument_index = self.universal_regions
+        let argument_index = self
+            .universal_regions
             .unnormalized_input_tys
             .iter()
             .skip(implicit_inputs)
             .position(|arg_ty| {
-                debug!("give_name_if_anonymous_region_appears_in_arguments: arg_ty = {:?}", arg_ty);
+                debug!(
+                    "give_name_if_anonymous_region_appears_in_arguments: arg_ty = {:?}",
+                    arg_ty
+                );
                 tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr)
-            })?
-            + implicit_inputs;
+            })?;
 
         debug!(
             "give_name_if_anonymous_region_appears_in_arguments: \
@@ -150,9 +158,23 @@ fn give_name_if_anonymous_region_appears_in_arguments(
             fr, argument_index, self.universal_regions.unnormalized_input_tys[argument_index],
         );
 
+        let arg_ty =
+            self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index];
+        if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument(
+            tcx,
+            mir_def_id,
+            fr,
+            arg_ty,
+            argument_index,
+            counter,
+            diag,
+        ) {
+            return Some(region_name);
+        }
+
         let region_name = self.synthesize_region_name(counter);
 
-        let argument_local = Local::new(argument_index + 1);
+        let argument_local = Local::new(argument_index + implicit_inputs + 1);
         let argument_span = mir.local_decls[argument_local].source_info.span;
         diag.span_label(
             argument_span,
@@ -162,6 +184,240 @@ fn give_name_if_anonymous_region_appears_in_arguments(
         Some(region_name)
     }
 
+    fn give_name_if_we_can_match_hir_ty_from_argument(
+        &self,
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        mir_def_id: DefId,
+        needle_fr: RegionVid,
+        argument_ty: Ty<'tcx>,
+        argument_index: usize,
+        counter: &mut usize,
+        diag: &mut DiagnosticBuilder<'_>,
+    ) -> Option<InternedString> {
+        let mir_node_id = tcx.hir.as_local_node_id(mir_def_id)?;
+        let fn_decl = tcx.hir.fn_decl(mir_node_id)?;
+        let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index];
+        match argument_hir_ty.node {
+            // This indicates a variable with no type annotation, like
+            // `|x|`... in that case, we can't highlight the type but
+            // must highlight the variable.
+            hir::TyInfer => None,
+
+            _ => self.give_name_if_we_can_match_hir_ty(
+                tcx,
+                needle_fr,
+                argument_ty,
+                argument_hir_ty,
+                counter,
+                diag,
+            ),
+        }
+    }
+
+    /// Attempts to highlight the specific part of a type annotation
+    /// that contains the anonymous reference we want to give a name
+    /// to. For example, we might produce an annotation like this:
+    ///
+    /// ```
+    ///  | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+    ///  |                - let's call the lifetime of this reference `'1`
+    /// ```
+    ///
+    /// the way this works is that we match up `argument_ty`, which is
+    /// a `Ty<'tcx>` (the internal form of the type) with
+    /// `argument_hir_ty`, a `hir::Ty` (the syntax of the type
+    /// annotation). We are descending through the types stepwise,
+    /// looking in to find the region `needle_fr` in the internal
+    /// type.  Once we find that, we can use the span of the `hir::Ty`
+    /// to add the highlight.
+    ///
+    /// This is a somewhat imperfect process, so long the way we also
+    /// keep track of the **closest** type we've found. If we fail to
+    /// find the exact `&` or `'_` to highlight, then we may fall back
+    /// to highlighting that closest type instead.
+    fn give_name_if_we_can_match_hir_ty(
+        &self,
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        needle_fr: RegionVid,
+        argument_ty: Ty<'tcx>,
+        argument_hir_ty: &hir::Ty,
+        counter: &mut usize,
+        diag: &mut DiagnosticBuilder<'_>,
+    ) -> Option<InternedString> {
+        let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> = &mut Vec::new();
+
+        search_stack.push((argument_ty, argument_hir_ty));
+
+        let mut closest_match: &hir::Ty = argument_hir_ty;
+
+        while let Some((ty, hir_ty)) = search_stack.pop() {
+            // While we search, also track the closet match.
+            if tcx.any_free_region_meets(&ty, |r| r.to_region_vid() == needle_fr) {
+                closest_match = hir_ty;
+            }
+
+            match (&ty.sty, &hir_ty.node) {
+                // Check if the `argument_ty` is `&'X ..` where `'X`
+                // is the region we are looking for -- if so, and we have a `&T`
+                // on the RHS, then we want to highlight the `&` like so:
+                //
+                //     &
+                //     - let's call the lifetime of this reference `'1`
+                (ty::TyRef(region, referent_ty, _), hir::TyRptr(_lifetime, referent_hir_ty)) => {
+                    if region.to_region_vid() == needle_fr {
+                        let region_name = self.synthesize_region_name(counter);
+
+                        // Just grab the first character, the `&`.
+                        let codemap = tcx.sess.codemap();
+                        let ampersand_span = codemap.start_point(hir_ty.span);
+
+                        diag.span_label(
+                            ampersand_span,
+                            format!(
+                                "let's call the lifetime of this reference `{}`",
+                                region_name
+                            ),
+                        );
+
+                        return Some(region_name);
+                    }
+
+                    // Otherwise, let's descend into the referent types.
+                    search_stack.push((referent_ty, &referent_hir_ty.ty));
+                }
+
+                // Match up something like `Foo<'1>`
+                (ty::TyAdt(_adt_def, substs), hir::TyPath(hir::QPath::Resolved(None, path))) => {
+                    if let Some(last_segment) = path.segments.last() {
+                        if let Some(name) = self.match_adt_and_segment(
+                            substs,
+                            needle_fr,
+                            last_segment,
+                            counter,
+                            diag,
+                            search_stack,
+                        ) {
+                            return Some(name);
+                        }
+                    }
+                }
+
+                // The following cases don't have lifetimes, so we
+                // just worry about trying to match up the rustc type
+                // with the HIR types:
+                (ty::TyTuple(elem_tys), hir::TyTup(elem_hir_tys)) => {
+                    search_stack.extend(elem_tys.iter().cloned().zip(elem_hir_tys));
+                }
+
+                (ty::TySlice(elem_ty), hir::TySlice(elem_hir_ty))
+                | (ty::TyArray(elem_ty, _), hir::TyArray(elem_hir_ty, _)) => {
+                    search_stack.push((elem_ty, elem_hir_ty));
+                }
+
+                (ty::TyRawPtr(mut_ty), hir::TyPtr(mut_hir_ty)) => {
+                    search_stack.push((mut_ty.ty, &mut_hir_ty.ty));
+                }
+
+                _ => {
+                    // FIXME there are other cases that we could trace
+                }
+            }
+        }
+
+        let region_name = self.synthesize_region_name(counter);
+        diag.span_label(
+            closest_match.span,
+            format!("lifetime `{}` appears in this type", region_name),
+        );
+
+        return Some(region_name);
+    }
+
+    /// We've found an enum/struct/union type with the substitutions
+    /// `substs` and -- in the HIR -- a path type with the final
+    /// segment `last_segment`. Try to find a `'_` to highlight in
+    /// the generic args (or, if not, to produce new zipped pairs of
+    /// types+hir to search through).
+    fn match_adt_and_segment<'hir>(
+        &self,
+        substs: &'tcx Substs<'tcx>,
+        needle_fr: RegionVid,
+        last_segment: &'hir hir::PathSegment,
+        counter: &mut usize,
+        diag: &mut DiagnosticBuilder<'_>,
+        search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>,
+    ) -> Option<InternedString> {
+        // Did the user give explicit arguments? (e.g., `Foo<..>`)
+        let args = last_segment.args.as_ref()?;
+        let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
+        match lifetime.name {
+            hir::LifetimeName::Param(_)
+            | hir::LifetimeName::Static
+            | hir::LifetimeName::Underscore => {
+                let region_name = self.synthesize_region_name(counter);
+                let ampersand_span = lifetime.span;
+                diag.span_label(ampersand_span, format!("let's call this `{}`", region_name));
+                return Some(region_name);
+            }
+
+            hir::LifetimeName::Implicit => {
+                // In this case, the user left off the lifetime; so
+                // they wrote something like:
+                //
+                // ```
+                // x: Foo<T>
+                // ```
+                //
+                // where the fully elaborated form is `Foo<'_, '1,
+                // T>`. We don't consider this a match; instead we let
+                // the "fully elaborated" type fallback above handle
+                // it.
+                return None;
+            }
+        }
+    }
+
+    /// We've found an enum/struct/union type with the substitutions
+    /// `substs` and -- in the HIR -- a path with the generic
+    /// arguments `args`. If `needle_fr` appears in the args, return
+    /// the `hir::Lifetime` that corresponds to it. If not, push onto
+    /// `search_stack` the types+hir to search through.
+    fn try_match_adt_and_generic_args<'hir>(
+        &self,
+        substs: &'tcx Substs<'tcx>,
+        needle_fr: RegionVid,
+        args: &'hir hir::GenericArgs,
+        search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>,
+    ) -> Option<&'hir hir::Lifetime> {
+        for (kind, hir_arg) in substs.iter().zip(&args.args) {
+            match (kind.unpack(), hir_arg) {
+                (UnpackedKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
+                    if r.to_region_vid() == needle_fr {
+                        return Some(lt);
+                    }
+                }
+
+                (UnpackedKind::Type(ty), hir::GenericArg::Type(hir_ty)) => {
+                    search_stack.push((ty, hir_ty));
+                }
+
+                (UnpackedKind::Lifetime(_), _) | (UnpackedKind::Type(_), _) => {
+                    // I *think* that HIR lowering should ensure this
+                    // doesn't happen, even in erroneous
+                    // programs. Else we should use delay-span-bug.
+                    span_bug!(
+                        hir_arg.span(),
+                        "unmatched subst and hir arg: found {:?} vs {:?}",
+                        kind,
+                        hir_arg,
+                    );
+                }
+            }
+        }
+
+        None
+    }
+
     /// Find a closure upvar that contains `fr` and label it with a
     /// fully elaborated type, returning something like `'1`. Result
     /// looks like:
@@ -178,7 +434,8 @@ fn give_name_if_anonymous_region_appears_in_upvars(
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
     ) -> Option<InternedString> {
-        let upvar_index = self.universal_regions
+        let upvar_index = self
+            .universal_regions
             .defining_ty
             .upvar_tys(tcx)
             .position(|upvar_ty| {
@@ -189,15 +446,16 @@ fn give_name_if_anonymous_region_appears_in_upvars(
                 tcx.any_free_region_meets(&upvar_ty, |r| r.to_region_vid() == fr)
             })?;
 
+        let upvar_ty = self
+            .universal_regions
+            .defining_ty
+            .upvar_tys(tcx)
+            .nth(upvar_index);
+
         debug!(
             "give_name_if_anonymous_region_appears_in_upvars: \
              found {:?} in upvar {} which has type {:?}",
-            fr,
-            upvar_index,
-            self.universal_regions
-                .defining_ty
-                .upvar_tys(tcx)
-                .nth(upvar_index),
+            fr, upvar_index, upvar_ty,
         );
 
         let region_name = self.synthesize_region_name(counter);
@@ -229,9 +487,11 @@ fn give_name_if_anonymous_region_appears_in_output(
         counter: &mut usize,
         diag: &mut DiagnosticBuilder<'_>,
     ) -> Option<InternedString> {
-        let return_ty = self.universal_regions
-            .unnormalized_output_ty;
-        debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
+        let return_ty = self.universal_regions.unnormalized_output_ty;
+        debug!(
+            "give_name_if_anonymous_region_appears_in_output: return_ty = {:?}",
+            return_ty
+        );
         if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) {
             return None;
         }
index b8dfd21e54076ce3de0b4ff6ec4f3ddf79731483..ee2a1c3bdeb10840ffdad4fd07c5cccf61c63d89 100644 (file)
@@ -4125,7 +4125,18 @@ fn lookup_import_candidates<FilterFn>(&mut self,
                 if ident.name == lookup_name && ns == namespace {
                     if filter_fn(name_binding.def()) {
                         // create the path
-                        let mut segms = path_segments.clone();
+                        let mut segms = if self.session.rust_2018() && !in_module_is_extern {
+                            // crate-local absolute paths start with `crate::` in edition 2018
+                            // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
+                            let mut full_segms = vec![
+                                ast::PathSegment::from_ident(keywords::Crate.ident())
+                            ];
+                            full_segms.extend(path_segments.clone());
+                            full_segms
+                        } else {
+                            path_segments.clone()
+                        };
+
                         segms.push(ast::PathSegment::from_ident(ident));
                         let path = Path {
                             span: name_binding.span,
index 27daebbf8c12d4b9cf90720b8f9f3f13f9cca298..cf61258577619e90dcf643ecc44c7e13dfa75cac 100644 (file)
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::hir::map::definitions::DefPathData;
 use rustc::hir::{self, ImplPolarity};
-use rustc::traits::{Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause,
-                    WhereClause, FromEnv, WellFormed};
+use rustc::traits::{
+    Clause, Clauses, DomainGoal, FromEnv, Goal, PolyDomainGoal, ProgramClause, WellFormed,
+    WhereClause,
+};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Slice, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
@@ -101,34 +103,50 @@ fn lower(&self) -> PolyDomainGoal<'tcx> {
             Predicate::RegionOutlives(predicate) => predicate.lower(),
             Predicate::TypeOutlives(predicate) => predicate.lower(),
             Predicate::Projection(predicate) => predicate.lower(),
-            Predicate::WellFormed(ty) => ty::Binder::dummy(
-                DomainGoal::WellFormed(WellFormed::Ty(*ty))
-            ),
-            Predicate::ObjectSafe(..) |
-            Predicate::ClosureKind(..) |
-            Predicate::Subtype(..) |
-            Predicate::ConstEvaluatable(..) => {
-                unimplemented!()
+            Predicate::WellFormed(ty) => {
+                ty::Binder::dummy(DomainGoal::WellFormed(WellFormed::Ty(*ty)))
             }
+            Predicate::ObjectSafe(..)
+            | Predicate::ClosureKind(..)
+            | Predicate::Subtype(..)
+            | Predicate::ConstEvaluatable(..) => unimplemented!(),
         }
     }
 }
 
-/// Transforms an existing goal into a FromEnv goal.
-///
-/// Used for lowered where clauses (see rustc guide).
+/// Used for implied bounds related rules (see rustc guide).
 trait IntoFromEnvGoal {
+    /// Transforms an existing goal into a `FromEnv` goal.
     fn into_from_env_goal(self) -> Self;
 }
 
+/// Used for well-formedness related rules (see rustc guide).
+trait IntoWellFormedGoal {
+    /// Transforms an existing goal into a `WellFormed` goal.
+    fn into_well_formed_goal(self) -> Self;
+}
+
 impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> {
     fn into_from_env_goal(self) -> DomainGoal<'tcx> {
         use self::WhereClause::*;
 
         match self {
-            DomainGoal::Holds(Implemented(trait_ref)) => DomainGoal::FromEnv(
-                FromEnv::Trait(trait_ref)
-            ),
+            DomainGoal::Holds(Implemented(trait_ref)) => {
+                DomainGoal::FromEnv(FromEnv::Trait(trait_ref))
+            }
+            other => other,
+        }
+    }
+}
+
+impl<'tcx> IntoWellFormedGoal for DomainGoal<'tcx> {
+    fn into_well_formed_goal(self) -> DomainGoal<'tcx> {
+        use self::WhereClause::*;
+
+        match self {
+            DomainGoal::Holds(Implemented(trait_ref)) => {
+                DomainGoal::WellFormed(WellFormed::Trait(trait_ref))
+            }
             other => other,
         }
     }
@@ -230,7 +248,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
     // `Implemented(Self: Trait<P1..Pn>)`
     let impl_trait: DomainGoal = trait_pred.lower();
 
-     // `FromEnv(Self: Trait<P1..Pn>)`
+    // `FromEnv(Self: Trait<P1..Pn>)`
     let from_env_goal = impl_trait.into_from_env_goal().into_goal();
     let hypotheses = tcx.intern_goals(&[from_env_goal]);
 
@@ -242,6 +260,8 @@ fn program_clauses_for_trait<'a, 'tcx>(
 
     let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env)));
 
+    let where_clauses = &tcx.predicates_defined_on(def_id).predicates;
+
     // Rule Implied-Bound-From-Trait
     //
     // For each where clause WC:
@@ -252,7 +272,6 @@ fn program_clauses_for_trait<'a, 'tcx>(
     // ```
 
     // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
-    let where_clauses = &tcx.predicates_defined_on(def_id).predicates;
     let implied_bound_clauses = where_clauses
         .into_iter()
         .map(|wc| wc.lower())
@@ -262,10 +281,40 @@ fn program_clauses_for_trait<'a, 'tcx>(
             goal: goal.into_from_env_goal(),
             hypotheses,
         }))
-
         .map(Clause::ForAll);
 
-    tcx.mk_clauses(clauses.chain(implied_bound_clauses))
+    // Rule WellFormed-TraitRef
+    //
+    // Here `WC` denotes the set of all where clauses:
+    // ```
+    // forall<Self, P1..Pn> {
+    //   WellFormed(Self: Trait<P1..Pn>) :- Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)
+    // }
+    // ```
+
+    // `Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)`
+    let wf_conditions = iter::once(ty::Binder::dummy(trait_pred.lower()))
+        .chain(
+            where_clauses
+                .into_iter()
+                .map(|wc| wc.lower())
+                .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()))
+        );
+
+    // `WellFormed(Self: Trait<P1..Pn>) :- Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)`
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Trait(trait_pred)),
+        hypotheses: tcx.mk_goals(
+            wf_conditions.map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
+        ),
+    };
+    let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause)));
+
+    tcx.mk_clauses(
+        clauses
+            .chain(implied_bound_clauses)
+            .chain(wf_clause)
+    )
 }
 
 fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> {
@@ -307,7 +356,6 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
 ) -> Clauses<'tcx> {
-
     // Rule WellFormed-Type
     //
     // `struct Ty<P1..Pn> where WC1, ..., WCm`
@@ -328,7 +376,10 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
     let well_formed = ProgramClause {
         goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
         hypotheses: tcx.mk_goals(
-            where_clauses.iter().cloned().map(|wc| Goal::from_poly_domain_goal(wc, tcx))
+            where_clauses
+                .iter()
+                .cloned()
+                .map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
         ),
     };
 
@@ -459,7 +510,8 @@ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
             }
 
             if let Some(clauses) = clauses {
-                let mut err = self.tcx
+                let mut err = self
+                    .tcx
                     .sess
                     .struct_span_err(attr.span, "program clause dump");
 
index 646c4f17568f05c3aab5e20b309d7ff14c58b7ff..c7ad3398873eabc00e12491b7ad70d74bd629a54 100644 (file)
@@ -1182,7 +1182,54 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                 fcx.tcx.sess.err("language item required, but not found: `panic_info`");
             }
         }
+    }
+
+    // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
+    if let Some(alloc_error_handler_did) = fcx.tcx.lang_items().oom() {
+        if alloc_error_handler_did == fcx.tcx.hir.local_def_id(fn_id) {
+            if let Some(alloc_layout_did) = fcx.tcx.lang_items().alloc_layout() {
+                if declared_ret_ty.sty != ty::TyNever {
+                    fcx.tcx.sess.span_err(
+                        decl.output.span(),
+                        "return type should be `!`",
+                    );
+                }
+
+                let inputs = fn_sig.inputs();
+                let span = fcx.tcx.hir.span(fn_id);
+                if inputs.len() == 1 {
+                    let arg_is_alloc_layout = match inputs[0].sty {
+                        ty::TyAdt(ref adt, _) => {
+                            adt.did == alloc_layout_did
+                        },
+                        _ => false,
+                    };
+
+                    if !arg_is_alloc_layout {
+                        fcx.tcx.sess.span_err(
+                            decl.inputs[0].span,
+                            "argument should be `Layout`",
+                        );
+                    }
 
+                    if let Node::NodeItem(item) = fcx.tcx.hir.get(fn_id) {
+                        if let Item_::ItemFn(_, _, ref generics, _) = item.node {
+                            if !generics.params.is_empty() {
+                                fcx.tcx.sess.span_err(
+                                    span,
+                                    "`#[alloc_error_handler]` function should have no type \
+                                     parameters",
+                                );
+                            }
+                        }
+                    }
+                } else {
+                    fcx.tcx.sess.span_err(span, "function should have one argument");
+                }
+            } else {
+                fcx.tcx.sess.err("language item required, but not found: `alloc_layout`");
+            }
+        }
     }
 
     (fcx, gen_ty)
index 2514fa044dd6bacc9a01ddeed8bd168a2d740981..417a78b2a3ae0ed17bf96f632896635d83df5463 100644 (file)
@@ -192,6 +192,7 @@ pub fn run_core(search_paths: SearchPaths,
 
     let intra_link_resolution_failure_name = lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE.name;
     let warnings_lint_name = lint::builtin::WARNINGS.name;
+    let missing_docs = rustc_lint::builtin::MISSING_DOCS.name;
     let lints = lint::builtin::HardwiredLints.get_lints()
                     .into_iter()
                     .chain(rustc_lint::SoftLints.get_lints().into_iter())
@@ -240,6 +241,26 @@ pub fn run_core(search_paths: SearchPaths,
         let mut sess = session::build_session_(
             sessopts, cpath, diagnostic_handler, codemap,
         );
+
+        lint::builtin::HardwiredLints.get_lints()
+                                     .into_iter()
+                                     .chain(rustc_lint::SoftLints.get_lints().into_iter())
+                                     .filter_map(|lint| {
+                                         // We don't want to whitelist *all* lints so let's
+                                         // ignore those ones.
+                                         if lint.name == warnings_lint_name ||
+                                            lint.name == intra_link_resolution_failure_name ||
+                                            lint.name == missing_docs {
+                                             None
+                                         } else {
+                                             Some(lint)
+                                         }
+                                     })
+                                     .for_each(|l| {
+                                         sess.driver_lint_caps.insert(lint::LintId::of(l),
+                                                                      lint::Allow);
+                                     });
+
         let codegen_backend = rustc_driver::get_codegen_backend(&sess);
         let cstore = Rc::new(CStore::new(codegen_backend.metadata_loader()));
         rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
@@ -304,7 +325,6 @@ pub fn run_core(search_paths: SearchPaths,
                                                             &sess);
 
         let resolver = RefCell::new(resolver);
-
         abort_on_err(driver::phase_3_run_analysis_passes(&*codegen_backend,
                                                         control,
                                                         &sess,
index f6cecbea11f8d89fefbf1114a74e4dfaf139d3bd..8db365cd21d67938be2bbca12cfee14a3fded4cd 100644 (file)
@@ -125,9 +125,10 @@ fn default_alloc_error_hook(layout: Layout) {
 
 #[cfg(not(test))]
 #[doc(hidden)]
-#[lang = "oom"]
+#[cfg_attr(stage0, lang = "oom")]
+#[cfg_attr(not(stage0), alloc_error_handler)]
 #[unstable(feature = "alloc_internals", issue = "0")]
-pub extern fn rust_oom(layout: Layout) -> ! {
+pub fn rust_oom(layout: Layout) -> ! {
     let hook = HOOK.load(Ordering::SeqCst);
     let hook: fn(Layout) = if hook.is_null() {
         default_alloc_error_hook
index d73cb1f8349a655ca5414a42445b93360bc31cc8..fec14b8d67d359c0322a449439e000878fe99d60 100644 (file)
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
 #![feature(alloc)]
-#![feature(allocator_api)]
+#![feature(alloc_error_handler)]
 #![feature(alloc_system)]
+#![feature(allocator_api)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
index ea6b39504e81d72463c90b4fd32d1fce8490c6dc..8381adaea79de3ef2619bcf9eef415e833a648ef 100644 (file)
@@ -689,6 +689,15 @@ pub fn def_span(&self, sp: Span) -> Span {
         self.span_until_char(sp, '{')
     }
 
+    /// Returns a new span representing just the start-point of this span
+    pub fn start_point(&self, sp: Span) -> Span {
+        let pos = sp.lo().0;
+        let width = self.find_width_of_character_at_span(sp, false);
+        let corrected_start_position = pos.checked_add(width).unwrap_or(pos);
+        let end_point = BytePos(cmp::max(corrected_start_position, sp.lo().0));
+        sp.with_hi(end_point)
+    }
+
     /// Returns a new span representing just the end-point of this span
     pub fn end_point(&self, sp: Span) -> Span {
         let pos = sp.hi().0;
index cbc421dbd328c281c58b075a89b8073a02542fdd..e70d93ae85a1d1dca16bd4708a03cb80a1b44964 100644 (file)
@@ -481,6 +481,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // Allows async and await syntax
     (active, async_await, "1.28.0", Some(50547), None),
+
+    // #[alloc_error_handler]
+    (active, alloc_error_handler, "1.29.0", Some(51540), None),
 );
 
 declare_features! (
@@ -1083,6 +1086,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                            "#[panic_implementation] is an unstable feature",
                            cfg_fn!(panic_implementation))),
 
+    ("alloc_error_handler", Normal, Gated(Stability::Unstable,
+                           "alloc_error_handler",
+                           "#[alloc_error_handler] is an unstable feature",
+                           cfg_fn!(alloc_error_handler))),
+
     // Crate level attributes
     ("crate_name", CrateLevel, Ungated),
     ("crate_type", CrateLevel, Ungated),
index df8602d0803a459d848040a2f3e2d299391e33a9..d82410618d04ba6253744b67ee7a0cd54af59ec3 100644 (file)
@@ -492,13 +492,8 @@ inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
   return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
 }
 
-#if LLVM_VERSION_GE(4, 0)
 static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
   DINode::DIFlags Result = DINode::DIFlags::FlagZero;
-#else
-static unsigned fromRust(LLVMRustDIFlags Flags) {
-  unsigned Result = 0;
-#endif
 
   switch (visibility(Flags)) {
   case LLVMRustDIFlags::FlagPrivate:
@@ -565,14 +560,12 @@ static unsigned fromRust(LLVMRustDIFlags Flags) {
   if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
     Result |= DINode::DIFlags::FlagBitField;
   }
-#if LLVM_RUSTLLVM || LLVM_VERSION_GE(4, 0)
   if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
     Result |= DINode::DIFlags::FlagNoReturn;
   }
   if (isSet(Flags & LLVMRustDIFlags::FlagMainSubprogram)) {
     Result |= DINode::DIFlags::FlagMainSubprogram;
   }
-#endif
 
   return Result;
 }
@@ -612,14 +605,8 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
     unsigned RuntimeVer, const char *SplitName) {
   auto *File = unwrapDI<DIFile>(FileRef);
 
-#if LLVM_VERSION_GE(4, 0)
   return wrap(Builder->createCompileUnit(Lang, File, Producer, isOptimized,
                                          Flags, RuntimeVer, SplitName));
-#else
-  return wrap(Builder->createCompileUnit(Lang, File->getFilename(),
-      File->getDirectory(), Producer, isOptimized,
-      Flags, RuntimeVer, SplitName));
-#endif
 }
 
 extern "C" LLVMMetadataRef
@@ -657,11 +644,7 @@ extern "C" LLVMMetadataRef
 LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
                                  uint64_t SizeInBits, uint32_t AlignInBits,
                                  unsigned Encoding) {
-  return wrap(Builder->createBasicType(Name, SizeInBits,
-#if LLVM_VERSION_LE(3, 9)
-                                       AlignInBits,
-#endif
-                                       Encoding));
+  return wrap(Builder->createBasicType(Name, SizeInBits, Encoding));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
@@ -722,7 +705,6 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
     LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
   llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
 
-#if LLVM_VERSION_GE(4, 0)
   llvm::DIExpression *InitExpr = nullptr;
   if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
     InitExpr = Builder->createConstantValueExpression(
@@ -741,12 +723,6 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
   InitVal->setMetadata("dbg", VarExpr);
 
   return wrap(VarExpr);
-#else
-  return wrap(Builder->createGlobalVariable(
-      unwrapDI<DIDescriptor>(Context), Name, LinkageName,
-      unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
-      InitVal, unwrapDIPtr<MDNode>(Decl)));
-#endif
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
@@ -757,12 +733,7 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
   if (Tag == 0x100) { // DW_TAG_auto_variable
     return wrap(Builder->createAutoVariable(
         unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNo,
-        unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)
-#if LLVM_VERSION_GE(4, 0)
-        ,
-  AlignInBits
-#endif
-        ));
+        unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
   } else {
     return wrap(Builder->createParameterVariable(
         unwrapDI<DIDescriptor>(Scope), Name, ArgNo, unwrapDI<DIFile>(File),
index 20d42ed852dfed745d79c177eb629e07d49e5649..1b92ff60226aa8a7f6c52a341a161befe5980e50 100644 (file)
@@ -12,8 +12,6 @@
 // scalar value.
 
 // compile-flags: -C no-prepopulate-passes
-// min-llvm-version 4.0
-
 
 #![crate_type = "lib"]
 
index e3fa7a7db39a254bd2736fdd8ced347ad4a0157c..c027dece01414255ea136847fe7d82c519f6268d 100644 (file)
@@ -149,7 +149,7 @@ pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
   x
 }
 
-// CHECK: i16 @enum_id_2(i16)
+// CHECK: { i8, i8 } @enum_id_2(i1 zeroext %x.0, i8 %x.1)
 #[no_mangle]
 pub fn enum_id_2(x: Option<u8>) -> Option<u8> {
   x
index df02426badcc5dde1e2055779a8f0396afde4460..a36a50415ada55f8e3532beeb9de6baf3c5a0951 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// min-llvm-version 4.0
 // compile-flags: -O
 // ignore-x86
 // ignore-arm
index 3702b6753898e125143ea03c36581ed8cdcadec7..149547639440cf39187535a6d168bae4bad3f70b 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// min-llvm-version 4.0
 // compile-flags: -O
+// min-llvm-version 6.0
 
 #![crate_type="rlib"]
 
index f0508bc90f20c9941b537b8fc4549d82f3ec4342..2cfc20e30ca5c79da9f8b2d3fe916847a2ebdefc 100644 (file)
@@ -14,7 +14,6 @@
 // ignore-tidy-linelength
 // ignore-windows
 // ignore-macos
-// min-llvm-version 4.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
index 8325318f9afc56dcecadf961d21de6b13a2acec0..62a996316c4f5d045a77bf171f9851970e4e52a1 100644 (file)
@@ -8,13 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// This test depends on a patch that was committed to upstream LLVM
-// before 4.0, formerly backported to the Rust LLVM fork.
-
 // ignore-tidy-linelength
 // ignore-windows
 // ignore-macos
-// min-llvm-version 4.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
index 7239223ca2019d032b2faa749bdf851f61843a72..f66369782e5a67e464ecbb42df040bf826a22811 100644 (file)
@@ -10,7 +10,6 @@
 
 // compile-flags: -g -C no-prepopulate-passes
 // ignore-tidy-linelength
-// min-llvm-version 4.0
 
 #![crate_type = "lib"]
 
diff --git a/src/test/codegen/scalar-pair-bool.rs b/src/test/codegen/scalar-pair-bool.rs
new file mode 100644 (file)
index 0000000..f50e032
--- /dev/null
@@ -0,0 +1,54 @@
+// 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: -O
+
+#![crate_type = "lib"]
+
+// CHECK: define { i8, i8 } @pair_bool_bool(i1 zeroext %pair.0, i1 zeroext %pair.1)
+#[no_mangle]
+pub fn pair_bool_bool(pair: (bool, bool)) -> (bool, bool) {
+    pair
+}
+
+// CHECK: define { i8, i32 } @pair_bool_i32(i1 zeroext %pair.0, i32 %pair.1)
+#[no_mangle]
+pub fn pair_bool_i32(pair: (bool, i32)) -> (bool, i32) {
+    pair
+}
+
+// CHECK: define { i32, i8 } @pair_i32_bool(i32 %pair.0, i1 zeroext %pair.1)
+#[no_mangle]
+pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) {
+    pair
+}
+
+// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %arg0.0, i1 zeroext %arg0.1)
+#[no_mangle]
+pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) {
+    // Make sure it can operate directly on the unpacked args
+    // CHECK: and i1 %arg0.0, %arg0.1
+    // CHECK: or i1 %arg0.0, %arg0.1
+    (a && b, a || b)
+}
+
+// CHECK: define void @pair_branches(i1 zeroext %arg0.0, i1 zeroext %arg0.1)
+#[no_mangle]
+pub fn pair_branches((a, b): (bool, bool)) {
+    // Make sure it can branch directly on the unpacked bool args
+    // CHECK: br i1 %arg0.0
+    if a {
+        println!("Hello!");
+    }
+    // CHECK: br i1 %arg0.1
+    if b {
+        println!("Goodbye!");
+    }
+}
index 6ab71723a1dc5f04aa4818178573875bc34aa7fc..b8c2e62abef622bcd6a7455ba7bca773288abe6c 100644 (file)
@@ -21,7 +21,6 @@
 // ignore-wasm
 // ignore-emscripten
 // ignore-windows
-// min-system-llvm-version 5.0
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
index b6466467548492be0f949776617ca5d2f0059ea9..abd1eb3e2cc7b061d16b054969534ea7a2614eb6 100644 (file)
@@ -14,7 +14,7 @@
 // ignore-tidy-linelength
 // ignore-windows
 // ignore-macos
-// min-system-llvm-version 5.1
+// min-llvm-version 6.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
diff --git a/src/test/compile-fail/alloc-error-handler-bad-signature-1.rs b/src/test/compile-fail/alloc-error-handler-bad-signature-1.rs
new file mode 100644 (file)
index 0000000..e398f16
--- /dev/null
@@ -0,0 +1,28 @@
+// 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:-C panic=abort
+
+#![feature(alloc_error_handler, panic_implementation)]
+#![no_std]
+#![no_main]
+
+use core::alloc::Layout;
+
+#[alloc_error_handler]
+fn oom(
+    info: &Layout, //~ ERROR argument should be `Layout`
+) -> () //~ ERROR return type should be `!`
+{
+    loop {}
+}
+
+#[panic_implementation]
+fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/compile-fail/alloc-error-handler-bad-signature-2.rs b/src/test/compile-fail/alloc-error-handler-bad-signature-2.rs
new file mode 100644 (file)
index 0000000..4fee9d2
--- /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:-C panic=abort
+
+#![feature(alloc_error_handler, panic_implementation)]
+#![no_std]
+#![no_main]
+
+struct Layout;
+
+#[alloc_error_handler]
+fn oom(
+    info: Layout, //~ ERROR argument should be `Layout`
+) { //~ ERROR return type should be `!`
+    loop {}
+}
+
+#[panic_implementation]
+fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/compile-fail/alloc-error-handler-bad-signature-3.rs b/src/test/compile-fail/alloc-error-handler-bad-signature-3.rs
new file mode 100644 (file)
index 0000000..828a780
--- /dev/null
@@ -0,0 +1,25 @@
+// 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:-C panic=abort
+
+#![feature(alloc_error_handler, panic_implementation)]
+#![no_std]
+#![no_main]
+
+struct Layout;
+
+#[alloc_error_handler]
+fn oom() -> ! { //~ ERROR function should have one argument
+    loop {}
+}
+
+#[panic_implementation]
+fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
diff --git a/src/test/compile-fail/feature-gate-alloc-error-handler.rs b/src/test/compile-fail/feature-gate-alloc-error-handler.rs
new file mode 100644 (file)
index 0000000..66691af
--- /dev/null
@@ -0,0 +1,21 @@
+// 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:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+use core::alloc::Layout;
+
+#[alloc_error_handler] //~ ERROR #[alloc_error_handler] is an unstable feature (see issue #51540)
+fn oom(info: Layout) -> ! {
+    loop {}
+}
index 57e4bb76a6ce8272678833bd3c98483e6639ef32..725960a866ba01745b972a27e3e760900de1cbd5 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// min-llvm-version 5.0
 // ignore-emscripten
 
 // Test that the simd_reduce_{op} intrinsics produce ok-ish error
index 27446d6bd28f58c2b7485d2abcb5e3e4e3da500c..b4b54e13a698ee87d2334ca6a3eae888e1b48ab6 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// asmjs can't even pass i128 as arguments or return values, so ignore it.
-// this will hopefully be fixed by the LLVM 5 upgrade (#43370)
-// ignore-asmjs
 // ignore-emscripten
 
 // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no
index cdc429d1f995e2f2831543c20c86abc50375ab6a..efe1b7072ffb8f75a3d5460a67e100c6854af46a 100644 (file)
@@ -1,5 +1,3 @@
-
-# min-llvm-version 4.0
 # ignore-msvc
 
 -include ../tools.mk
index 720ce1512f26a8120c0beae2193bb0c441afdb4b..453602b800b5e546d7cecb9d7e4069885a04a8dd 100644 (file)
@@ -14,6 +14,7 @@
 #![no_main]
 #![no_std]
 
+use core::alloc::Layout;
 use core::panic::PanicInfo;
 
 #[panic_implementation]
@@ -25,4 +26,6 @@ fn panic(_: &PanicInfo) -> ! {
 fn eh() {}
 
 #[lang = "oom"]
-fn oom() {}
+fn oom(_: Layout) -> ! {
+    loop {}
+}
index 880c9bce5628f4a3b4d377bcb42a101ff23198c5..c0a17d920cffc91154ee4b0e22d473225a408b92 100644 (file)
@@ -28,12 +28,7 @@ namespace {
 
     bool runOnFunction(Function &F) override;
 
-#if LLVM_VERSION_MAJOR >= 4
-    StringRef
-#else
-    const char *
-#endif
-    getPassName() const override {
+    StringRef getPassName() const override {
       return "Some LLVM pass";
     }
 
index 280eca7e8f0155fe2c26f3960f6cf195c87a1eb9..70051681ab0350393a8f25eae75e5becce325974 100644 (file)
@@ -27,12 +27,7 @@ namespace {
 
     bool runOnModule(Module &M) override;
 
-#if LLVM_VERSION_MAJOR >= 4
-    StringRef
-#else
-    const char *
-#endif
-    getPassName() const override {
+    StringRef getPassName() const override {
       return "Some LLVM pass";
     }
 
diff --git a/src/test/run-pass/default-alloc-error-hook.rs b/src/test/run-pass/default-alloc-error-hook.rs
new file mode 100644 (file)
index 0000000..5f6b60a
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+// ignore-cloudabi no processes
+// ignore-emscripten no processes
+
+use std::alloc::{Layout, handle_alloc_error};
+use std::env;
+use std::process::Command;
+use std::str;
+
+fn main() {
+    if env::args().len() > 1 {
+        handle_alloc_error(Layout::new::<[u8; 42]>())
+    }
+
+    let me = env::current_exe().unwrap();
+    let output = Command::new(&me).arg("next").output().unwrap();
+    assert!(!output.status.success(), "{:?} is a success", output.status);
+    assert_eq!(str::from_utf8(&output.stderr).unwrap(), "memory allocation of 42 bytes failed");
+}
index feb4a88a1d1e15b0ff8d35be92c71895514b0a49..c1f3b2028aa7ef5df27fccd497b75172baba91da 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // check that we don't have linear stack usage with multiple calls to `push`
-// min-llvm-version 4.0
 
 #![feature(test)]
 
index 9a1214d3b35e5b7ac4ac2e2b022f961a739bc34b..8e999b7115ea13ee71292444870138f04a687934 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// min-llvm-version 5.0
 // ignore-emscripten
 
 // Test that the simd_reduce_{op} intrinsics produce the correct results.
index 3fef19c51bd288722bb95fb8ec7a3cb765102f99..ff5413ce06ca05384c6cd6a913f767f2bd42575c 100644 (file)
@@ -21,7 +21,6 @@
 // ignore-emscripten no processes
 // ignore-musl FIXME #31506
 // ignore-pretty
-// min-system-llvm-version 5.0
 // compile-flags: -C lto
 // no-prefer-dynamic
 
index c93dcf019397b34eef0a91adc26ec9a92f805dd2..1334ab8dc63780346d99252995c20c19aef8bf89 100644 (file)
@@ -20,7 +20,6 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-musl FIXME #31506
-// min-system-llvm-version 5.0
 
 use std::mem;
 use std::process::Command;
index 3a0e2fe01db055ce62388095eca1225f80ae01a6..257d5bbc30677e2f5658fe5dc165c1673d3b37c1 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // compile-flags: -Z thinlto -C codegen-units=2
-// min-llvm-version 4.0
 
 #[global_allocator]
 static A: std::alloc::System = std::alloc::System;
index 772a9ec8293e4becbb76955de1d059473206ee70..8d68202d71176922148a0cb12bb60f1ddeb15237 100644 (file)
@@ -10,7 +10,6 @@
 
 // compile-flags: -Clto=thin
 // no-prefer-dynamic
-// min-llvm-version 4.0
 
 fn main() {
     println!("hello!");
index 3f54519d0d8ceb23a17463a84419a31065a0ce73..06df40f61427d4db537eded2401b4ece6d81afe1 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // aux-build:dylib.rs
-// min-llvm-version 4.0
 
 extern crate dylib;
 
index 8329c7032f1b695b04ffaff630c8c1e87804e76e..95cff2a28620743cee6c41b7ae0d7843688fb9df 100644 (file)
@@ -10,7 +10,6 @@
 
 // aux-build:msvc-imp-present.rs
 // compile-flags: -Z thinlto -C codegen-units=8
-// min-llvm-version: 4.0
 // no-prefer-dynamic
 
 // On MSVC we have a "hack" where we emit symbols that look like `_imp_$name`
index 7a71dd2bc5125f080d7c0e9804f561cc2f96fc01..41ca983af51c7810ae72726d90e44b47b67defa9 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // compile-flags: -Z thinlto -C codegen-units=8 -O
-// min-llvm-version 4.0
 // ignore-emscripten can't inspect instructions on emscripten
 
 // We want to assert here that ThinLTO will inline across codegen units. There's
index 6020f72415dad2740d2d543a8ec2c4fef1a7d29e..3c0e904662a3534e871f2ae95621fcbe5df96bc2 100644 (file)
@@ -10,7 +10,6 @@
 
 // compile-flags: -C codegen-units=8 -O -C lto=thin
 // aux-build:thin-lto-inlines-aux.rs
-// min-llvm-version 4.0
 // no-prefer-dynamic
 // ignore-emscripten can't inspect instructions on emscripten
 
index b9719e04f34470b6e67804bf5e95a58be11a7a2f..0a1b7307a46ff705ca48bb8b1a3014c9f1806c33 100644 (file)
@@ -10,7 +10,6 @@
 
 // compile-flags: -C codegen-units=8 -Z thinlto
 // ignore-windows
-// min-llvm-version 4.0
 
 #![feature(linkage)]
 
diff --git a/src/test/rustdoc-ui/unused.rs b/src/test/rustdoc-ui/unused.rs
new file mode 100644 (file)
index 0000000..8b53098
--- /dev/null
@@ -0,0 +1,24 @@
+// 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-pass
+
+// This test purpose is to check that unused_imports lint isn't fired
+// by rustdoc. Why would it? Because when rustdoc is running, it uses
+// "everybody-loops" which replaces parts of code with "loop {}" to get
+// huge performance improvements.
+
+#![deny(unused_imports)]
+
+use std::fs::File;
+
+pub fn f() {
+    let _: File;
+}
index daa0a320b88d6cc8b69f04a58c12f1357ca61635..5904e98753694a894369ed34ec88fae166766fb8 100644 (file)
@@ -11,7 +11,7 @@ LL |     let mut lines_to_use: Vec<&CrateId> = Vec::new();
    |         ---------------- lifetime `'2` appears in the type of `lines_to_use`
 LL |         //~^ NOTE cannot infer an appropriate lifetime
 LL |     let push_id = |installed_id: &CrateId| {
-   |                    ------------ lifetime `'1` appears in this argument
+   |                                  - let's call the lifetime of this reference `'1`
 ...
 LL |         lines_to_use.push(installed_id);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
index 812418a3053e99554784b49da3b316ff6b29efa9..d6673f6a8a6fb6b77b506d79f4438ac9f11378a4 100644 (file)
@@ -7,6 +7,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
    = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
    = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
+   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo).
 
 error: program clause dump
   --> $DIR/lower_env1.rs:19:1
@@ -19,6 +20,9 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
    = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
    = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo).
+   = note: WellFormed(Self: Foo) :- Implemented(Self: Foo).
+   = note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized).
 
 error: aborting due to 2 previous errors
 
index 55cd9699b06164de3fc62518a0c2c3666748d854..c4e768415d60b5501ff5156f6c8a26b8bbab1b0d 100644 (file)
@@ -8,6 +8,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
    = note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
    = note: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
+   = note: WellFormed(Self: Foo<S, T, U>) :- Implemented(Self: Foo<S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(U: std::marker::Sized).
 
 error: aborting due to previous error
 
index ea275d647fa7c143fb66a355d8853c1355906656..afb2cd4b563329aa8e07f57de163ac70aeb9aa34 100644 (file)
@@ -8,6 +8,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
    = note: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
    = note: ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
+   = note: WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), WellFormed(F: std::marker::Sized), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }.
 
 error: aborting due to previous error
 
index 68bc2ddf2930ebf3276b15d7393eba89f6f1fb3f..5ea397d424b63986b885c9c10fb5f5bf7a768611 100644 (file)
@@ -11,6 +11,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
    = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
    = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow<U>), RegionOutlives('a : 'b), TypeOutlives(U : 'b).
 
 error: aborting due to previous error
 
index 5487d34813b47a36a5f0b21bc2c28da537575086..c8c8ef8215ae28a7a2a9cfdd392a01cba6132735 100644 (file)
@@ -38,7 +38,7 @@ error: unsatisfied lifetime constraints
 LL |     let mut f: Option<&u32> = None;
    |         ----- lifetime `'2` appears in the type of `f`
 LL |     closure_expecting_bound(|x: &u32| {
-   |                              - lifetime `'1` appears in this argument
+   |                                 - let's call the lifetime of this reference `'1`
 LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
    |         ^^^^^^^^^^^ free region requires that `'1` must outlive `'2`
 
@@ -49,7 +49,7 @@ LL |     let mut f: Option<&u32> = None;
    |         ----- lifetime `'2` appears in the type of `f`
 ...
 LL |     closure_expecting_bound(|x: &'x u32| {
-   |                              - lifetime `'1` appears in this argument
+   |                                 - let's call the lifetime of this reference `'1`
 ...
 LL |         f = Some(x);
    |         ^^^^^^^^^^^ free region requires that `'1` must outlive `'2`
index 9aad7efdee5b277ae8c26490f2e691ab60a293a8..4c0b3a5d93120efb01a67e854ff0980cdac80b05 100644 (file)
@@ -14,7 +14,7 @@ error: unsatisfied lifetime constraints
   --> $DIR/static-return-lifetime-infered.rs:17:9
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         ----- lifetime `'1` appears in this argument
+   |                         - let's call the lifetime of this reference `'1`
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^ cast requires that `'1` must outlive `'static`
 
diff --git a/src/test/ui/missing-alloc_error_handler.rs b/src/test/ui/missing-alloc_error_handler.rs
new file mode 100644 (file)
index 0000000..3842d48
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 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: -C panic=abort
+// no-prefer-dynamic
+
+#![no_std]
+#![crate_type = "staticlib"]
+#![feature(panic_implementation, alloc_error_handler, alloc)]
+
+#[panic_implementation]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+extern crate alloc;
+
+#[global_allocator]
+static A: MyAlloc = MyAlloc;
+
+struct MyAlloc;
+
+unsafe impl core::alloc::GlobalAlloc for MyAlloc {
+    unsafe fn alloc(&self, _: core::alloc::Layout) -> *mut u8 { 0 as _ }
+    unsafe fn dealloc(&self, _: *mut u8, _: core::alloc::Layout) {}
+}
diff --git a/src/test/ui/missing-alloc_error_handler.stderr b/src/test/ui/missing-alloc_error_handler.stderr
new file mode 100644 (file)
index 0000000..5489b2c
--- /dev/null
@@ -0,0 +1,4 @@
+error: `#[alloc_error_handler]` function required, but not found
+
+error: aborting due to previous error
+
index 24282631b7eead69381a764e5c5f34852b39ed05..c949dcb635aad5ccbc0bf998cb06531515e109b1 100644 (file)
 
 #![no_std]
 #![crate_type = "staticlib"]
-#![feature(panic_implementation, lang_items, alloc)]
+#![feature(panic_implementation, alloc_error_handler, alloc)]
 
 #[panic_implementation]
 fn panic(_: &core::panic::PanicInfo) -> ! {
     loop {}
 }
 
-#[lang = "oom"]
-fn oom() {}
+#[alloc_error_handler]
+fn oom(_: core::alloc::Layout) -> ! {
+    loop {}
+}
 
 extern crate alloc;
diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.rs b/src/test/ui/rust-2018/issue-52202-use-suggestions.rs
new file mode 100644 (file)
index 0000000..5acd19c
--- /dev/null
@@ -0,0 +1,23 @@
+// 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: --edition 2018
+
+// The local `use` suggestion should start with `crate::` (but the
+// standard-library suggestions should not, obviously).
+
+mod plumbing {
+    pub struct Drain;
+}
+
+fn main() {
+    let _d = Drain {};
+    //~^ ERROR cannot find struct, variant or union type `Drain` in this scope
+}
diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
new file mode 100644 (file)
index 0000000..95158db
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0422]: cannot find struct, variant or union type `Drain` in this scope
+  --> $DIR/issue-52202-use-suggestions.rs:21:14
+   |
+LL |     let _d = Drain {};
+   |              ^^^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use crate::plumbing::Drain;
+   |
+LL | use std::collections::binary_heap::Drain;
+   |
+LL | use std::collections::hash_map::Drain;
+   |
+LL | use std::collections::hash_set::Drain;
+   |
+and 3 other candidates
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
index 04c3ed2d6ee19ec71a299aab2e4c4005f584de84..6385578698cf745b75258d60065ab5effa5bfdd6 100644 (file)
@@ -26,7 +26,7 @@ error: unsatisfied lifetime constraints
   --> $DIR/dyn-trait-underscore.rs:18:5
    |
 LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
-   |         ----- lifetime `'1` appears in this argument
+   |                - let's call the lifetime of this reference `'1`
 LL |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |     ^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static`