]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #86873 - nikic:opaque-ptrs, r=nagisa
authorbors <bors@rust-lang.org>
Sat, 10 Jul 2021 19:01:41 +0000 (19:01 +0000)
committerbors <bors@rust-lang.org>
Sat, 10 Jul 2021 19:01:41 +0000 (19:01 +0000)
Improve opaque pointers support

Opaque pointers are coming, and rustc is not ready.

This adds partial support by passing an explicit load type to LLVM. Two issues I've encountered:
 * The necessary type was not available at the point where non-temporal copies were generated. I've pushed the code for that upwards out of the memcpy implementation and moved the position of a cast to make do with the types we have available. (I'm not sure that cast is needed at all, but have retained it in the interest of conservativeness.)
 * The `PlaceRef::project_deref()` function used during debuginfo generation seems to be buggy in some way -- though I haven't figured out specifically what it does wrong. Replacing it with `load_operand().deref()` did the trick, but I don't really know what I'm doing here.

169 files changed:
compiler/rustc_attr/src/builtin.rs
compiler/rustc_codegen_llvm/src/back/archive.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/removed.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_middle/src/dep_graph/dep_node.rs
compiler/rustc_middle/src/middle/cstore.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_mir/src/transform/check_consts/ops.rs
compiler/rustc_mir/src/transform/check_unsafety.rs
compiler/rustc_mir/src/transform/inline.rs
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/thir/visit.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/collect.rs
library/std/src/os/windows/process.rs
library/std/src/sys/windows/process.rs
library/std/src/sys/windows/process/tests.rs
library/std/src/thread/mod.rs
src/test/run-make/raw-dylib-alt-calling-convention/Makefile [new file with mode: 0644]
src/test/run-make/raw-dylib-alt-calling-convention/driver.rs [new file with mode: 0644]
src/test/run-make/raw-dylib-alt-calling-convention/extern.c [new file with mode: 0644]
src/test/run-make/raw-dylib-alt-calling-convention/lib.rs [new file with mode: 0644]
src/test/run-make/raw-dylib-alt-calling-convention/output.txt [new file with mode: 0644]
src/test/run-make/raw-dylib-c/Makefile [new file with mode: 0644]
src/test/run-make/raw-dylib-c/driver.rs [new file with mode: 0644]
src/test/run-make/raw-dylib-c/extern_1.c [new file with mode: 0644]
src/test/run-make/raw-dylib-c/extern_2.c [new file with mode: 0644]
src/test/run-make/raw-dylib-c/lib.rs [new file with mode: 0644]
src/test/run-make/raw-dylib-c/output.txt [new file with mode: 0644]
src/test/run-make/raw-dylib/Makefile [deleted file]
src/test/run-make/raw-dylib/driver.rs [deleted file]
src/test/run-make/raw-dylib/extern_1.c [deleted file]
src/test/run-make/raw-dylib/extern_2.c [deleted file]
src/test/run-make/raw-dylib/lib.rs [deleted file]
src/test/run-make/raw-dylib/output.txt [deleted file]
src/test/ui/attributes/nonterminal-expansion.rs
src/test/ui/attributes/nonterminal-expansion.stderr
src/test/ui/cast/cast-ptr-to-int-const.mir.stderr [deleted file]
src/test/ui/cast/cast-ptr-to-int-const.rs [deleted file]
src/test/ui/cast/cast-ptr-to-int-const.thir.stderr [deleted file]
src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs [deleted file]
src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr [deleted file]
src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
src/test/ui/const-ptr/ptr_to_usize_cast.rs [deleted file]
src/test/ui/const-ptr/ptr_to_usize_cast.stderr [deleted file]
src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs
src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr
src/test/ui/consts/const-eval/issue-52442.rs [deleted file]
src/test/ui/consts/const-eval/issue-52442.stderr [deleted file]
src/test/ui/consts/const-eval/match-test-ptr-null.rs
src/test/ui/consts/const-eval/match-test-ptr-null.stderr
src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs
src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs
src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr
src/test/ui/consts/issue-17458.rs
src/test/ui/consts/issue-17458.stderr
src/test/ui/consts/issue-51559.rs [deleted file]
src/test/ui/consts/issue-51559.stderr [deleted file]
src/test/ui/consts/issue-52023-array-size-pointer-cast.rs
src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr
src/test/ui/consts/issue-52432.rs [deleted file]
src/test/ui/consts/issue-52432.stderr [deleted file]
src/test/ui/consts/min_const_fn/min_const_fn.rs
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/issues/issue-18294.rs
src/test/ui/issues/issue-18294.stderr
src/test/ui/issues/issue-47412.mir.stderr
src/test/ui/issues/issue-47412.rs
src/test/ui/issues/issue-47412.thir.stderr
src/test/ui/lint/missing-doc-private-macro.rs [new file with mode: 0644]
src/test/ui/lint/missing-doc-private-macro.stderr [new file with mode: 0644]
src/test/ui/repr/issue-83921-ice.rs [new file with mode: 0644]
src/test/ui/repr/issue-83921-ice.stderr [new file with mode: 0644]
src/test/ui/repr/issue-83921-pretty.normal.stderr [new file with mode: 0644]
src/test/ui/repr/issue-83921-pretty.pretty.stdout [new file with mode: 0644]
src/test/ui/repr/issue-83921-pretty.rs [new file with mode: 0644]
src/test/ui/rfc-2091-track-caller/tracked-trait-obj.rs
src/test/ui/rfc-2627-raw-dylib/multiple-definitions.rs [new file with mode: 0644]
src/test/ui/rfc-2627-raw-dylib/multiple-definitions.stderr [new file with mode: 0644]
src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs [new file with mode: 0644]
src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr [new file with mode: 0644]
src/test/ui/union/union-align.rs
src/test/ui/union/union-backcomp.rs
src/test/ui/union/union-basic.rs
src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-borrow-move-parent-sibling.rs
src/test/ui/union/union-borrow-move-parent-sibling.stderr [deleted file]
src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-const-codegen.rs
src/test/ui/union/union-const-eval-field.rs
src/test/ui/union/union-const-eval.rs
src/test/ui/union/union-deref.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-deref.rs
src/test/ui/union/union-deref.stderr [deleted file]
src/test/ui/union/union-deref.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-clone.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-clone.rs
src/test/ui/union/union-derive-clone.stderr [deleted file]
src/test/ui/union/union-derive-clone.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-eq.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-eq.rs
src/test/ui/union/union-derive-eq.stderr [deleted file]
src/test/ui/union/union-derive-eq.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-derive-rpass.rs
src/test/ui/union/union-drop.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-fields-1.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-fields-1.rs
src/test/ui/union/union-fields-1.stderr [deleted file]
src/test/ui/union/union-fields-1.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-fields-2.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-fields-2.rs
src/test/ui/union/union-fields-2.stderr [deleted file]
src/test/ui/union/union-fields-2.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-generic-rpass.rs
src/test/ui/union/union-generic.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-generic.rs
src/test/ui/union/union-generic.stderr [deleted file]
src/test/ui/union/union-generic.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-inherent-method.rs
src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-lint-dead-code.rs
src/test/ui/union/union-lint-dead-code.stderr [deleted file]
src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-macro.rs
src/test/ui/union/union-manuallydrop-rpass.rs
src/test/ui/union/union-move.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-move.rs
src/test/ui/union/union-move.stderr [deleted file]
src/test/ui/union/union-move.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-nodrop.rs
src/test/ui/union/union-nonzero.rs
src/test/ui/union/union-overwrite.rs
src/test/ui/union/union-packed.rs
src/test/ui/union/union-pat-refutability.rs
src/test/ui/union/union-suggest-field.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-suggest-field.rs
src/test/ui/union/union-suggest-field.stderr [deleted file]
src/test/ui/union/union-suggest-field.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-trait-impl.rs
src/test/ui/union/union-transmute.rs
src/test/ui/union/union-unsafe.mir.stderr [new file with mode: 0644]
src/test/ui/union/union-unsafe.rs
src/test/ui/union/union-unsafe.stderr [deleted file]
src/test/ui/union/union-unsafe.thir.stderr [new file with mode: 0644]
src/test/ui/union/union-unsized.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-unsized.rs
src/test/ui/union/union-unsized.stderr [deleted file]
src/test/ui/union/union-unsized.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr [new file with mode: 0644]
src/test/ui/union/union-with-drop-fields.rs
src/test/ui/union/union-with-drop-fields.stderr [deleted file]
src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr [new file with mode: 0644]
src/test/ui/unsafe/access_union_field.mir.stderr [new file with mode: 0644]
src/test/ui/unsafe/access_union_field.rs [new file with mode: 0644]
src/test/ui/unsafe/access_union_field.thir.stderr [new file with mode: 0644]
src/test/ui/unsafe/union.mir.stderr [new file with mode: 0644]
src/test/ui/unsafe/union.rs [new file with mode: 0644]
src/test/ui/unsafe/union_access_through_block.rs [new file with mode: 0644]
src/test/ui/unsafe/union_destructure.mir.stderr [new file with mode: 0644]
src/test/ui/unsafe/union_destructure.rs [new file with mode: 0644]
src/test/ui/unsafe/union_wild_or_wild.rs [new file with mode: 0644]

index 20971ebb95748888568d994fbf31286e33ea2282..b7b053cd5ddb7a910f24f795abb0ddac2ecb1044 100644 (file)
@@ -870,6 +870,23 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                         sym::simd => Some(ReprSimd),
                         sym::transparent => Some(ReprTransparent),
                         sym::no_niche => Some(ReprNoNiche),
+                        sym::align => {
+                            let mut err = struct_span_err!(
+                                diagnostic,
+                                item.span(),
+                                E0589,
+                                "invalid `repr(align)` attribute: `align` needs an argument"
+                            );
+                            err.span_suggestion(
+                                item.span(),
+                                "supply an argument here",
+                                "align(...)".to_string(),
+                                Applicability::HasPlaceholders,
+                            );
+                            err.emit();
+                            recognised = true;
+                            None
+                        }
                         name => int_type_of_word(name).map(ReprInt),
                     };
 
@@ -891,33 +908,47 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                             Ok(literal) => acc.push(ReprPacked(literal)),
                             Err(message) => literal_error = Some(message),
                         };
+                    } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche)
+                        || int_type_of_word(name).is_some()
+                    {
+                        recognised = true;
+                        struct_span_err!(
+                                diagnostic,
+                                item.span(),
+                                E0552,
+                                "invalid representation hint: `{}` does not take a parenthesized argument list",
+                                name.to_ident_string(),
+                            ).emit();
                     }
                     if let Some(literal_error) = literal_error {
                         struct_span_err!(
                             diagnostic,
                             item.span(),
                             E0589,
-                            "invalid `repr(align)` attribute: {}",
+                            "invalid `repr({})` attribute: {}",
+                            name.to_ident_string(),
                             literal_error
                         )
                         .emit();
                     }
                 } else if let Some(meta_item) = item.meta_item() {
-                    if meta_item.has_name(sym::align) {
-                        if let MetaItemKind::NameValue(ref value) = meta_item.kind {
+                    if let MetaItemKind::NameValue(ref value) = meta_item.kind {
+                        if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
+                            let name = meta_item.name_or_empty().to_ident_string();
                             recognised = true;
                             let mut err = struct_span_err!(
                                 diagnostic,
                                 item.span(),
                                 E0693,
-                                "incorrect `repr(align)` attribute format"
+                                "incorrect `repr({})` attribute format",
+                                name,
                             );
                             match value.kind {
                                 ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
                                     err.span_suggestion(
                                         item.span(),
                                         "use parentheses instead",
-                                        format!("align({})", int),
+                                        format!("{}({})", name, int),
                                         Applicability::MachineApplicable,
                                     );
                                 }
@@ -925,19 +956,76 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                                     err.span_suggestion(
                                         item.span(),
                                         "use parentheses instead",
-                                        format!("align({})", s),
+                                        format!("{}({})", name, s),
                                         Applicability::MachineApplicable,
                                     );
                                 }
                                 _ => {}
                             }
                             err.emit();
+                        } else {
+                            if matches!(
+                                meta_item.name_or_empty(),
+                                sym::C | sym::simd | sym::transparent | sym::no_niche
+                            ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                            {
+                                recognised = true;
+                                struct_span_err!(
+                                    diagnostic,
+                                    meta_item.span,
+                                    E0552,
+                                    "invalid representation hint: `{}` does not take a value",
+                                    meta_item.name_or_empty().to_ident_string(),
+                                )
+                                .emit();
+                            }
+                        }
+                    } else if let MetaItemKind::List(_) = meta_item.kind {
+                        if meta_item.has_name(sym::align) {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0693,
+                                "incorrect `repr(align)` attribute format: \
+                                 `align` takes exactly one argument in parentheses"
+                            )
+                            .emit();
+                        } else if meta_item.has_name(sym::packed) {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0552,
+                                "incorrect `repr(packed)` attribute format: \
+                                 `packed` takes exactly one parenthesized argument, \
+                                 or no parentheses at all"
+                            )
+                            .emit();
+                        } else if matches!(
+                            meta_item.name_or_empty(),
+                            sym::C | sym::simd | sym::transparent | sym::no_niche
+                        ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                        {
+                            recognised = true;
+                            struct_span_err!(
+                                diagnostic,
+                                meta_item.span,
+                                E0552,
+                                "invalid representation hint: `{}` does not take a parenthesized argument list",
+                                meta_item.name_or_empty().to_ident_string(),
+                            ).emit();
                         }
                     }
                 }
                 if !recognised {
-                    // Not a word we recognize
-                    diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
+                    // Not a word we recognize. This will be caught and reported by
+                    // the `check_mod_attrs` pass, but this pass doesn't always run
+                    // (e.g. if we only pretty-print the source), so we have to gate
+                    // the `delay_span_bug` call as follows:
+                    if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
+                        diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
+                    }
                 }
             }
         }
index 64416bced31d024dcd8819dbeaa6f35e0f2cf8ad..6ac7093b7dee833870d4568529293b088950f62f 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
 use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME};
 use rustc_data_structures::temp_dir::MaybeTempDir;
-use rustc_middle::middle::cstore::DllImport;
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
@@ -208,10 +208,12 @@ fn inject_dll_import_lib(
         // have any \0 characters
         let import_name_vector: Vec<CString> = dll_imports
             .iter()
-            .map(if self.config.sess.target.arch == "x86" {
-                |import: &DllImport| CString::new(format!("_{}", import.name.to_string())).unwrap()
-            } else {
-                |import: &DllImport| CString::new(import.name.to_string()).unwrap()
+            .map(|import: &DllImport| {
+                if self.config.sess.target.arch == "x86" {
+                    LlvmArchiveBuilder::i686_decorated_name(import)
+                } else {
+                    CString::new(import.name.to_string()).unwrap()
+                }
             })
             .collect();
 
@@ -391,6 +393,21 @@ fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
             ret
         }
     }
+
+    fn i686_decorated_name(import: &DllImport) -> CString {
+        let name = import.name;
+        // We verified during construction that `name` does not contain any NULL characters, so the
+        // conversion to CString is guaranteed to succeed.
+        CString::new(match import.calling_convention {
+            DllCallingConvention::C => format!("_{}", name),
+            DllCallingConvention::Stdcall(arg_list_size) => format!("_{}@{}", name, arg_list_size),
+            DllCallingConvention::Fastcall(arg_list_size) => format!("@{}@{}", name, arg_list_size),
+            DllCallingConvention::Vectorcall(arg_list_size) => {
+                format!("{}@@{}", name, arg_list_size)
+            }
+        })
+        .unwrap()
+    }
 }
 
 fn string_to_io_error(s: String) -> io::Error {
index 59447e9de13507cf1a8ec5c0b2c3f103960b84e7..f9efa448c93fa32ef6970e414deb5f46443c66d2 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_errors::Handler;
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::DllImport;
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
 use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
@@ -34,8 +34,8 @@
 use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind};
 use tempfile::Builder as TempFileBuilder;
 
-use std::cmp::Ordering;
 use std::ffi::OsString;
+use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
 use std::{ascii, char, env, fmt, fs, io, mem, str};
@@ -259,7 +259,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     }
 
     for (raw_dylib_name, raw_dylib_imports) in
-        collate_raw_dylibs(&codegen_results.crate_info.used_libraries)
+        collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)
     {
         ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir);
     }
@@ -451,8 +451,11 @@ fn create_metadata_file(sess: &Session, metadata: &[u8]) -> Vec<u8> {
 /// then the CodegenResults value contains one NativeLib instance for each block.  However, the
 /// linker appears to expect only a single import library for each library used, so we need to
 /// collate the symbols together by library name before generating the import libraries.
-fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImport>)> {
-    let mut dylib_table: FxHashMap<String, FxHashSet<Symbol>> = FxHashMap::default();
+fn collate_raw_dylibs(
+    sess: &Session,
+    used_libraries: &[NativeLib],
+) -> Vec<(String, Vec<DllImport>)> {
+    let mut dylib_table: FxHashMap<String, FxHashSet<DllImport>> = FxHashMap::default();
 
     for lib in used_libraries {
         if lib.kind == NativeLibKind::RawDylib {
@@ -464,35 +467,51 @@ fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImpor
             } else {
                 format!("{}.dll", name)
             };
-            dylib_table
-                .entry(name)
-                .or_default()
-                .extend(lib.dll_imports.iter().map(|import| import.name));
+            dylib_table.entry(name).or_default().extend(lib.dll_imports.iter().cloned());
         }
     }
 
-    // FIXME: when we add support for ordinals, fix this to propagate ordinals.  Also figure out
-    // what we should do if we have two DllImport values with the same name but different
-    // ordinals.
-    let mut result = dylib_table
+    // Rustc already signals an error if we have two imports with the same name but different
+    // calling conventions (or function signatures), so we don't have pay attention to those
+    // when ordering.
+    // FIXME: when we add support for ordinals, figure out if we need to do anything if we
+    // have two DllImport values with the same name but different ordinals.
+    let mut result: Vec<(String, Vec<DllImport>)> = dylib_table
         .into_iter()
-        .map(|(lib_name, imported_names)| {
-            let mut names = imported_names
-                .iter()
-                .map(|name| DllImport { name: *name, ordinal: None })
-                .collect::<Vec<_>>();
-            names.sort_unstable_by(|a: &DllImport, b: &DllImport| {
-                match a.name.as_str().cmp(&b.name.as_str()) {
-                    Ordering::Equal => a.ordinal.cmp(&b.ordinal),
-                    x => x,
-                }
-            });
-            (lib_name, names)
+        .map(|(lib_name, import_table)| {
+            let mut imports = Vec::from_iter(import_table.into_iter());
+            imports.sort_unstable_by_key(|x: &DllImport| x.name.as_str());
+            (lib_name, imports)
         })
         .collect::<Vec<_>>();
     result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
         a.0.cmp(&b.0)
     });
+    let result = result;
+
+    // Check for multiple imports with the same name but different calling conventions or
+    // (when relevant) argument list sizes.  Rustc only signals an error for this if the
+    // declarations are at the same scope level; if one shadows the other, we only get a lint
+    // warning.
+    for (library, imports) in &result {
+        let mut import_table: FxHashMap<Symbol, DllCallingConvention> = FxHashMap::default();
+        for import in imports {
+            if let Some(old_convention) =
+                import_table.insert(import.name, import.calling_convention)
+            {
+                if import.calling_convention != old_convention {
+                    sess.span_fatal(
+                        import.span,
+                        &format!(
+                            "multiple definitions of external function `{}` from library `{}` have different calling conventions",
+                            import.name,
+                            library,
+                    ));
+                }
+            }
+        }
+    }
+
     result
 }
 
index d01804aca88b22f007cd650355e9a9944cc0221b..9eaf4693811ca100844fe5fd4fc51d614463a468 100644 (file)
@@ -416,9 +416,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows accessing fields of unions inside `const` functions.
     (active, const_fn_union, "1.27.0", Some(51909), None),
 
-    /// Allows casting raw pointers to `usize` during const eval.
-    (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),
-
     /// Allows dereferencing raw pointers during const eval.
     (active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
 
index 71c10eb650754699eb8d98456c7fe0a4dd2e46ca..6d3e2b9c5171366219cb1d904d1288e86349285e 100644 (file)
@@ -144,6 +144,10 @@ macro_rules! declare_features {
     (removed, external_doc, "1.54.0", Some(44732), None,
      Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
 
+     /// Allows casting raw pointers to `usize` during const eval.
+    (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None,
+     Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")),
+
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
     // -------------------------------------------------------------------------
index b303f55cf772b8af4a73efb55e3f5e6f0aad4190..92e627bce02934de317fe5cf8ae55416f5aa68d8 100644 (file)
@@ -571,6 +571,12 @@ fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) {
         self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.inner, "the", "crate");
 
         for macro_def in krate.exported_macros {
+            // Non exported macros should be skipped, since `missing_docs` only
+            // applies to externally visible items.
+            if !cx.access_levels.is_exported(macro_def.hir_id()) {
+                continue;
+            }
+
             let attrs = cx.tcx.hir().attrs(macro_def.hir_id());
             let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
             if !has_doc {
index cd4c394ae14ecf752d1deba6ff36927be57ca8ab..16b4d26b37b4b79879bea9822765f137946a9a39 100644 (file)
@@ -3,8 +3,8 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_middle::middle::cstore::{DllImport, NativeLib};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport, NativeLib};
+use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_session::parse::feature_err;
 use rustc_session::utils::NativeLibKind;
 use rustc_session::Session;
@@ -199,22 +199,10 @@ fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
             }
 
             if lib.kind == NativeLibKind::RawDylib {
-                match abi {
-                    Abi::C { .. } => (),
-                    Abi::Cdecl => (),
-                    _ => {
-                        if sess.target.arch == "x86" {
-                            sess.span_fatal(
-                                it.span,
-                                r#"`#[link(kind = "raw-dylib")]` only supports C and Cdecl ABIs"#,
-                            );
-                        }
-                    }
-                };
                 lib.dll_imports.extend(
                     foreign_mod_items
                         .iter()
-                        .map(|child_item| DllImport { name: child_item.ident.name, ordinal: None }),
+                        .map(|child_item| self.build_dll_import(abi, child_item)),
                 );
             }
 
@@ -396,4 +384,58 @@ fn process_command_line(&mut self) {
             }
         }
     }
+
+    fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize {
+        let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
+            self.tcx
+                .type_of(item.id.def_id)
+                .fn_sig(self.tcx)
+                .inputs()
+                .map_bound(|slice| self.tcx.mk_type_list(slice.iter())),
+        );
+
+        argument_types
+            .iter()
+            .map(|ty| {
+                let layout = self
+                    .tcx
+                    .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty })
+                    .expect("layout")
+                    .layout;
+                // In both stdcall and fastcall, we always round up the argument size to the
+                // nearest multiple of 4 bytes.
+                (layout.size.bytes_usize() + 3) & !3
+            })
+            .sum()
+    }
+
+    fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport {
+        let calling_convention = if self.tcx.sess.target.arch == "x86" {
+            match abi {
+                Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C,
+                Abi::Stdcall { .. } | Abi::System { .. } => {
+                    DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
+                }
+                Abi::Fastcall => DllCallingConvention::Fastcall(self.i686_arg_list_size(item)),
+                // Vectorcall is intentionally not supported at this time.
+                _ => {
+                    self.tcx.sess.span_fatal(
+                        item.span,
+                        r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#,
+                    );
+                }
+            }
+        } else {
+            match abi {
+                Abi::C { .. } | Abi::Win64 | Abi::System { .. } => DllCallingConvention::C,
+                _ => {
+                    self.tcx.sess.span_fatal(
+                        item.span,
+                        r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#,
+                    );
+                }
+            }
+        };
+        DllImport { name: item.ident.name, ordinal: None, calling_convention, span: item.span }
+    }
 }
index aa54d1ae7b9d118426d9702dac6384725e0b50c4..8476929eaeced2b1d230e5e6f6d964e2e7d2a088 100644 (file)
@@ -285,7 +285,7 @@ pub mod label_strs {
 // required that their size stay the same, but we don't want to change
 // it inadvertently. This assert just ensures we're aware of any change.
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-static_assert_size!(DepNode, 17);
+static_assert_size!(DepNode, 18);
 
 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 static_assert_size!(DepNode, 24);
index 3c4c4a84d244fa3f0252b1b8ee3a1ad0cfd48c6c..d69904f7b11a2c0a5abb76f10f09f35d501108e6 100644 (file)
@@ -77,10 +77,29 @@ pub struct NativeLib {
     pub dll_imports: Vec<DllImport>,
 }
 
-#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
 pub struct DllImport {
     pub name: Symbol,
     pub ordinal: Option<u16>,
+    /// Calling convention for the function.
+    ///
+    /// On x86_64, this is always `DllCallingConvention::C`; on i686, it can be any
+    /// of the values, and we use `DllCallingConvention::C` to represent `"cdecl"`.
+    pub calling_convention: DllCallingConvention,
+    /// Span of import's "extern" declaration; used for diagnostics.
+    pub span: Span,
+}
+
+/// Calling convention for a function defined in an external library.
+///
+/// The usize value, where present, indicates the size of the function's argument list
+/// in bytes.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
+pub enum DllCallingConvention {
+    C,
+    Stdcall(usize),
+    Fastcall(usize),
+    Vectorcall(usize),
 }
 
 #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
index 9a2f1149316e26e0a547aca9334c82aeb1a08cf2..d218172282d6fc99385de746feb5edbfd61226bf 100644 (file)
         desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) }
     }
 
+    query should_inherit_track_caller(def_id: DefId) -> bool {
+        desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) }
+    }
+
     query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
         desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
     }
index c9b73c682098b6fd728e8c388294de4774658beb..892a29e4e22c7e4e090d95b0cb01431c88321aec 100644 (file)
@@ -426,10 +426,10 @@ pub enum SelectionError<'tcx> {
 /// impl Clone for i32 { ... }                   // Impl_3
 ///
 /// fn foo<T: Clone>(concrete: Option<Box<i32>>, param: T, mixed: Option<T>) {
-///     // Case A: Vtable points at a specific impl. Only possible when
+///     // Case A: ImplSource points at a specific impl. Only possible when
 ///     // type is concretely known. If the impl itself has bounded
-///     // type parameters, Vtable will carry resolutions for those as well:
-///     concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
+///     // type parameters, ImplSource will carry resolutions for those as well:
+///     concrete.clone(); // ImpleSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
 ///
 ///     // Case A: ImplSource points at a specific impl. Only possible when
 ///     // type is concretely known. If the impl itself has bounded
index 41d953216e0dd1425d2b59d465c4720c2e57ebdf..261a19f862e02958b226f4e386f04c6ce17793b6 100644 (file)
@@ -227,8 +227,9 @@ pub fn generates_cgu_internal_copy(&self, tcx: TyCtxt<'tcx>) -> bool {
 
     pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
         match *self {
-            InstanceDef::Item(def) => {
-                tcx.codegen_fn_attrs(def.did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
+            InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. })
+            | InstanceDef::Virtual(def_id, _) => {
+                tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
             }
             _ => false,
         }
@@ -403,7 +404,7 @@ pub fn resolve_for_vtable(
         def_id: DefId,
         substs: SubstsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
-        debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
+        debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs);
         let fn_sig = tcx.fn_sig(def_id);
         let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
             && fn_sig.input(0).skip_binder().is_param(0)
@@ -412,7 +413,50 @@ pub fn resolve_for_vtable(
             debug!(" => associated item with unsizeable self: Self");
             Some(Instance { def: InstanceDef::VtableShim(def_id), substs })
         } else {
-            Instance::resolve_for_fn_ptr(tcx, param_env, def_id, substs)
+            Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
+                match resolved.def {
+                    InstanceDef::Item(def) => {
+                        // We need to generate a shim when we cannot guarantee that
+                        // the caller of a trait object method will be aware of
+                        // `#[track_caller]` - this ensures that the caller
+                        // and callee ABI will always match.
+                        //
+                        // The shim is generated when all of these conditions are met:
+                        //
+                        // 1) The underlying method expects a caller location parameter
+                        // in the ABI
+                        if resolved.def.requires_caller_location(tcx)
+                            // 2) The caller location parameter comes from having `#[track_caller]`
+                            // on the implementation, and *not* on the trait method.
+                            && !tcx.should_inherit_track_caller(def.did)
+                            // If the method implementation comes from the trait definition itself
+                            // (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`),
+                            // then we don't need to generate a shim. This check is needed because
+                            // `should_inherit_track_caller` returns `false` if our method
+                            // implementation comes from the trait block, and not an impl block
+                            && !matches!(
+                                tcx.opt_associated_item(def.did),
+                                Some(ty::AssocItem {
+                                    container: ty::AssocItemContainer::TraitContainer(_),
+                                    ..
+                                })
+                            )
+                        {
+                            debug!(
+                                " => vtable fn pointer created for function with #[track_caller]"
+                            );
+                            resolved.def = InstanceDef::ReifyShim(def.did);
+                        }
+                    }
+                    InstanceDef::Virtual(def_id, _) => {
+                        debug!(" => vtable fn pointer created for virtual call");
+                        resolved.def = InstanceDef::ReifyShim(def_id);
+                    }
+                    _ => {}
+                }
+
+                resolved
+            })
         }
     }
 
index dcbc9c523dc1946f55687f59f0b8281d4f8e5d9e..fd72ec4340f9f2a7f9c462c9039f3888998e70c2 100644 (file)
@@ -397,6 +397,9 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<
     }
 }
 
+/// Comparing raw pointers for equality.
+/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
+/// allocation base addresses that are not known at compile-time.
 #[derive(Debug)]
 pub struct RawPtrComparison;
 impl NonConstOp for RawPtrComparison {
@@ -430,20 +433,22 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<
     }
 }
 
+/// Casting raw pointer or function pointer to an integer.
+/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
+/// allocation base addresses that are not known at compile-time.
 #[derive(Debug)]
 pub struct RawPtrToIntCast;
 impl NonConstOp for RawPtrToIntCast {
-    fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
-        Status::Unstable(sym::const_raw_ptr_to_usize_cast)
-    }
-
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-        feature_err(
-            &ccx.tcx.sess.parse_sess,
-            sym::const_raw_ptr_to_usize_cast,
-            span,
-            &format!("casting pointers to integers in {}s is unstable", ccx.const_kind(),),
-        )
+        let mut err = ccx
+            .tcx
+            .sess
+            .struct_span_err(span, "pointers cannot be cast to integers during const eval.");
+        err.note("at compile-time, pointers do not have an integer value");
+        err.note(
+            "avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior",
+        );
+        err
     }
 }
 
index 103ddda1a1d262c45069da1fab78d78404a7776b..1ff9bd157210874391deafc577a31eb4dd435c42 100644 (file)
@@ -7,7 +7,6 @@
 use rustc_hir::Node;
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
@@ -18,7 +17,6 @@
 pub struct UnsafetyChecker<'a, 'tcx> {
     body: &'a Body<'tcx>,
     body_did: LocalDefId,
-    const_context: bool,
     violations: Vec<UnsafetyViolation>,
     source_info: SourceInfo,
     tcx: TyCtxt<'tcx>,
@@ -30,7 +28,6 @@ pub struct UnsafetyChecker<'a, 'tcx> {
 
 impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
     fn new(
-        const_context: bool,
         body: &'a Body<'tcx>,
         body_did: LocalDefId,
         tcx: TyCtxt<'tcx>,
@@ -39,7 +36,6 @@ fn new(
         Self {
             body,
             body_did,
-            const_context,
             violations: vec![],
             source_info: SourceInfo::outermost(body.span),
             tcx,
@@ -136,25 +132,6 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                     self.register_violations(&violations, &unsafe_blocks);
                 }
             },
-            // casting pointers to ints is unsafe in const fn because the const evaluator cannot
-            // possibly know what the result of various operations like `address / 2` would be
-            // pointers during const evaluation have no integral address, only an abstract one
-            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty)
-                if self.const_context && self.tcx.features().const_raw_ptr_to_usize_cast =>
-            {
-                let operand_ty = operand.ty(self.body, self.tcx);
-                let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
-                let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
-                match (cast_in, cast_out) {
-                    (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
-                        self.require_unsafe(
-                            UnsafetyViolationKind::General,
-                            UnsafetyViolationDetails::CastOfPointerToInt,
-                        );
-                    }
-                    _ => {}
-                }
-            }
             _ => {}
         }
         self.super_rvalue(rvalue, location);
@@ -469,13 +446,7 @@ fn unsafety_check_result<'tcx>(
 
     let param_env = tcx.param_env(def.did);
 
-    let id = tcx.hir().local_def_id_to_hir_id(def.did);
-    let const_context = match tcx.hir().body_owner_kind(id) {
-        hir::BodyOwnerKind::Closure => false,
-        hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
-        hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
-    };
-    let mut checker = UnsafetyChecker::new(const_context, body, def.did, tcx, param_env);
+    let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
     checker.visit_body(&body);
 
     check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks);
index c8791ec227cdfdd2eeda3cacb3671fa467f8332b..703ac39dc30802c606e73d774d8e8bb8ec4b448c 100644 (file)
@@ -284,7 +284,7 @@ fn check_codegen_attributes(
         &self,
         callsite: &CallSite<'tcx>,
         callee_attrs: &CodegenFnAttrs,
-    ) -> Result<(), &'satic str> {
+    ) -> Result<(), &'static str> {
         if let InlineAttr::Never = callee_attrs.inline {
             return Err("never inline hint");
         }
index 9bef8ac2413d6aa3027c8b6eaab4ef1566ffb0c0..38111527a4ec719e133138452ad4eea2247238a5 100644 (file)
@@ -25,7 +25,8 @@ struct UnsafetyVisitor<'a, 'tcx> {
     /// The `#[target_feature]` attributes of the body. Used for checking
     /// calls to functions with `#[target_feature]` (RFC 2396).
     body_target_features: &'tcx Vec<Symbol>,
-    is_const: bool,
+    in_possible_lhs_union_assign: bool,
+    in_union_destructure: bool,
 }
 
 impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
@@ -158,14 +159,115 @@ fn visit_block(&mut self, block: &Block) {
         }
     }
 
+    fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+        use PatKind::*;
+
+        if self.in_union_destructure {
+            match *pat.kind {
+                // binding to a variable allows getting stuff out of variable
+                Binding { .. }
+                // match is conditional on having this value
+                | Constant { .. }
+                | Variant { .. }
+                | Leaf { .. }
+                | Deref { .. }
+                | Range { .. }
+                | Slice { .. }
+                | Array { .. } => {
+                    self.requires_unsafe(pat.span, AccessToUnionField);
+                    return; // don't walk pattern
+                }
+                // wildcard doesn't take anything
+                Wild |
+                // these just wrap other patterns
+                Or { .. } |
+                AscribeUserType { .. } => {}
+            }
+        };
+
+        if let ty::Adt(adt_def, _) = pat.ty.kind() {
+            // check for extracting values from union via destructuring
+            if adt_def.is_union() {
+                match *pat.kind {
+                    // assigning the whole union is okay
+                    // let x = Union { ... };
+                    // let y = x; // safe
+                    Binding { .. } |
+                    // binding to wildcard is okay since that never reads anything and stops double errors
+                    // with implict wildcard branches from `if let`s
+                    Wild |
+                    // doesn't have any effect on semantics
+                    AscribeUserType { .. } |
+                    // creating a union literal
+                    Constant { .. } => {},
+                    Leaf { .. } | Or { .. } => {
+                        // pattern matching with a union and not doing something like v = Union { bar: 5 }
+                        self.in_union_destructure = true;
+                        visit::walk_pat(self, pat);
+                        self.in_union_destructure = false;
+                        return; // don't walk pattern
+                    }
+                    Variant { .. } | Deref { .. } | Range { .. } | Slice { .. } | Array { .. } =>
+                        unreachable!("impossible union destructuring type"),
+                }
+            }
+        }
+
+        visit::walk_pat(self, pat);
+    }
+
     fn visit_expr(&mut self, expr: &Expr<'tcx>) {
+        // could we be in a the LHS of an assignment of a union?
+        match expr.kind {
+            ExprKind::Field { .. }
+            | ExprKind::VarRef { .. }
+            | ExprKind::UpvarRef { .. }
+            | ExprKind::Scope { .. }
+            | ExprKind::Cast { .. } => {}
+
+            ExprKind::AddressOf { .. }
+            | ExprKind::Adt { .. }
+            | ExprKind::Array { .. }
+            | ExprKind::Binary { .. }
+            | ExprKind::Block { .. }
+            | ExprKind::Borrow { .. }
+            | ExprKind::Literal { .. }
+            | ExprKind::ConstBlock { .. }
+            | ExprKind::Deref { .. }
+            | ExprKind::Index { .. }
+            | ExprKind::NeverToAny { .. }
+            | ExprKind::PlaceTypeAscription { .. }
+            | ExprKind::ValueTypeAscription { .. }
+            | ExprKind::Pointer { .. }
+            | ExprKind::Repeat { .. }
+            | ExprKind::StaticRef { .. }
+            | ExprKind::ThreadLocalRef { .. }
+            | ExprKind::Tuple { .. }
+            | ExprKind::Unary { .. }
+            | ExprKind::Call { .. }
+            | ExprKind::Assign { .. }
+            | ExprKind::AssignOp { .. }
+            | ExprKind::Break { .. }
+            | ExprKind::Closure { .. }
+            | ExprKind::Continue { .. }
+            | ExprKind::Return { .. }
+            | ExprKind::Yield { .. }
+            | ExprKind::Loop { .. }
+            | ExprKind::Match { .. }
+            | ExprKind::Box { .. }
+            | ExprKind::If { .. }
+            | ExprKind::InlineAsm { .. }
+            | ExprKind::LlvmInlineAsm { .. }
+            | ExprKind::LogicalOp { .. }
+            | ExprKind::Use { .. } => self.in_possible_lhs_union_assign = false,
+        };
         match expr.kind {
             ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => {
                 let prev_id = self.hir_context;
                 self.hir_context = hir_id;
                 self.visit_expr(&self.thir[value]);
                 self.hir_context = prev_id;
-                return;
+                return; // don't visit the whole expression
             }
             ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
                 if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
@@ -212,16 +314,6 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 (Bound::Unbounded, Bound::Unbounded) => {}
                 _ => self.requires_unsafe(expr.span, InitializingTypeWith),
             },
-            ExprKind::Cast { source } => {
-                let source = &self.thir[source];
-                if self.tcx.features().const_raw_ptr_to_usize_cast
-                    && self.is_const
-                    && (source.ty.is_unsafe_ptr() || source.ty.is_fn_ptr())
-                    && expr.ty.is_integral()
-                {
-                    self.requires_unsafe(expr.span, CastOfPointerToInt);
-                }
-            }
             ExprKind::Closure {
                 closure_id,
                 substs: _,
@@ -246,9 +338,29 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 // Unsafe blocks can be used in closures, make sure to take it into account
                 self.safety_context = closure_visitor.safety_context;
             }
+            ExprKind::Field { lhs, .. } => {
+                // assigning to union field is okay for AccessToUnionField
+                if let ty::Adt(adt_def, _) = &self.thir[lhs].ty.kind() {
+                    if adt_def.is_union() {
+                        if self.in_possible_lhs_union_assign {
+                            // FIXME: trigger AssignToDroppingUnionField unsafety if needed
+                        } else {
+                            self.requires_unsafe(expr.span, AccessToUnionField);
+                        }
+                    }
+                }
+            }
+            // don't have any special handling for AssignOp since it causes a read *and* write to lhs
+            ExprKind::Assign { lhs, rhs } => {
+                // assigning to a union is safe, check here so it doesn't get treated as a read later
+                self.in_possible_lhs_union_assign = true;
+                visit::walk_expr(self, &self.thir()[lhs]);
+                self.in_possible_lhs_union_assign = false;
+                visit::walk_expr(self, &self.thir()[rhs]);
+                return; // don't visit the whole expression
+            }
             _ => {}
         }
-
         visit::walk_expr(self, expr);
     }
 }
@@ -290,13 +402,11 @@ enum UnsafeOpKind {
     CallToUnsafeFunction,
     UseOfInlineAssembly,
     InitializingTypeWith,
-    CastOfPointerToInt,
     UseOfMutableStatic,
     UseOfExternStatic,
     DerefOfRawPointer,
     #[allow(dead_code)] // FIXME
     AssignToDroppingUnionField,
-    #[allow(dead_code)] // FIXME
     AccessToUnionField,
     #[allow(dead_code)] // FIXME
     MutationOfLayoutConstrainedField,
@@ -324,9 +434,6 @@ pub fn description_and_note(&self) -> (&'static str, &'static str) {
                 "initializing a layout restricted type's field with a value outside the valid \
                  range is undefined behavior",
             ),
-            CastOfPointerToInt => {
-                ("cast of pointer to int", "casting pointers to integers in constants")
-            }
             UseOfMutableStatic => (
                 "use of mutable static",
                 "mutable statics can be mutated by multiple threads: aliasing violations or data \
@@ -404,11 +511,6 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
     let body_target_features = &tcx.codegen_fn_attrs(def.did).target_features;
     let safety_context =
         if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
-    let is_const = match tcx.hir().body_owner_kind(hir_id) {
-        hir::BodyOwnerKind::Closure => false,
-        hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
-        hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
-    };
     let mut visitor = UnsafetyVisitor {
         tcx,
         thir,
@@ -416,7 +518,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
         hir_context: hir_id,
         body_unsafety,
         body_target_features,
-        is_const,
+        in_possible_lhs_union_assign: false,
+        in_union_destructure: false,
     };
     visitor.visit_expr(&thir[expr]);
 }
index f611bb6eb43e9e52bddad01bbd7a41e6136b4840..ce5d4362c086ccb9f9bee5e94683e520322c21b2 100644 (file)
@@ -153,8 +153,8 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
 }
 
 pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
-    match stmt.kind {
-        StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]),
+    match &stmt.kind {
+        StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
         StmtKind::Let {
             initializer,
             remainder_scope: _,
@@ -163,7 +163,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
             lint_level: _,
         } => {
             if let Some(init) = initializer {
-                visitor.visit_expr(&visitor.thir()[init]);
+                visitor.visit_expr(&visitor.thir()[*init]);
             }
             visitor.visit_pat(pattern);
         }
index 0e063c86f2f4eb208aab39215388a5eb81570140..4838d70a83186843150cf2d5b7f25a8512163a08 100644 (file)
@@ -738,15 +738,19 @@ fn check_where_clauses<'tcx, 'fcx>(
                 }
             }
             GenericParamDefKind::Const { .. } => {
-                // FIXME(const_generics_defaults): Figure out if this
-                // is the behavior we want, see the comment further below.
                 if is_our_default(&param) {
+                    // FIXME(const_generics_defaults): This
+                    // is incorrect when dealing with unused substs, for example
+                    // for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
+                    // we should eagerly error.
                     let default_ct = tcx.const_param_default(param.def_id);
-                    fcx.register_wf_obligation(
-                        default_ct.into(),
-                        tcx.def_span(param.def_id),
-                        ObligationCauseCode::MiscObligation,
-                    );
+                    if !default_ct.needs_subst() {
+                        fcx.register_wf_obligation(
+                            default_ct.into(),
+                            tcx.def_span(param.def_id),
+                            ObligationCauseCode::MiscObligation,
+                        );
+                    }
                 }
             }
             // Doesn't have defaults.
@@ -783,14 +787,6 @@ fn check_where_clauses<'tcx, 'fcx>(
                 tcx.mk_param_from_def(param)
             }
             GenericParamDefKind::Const { .. } => {
-                // FIXME(const_generics_defaults): I(@lcnr) feel like always
-                // using the const parameter is the right choice here, even
-                // if it needs substs.
-                //
-                // Before stabilizing this we probably want to get some tests
-                // where this makes a difference and figure out what's the exact
-                // behavior we want here.
-
                 // If the param has a default, ...
                 if is_our_default(param) {
                     let default_ct = tcx.const_param_default(param.def_id);
index b0e5453b7db924079e1c2f4dcb77d307faf42505..506ca98b96026180e84e5be71fb5b07161e4fbb3 100644 (file)
@@ -92,6 +92,7 @@ pub fn provide(providers: &mut Providers) {
         generator_kind,
         codegen_fn_attrs,
         collect_mod_item_types,
+        should_inherit_track_caller,
         ..*providers
     };
 }
@@ -2308,6 +2309,16 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
                 ));
             }
         }
+
+        fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
+            // Do not look into const param defaults,
+            // these get checked when they are actually instantiated.
+            //
+            // We do not want the following to error:
+            //
+            //     struct Foo<const N: usize, const M: usize = { N + 1 }>;
+            //     struct Bar<const N: usize>(Foo<N, 3>);
+        }
     }
 
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
@@ -2676,7 +2687,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
     let attrs = tcx.get_attrs(id);
 
     let mut codegen_fn_attrs = CodegenFnAttrs::new();
-    if should_inherit_track_caller(tcx, id) {
+    if tcx.should_inherit_track_caller(id) {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
     }
 
index 67756b15531bf360b9d5bc8995e240f713a29cb6..9e7ccd015b65815336ce3cac06c3b2ed2f9cf76a 100644 (file)
@@ -2,6 +2,7 @@
 
 #![stable(feature = "process_extensions", since = "1.2.0")]
 
+use crate::ffi::OsStr;
 use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
 use crate::process;
 use crate::sealed::Sealed;
@@ -125,6 +126,13 @@ pub trait CommandExt: Sealed {
     /// [2]: <https://msdn.microsoft.com/en-us/library/17w5ykft.aspx>
     #[unstable(feature = "windows_process_extensions_force_quotes", issue = "82227")]
     fn force_quotes(&mut self, enabled: bool) -> &mut process::Command;
+
+    /// Append literal text to the command line without any quoting or escaping.
+    ///
+    /// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow
+    /// `CommandLineToArgvW` escaping rules.
+    #[unstable(feature = "windows_process_extensions_raw_arg", issue = "29494")]
+    fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command;
 }
 
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
@@ -138,4 +146,9 @@ fn force_quotes(&mut self, enabled: bool) -> &mut process::Command {
         self.as_inner_mut().force_quotes(enabled);
         self
     }
+
+    fn raw_arg<S: AsRef<OsStr>>(&mut self, raw_text: S) -> &mut process::Command {
+        self.as_inner_mut().raw_arg(raw_text.as_ref());
+        self
+    }
 }
index b082e21ab3bcc893e8f9ad0d9747e338d33a6439..0fdf72c8067d25abf66ddc39df771fb5bcf9f37d 100644 (file)
@@ -137,7 +137,7 @@ fn ensure_no_nuls<T: AsRef<OsStr>>(str: T) -> io::Result<T> {
 
 pub struct Command {
     program: OsString,
-    args: Vec<OsString>,
+    args: Vec<Arg>,
     env: CommandEnv,
     cwd: Option<OsString>,
     flags: u32,
@@ -161,6 +161,14 @@ pub struct StdioPipes {
     pub stderr: Option<AnonPipe>,
 }
 
+#[derive(Debug)]
+enum Arg {
+    /// Add quotes (if needed)
+    Regular(OsString),
+    /// Append raw string without quoting
+    Raw(OsString),
+}
+
 impl Command {
     pub fn new(program: &OsStr) -> Command {
         Command {
@@ -178,7 +186,7 @@ pub fn new(program: &OsStr) -> Command {
     }
 
     pub fn arg(&mut self, arg: &OsStr) {
-        self.args.push(arg.to_os_string())
+        self.args.push(Arg::Regular(arg.to_os_string()))
     }
     pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
@@ -203,6 +211,10 @@ pub fn force_quotes(&mut self, enabled: bool) {
         self.force_quotes_enabled = enabled;
     }
 
+    pub fn raw_arg(&mut self, command_str_to_append: &OsStr) {
+        self.args.push(Arg::Raw(command_str_to_append.to_os_string()))
+    }
+
     pub fn get_program(&self) -> &OsStr {
         &self.program
     }
@@ -315,9 +327,13 @@ pub fn spawn(
 
 impl fmt::Debug for Command {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self.program)?;
+        self.program.fmt(f)?;
         for arg in &self.args {
-            write!(f, " {:?}", arg)?;
+            f.write_str(" ")?;
+            match arg {
+                Arg::Regular(s) => s.fmt(f),
+                Arg::Raw(s) => f.write_str(&s.to_string_lossy()),
+            }?;
         }
         Ok(())
     }
@@ -536,44 +552,63 @@ fn zeroed_process_information() -> c::PROCESS_INFORMATION {
     }
 }
 
+enum Quote {
+    // Every arg is quoted
+    Always,
+    // Whitespace and empty args are quoted
+    Auto,
+    // Arg appended without any changes (#29494)
+    Never,
+}
+
 // Produces a wide string *without terminating null*; returns an error if
 // `prog` or any of the `args` contain a nul.
-fn make_command_line(prog: &OsStr, args: &[OsString], force_quotes: bool) -> io::Result<Vec<u16>> {
+fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Result<Vec<u16>> {
     // Encode the command and arguments in a command line string such
     // that the spawned process may recover them using CommandLineToArgvW.
     let mut cmd: Vec<u16> = Vec::new();
     // Always quote the program name so CreateProcess doesn't interpret args as
     // part of the name if the binary wasn't found first time.
-    append_arg(&mut cmd, prog, true)?;
+    append_arg(&mut cmd, prog, Quote::Always)?;
     for arg in args {
         cmd.push(' ' as u16);
-        append_arg(&mut cmd, arg, force_quotes)?;
+        let (arg, quote) = match arg {
+            Arg::Regular(arg) => (arg, if force_quotes { Quote::Always } else { Quote::Auto }),
+            Arg::Raw(arg) => (arg, Quote::Never),
+        };
+        append_arg(&mut cmd, arg, quote)?;
     }
     return Ok(cmd);
 
-    fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, force_quotes: bool) -> io::Result<()> {
+    fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, quote: Quote) -> io::Result<()> {
         // If an argument has 0 characters then we need to quote it to ensure
         // that it actually gets passed through on the command line or otherwise
         // it will be dropped entirely when parsed on the other end.
         ensure_no_nuls(arg)?;
         let arg_bytes = &arg.as_inner().inner.as_inner();
-        let quote = force_quotes
-            || arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t')
-            || arg_bytes.is_empty();
+        let (quote, escape) = match quote {
+            Quote::Always => (true, true),
+            Quote::Auto => {
+                (arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t') || arg_bytes.is_empty(), true)
+            }
+            Quote::Never => (false, false),
+        };
         if quote {
             cmd.push('"' as u16);
         }
 
         let mut backslashes: usize = 0;
         for x in arg.encode_wide() {
-            if x == '\\' as u16 {
-                backslashes += 1;
-            } else {
-                if x == '"' as u16 {
-                    // Add n+1 backslashes to total 2n+1 before internal '"'.
-                    cmd.extend((0..=backslashes).map(|_| '\\' as u16));
+            if escape {
+                if x == '\\' as u16 {
+                    backslashes += 1;
+                } else {
+                    if x == '"' as u16 {
+                        // Add n+1 backslashes to total 2n+1 before internal '"'.
+                        cmd.extend((0..=backslashes).map(|_| '\\' as u16));
+                    }
+                    backslashes = 0;
                 }
-                backslashes = 0;
             }
             cmd.push(x);
         }
@@ -626,13 +661,15 @@ fn make_dirp(d: Option<&OsString>) -> io::Result<(*const u16, Vec<u16>)> {
 }
 
 pub struct CommandArgs<'a> {
-    iter: crate::slice::Iter<'a, OsString>,
+    iter: crate::slice::Iter<'a, Arg>,
 }
 
 impl<'a> Iterator for CommandArgs<'a> {
     type Item = &'a OsStr;
     fn next(&mut self) -> Option<&'a OsStr> {
-        self.iter.next().map(|s| s.as_ref())
+        self.iter.next().map(|arg| match arg {
+            Arg::Regular(s) | Arg::Raw(s) => s.as_ref(),
+        })
     }
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
index ff3f9131cc889b3303b9bc6e5dbd552ac433084b..3b65856dcaca6d4f3e017a2ba97fccf2cf8f339c 100644 (file)
@@ -1,14 +1,35 @@
 use super::make_command_line;
+use super::Arg;
 use crate::env;
 use crate::ffi::{OsStr, OsString};
 use crate::process::Command;
 
+#[test]
+fn test_raw_args() {
+    let command_line = &make_command_line(
+        OsStr::new("quoted exe"),
+        &[
+            Arg::Regular(OsString::from("quote me")),
+            Arg::Raw(OsString::from("quote me *not*")),
+            Arg::Raw(OsString::from("\t\\")),
+            Arg::Raw(OsString::from("internal \\\"backslash-\"quote")),
+            Arg::Regular(OsString::from("optional-quotes")),
+        ],
+        false,
+    )
+    .unwrap();
+    assert_eq!(
+        String::from_utf16(command_line).unwrap(),
+        "\"quoted exe\" \"quote me\" quote me *not* \t\\ internal \\\"backslash-\"quote optional-quotes"
+    );
+}
+
 #[test]
 fn test_make_command_line() {
     fn test_wrapper(prog: &str, args: &[&str], force_quotes: bool) -> String {
         let command_line = &make_command_line(
             OsStr::new(prog),
-            &args.iter().map(|a| OsString::from(a)).collect::<Vec<OsString>>(),
+            &args.iter().map(|a| Arg::Regular(OsString::from(a))).collect::<Vec<_>>(),
             force_quotes,
         )
         .unwrap();
@@ -17,6 +38,11 @@ fn test_wrapper(prog: &str, args: &[&str], force_quotes: bool) -> String {
 
     assert_eq!(test_wrapper("prog", &["aaa", "bbb", "ccc"], false), "\"prog\" aaa bbb ccc");
 
+    assert_eq!(test_wrapper("prog", &[r"C:\"], false), r#""prog" C:\"#);
+    assert_eq!(test_wrapper("prog", &[r"2slashes\\"], false), r#""prog" 2slashes\\"#);
+    assert_eq!(test_wrapper("prog", &[r" C:\"], false), r#""prog" " C:\\""#);
+    assert_eq!(test_wrapper("prog", &[r" 2slashes\\"], false), r#""prog" " 2slashes\\\\""#);
+
     assert_eq!(
         test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa"], false),
         "\"C:\\Program Files\\blah\\blah.exe\" aaa"
index da2d11604934fa118b0dfd38a158972098f51c5f..9f7e6b95dfb90c0d496eb88ead3679226ed02379 100644 (file)
@@ -999,11 +999,12 @@ fn new() -> ThreadId {
         static mut COUNTER: u64 = 1;
 
         unsafe {
-            let _guard = GUARD.lock();
+            let guard = GUARD.lock();
 
             // If we somehow use up all our bits, panic so that we're not
             // covering up subtle bugs of IDs being reused.
             if COUNTER == u64::MAX {
+                drop(guard); // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire.
                 panic!("failed to generate unique thread ID: bitspace exhausted");
             }
 
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/Makefile b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile
new file mode 100644 (file)
index 0000000..0f87433
--- /dev/null
@@ -0,0 +1,18 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
+
+# only-i686-pc-windows-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+       $(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
+       $(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll
+       $(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
+       $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+       "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/output.txt output.txt
+else
+       $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs
new file mode 100644 (file)
index 0000000..3710507
--- /dev/null
@@ -0,0 +1,5 @@
+extern crate raw_dylib_alt_calling_convention_test;
+
+fn main() {
+    raw_dylib_alt_calling_convention_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/extern.c b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c
new file mode 100644 (file)
index 0000000..8f64abf
--- /dev/null
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <stdint.h>
+
+struct S {
+    uint8_t x;
+    int32_t y;
+};
+
+struct S2 {
+    int32_t x;
+    uint8_t y;
+};
+
+struct S3 {
+    uint8_t x[5];
+};
+
+__declspec(dllexport) void __stdcall stdcall_fn_1(int i) {
+    printf("stdcall_fn_1(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_2(uint8_t i, float f) {
+    printf("stdcall_fn_2(%d, %.1f)\n", i, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_3(double d) {
+    printf("stdcall_fn_3(%.1f)\n", d);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_4(uint8_t i, uint8_t j, float f) {
+    printf("stdcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_5(struct S s, int i) {
+    printf("stdcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+// Test that stdcall support works correctly with the nullable pointer optimization.
+__declspec(dllexport) void __stdcall stdcall_fn_6(struct S* s) {
+    if (s) {
+        printf("stdcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+    } else {
+        printf("stdcall_fn_6(null)\n");
+    }
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_7(struct S2 s, int i) {
+    printf("stdcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+// Verify that we compute the correct amount of space in the argument list for a 5-byte struct.
+__declspec(dllexport) void __stdcall stdcall_fn_8(struct S3 s, struct S3 t) {
+    printf("stdcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+           s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+           t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+        );
+    fflush(stdout);
+}
+
+// test whether f64/double values are aligned on 4-byte or 8-byte boundaries.
+__declspec(dllexport) void __stdcall stdcall_fn_9(uint8_t x, double y) {
+    printf("stdcall_fn_9(%d, %.1f)\n", x, y);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_1(int i) {
+    printf("fastcall_fn_1(%d)\n", i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_2(uint8_t i, float f) {
+    printf("fastcall_fn_2(%d, %.1f)\n", i, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_3(double d) {
+    printf("fastcall_fn_3(%.1f)\n", d);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_4(uint8_t i, uint8_t j, float f) {
+    printf("fastcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_5(struct S s, int i) {
+    printf("fastcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_6(struct S* s) {
+    if (s) {
+        printf("fastcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+    } else {
+        printf("fastcall_fn_6(null)\n");
+    }
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_7(struct S2 s, int i) {
+    printf("fastcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_8(struct S3 s, struct S3 t) {
+    printf("fastcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+           s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+           t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+        );
+    fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) {
+    printf("fastcall_fn_9(%d, %.1f)\n", x, y);
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs
new file mode 100644 (file)
index 0000000..ba0f141
--- /dev/null
@@ -0,0 +1,71 @@
+#![feature(raw_dylib)]
+
+#[repr(C)]
+#[derive(Clone)]
+struct S {
+    x: u8,
+    y: i32,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S2 {
+    x: i32,
+    y: u8,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S3 {
+    x: [u8; 5],
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "stdcall" {
+    fn stdcall_fn_1(i: i32);
+    fn stdcall_fn_2(c: u8, f: f32);
+    fn stdcall_fn_3(d: f64);
+    fn stdcall_fn_4(i: u8, j: u8, f: f32);
+    fn stdcall_fn_5(a: S, b: i32);
+    fn stdcall_fn_6(a: Option<&S>);
+    fn stdcall_fn_7(a: S2, b: i32);
+    fn stdcall_fn_8(a: S3, b: S3);
+    fn stdcall_fn_9(x: u8, y: f64);
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "fastcall" {
+    fn fastcall_fn_1(i: i32);
+    fn fastcall_fn_2(c: u8, f: f32);
+    fn fastcall_fn_3(d: f64);
+    fn fastcall_fn_4(i: u8, j: u8, f: f32);
+    fn fastcall_fn_5(a: S, b: i32);
+    fn fastcall_fn_6(a: Option<&S>);
+    fn fastcall_fn_7(a: S2, b: i32);
+    fn fastcall_fn_8(a: S3, b: S3);
+    fn fastcall_fn_9(x: u8, y: f64);
+}
+
+pub fn library_function() {
+    unsafe {
+        stdcall_fn_1(14);
+        stdcall_fn_2(16, 3.5);
+        stdcall_fn_3(3.5);
+        stdcall_fn_4(1, 2, 3.0);
+        stdcall_fn_5(S { x: 1, y: 2 }, 16);
+        stdcall_fn_6(Some(&S { x: 10, y: 12 }));
+        stdcall_fn_7(S2 { x: 15, y: 16 }, 3);
+        stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+        stdcall_fn_9(1, 3.0);
+
+        fastcall_fn_1(14);
+        fastcall_fn_2(16, 3.5);
+        fastcall_fn_3(3.5);
+        fastcall_fn_4(1, 2, 3.0);
+        fastcall_fn_5(S { x: 1, y: 2 }, 16);
+        fastcall_fn_6(Some(&S { x: 10, y: 12 }));
+        fastcall_fn_7(S2 { x: 15, y: 16 }, 3);
+        fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+        fastcall_fn_9(1, 3.0);
+    }
+}
diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/output.txt b/src/test/run-make/raw-dylib-alt-calling-convention/output.txt
new file mode 100644 (file)
index 0000000..be598a2
--- /dev/null
@@ -0,0 +1,18 @@
+stdcall_fn_1(14)
+stdcall_fn_2(16, 3.5)
+stdcall_fn_3(3.5)
+stdcall_fn_4(1, 2, 3.0)
+stdcall_fn_5(S { x: 1, y: 2 }, 16)
+stdcall_fn_6(S { x: 10, y: 12 })
+stdcall_fn_7(S2 { x: 15, y: 16 }, 3)
+stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+stdcall_fn_9(1, 3.0)
+fastcall_fn_1(14)
+fastcall_fn_2(16, 3.5)
+fastcall_fn_3(3.5)
+fastcall_fn_4(1, 2, 3.0)
+fastcall_fn_5(S { x: 1, y: 2 }, 16)
+fastcall_fn_6(S { x: 10, y: 12 })
+fastcall_fn_7(S2 { x: 15, y: 16 }, 3)
+fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+fastcall_fn_9(1, 3.0)
diff --git a/src/test/run-make/raw-dylib-c/Makefile b/src/test/run-make/raw-dylib-c/Makefile
new file mode 100644 (file)
index 0000000..26ab4d3
--- /dev/null
@@ -0,0 +1,20 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
+
+# only-windows-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
+       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+       $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
+       $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
+       $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+       $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+       "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/output.txt output.txt
+else
+       $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/src/test/run-make/raw-dylib-c/driver.rs b/src/test/run-make/raw-dylib-c/driver.rs
new file mode 100644 (file)
index 0000000..4059ede
--- /dev/null
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+    raw_dylib_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib-c/extern_1.c b/src/test/run-make/raw-dylib-c/extern_1.c
new file mode 100644 (file)
index 0000000..72737c0
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_1() {
+    printf("extern_fn_1\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_2() {
+    printf("extern_fn_2; didn't get the rename\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_with_long_name() {
+    printf("extern_fn_with_long_name; got the rename\n");
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-c/extern_2.c b/src/test/run-make/raw-dylib-c/extern_2.c
new file mode 100644 (file)
index 0000000..ae87fc3
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_3() {
+    printf("extern_fn_3\n");
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib-c/lib.rs b/src/test/run-make/raw-dylib-c/lib.rs
new file mode 100644 (file)
index 0000000..d8e6301
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
+
+#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
+extern {
+    fn extern_fn_1();
+}
+
+#[link(name = "extern_2", kind = "raw-dylib")]
+extern {
+    fn extern_fn_3();
+}
+
+pub fn library_function() {
+    #[link(name = "extern_1", kind = "raw-dylib")]
+    extern { fn extern_fn_2(); }
+
+    unsafe {
+        extern_fn_1();
+        extern_fn_2();
+        extern_fn_3();
+    }
+}
diff --git a/src/test/run-make/raw-dylib-c/output.txt b/src/test/run-make/raw-dylib-c/output.txt
new file mode 100644 (file)
index 0000000..7800cba
--- /dev/null
@@ -0,0 +1,3 @@
+extern_fn_1
+extern_fn_2; didn't get the rename
+extern_fn_3
diff --git a/src/test/run-make/raw-dylib/Makefile b/src/test/run-make/raw-dylib/Makefile
deleted file mode 100644 (file)
index 7ce46fd..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
-
-# only-windows
-# only-msvc
-
--include ../../run-make-fulldeps/tools.mk
-
-all:
-       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
-       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
-       $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
-       $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
-       $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
-       $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
-       "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
-
-ifdef RUSTC_BLESS_TEST
-       cp "$(TMPDIR)"/output.txt output.txt
-else
-       $(DIFF) output.txt "$(TMPDIR)"/output.txt
-endif
diff --git a/src/test/run-make/raw-dylib/driver.rs b/src/test/run-make/raw-dylib/driver.rs
deleted file mode 100644 (file)
index 4059ede..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-extern crate raw_dylib_test;
-
-fn main() {
-    raw_dylib_test::library_function();
-}
diff --git a/src/test/run-make/raw-dylib/extern_1.c b/src/test/run-make/raw-dylib/extern_1.c
deleted file mode 100644 (file)
index 72737c0..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-
-__declspec(dllexport) void extern_fn_1() {
-    printf("extern_fn_1\n");
-    fflush(stdout);
-}
-
-__declspec(dllexport) void extern_fn_2() {
-    printf("extern_fn_2; didn't get the rename\n");
-    fflush(stdout);
-}
-
-__declspec(dllexport) void extern_fn_with_long_name() {
-    printf("extern_fn_with_long_name; got the rename\n");
-    fflush(stdout);
-}
diff --git a/src/test/run-make/raw-dylib/extern_2.c b/src/test/run-make/raw-dylib/extern_2.c
deleted file mode 100644 (file)
index ae87fc3..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-__declspec(dllexport) void extern_fn_3() {
-    printf("extern_fn_3\n");
-    fflush(stdout);
-}
diff --git a/src/test/run-make/raw-dylib/lib.rs b/src/test/run-make/raw-dylib/lib.rs
deleted file mode 100644 (file)
index d8e6301..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
-
-#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
-extern {
-    fn extern_fn_1();
-}
-
-#[link(name = "extern_2", kind = "raw-dylib")]
-extern {
-    fn extern_fn_3();
-}
-
-pub fn library_function() {
-    #[link(name = "extern_1", kind = "raw-dylib")]
-    extern { fn extern_fn_2(); }
-
-    unsafe {
-        extern_fn_1();
-        extern_fn_2();
-        extern_fn_3();
-    }
-}
diff --git a/src/test/run-make/raw-dylib/output.txt b/src/test/run-make/raw-dylib/output.txt
deleted file mode 100644 (file)
index 7800cba..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-extern_fn_1
-extern_fn_2; didn't get the rename
-extern_fn_3
index d663431d6836fe1abca2206bc4633be09688264b..97bf225f0cc733b9803844bc583f8ea6134aaeb1 100644 (file)
@@ -2,7 +2,9 @@
 
 macro_rules! pass_nonterminal {
     ($n:expr) => {
-        #[repr(align($n))] //~ ERROR expected unsuffixed literal or identifier, found `n!()`
+        #[repr(align($n))]
+        //~^ ERROR expected unsuffixed literal or identifier, found `n!()`
+        //~| ERROR incorrect `repr(align)` attribute format
         struct S;
     };
 }
index 4124f8cea8ebfe0a588114e5f446cfdb2596f387..9bf36f3c58e8120401905cd8cbce8131aefd22a2 100644 (file)
@@ -9,5 +9,17 @@ LL | pass_nonterminal!(n!());
    |
    = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/nonterminal-expansion.rs:5:16
+   |
+LL |         #[repr(align($n))]
+   |                ^^^^^^^^^
+...
+LL | pass_nonterminal!(n!());
+   | ------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0693`.
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.mir.stderr b/src/test/ui/cast/cast-ptr-to-int-const.mir.stderr
deleted file mode 100644 (file)
index dcc9a24..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
-  --> $DIR/cast-ptr-to-int-const.rs:10:9
-   |
-LL |         &Y as *const u32 as usize
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
-   |
-   = note: casting pointers to integers in constants
-
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
-  --> $DIR/cast-ptr-to-int-const.rs:17:5
-   |
-LL |     &0 as *const i32 as usize
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
-   |
-   = note: casting pointers to integers in constants
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.rs b/src/test/ui/cast/cast-ptr-to-int-const.rs
deleted file mode 100644 (file)
index 01ea627..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
-    const Y: u32 = 0;
-    // Cast in `const` without `unsafe` block
-    const SAFE: usize = {
-        &Y as *const u32 as usize
-        //~^ ERROR cast of pointer to int is unsafe and requires unsafe
-    };
-}
-
-// Cast in `const fn` without `unsafe` block
-const fn test() -> usize {
-    &0 as *const i32 as usize
-    //~^ ERROR cast of pointer to int is unsafe and requires unsafe
-}
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.thir.stderr b/src/test/ui/cast/cast-ptr-to-int-const.thir.stderr
deleted file mode 100644 (file)
index dcc9a24..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
-  --> $DIR/cast-ptr-to-int-const.rs:10:9
-   |
-LL |         &Y as *const u32 as usize
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
-   |
-   = note: casting pointers to integers in constants
-
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
-  --> $DIR/cast-ptr-to-int-const.rs:17:5
-   |
-LL |     &0 as *const i32 as usize
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
-   |
-   = note: casting pointers to integers in constants
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs b/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs
deleted file mode 100644 (file)
index 03e99eb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-fn main() {
-    const X: usize = unsafe {
-        main as usize //~ ERROR casting pointers to integers in constants is unstable
-    };
-    const Y: u32 = 0;
-    const Z: usize = unsafe {
-        &Y as *const u32 as usize //~ ERROR is unstable
-    };
-}
-
-const fn test() -> usize {
-    &0 as *const i32 as usize //~ ERROR is unstable
-}
diff --git a/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr b/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr
deleted file mode 100644 (file)
index 4a0b424..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error[E0658]: casting pointers to integers in constants is unstable
-  --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:3:9
-   |
-LL |         main as usize
-   |         ^^^^^^^^^^^^^
-   |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error[E0658]: casting pointers to integers in constants is unstable
-  --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:7:9
-   |
-LL |         &Y as *const u32 as usize
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error[E0658]: casting pointers to integers in constant functions is unstable
-  --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:12:5
-   |
-LL |     &0 as *const i32 as usize
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs b/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs
new file mode 100644 (file)
index 0000000..21f14f5
--- /dev/null
@@ -0,0 +1,6 @@
+// check-pass
+#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+struct Bar<const N: usize>(Foo<N, 3>);
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
deleted file mode 100644 (file)
index e0e2b6c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/complex-generic-default-expr.rs:6:34
-   |
-LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
-   |                                  ^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/complex-generic-default-expr.rs:10:21
-   |
-LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
-   |                     ^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
index 58abd8db9f09fe3760d9168817a9a84b4f4186d5..44df2ac9f40fadb66034354973eb88cd1935ac74 100644 (file)
@@ -1,5 +1,5 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/complex-generic-default-expr.rs:6:47
+  --> $DIR/complex-generic-default-expr.rs:7:47
    |
 LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
    |                                               ^ cannot perform const operation using `N`
index a7b712f7b4b863652f1dd4d91a88d4090eb1075e..d3558007977e46a9f10df41015548eafe1ebc0e6 100644 (file)
@@ -1,14 +1,13 @@
 // revisions: full min
+//[full] check-pass
 #![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
 struct Foo<const N: usize, const M: usize = { N + 1 }>;
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
 
 struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
 
 fn main() {}
diff --git a/src/test/ui/const-ptr/ptr_to_usize_cast.rs b/src/test/ui/const-ptr/ptr_to_usize_cast.rs
deleted file mode 100644 (file)
index bf1e790..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
-    const OK: usize = unsafe { 0 as *const i32 as usize };
-
-    const _ERROR: usize = unsafe { &0 as *const i32 as usize };
-    //~^ ERROR [const_err]
-    //~| NOTE cannot cast pointer to integer because it was not created by cast from integer
-    //~| NOTE
-    //~| NOTE `#[deny(const_err)]` on by default
-    //~| WARN this was previously accepted by the compiler but is being phased out
-    //~| NOTE see issue #71800
-}
diff --git a/src/test/ui/const-ptr/ptr_to_usize_cast.stderr b/src/test/ui/const-ptr/ptr_to_usize_cast.stderr
deleted file mode 100644 (file)
index 4825586..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: any use of this value will cause an error
-  --> $DIR/ptr_to_usize_cast.rs:6:36
-   |
-LL |     const _ERROR: usize = unsafe { &0 as *const i32 as usize };
-   |     -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                    |
-   |                                    cannot cast pointer to integer because it was not created by cast from integer
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
index c6a623b29327699971454ae03676a2bf090e8e8d..a177ed6b3413eb9f7b26e099aa6934d3c931a291 100644 (file)
@@ -1,15 +1,11 @@
-#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)]
+#![feature(const_raw_ptr_deref)]
 
 fn main() {}
 
-// unconst and fine
-const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
-// unconst and bad, will thus error in miri
-const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
-//~| WARN this was previously accepted by the compiler but is being phased out
-// unconst and fine
+// fine
 const Z: i32 = unsafe { *(&1 as *const i32) };
-// unconst and bad, will thus error in miri
+
+// bad, will thus error in miri
 const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause
 //~| WARN this was previously accepted by the compiler but is being phased out
 const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause
index df8b33a0898f659deab953e1a3b9e7614a8a5dcd..de54ea3b9fbd0c7b6754b766a758c500a9dfaf6d 100644 (file)
@@ -1,28 +1,17 @@
 error: any use of this value will cause an error
-  --> $DIR/const_raw_ptr_ops2.rs:8:28
-   |
-LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 };
-   | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^-------
-   |                            |
-   |                            cannot cast pointer to integer because it was not created by cast from integer
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: any use of this value will cause an error
-  --> $DIR/const_raw_ptr_ops2.rs:13:26
+  --> $DIR/const_raw_ptr_ops2.rs:9:26
    |
 LL | const Z2: i32 = unsafe { *(42 as *const i32) };
    | -------------------------^^^^^^^^^^^^^^^^^^^---
    |                          |
    |                          unable to turn bytes into a pointer
    |
+   = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
 error: any use of this value will cause an error
-  --> $DIR/const_raw_ptr_ops2.rs:15:26
+  --> $DIR/const_raw_ptr_ops2.rs:11:26
    |
 LL | const Z3: i32 = unsafe { *(44 as *const i32) };
    | -------------------------^^^^^^^^^^^^^^^^^^^---
@@ -32,5 +21,5 @@ LL | const Z3: i32 = unsafe { *(44 as *const i32) };
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/const-eval/issue-52442.rs b/src/test/ui/consts/const-eval/issue-52442.rs
deleted file mode 100644 (file)
index 159b48d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    [();  { &loop { break } as *const _ as usize } ];
-    //~^ ERROR casting pointers to integers in constants is unstable
-}
diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr
deleted file mode 100644 (file)
index 2a8f342..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: casting pointers to integers in constants is unstable
-  --> $DIR/issue-52442.rs:2:13
-   |
-LL |     [();  { &loop { break } as *const _ as usize } ];
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
index d980eb92a243e87f47020b8c2997f676d40b3ed3..4af97b5487929ce0184a84d429edaf07a1c20b6f 100644 (file)
@@ -4,7 +4,7 @@ fn main() {
     // bytes.
     let _: [u8; 0] = [4; {
         match &1 as *const i32 as usize {
-            //~^ ERROR casting pointers to integers in constants
+            //~^ ERROR pointers cannot be cast to integers during const eval
             0 => 42,
             n => n,
         }
index 22d6bb16944b57427eb83560c90df86b09492b43..4e55b36da73929237f0f52a147fc5900975dd388 100644 (file)
@@ -1,12 +1,11 @@
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/match-test-ptr-null.rs:6:15
    |
 LL |         match &1 as *const i32 as usize {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index d724fe3060b21b748998189dd2e68a9c14f30d75..c7d84303fe54ca6028248b792869357a0605c38e 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)]
+#![feature(const_raw_ptr_deref)]
 
 fn main() {
     let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
index 76380ebcb6599b13a671da959749f61249a6da13..46748673067cebb02e795c78449a413186722521 100644 (file)
@@ -7,7 +7,7 @@
 const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
 //~^ ERROR floating point arithmetic
 const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 
 
 fn main() {}
index 80d234b0e881eefe992f83eeb265b39f5ddec67c..2e52bae2b676cf1601d94ded482deb7bcb76489a 100644 (file)
@@ -25,14 +25,14 @@ LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
    = note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
    = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/const-extern-fn-min-const-fn.rs:9:48
    |
 LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
    |                                                ^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to 4 previous errors
 
index d56ffebad7d5aeb339713ebdd6845c376702050d..44125a1c3df8d64302f9688a81883083c73873da 100644 (file)
@@ -1,5 +1,5 @@
 static X: usize = unsafe { core::ptr::null::<usize>() as usize };
-//~^ ERROR: casting pointers to integers in statics is unstable
+//~^ ERROR: pointers cannot be cast to integers during const eval
 
 fn main() {
     assert_eq!(X, 0);
index 68e86ea21bd963435501cf3df97b5083b236f530..aab7d798db2e7f663882befd9bbf10a7b0e4d34e 100644 (file)
@@ -1,12 +1,11 @@
-error[E0658]: casting pointers to integers in statics is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/issue-17458.rs:1:28
    |
 LL | static X: usize = unsafe { core::ptr::null::<usize>() as usize };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/issue-51559.rs b/src/test/ui/consts/issue-51559.rs
deleted file mode 100644 (file)
index cc64440..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#![feature(const_raw_ptr_to_usize_cast)]
-
-const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut ();
-pub const FOO: usize = unsafe { BAR as usize };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-fn main() {}
diff --git a/src/test/ui/consts/issue-51559.stderr b/src/test/ui/consts/issue-51559.stderr
deleted file mode 100644 (file)
index d571eb5..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: any use of this value will cause an error
-  --> $DIR/issue-51559.rs:4:33
-   |
-LL | pub const FOO: usize = unsafe { BAR as usize };
-   | --------------------------------^^^^^^^^^^^^---
-   |                                 |
-   |                                 cannot cast pointer to integer because it was not created by cast from integer
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
index cc756ce815f15c19af1038930ce2a002911d2fbb..2249d9879f5dc9243991ddcfb0b945ffdb152ee9 100644 (file)
@@ -1,3 +1,3 @@
 fn main() {
-    let _ = [0; (&0 as *const i32) as usize]; //~ ERROR casting pointers to integers in constants
+    let _ = [0; (&0 as *const i32) as usize]; //~ ERROR pointers cannot be cast to integers during const eval
 }
index 68b5cbd9bd7c7a8be4174f1cef77b077887b3b7d..363c7b2c8e462d54281956911cebc8709b4c85b0 100644 (file)
@@ -1,12 +1,11 @@
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/issue-52023-array-size-pointer-cast.rs:2:17
    |
 LL |     let _ = [0; (&0 as *const i32) as usize];
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/issue-52432.rs b/src/test/ui/consts/issue-52432.rs
deleted file mode 100644 (file)
index d719bf1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
-    [(); &(static |x| {}) as *const _ as usize];
-    //~^ ERROR: closures cannot be static
-    //~| ERROR: type annotations needed
-    [(); &(static || {}) as *const _ as usize];
-    //~^ ERROR: closures cannot be static
-    //~| ERROR evaluation of constant value failed
-}
diff --git a/src/test/ui/consts/issue-52432.stderr b/src/test/ui/consts/issue-52432.stderr
deleted file mode 100644 (file)
index 2999895..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0697]: closures cannot be static
-  --> $DIR/issue-52432.rs:4:12
-   |
-LL |     [(); &(static |x| {}) as *const _ as usize];
-   |            ^^^^^^^^^^
-
-error[E0697]: closures cannot be static
-  --> $DIR/issue-52432.rs:7:12
-   |
-LL |     [(); &(static || {}) as *const _ as usize];
-   |            ^^^^^^^^^
-
-error[E0282]: type annotations needed
-  --> $DIR/issue-52432.rs:4:20
-   |
-LL |     [(); &(static |x| {}) as *const _ as usize];
-   |                    ^ consider giving this closure parameter a type
-
-error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-52432.rs:7:10
-   |
-LL |     [(); &(static || {}) as *const _ as usize];
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot cast pointer to integer because it was not created by cast from integer
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0080, E0282, E0697.
-For more information about an error, try `rustc --explain E0080`.
index b7904e6841b5d448a26b48b9916757fd99993bbd..bb525d57197789ad5b1ebfbd6a370b00e155e848 100644 (file)
@@ -90,13 +90,13 @@ const fn foo11_2<T: Send>(t: T) -> T { t }
 const fn foo25() -> u32 { BAR } //~ ERROR cannot refer to statics
 const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot refer to statics
 const fn foo30(x: *const u32) -> usize { x as usize }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 const fn foo30_2(x: *mut u32) -> usize { x as usize }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
 const fn foo30_6() -> bool { let x = true; x }
 const fn inc(x: &mut i32) { *x += 1 }
 //~^ ERROR mutable references
index d31d4121936981f3b0b991c7a8905ad419d00d10..fcbf39d38690b5861ddd04d8d04b3eb9a35d7905 100644 (file)
@@ -164,41 +164,41 @@ LL | const fn foo26() -> &'static u32 { &BAR }
    |
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/min_const_fn.rs:92:42
    |
 LL | const fn foo30(x: *const u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/min_const_fn.rs:94:63
    |
 LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
    |                                                               ^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/min_const_fn.rs:96:42
    |
 LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/min_const_fn.rs:98:63
    |
 LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
    |                                                               ^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error[E0658]: mutable references are not allowed in constant functions
   --> $DIR/min_const_fn.rs:101:14
index 1c2229fb9eae4f9258ff8505ba305130a2138ba5..77355f0d7c994423a142ceeb4cf87963def7cbcd 100644 (file)
@@ -1,5 +1,5 @@
 fn main() {
     const X: u32 = 1;
-    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
+    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
     println!("{}", Y);
 }
index 52df558bfce5e7c85628da8d428064524c581144..432e9a6518765d1e2848f8bc1003405d634a234b 100644 (file)
@@ -1,12 +1,11 @@
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
   --> $DIR/issue-18294.rs:3:31
    |
 LL |     const Y: usize = unsafe { &X as *const u32 as usize };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
-   = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index 96e50ba67991c62a91423fce16d9172b47d203a9..305f482e8c21def2ee306dbe25e310e2bb2d53ad 100644 (file)
@@ -7,7 +7,7 @@ LL |     match u.void {}
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-47412.rs:21:11
+  --> $DIR/issue-47412.rs:20:11
    |
 LL |     match *ptr {}
    |           ^^^^ dereference of raw pointer
index d395285eee0a03cf01a1c0a79b6e1e951874f8a1..df6d6e4222e8201b4054a4229bafb42281217ab1 100644 (file)
@@ -12,8 +12,7 @@ fn union_field() {
     union Union { unit: (), void: Void }
     let u = Union { unit: () };
     match u.void {}
-    //[mir]~^ ERROR access to union field is unsafe
-    // FIXME(thir-unsafeck): AccessToUnionField unimplemented
+    //~^ ERROR access to union field is unsafe
 }
 
 fn raw_ptr_deref() {
index 66a0cfcd710f034eb2ae7f88522af088583f802f..305f482e8c21def2ee306dbe25e310e2bb2d53ad 100644 (file)
@@ -1,11 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/issue-47412.rs:14:11
+   |
+LL |     match u.void {}
+   |           ^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-47412.rs:21:11
+  --> $DIR/issue-47412.rs:20:11
    |
 LL |     match *ptr {}
    |           ^^^^ dereference of raw pointer
    |
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/lint/missing-doc-private-macro.rs b/src/test/ui/lint/missing-doc-private-macro.rs
new file mode 100644 (file)
index 0000000..8d1d5c5
--- /dev/null
@@ -0,0 +1,43 @@
+// Checks that undocumented private macros will not generate `missing_docs`
+// lints, but public ones will.
+//
+// This is a regression test for issue #57569
+#![deny(missing_docs)]
+#![feature(decl_macro)]
+//! Empty documentation.
+
+macro new_style_private_macro {
+    () => ()
+}
+
+pub(crate) macro new_style_crate_macro {
+    () => ()
+}
+
+macro_rules! old_style_private_macro {
+    () => ()
+}
+
+mod submodule {
+    pub macro new_style_macro_in_private_module {
+        () => ()
+    }
+
+    macro_rules! old_style_mod_private_macro {
+        () => ()
+    }
+
+    #[macro_export]
+    macro_rules! exported_to_top_level {
+        //~^ ERROR missing documentation for macro
+        () => ()
+    }
+}
+
+pub macro top_level_pub_macro {
+    //~^ ERROR missing documentation for macro
+    () => ()
+}
+
+/// Empty documentation.
+pub fn main() {}
diff --git a/src/test/ui/lint/missing-doc-private-macro.stderr b/src/test/ui/lint/missing-doc-private-macro.stderr
new file mode 100644 (file)
index 0000000..a5d39fa
--- /dev/null
@@ -0,0 +1,20 @@
+error: missing documentation for macro
+  --> $DIR/missing-doc-private-macro.rs:31:5
+   |
+LL |     macro_rules! exported_to_top_level {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/missing-doc-private-macro.rs:5:9
+   |
+LL | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: missing documentation for macro
+  --> $DIR/missing-doc-private-macro.rs:37:1
+   |
+LL | pub macro top_level_pub_macro {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/repr/issue-83921-ice.rs b/src/test/ui/repr/issue-83921-ice.rs
new file mode 100644 (file)
index 0000000..70583eb
--- /dev/null
@@ -0,0 +1,34 @@
+// Regression test for various ICEs inspired by
+// https://github.com/rust-lang/rust/issues/83921#issuecomment-814640734
+
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
+#[repr(packed())]
+//~^ ERROR: incorrect `repr(packed)` attribute format
+struct S1;
+
+#[repr(align)]
+//~^ ERROR: invalid `repr(align)` attribute
+struct S2;
+
+#[repr(align(2, 4))]
+//~^ ERROR: incorrect `repr(align)` attribute format
+struct S3;
+
+#[repr(align())]
+//~^ ERROR: incorrect `repr(align)` attribute format
+struct S4;
+
+#[repr(i8())]
+//~^ ERROR: invalid representation hint
+enum E1 { A, B }
+
+#[repr(u32(42))]
+//~^ ERROR: invalid representation hint
+enum E2 { A, B }
+
+#[repr(i64 = 2)]
+//~^ ERROR: invalid representation hint
+enum E3 { A, B }
+
+fn main() {}
diff --git a/src/test/ui/repr/issue-83921-ice.stderr b/src/test/ui/repr/issue-83921-ice.stderr
new file mode 100644 (file)
index 0000000..32c4504
--- /dev/null
@@ -0,0 +1,46 @@
+error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
+  --> $DIR/issue-83921-ice.rs:6:8
+   |
+LL | #[repr(packed())]
+   |        ^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: `align` needs an argument
+  --> $DIR/issue-83921-ice.rs:10:8
+   |
+LL | #[repr(align)]
+   |        ^^^^^ help: supply an argument here: `align(...)`
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/issue-83921-ice.rs:14:8
+   |
+LL | #[repr(align(2, 4))]
+   |        ^^^^^^^^^^^
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+  --> $DIR/issue-83921-ice.rs:18:8
+   |
+LL | #[repr(align())]
+   |        ^^^^^^^
+
+error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list
+  --> $DIR/issue-83921-ice.rs:22:8
+   |
+LL | #[repr(i8())]
+   |        ^^^^
+
+error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list
+  --> $DIR/issue-83921-ice.rs:26:8
+   |
+LL | #[repr(u32(42))]
+   |        ^^^^^^^
+
+error[E0552]: invalid representation hint: `i64` does not take a value
+  --> $DIR/issue-83921-ice.rs:30:8
+   |
+LL | #[repr(i64 = 2)]
+   |        ^^^^^^^
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0552, E0589, E0693.
+For more information about an error, try `rustc --explain E0552`.
diff --git a/src/test/ui/repr/issue-83921-pretty.normal.stderr b/src/test/ui/repr/issue-83921-pretty.normal.stderr
new file mode 100644 (file)
index 0000000..6b7e831
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0565]: meta item in `repr` must be an identifier
+  --> $DIR/issue-83921-pretty.rs:10:8
+   |
+LL | #[repr("C")]
+   |        ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0565`.
diff --git a/src/test/ui/repr/issue-83921-pretty.pretty.stdout b/src/test/ui/repr/issue-83921-pretty.pretty.stdout
new file mode 100644 (file)
index 0000000..dad3641
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// Regression test for #83921. A `delay_span_bug()` call was issued, but the
+// error was never reported because the pass responsible for detecting and
+// reporting the error does not run in certain modes of pretty-printing.
+
+// Make sure the error is reported if we do not just pretty-print:
+// revisions: pretty normal
+// [pretty]compile-flags: -Zunpretty=everybody_loops
+// [pretty]check-pass
+#[repr("C")]
+struct A {
+}
+
+fn main() { loop { } }
diff --git a/src/test/ui/repr/issue-83921-pretty.rs b/src/test/ui/repr/issue-83921-pretty.rs
new file mode 100644 (file)
index 0000000..d5d3647
--- /dev/null
@@ -0,0 +1,14 @@
+// Regression test for #83921. A `delay_span_bug()` call was issued, but the
+// error was never reported because the pass responsible for detecting and
+// reporting the error does not run in certain modes of pretty-printing.
+
+// Make sure the error is reported if we do not just pretty-print:
+// revisions: pretty normal
+// [pretty]compile-flags: -Zunpretty=everybody_loops
+// [pretty]check-pass
+
+#[repr("C")]
+//[normal]~^ ERROR: meta item in `repr` must be an identifier [E0565]
+struct A {}
+
+fn main() {}
index 3b2a2238fa82d4b8b48162c0ac579872cb608f23..06883a857900ef5e027eb00c1db6015d33d16b5b 100644 (file)
@@ -2,22 +2,60 @@
 
 trait Tracked {
     #[track_caller]
-    fn handle(&self) {
+    fn track_caller_trait_method(&self, line: u32, col: u32) {
         let location = std::panic::Location::caller();
         assert_eq!(location.file(), file!());
-        // we only call this via trait object, so the def site should *always* be returned
-        assert_eq!(location.line(), line!() - 4);
-        assert_eq!(location.column(), 5);
+        // The trait method definition is annotated with `#[track_caller]`,
+        // so caller location information will work through a method
+        // call on a trait object
+        assert_eq!(location.line(), line, "Bad line");
+        assert_eq!(location.column(), col, "Bad col");
     }
+
+    fn track_caller_not_on_trait_method(&self);
+
+    #[track_caller]
+    fn track_caller_through_self(self: Box<Self>, line: u32, col: u32);
 }
 
-impl Tracked for () {}
-impl Tracked for u8 {}
+impl Tracked for () {
+    // We have `#[track_caller]` on the implementation of the method,
+    // but not on the definition of the method in the trait. Therefore,
+    // caller location information will *not* work through a method call
+    // on a trait object. Instead, we will get the location of this method
+    #[track_caller]
+    fn track_caller_not_on_trait_method(&self) {
+        let location = std::panic::Location::caller();
+        assert_eq!(location.file(), file!());
+        assert_eq!(location.line(), line!() - 3);
+        assert_eq!(location.column(), 5);
+    }
+
+    // We don't have a `#[track_caller]` attribute, but
+    // `#[track_caller]` is present on the trait definition,
+    // so we'll still get location information
+    fn track_caller_through_self(self: Box<Self>, line: u32, col: u32) {
+        let location = std::panic::Location::caller();
+        assert_eq!(location.file(), file!());
+        // The trait method definition is annotated with `#[track_caller]`,
+        // so caller location information will work through a method
+        // call on a trait object
+        assert_eq!(location.line(), line, "Bad line");
+        assert_eq!(location.column(), col, "Bad col");
+    }
+}
 
 fn main() {
-    let tracked: &dyn Tracked = &5u8;
-    tracked.handle();
+    let tracked: &dyn Tracked = &();
+    // The column is the start of 'track_caller_trait_method'
+    tracked.track_caller_trait_method(line!(), 13);
 
     const TRACKED: &dyn Tracked = &();
-    TRACKED.handle();
+    // The column is the start of 'track_caller_trait_method'
+    TRACKED.track_caller_trait_method(line!(), 13);
+    TRACKED.track_caller_not_on_trait_method();
+
+    // The column is the start of `track_caller_through_self`
+    let boxed: Box<dyn Tracked> = Box::new(());
+    boxed.track_caller_through_self(line!(), 11);
 }
diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-definitions.rs b/src/test/ui/rfc-2627-raw-dylib/multiple-definitions.rs
new file mode 100644 (file)
index 0000000..3f75974
--- /dev/null
@@ -0,0 +1,19 @@
+// only-i686-pc-windows-msvc
+// compile-flags: --crate-type lib --emit link
+#![allow(clashing_extern_declarations)]
+#![feature(raw_dylib)]
+//~^ WARN the feature `raw_dylib` is incomplete
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+    fn f(x: i32);
+    //~^ ERROR multiple definitions of external function `f` from library `foo.dll` have different calling conventions
+}
+
+pub fn lib_main() {
+    #[link(name = "foo", kind = "raw-dylib")]
+    extern "stdcall" {
+        fn f(x: i32);
+    }
+
+    unsafe { f(42); }
+}
diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-definitions.stderr b/src/test/ui/rfc-2627-raw-dylib/multiple-definitions.stderr
new file mode 100644 (file)
index 0000000..91f6f0c
--- /dev/null
@@ -0,0 +1,17 @@
+warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/multiple-definitions.rs:4:12
+   |
+LL | #![feature(raw_dylib)]
+   |            ^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+
+error: multiple definitions of external function `f` from library `foo.dll` have different calling conventions
+  --> $DIR/multiple-definitions.rs:8:5
+   |
+LL |     fn f(x: i32);
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs
new file mode 100644 (file)
index 0000000..e5a5ac2
--- /dev/null
@@ -0,0 +1,13 @@
+// only-x86_64-pc-windows-msvc
+// compile-flags: --crate-type lib --emit link
+#![allow(incomplete_features)]
+#![feature(raw_dylib)]
+#[link(name = "foo", kind = "raw-dylib")]
+extern "stdcall" {
+    fn f(x: i32);
+    //~^ ERROR ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+}
+
+pub fn lib_main() {
+    unsafe { f(42); }
+}
diff --git a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr
new file mode 100644 (file)
index 0000000..fc90081
--- /dev/null
@@ -0,0 +1,8 @@
+error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+  --> $DIR/unsupported-abi.rs:7:5
+   |
+LL |     fn f(x: i32);
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index 1340ae43cd6afd5c6182b79e7cc65990f5602da6..6a44f27dbb2a48b474d18d9934ee007857d1b603 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 
 use std::mem::{size_of, size_of_val, align_of, align_of_val};
index 4efd4c4d3d3aa2b9882a9fe95100201c24554bea..b19eab9f52b5294e248d25740569fe22ce1ca8fe 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(path_statements)]
 #![allow(dead_code)]
 
index 73cc9793f2c4c911947408bc6627529ec55fc590..dcc552ac75c89a6294faf19981eb0f00c83dc257 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(unused_imports)]
 
 // aux-build:union.rs
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..e785a2e
--- /dev/null
@@ -0,0 +1,60 @@
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:56:13
+   |
+LL |     let a = &mut u.x.0;
+   |             ---------- mutable borrow occurs here (via `u.x.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:63:13
+   |
+LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = u.x.0;
+   |             ----- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:69:13
+   |
+LL |     let a = &mut (u.x.0).0;
+   |             -------------- mutable borrow occurs here (via `u.x.0.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:76:13
+   |
+LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = (u.x.0).0;
+   |             --------- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:82:13
+   |
+LL |     let a = &mut *u.y;
+   |                   --- mutable borrow occurs here (via `u.y`)
+LL |     let b = &u.x;
+   |             ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.
index edf08e6ca678f13a4340aac6b5afd54052fc8bff..e56d87255dbaff1e590d53bd5f2698a65d006051 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(untagged_unions)]
 #![allow(unused)]
 
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.stderr
deleted file mode 100644 (file)
index 8ba155b..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
-  --> $DIR/union-borrow-move-parent-sibling.rs:53:13
-   |
-LL |     let a = &mut u.x.0;
-   |             ---------- mutable borrow occurs here (via `u.x.0`)
-LL |     let b = &u.y;
-   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
-LL |     use_borrow(a);
-   |                - mutable borrow later used here
-   |
-   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
-
-error[E0382]: use of moved value: `u`
-  --> $DIR/union-borrow-move-parent-sibling.rs:60:13
-   |
-LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
-   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
-LL |     let a = u.x.0;
-   |             ----- value moved here
-LL |     let b = u.y;
-   |             ^^^ value used here after move
-
-error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
-  --> $DIR/union-borrow-move-parent-sibling.rs:66:13
-   |
-LL |     let a = &mut (u.x.0).0;
-   |             -------------- mutable borrow occurs here (via `u.x.0.0`)
-LL |     let b = &u.y;
-   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
-LL |     use_borrow(a);
-   |                - mutable borrow later used here
-   |
-   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
-
-error[E0382]: use of moved value: `u`
-  --> $DIR/union-borrow-move-parent-sibling.rs:73:13
-   |
-LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
-   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
-LL |     let a = (u.x.0).0;
-   |             --------- value moved here
-LL |     let b = u.y;
-   |             ^^^ value used here after move
-
-error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
-  --> $DIR/union-borrow-move-parent-sibling.rs:79:13
-   |
-LL |     let a = &mut *u.y;
-   |                   --- mutable borrow occurs here (via `u.y`)
-LL |     let b = &u.x;
-   |             ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
-LL |     use_borrow(a);
-   |                - mutable borrow later used here
-   |
-   = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0382, E0502.
-For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..e785a2e
--- /dev/null
@@ -0,0 +1,60 @@
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:56:13
+   |
+LL |     let a = &mut u.x.0;
+   |             ---------- mutable borrow occurs here (via `u.x.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:63:13
+   |
+LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = u.x.0;
+   |             ----- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:69:13
+   |
+LL |     let a = &mut (u.x.0).0;
+   |             -------------- mutable borrow occurs here (via `u.x.0.0`)
+LL |     let b = &u.y;
+   |             ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
+
+error[E0382]: use of moved value: `u`
+  --> $DIR/union-borrow-move-parent-sibling.rs:76:13
+   |
+LL |     let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+   |         - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL |     let a = (u.x.0).0;
+   |             --------- value moved here
+LL |     let b = u.y;
+   |             ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
+  --> $DIR/union-borrow-move-parent-sibling.rs:82:13
+   |
+LL |     let a = &mut *u.y;
+   |                   --- mutable borrow occurs here (via `u.y`)
+LL |     let b = &u.x;
+   |             ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
+LL |     use_borrow(a);
+   |                - mutable borrow later used here
+   |
+   = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.
index d5b305595956386ff4dc4dc71ea79aa45a8b6400..32a546cf35f2cd2d33f9ad7cb2513260220dd9ee 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 union U {
     a: u64,
index 15a20899a78d1a24419303e24dde5591a9ecb19d..ca48785cd9f5ae2ab062d5790e6d0b06aa652baa 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 type Field1 = (i32, u32);
 type Field2 = f32;
index 90af8de447dfdaa2c9eea756580b7c51bb3a5a6a..0b6788b4226ab9d1f9b6fa3829b11c7eca336fe5 100644 (file)
@@ -1,4 +1,7 @@
 // build-pass (FIXME(62277): could be check-pass?)
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(const_fn_union)]
 
 union U {
diff --git a/src/test/ui/union/union-deref.mirunsafeck.stderr b/src/test/ui/union/union-deref.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..ff37e6f
--- /dev/null
@@ -0,0 +1,56 @@
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:17:14
+   |
+LL |     unsafe { u.f.0 = Vec::new() };
+   |              ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:19:19
+   |
+LL |     unsafe { &mut u.f.0 };
+   |                   ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:21:14
+   |
+LL |     unsafe { u.f.0.push(0) };
+   |              ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:25:14
+   |
+LL |     unsafe { u.f.0.0 = Vec::new() };
+   |              ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:27:19
+   |
+LL |     unsafe { &mut u.f.0.0 };
+   |                   ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:29:14
+   |
+LL |     unsafe { u.f.0.0.push(0) };
+   |              ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: aborting due to 6 previous errors
+
index 48f5b36bd17f3927a1734760f418d0eb3c24ba9a..4bf2ba2f1bfce0bccad8cef5f7780e3361f4c118 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 //! Test the part of RFC 2514 that is about not applying `DerefMut` coercions
 //! of union fields.
 #![feature(untagged_unions)]
diff --git a/src/test/ui/union/union-deref.stderr b/src/test/ui/union/union-deref.stderr
deleted file mode 100644 (file)
index 6af050b..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:14:14
-   |
-LL |     unsafe { u.f.0 = Vec::new() };
-   |              ^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:16:19
-   |
-LL |     unsafe { &mut u.f.0 };
-   |                   ^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:18:14
-   |
-LL |     unsafe { u.f.0.push(0) };
-   |              ^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:22:14
-   |
-LL |     unsafe { u.f.0.0 = Vec::new() };
-   |              ^^^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:24:19
-   |
-LL |     unsafe { &mut u.f.0.0 };
-   |                   ^^^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
-  --> $DIR/union-deref.rs:26:14
-   |
-LL |     unsafe { u.f.0.0.push(0) };
-   |              ^^^^^
-   |
-   = help: writing to this reference calls the destructor for the old value
-   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/union/union-deref.thirunsafeck.stderr b/src/test/ui/union/union-deref.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..ff37e6f
--- /dev/null
@@ -0,0 +1,56 @@
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:17:14
+   |
+LL |     unsafe { u.f.0 = Vec::new() };
+   |              ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:19:19
+   |
+LL |     unsafe { &mut u.f.0 };
+   |                   ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:21:14
+   |
+LL |     unsafe { u.f.0.push(0) };
+   |              ^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:25:14
+   |
+LL |     unsafe { u.f.0.0 = Vec::new() };
+   |              ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:27:19
+   |
+LL |     unsafe { &mut u.f.0.0 };
+   |                   ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+  --> $DIR/union-deref.rs:29:14
+   |
+LL |     unsafe { u.f.0.0.push(0) };
+   |              ^^^^^
+   |
+   = help: writing to this reference calls the destructor for the old value
+   = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..41e828c
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0277]: the trait bound `U1: Copy` is not satisfied
+  --> $DIR/union-derive-clone.rs:6:10
+   |
+LL | #[derive(Clone)]
+   |          ^^^^^ the trait `Copy` is not implemented for `U1`
+   | 
+  ::: $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+   |                                 ---- required by this bound in `AssertParamIsCopy`
+   |
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
+  --> $DIR/union-derive-clone.rs:38:15
+   |
+LL | union U5<T> {
+   | -----------
+   | |
+   | method `clone` not found for this
+   | doesn't satisfy `U5<CloneNoCopy>: Clone`
+...
+LL | struct CloneNoCopy;
+   | ------------------- doesn't satisfy `CloneNoCopy: Copy`
+...
+LL |     let w = u.clone();
+   |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `CloneNoCopy: Copy`
+           which is required by `U5<CloneNoCopy>: Clone`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
index 7ab19edb47179d385f014791c66938914e0c1f10..7aa62146e5490b913f31cf795317b041d1c22346 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 use std::mem::ManuallyDrop;
 
 #[derive(Clone)] //~ ERROR the trait bound `U1: Copy` is not satisfied
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
deleted file mode 100644 (file)
index 789bcc9..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0277]: the trait bound `U1: Copy` is not satisfied
-  --> $DIR/union-derive-clone.rs:3:10
-   |
-LL | #[derive(Clone)]
-   |          ^^^^^ the trait `Copy` is not implemented for `U1`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ---- required by this bound in `AssertParamIsCopy`
-   |
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
-  --> $DIR/union-derive-clone.rs:35:15
-   |
-LL | union U5<T> {
-   | -----------
-   | |
-   | method `clone` not found for this
-   | doesn't satisfy `U5<CloneNoCopy>: Clone`
-...
-LL | struct CloneNoCopy;
-   | ------------------- doesn't satisfy `CloneNoCopy: Copy`
-...
-LL |     let w = u.clone();
-   |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
-   |
-   = note: the following trait bounds were not satisfied:
-           `CloneNoCopy: Copy`
-           which is required by `U5<CloneNoCopy>: Clone`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0599.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..41e828c
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0277]: the trait bound `U1: Copy` is not satisfied
+  --> $DIR/union-derive-clone.rs:6:10
+   |
+LL | #[derive(Clone)]
+   |          ^^^^^ the trait `Copy` is not implemented for `U1`
+   | 
+  ::: $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+   |                                 ---- required by this bound in `AssertParamIsCopy`
+   |
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
+  --> $DIR/union-derive-clone.rs:38:15
+   |
+LL | union U5<T> {
+   | -----------
+   | |
+   | method `clone` not found for this
+   | doesn't satisfy `U5<CloneNoCopy>: Clone`
+...
+LL | struct CloneNoCopy;
+   | ------------------- doesn't satisfy `CloneNoCopy: Copy`
+...
+LL |     let w = u.clone();
+   |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `CloneNoCopy: Copy`
+           which is required by `U5<CloneNoCopy>: Clone`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-derive-eq.mirunsafeck.stderr b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9477d84
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
+  --> $DIR/union-derive-eq.rs:16:5
+   |
+LL |     a: PartialEqNotEq,
+   |     ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
+   | 
+  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
+   |                               -- required by this bound in `AssertParamIsEq`
+   |
+   = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index e689f8c27d772ba38fe16ed86b68671e06b8c7e6..b7e7f343f8a28b35ac83db3c48f8a3850960b302 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #[derive(Eq)] // OK
 union U1 {
     a: u8,
diff --git a/src/test/ui/union/union-derive-eq.stderr b/src/test/ui/union/union-derive-eq.stderr
deleted file mode 100644 (file)
index 3198e97..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
-  --> $DIR/union-derive-eq.rs:13:5
-   |
-LL |     a: PartialEqNotEq,
-   |     ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
-   | 
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               -- required by this bound in `AssertParamIsEq`
-   |
-   = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-derive-eq.thirunsafeck.stderr b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9477d84
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
+  --> $DIR/union-derive-eq.rs:16:5
+   |
+LL |     a: PartialEqNotEq,
+   |     ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
+   | 
+  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
+   |                               -- required by this bound in `AssertParamIsEq`
+   |
+   = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index db18a81c1f6651a0c8ec95090cac5d412afff8a7..8276bc635fc748799a161d9b3de98681e2fe47c5 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
diff --git a/src/test/ui/union/union-drop.thirunsafeck.stderr b/src/test/ui/union/union-drop.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9766ae4
--- /dev/null
@@ -0,0 +1,22 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/union-drop.rs:27:9
+   |
+LL |         unsafe { CHECK += 1; }
+   |         ^^^^^^ unnecessary `unsafe` block
+   |
+   = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+  --> $DIR/union-drop.rs:33:9
+   |
+LL |         unsafe { CHECK += 1; }
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+  --> $DIR/union-drop.rs:40:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/union/union-fields-1.mirunsafeck.stderr b/src/test/ui/union/union-fields-1.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9f1e294
--- /dev/null
@@ -0,0 +1,32 @@
+error: field is never read: `c`
+  --> $DIR/union-fields-1.rs:9:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/union-fields-1.rs:4:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: field is never read: `a`
+  --> $DIR/union-fields-1.rs:12:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field is never read: `a`
+  --> $DIR/union-fields-1.rs:16:20
+   |
+LL | union NoDropLike { a: u8 }
+   |                    ^^^^^
+
+error: field is never read: `c`
+  --> $DIR/union-fields-1.rs:21:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+
+error: aborting due to 4 previous errors
+
index edef41de159bae806cd36b26a0a9f07e90d3a18e..3d3e2355a26f2b10a9280d6c8178fb4057f5b1b5 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![deny(dead_code)]
 
 union U1 {
diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr
deleted file mode 100644 (file)
index 87621cc..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error: field is never read: `c`
-  --> $DIR/union-fields-1.rs:6:5
-   |
-LL |     c: u8,
-   |     ^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/union-fields-1.rs:1:9
-   |
-LL | #![deny(dead_code)]
-   |         ^^^^^^^^^
-
-error: field is never read: `a`
-  --> $DIR/union-fields-1.rs:9:5
-   |
-LL |     a: u8,
-   |     ^^^^^
-
-error: field is never read: `a`
-  --> $DIR/union-fields-1.rs:13:20
-   |
-LL | union NoDropLike { a: u8 }
-   |                    ^^^^^
-
-error: field is never read: `c`
-  --> $DIR/union-fields-1.rs:18:5
-   |
-LL |     c: u8,
-   |     ^^^^^
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/union/union-fields-1.thirunsafeck.stderr b/src/test/ui/union/union-fields-1.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..9f1e294
--- /dev/null
@@ -0,0 +1,32 @@
+error: field is never read: `c`
+  --> $DIR/union-fields-1.rs:9:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/union-fields-1.rs:4:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: field is never read: `a`
+  --> $DIR/union-fields-1.rs:12:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field is never read: `a`
+  --> $DIR/union-fields-1.rs:16:20
+   |
+LL | union NoDropLike { a: u8 }
+   |                    ^^^^^
+
+error: field is never read: `c`
+  --> $DIR/union-fields-1.rs:21:5
+   |
+LL |     c: u8,
+   |     ^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/union/union-fields-2.mirunsafeck.stderr b/src/test/ui/union/union-fields-2.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..867bf75
--- /dev/null
@@ -0,0 +1,84 @@
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:10:13
+   |
+LL |     let u = U {};
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:12:13
+   |
+LL |     let u = U { a: 0, b: 1 };
+   |             ^
+
+error[E0560]: union `U` has no field named `c`
+  --> $DIR/union-fields-2.rs:13:29
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |                             ^ `U` does not have this field
+   |
+   = note: available fields are: `a`, `b`
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:13:13
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:15:13
+   |
+LL |     let u = U { ..u };
+   |             ^
+
+error[E0436]: functional record update syntax requires a struct
+  --> $DIR/union-fields-2.rs:15:19
+   |
+LL |     let u = U { ..u };
+   |                   ^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:18:9
+   |
+LL |     let U {} = u;
+   |         ^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:20:9
+   |
+LL |     let U { a, b } = u;
+   |         ^^^^^^^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:21:9
+   |
+LL |     let U { a, b, c } = u;
+   |         ^^^^^^^^^^^^^
+
+error[E0026]: union `U` does not have a field named `c`
+  --> $DIR/union-fields-2.rs:21:19
+   |
+LL |     let U { a, b, c } = u;
+   |                   ^ union `U` does not have this field
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:23:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:23:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:25:9
+   |
+LL |     let U { a, .. } = u;
+   |         ^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0026, E0436, E0560.
+For more information about an error, try `rustc --explain E0026`.
index 71b204fcdc5b88f1a414734da64a4beb085ff193..e738b18470337b586799488df597e9112567c720 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 union U {
     a: u8,
     b: u16,
diff --git a/src/test/ui/union/union-fields-2.stderr b/src/test/ui/union/union-fields-2.stderr
deleted file mode 100644 (file)
index 4865434..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-error: union expressions should have exactly one field
-  --> $DIR/union-fields-2.rs:7:13
-   |
-LL |     let u = U {};
-   |             ^
-
-error: union expressions should have exactly one field
-  --> $DIR/union-fields-2.rs:9:13
-   |
-LL |     let u = U { a: 0, b: 1 };
-   |             ^
-
-error[E0560]: union `U` has no field named `c`
-  --> $DIR/union-fields-2.rs:10:29
-   |
-LL |     let u = U { a: 0, b: 1, c: 2 };
-   |                             ^ `U` does not have this field
-   |
-   = note: available fields are: `a`, `b`
-
-error: union expressions should have exactly one field
-  --> $DIR/union-fields-2.rs:10:13
-   |
-LL |     let u = U { a: 0, b: 1, c: 2 };
-   |             ^
-
-error: union expressions should have exactly one field
-  --> $DIR/union-fields-2.rs:12:13
-   |
-LL |     let u = U { ..u };
-   |             ^
-
-error[E0436]: functional record update syntax requires a struct
-  --> $DIR/union-fields-2.rs:12:19
-   |
-LL |     let u = U { ..u };
-   |                   ^
-
-error: union patterns should have exactly one field
-  --> $DIR/union-fields-2.rs:15:9
-   |
-LL |     let U {} = u;
-   |         ^^^^
-
-error: union patterns should have exactly one field
-  --> $DIR/union-fields-2.rs:17:9
-   |
-LL |     let U { a, b } = u;
-   |         ^^^^^^^^^^
-
-error: union patterns should have exactly one field
-  --> $DIR/union-fields-2.rs:18:9
-   |
-LL |     let U { a, b, c } = u;
-   |         ^^^^^^^^^^^^^
-
-error[E0026]: union `U` does not have a field named `c`
-  --> $DIR/union-fields-2.rs:18:19
-   |
-LL |     let U { a, b, c } = u;
-   |                   ^ union `U` does not have this field
-
-error: union patterns should have exactly one field
-  --> $DIR/union-fields-2.rs:20:9
-   |
-LL |     let U { .. } = u;
-   |         ^^^^^^^^
-
-error: `..` cannot be used in union patterns
-  --> $DIR/union-fields-2.rs:20:9
-   |
-LL |     let U { .. } = u;
-   |         ^^^^^^^^
-
-error: `..` cannot be used in union patterns
-  --> $DIR/union-fields-2.rs:22:9
-   |
-LL |     let U { a, .. } = u;
-   |         ^^^^^^^^^^^
-
-error: aborting due to 13 previous errors
-
-Some errors have detailed explanations: E0026, E0436, E0560.
-For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/union/union-fields-2.thirunsafeck.stderr b/src/test/ui/union/union-fields-2.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..867bf75
--- /dev/null
@@ -0,0 +1,84 @@
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:10:13
+   |
+LL |     let u = U {};
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:12:13
+   |
+LL |     let u = U { a: 0, b: 1 };
+   |             ^
+
+error[E0560]: union `U` has no field named `c`
+  --> $DIR/union-fields-2.rs:13:29
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |                             ^ `U` does not have this field
+   |
+   = note: available fields are: `a`, `b`
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:13:13
+   |
+LL |     let u = U { a: 0, b: 1, c: 2 };
+   |             ^
+
+error: union expressions should have exactly one field
+  --> $DIR/union-fields-2.rs:15:13
+   |
+LL |     let u = U { ..u };
+   |             ^
+
+error[E0436]: functional record update syntax requires a struct
+  --> $DIR/union-fields-2.rs:15:19
+   |
+LL |     let u = U { ..u };
+   |                   ^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:18:9
+   |
+LL |     let U {} = u;
+   |         ^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:20:9
+   |
+LL |     let U { a, b } = u;
+   |         ^^^^^^^^^^
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:21:9
+   |
+LL |     let U { a, b, c } = u;
+   |         ^^^^^^^^^^^^^
+
+error[E0026]: union `U` does not have a field named `c`
+  --> $DIR/union-fields-2.rs:21:19
+   |
+LL |     let U { a, b, c } = u;
+   |                   ^ union `U` does not have this field
+
+error: union patterns should have exactly one field
+  --> $DIR/union-fields-2.rs:23:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:23:9
+   |
+LL |     let U { .. } = u;
+   |         ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+  --> $DIR/union-fields-2.rs:25:9
+   |
+LL |     let U { a, .. } = u;
+   |         ^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0026, E0436, E0560.
+For more information about an error, try `rustc --explain E0026`.
index 69837f31cab27aa78e6ef57bf11ca08d6f1797d3..25f1f5050f99b46cf6835facd26d73ec775ec8a6 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 
 use std::mem::ManuallyDrop;
diff --git a/src/test/ui/union/union-generic.mirunsafeck.stderr b/src/test/ui/union/union-generic.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..fcd0bde
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:11:13
+   |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
+LL |     let u = U { a: Rc::new(0u32) };
+   |             ^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:13:13
+   |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
+LL |     let u = U::<Rc<u32>> { a: Default::default() };
+   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index ff877892579b9008a9d87425b267fcf517659132..3d68ecb87d8d673d1c93dfb2409e915e808c7e0e 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 use std::rc::Rc;
 
 union U<T: Copy> {
diff --git a/src/test/ui/union/union-generic.stderr b/src/test/ui/union/union-generic.stderr
deleted file mode 100644 (file)
index c418b27..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
-  --> $DIR/union-generic.rs:8:13
-   |
-LL | union U<T: Copy> {
-   | ---------------- required by `U`
-...
-LL |     let u = U { a: Rc::new(0u32) };
-   |             ^ the trait `Copy` is not implemented for `Rc<u32>`
-
-error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
-  --> $DIR/union-generic.rs:10:13
-   |
-LL | union U<T: Copy> {
-   | ---------------- required by `U`
-...
-LL |     let u = U::<Rc<u32>> { a: Default::default() };
-   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-generic.thirunsafeck.stderr b/src/test/ui/union/union-generic.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..fcd0bde
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:11:13
+   |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
+LL |     let u = U { a: Rc::new(0u32) };
+   |             ^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+  --> $DIR/union-generic.rs:13:13
+   |
+LL | union U<T: Copy> {
+   | ---------------- required by `U`
+...
+LL |     let u = U::<Rc<u32>> { a: Default::default() };
+   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 2e75cce7b108be3955582b0aeb98b4c51b0811ac..b0fd22da73adc146c203e8aa687a667b2753fe70 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 union U {
     a: u8,
diff --git a/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..22d4428
--- /dev/null
@@ -0,0 +1,14 @@
+error: field is never read: `b`
+  --> $DIR/union-lint-dead-code.rs:8:5
+   |
+LL |     b: bool,
+   |     ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/union-lint-dead-code.rs:4:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
index ae5337c618a754d470c8af176689390c56be7c60..64c28d72e9eaa3ee59656d0e29bad07dba2a2299 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![deny(dead_code)]
 
 union Foo {
diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr
deleted file mode 100644 (file)
index 7de70ec..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: field is never read: `b`
-  --> $DIR/union-lint-dead-code.rs:5:5
-   |
-LL |     b: bool,
-   |     ^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/union-lint-dead-code.rs:1:9
-   |
-LL | #![deny(dead_code)]
-   |         ^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..22d4428
--- /dev/null
@@ -0,0 +1,14 @@
+error: field is never read: `b`
+  --> $DIR/union-lint-dead-code.rs:8:5
+   |
+LL |     b: bool,
+   |     ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/union-lint-dead-code.rs:4:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
index e938cd5a614e9ff143618d063f5fa25758fc7b3d..7fd9d8221c612a0602bc875e1f153910af46743c 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(unused_variables)]
 
 macro_rules! duplicate {
index 977d12f1086028bb1e37fc7c4933955a4f27a36f..826bdf07cef5ec35937b8d4c9304bdb6cc3d8c25 100644 (file)
@@ -1,5 +1,8 @@
-#![allow(dead_code)]
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![allow(dead_code)]
 
 use std::mem::needs_drop;
 use std::mem::ManuallyDrop;
diff --git a/src/test/ui/union/union-move.mirunsafeck.stderr b/src/test/ui/union/union-move.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..f55fbea
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:29:18
+   |
+LL | fn test1(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f1_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f2_nocopy);
+   |                  ^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:45:18
+   |
+LL | fn test3(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f2_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f3_copy);
+   |                  ^^^^^^^^^ value used here after move
+
+error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
+  --> $DIR/union-move.rs:52:18
+   |
+LL |         move_out(x.f1_nocopy);
+   |                  ^^^^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0382, E0509.
+For more information about an error, try `rustc --explain E0382`.
index a0a2d0d659837a60bbe6e4b6a04ea34796938cfd..8f78c30d67a5537824396294b3ef9ac88f068720 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 //! Test the behavior of moving out of non-`Copy` union fields.
 //! Avoid types that `Drop`, we want to focus on moving.
 #![feature(untagged_unions)]
diff --git a/src/test/ui/union/union-move.stderr b/src/test/ui/union/union-move.stderr
deleted file mode 100644 (file)
index 5679192..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0382]: use of moved value: `x`
-  --> $DIR/union-move.rs:26:18
-   |
-LL | fn test1(x: U1) {
-   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
-...
-LL |         move_out(x.f1_nocopy);
-   |                  ----------- value moved here
-LL |         move_out(x.f2_nocopy);
-   |                  ^^^^^^^^^^^ value used here after move
-
-error[E0382]: use of moved value: `x`
-  --> $DIR/union-move.rs:42:18
-   |
-LL | fn test3(x: U1) {
-   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
-...
-LL |         move_out(x.f2_nocopy);
-   |                  ----------- value moved here
-LL |         move_out(x.f3_copy);
-   |                  ^^^^^^^^^ value used here after move
-
-error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
-  --> $DIR/union-move.rs:49:18
-   |
-LL |         move_out(x.f1_nocopy);
-   |                  ^^^^^^^^^^^
-   |                  |
-   |                  cannot move out of here
-   |                  move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0382, E0509.
-For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/union/union-move.thirunsafeck.stderr b/src/test/ui/union/union-move.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..f55fbea
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:29:18
+   |
+LL | fn test1(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f1_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f2_nocopy);
+   |                  ^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:45:18
+   |
+LL | fn test3(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f2_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f3_copy);
+   |                  ^^^^^^^^^ value used here after move
+
+error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
+  --> $DIR/union-move.rs:52:18
+   |
+LL |         move_out(x.f1_nocopy);
+   |                  ^^^^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0382, E0509.
+For more information about an error, try `rustc --explain E0382`.
index bc58c5995cb80e2ed8317a7976362fe9a7fc2bae..6e6b105a73e9f461f2adeb5cfa64916f11aff7d8 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 #![allow(dead_code)]
 
index bd84b46bf3d234a9e6bbb3db18775974d837241b..d29e7a97180cf633d44f1d754a172c68682f0b8e 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 
 // Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations.
index 399ed9ae458b8f664435e414a4b0f9da2debbbea..0eea14d9de0fc34beda14ecaa63f6b737406d28e 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 #[repr(C)]
 #[derive(Copy, Clone)]
index 9cde44c06bd476ccdf363079d3fe149a1582632e..9c6398bf5aa631039253d25a501cc344f9b6df10 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 #![allow(non_snake_case)]
 
index ebb0672664716ebed36c384e20e85fb64c7e348c..d628a200a076e675fcf184fe53a53a5dd275db11 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 #![allow(illegal_floating_point_literal_pattern)]
 
diff --git a/src/test/ui/union/union-suggest-field.mirunsafeck.stderr b/src/test/ui/union/union-suggest-field.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..26fc25b
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0560]: union `U` has no field named `principle`
+  --> $DIR/union-suggest-field.rs:13:17
+   |
+LL |     let u = U { principle: 0 };
+   |                 ^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0609]: no field `principial` on type `U`
+  --> $DIR/union-suggest-field.rs:17:15
+   |
+LL |     let w = u.principial;
+   |               ^^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0615]: attempted to take value of method `calculate` on type `U`
+  --> $DIR/union-suggest-field.rs:21:15
+   |
+LL |     let y = u.calculate;
+   |               ^^^^^^^^^ method, not a field
+   |
+help: use parentheses to call the method
+   |
+LL |     let y = u.calculate();
+   |                        ^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0560, E0609, E0615.
+For more information about an error, try `rustc --explain E0560`.
index 71b93e873c22026ceca22d8e30c146afa2b3745c..601a22a060048ec5bd64a95c6aae2eba06a6c765 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 union U {
     principal: u8,
 }
diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.stderr
deleted file mode 100644 (file)
index 461db17..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0560]: union `U` has no field named `principle`
-  --> $DIR/union-suggest-field.rs:10:17
-   |
-LL |     let u = U { principle: 0 };
-   |                 ^^^^^^^^^ help: a field with a similar name exists: `principal`
-
-error[E0609]: no field `principial` on type `U`
-  --> $DIR/union-suggest-field.rs:14:15
-   |
-LL |     let w = u.principial;
-   |               ^^^^^^^^^^ help: a field with a similar name exists: `principal`
-
-error[E0615]: attempted to take value of method `calculate` on type `U`
-  --> $DIR/union-suggest-field.rs:18:15
-   |
-LL |     let y = u.calculate;
-   |               ^^^^^^^^^ method, not a field
-   |
-help: use parentheses to call the method
-   |
-LL |     let y = u.calculate();
-   |                        ^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0560, E0609, E0615.
-For more information about an error, try `rustc --explain E0560`.
diff --git a/src/test/ui/union/union-suggest-field.thirunsafeck.stderr b/src/test/ui/union/union-suggest-field.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..26fc25b
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0560]: union `U` has no field named `principle`
+  --> $DIR/union-suggest-field.rs:13:17
+   |
+LL |     let u = U { principle: 0 };
+   |                 ^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0609]: no field `principial` on type `U`
+  --> $DIR/union-suggest-field.rs:17:15
+   |
+LL |     let w = u.principial;
+   |               ^^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0615]: attempted to take value of method `calculate` on type `U`
+  --> $DIR/union-suggest-field.rs:21:15
+   |
+LL |     let y = u.calculate;
+   |               ^^^^^^^^^ method, not a field
+   |
+help: use parentheses to call the method
+   |
+LL |     let y = u.calculate();
+   |                        ^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0560, E0609, E0615.
+For more information about an error, try `rustc --explain E0560`.
index 8a7ac81724040cd4d2d2279a3a43abf24a10ed96..6134e91f31e49023b341abb7d32f99fda2b4eb43 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 use std::fmt;
 
index be8062f6276fd8a90a92e7c9a9410da927c76355..1a3b32d55f321cb161db870eb28fbf64afcfd6bb 100644 (file)
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
 
 union U {
     a: (u8, u8),
diff --git a/src/test/ui/union/union-unsafe.mir.stderr b/src/test/ui/union/union-unsafe.mir.stderr
new file mode 100644 (file)
index 0000000..84a7eb2
--- /dev/null
@@ -0,0 +1,91 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:34:5
+   |
+LL |     *(u.p) = 13;
+   |     ^^^^^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:39:5
+   |
+LL |     u.a = (RefCell::new(0), 1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:40:5
+   |
+LL |     u.a.0 = RefCell::new(0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+   |
+   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:47:6
+   |
+LL |     *u3.a = T::default();
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:53:6
+   |
+LL |     *u3.a = T::default();
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:61:13
+   |
+LL |     let a = u1.a;
+   |             ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:64:14
+   |
+LL |     let U1 { a } = u1;
+   |              ^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:65:20
+   |
+LL |     if let U1 { a: 12 } = u1 {}
+   |                    ^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:70:6
+   |
+LL |     *u2.a = String::from("new");
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:74:6
+   |
+LL |     *u3.a = 1;
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:78:6
+   |
+LL |     *u3.a = String::from("new");
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
index 6adf0ac59b93ce518c60660290803fdcab1aa93e..e8414903d548fbd80e8e6efdbbaa3ff54694e041 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
 #![feature(untagged_unions)]
 use std::mem::ManuallyDrop;
 use std::cell::RefCell;
@@ -32,8 +35,9 @@ fn deref_union_field(mut u: URef) {
 }
 
 fn assign_noncopy_union_field(mut u: URefCell) {
-    u.a = (RefCell::new(0), 1); //~ ERROR assignment to union field that might need dropping
-    u.a.0 = RefCell::new(0); //~ ERROR assignment to union field that might need dropping
+    // FIXME(thir-unsafeck)
+    u.a = (RefCell::new(0), 1); //[mir]~ ERROR assignment to union field that might need dropping
+    u.a.0 = RefCell::new(0); //[mir]~ ERROR assignment to union field that might need dropping
     u.a.1 = 1; // OK
 }
 
diff --git a/src/test/ui/union/union-unsafe.stderr b/src/test/ui/union/union-unsafe.stderr
deleted file mode 100644 (file)
index a25c091..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:31:5
-   |
-LL |     *(u.p) = 13;
-   |     ^^^^^^^^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:35:5
-   |
-LL |     u.a = (RefCell::new(0), 1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
-   |
-   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
-
-error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:36:5
-   |
-LL |     u.a.0 = RefCell::new(0);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
-   |
-   = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:43:6
-   |
-LL |     *u3.a = T::default();
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:49:6
-   |
-LL |     *u3.a = T::default();
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:57:13
-   |
-LL |     let a = u1.a;
-   |             ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:60:14
-   |
-LL |     let U1 { a } = u1;
-   |              ^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:61:20
-   |
-LL |     if let U1 { a: 12 } = u1 {}
-   |                    ^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:66:6
-   |
-LL |     *u2.a = String::from("new");
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:70:6
-   |
-LL |     *u3.a = 1;
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:74:6
-   |
-LL |     *u3.a = String::from("new");
-   |      ^^^^ access to union field
-   |
-   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error: aborting due to 11 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/union/union-unsafe.thir.stderr b/src/test/ui/union/union-unsafe.thir.stderr
new file mode 100644 (file)
index 0000000..51f1987
--- /dev/null
@@ -0,0 +1,75 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:34:6
+   |
+LL |     *(u.p) = 13;
+   |      ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:47:6
+   |
+LL |     *u3.a = T::default();
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:53:6
+   |
+LL |     *u3.a = T::default();
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:61:13
+   |
+LL |     let a = u1.a;
+   |             ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:64:14
+   |
+LL |     let U1 { a } = u1;
+   |              ^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:65:20
+   |
+LL |     if let U1 { a: 12 } = u1 {}
+   |                    ^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:70:6
+   |
+LL |     *u2.a = String::from("new");
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:74:6
+   |
+LL |     *u3.a = 1;
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-unsafe.rs:78:6
+   |
+LL |     *u3.a = String::from("new");
+   |      ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/union/union-unsized.mirunsafeck.stderr b/src/test/ui/union/union-unsized.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..86a13c1
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:7:8
+   |
+LL |     a: str,
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     a: &str,
+   |        ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     a: Box<str>,
+   |        ^^^^   ^
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:15:8
+   |
+LL |     b: str,
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     b: &str,
+   |        ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     b: Box<str>,
+   |        ^^^^   ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 16f2a73d42570a70f21de7107addbb6390a7d83d..e9792f527dc71ef672c44e51a1a9b1a6a8fe0bcb 100644 (file)
@@ -1,3 +1,6 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![feature(untagged_unions)]
 
 union U {
diff --git a/src/test/ui/union/union-unsized.stderr b/src/test/ui/union/union-unsized.stderr
deleted file mode 100644 (file)
index 454580d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/union-unsized.rs:4:8
-   |
-LL |     a: str,
-   |        ^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `str`
-   = note: no field of a union may have a dynamically sized type
-   = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
-   |
-LL |     a: &str,
-   |        ^
-help: the `Box` type always has a statically known size and allocates its contents in the heap
-   |
-LL |     a: Box<str>,
-   |        ^^^^   ^
-
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/union-unsized.rs:12:8
-   |
-LL |     b: str,
-   |        ^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `str`
-   = note: no field of a union may have a dynamically sized type
-   = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
-   |
-LL |     b: &str,
-   |        ^
-help: the `Box` type always has a statically known size and allocates its contents in the heap
-   |
-LL |     b: Box<str>,
-   |        ^^^^   ^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-unsized.thirunsafeck.stderr b/src/test/ui/union/union-unsized.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..86a13c1
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:7:8
+   |
+LL |     a: str,
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     a: &str,
+   |        ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     a: Box<str>,
+   |        ^^^^   ^
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/union-unsized.rs:15:8
+   |
+LL |     b: str,
+   |        ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+   = note: no field of a union may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     b: &str,
+   |        ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     b: Box<str>,
+   |        ^^^^   ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr
new file mode 100644 (file)
index 0000000..2062fb7
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:11:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:11:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:19:5
+   |
+LL |     a: S,
+   |     ^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:19:5
+   |
+LL |     a: S,
+   |     ^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:24:5
+   |
+LL |     a: T,
+   |     ^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:24:5
+   |
+LL |     a: T,
+   |     ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0740`.
index e3c63a6d5b5a2e7ad447a3ff7bb7a8d3e794e4fa..96c293418b62951fc548d7ef00872fe8bb348e52 100644 (file)
@@ -1,4 +1,6 @@
-#![feature(untagged_unions)]
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
 #![allow(dead_code)]
 
 union U {
diff --git a/src/test/ui/union/union-with-drop-fields.stderr b/src/test/ui/union/union-with-drop-fields.stderr
deleted file mode 100644 (file)
index 0e77279..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/union-with-drop-fields.rs:9:5
-   |
-LL |     a: String,
-   |     ^^^^^^^^^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/union-with-drop-fields.rs:9:5
-   |
-LL |     a: String,
-   |     ^^^^^^^^^
-
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/union-with-drop-fields.rs:17:5
-   |
-LL |     a: S,
-   |     ^^^^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/union-with-drop-fields.rs:17:5
-   |
-LL |     a: S,
-   |     ^^^^
-
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/union-with-drop-fields.rs:22:5
-   |
-LL |     a: T,
-   |     ^^^^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/union-with-drop-fields.rs:22:5
-   |
-LL |     a: T,
-   |     ^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0740`.
diff --git a/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr
new file mode 100644 (file)
index 0000000..2062fb7
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:11:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:11:5
+   |
+LL |     a: String,
+   |     ^^^^^^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:19:5
+   |
+LL |     a: S,
+   |     ^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:19:5
+   |
+LL |     a: S,
+   |     ^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+  --> $DIR/union-with-drop-fields.rs:24:5
+   |
+LL |     a: T,
+   |     ^^^^
+   |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+  --> $DIR/union-with-drop-fields.rs:24:5
+   |
+LL |     a: T,
+   |     ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0740`.
diff --git a/src/test/ui/unsafe/access_union_field.mir.stderr b/src/test/ui/unsafe/access_union_field.mir.stderr
new file mode 100644 (file)
index 0000000..98bc407
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/access_union_field.rs:13:13
+   |
+LL |     let a = foo.bar;
+   |             ^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/access_union_field.rs:14:13
+   |
+LL |     let b = foo.baz;
+   |             ^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/access_union_field.rs b/src/test/ui/unsafe/access_union_field.rs
new file mode 100644 (file)
index 0000000..5c4e695
--- /dev/null
@@ -0,0 +1,15 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(unused_variables)]
+
+union Foo {
+    bar: i8,
+    baz: u8,
+}
+
+fn main() {
+    let foo = Foo { bar: 5 };
+    let a = foo.bar; //~ ERROR access to union field is unsafe and requires unsafe function or block
+    let b = foo.baz; //~ ERROR access to union field is unsafe and requires unsafe function or block
+}
diff --git a/src/test/ui/unsafe/access_union_field.thir.stderr b/src/test/ui/unsafe/access_union_field.thir.stderr
new file mode 100644 (file)
index 0000000..98bc407
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/access_union_field.rs:13:13
+   |
+LL |     let a = foo.bar;
+   |             ^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/access_union_field.rs:14:13
+   |
+LL |     let b = foo.baz;
+   |             ^^^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/union.mir.stderr b/src/test/ui/unsafe/union.mir.stderr
new file mode 100644 (file)
index 0000000..f7bd411
--- /dev/null
@@ -0,0 +1,16 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/union.rs:61:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+   |
+   = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+  --> $DIR/union.rs:66:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/unsafe/union.rs b/src/test/ui/unsafe/union.rs
new file mode 100644 (file)
index 0000000..0130fa6
--- /dev/null
@@ -0,0 +1,80 @@
+// run-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![feature(untagged_unions)]
+
+union Foo {
+    bar: i8,
+    zst: (),
+    pizza: Pizza,
+}
+
+struct Pizza {
+    topping: Option<PizzaTopping>
+}
+
+#[allow(dead_code)]
+enum PizzaTopping {
+    Cheese,
+    Pineapple,
+}
+
+struct FooHolder {
+    inner_foo: Foo
+}
+
+fn do_nothing(_x: &mut Foo) {}
+
+pub fn main() {
+    let mut foo = Foo { bar: 5 };
+    do_nothing(&mut foo);
+    foo.bar = 6;
+    unsafe { foo.bar += 1; }
+    assert_eq!(unsafe { foo.bar }, 7);
+    unsafe {
+        let Foo { bar: inner } = foo;
+        assert_eq!(inner, 7);
+    }
+    let foo = if let true = true { foo } else { foo };
+
+    unsafe {
+        match foo {
+            Foo { bar: _a } => {},
+        }
+    }
+    unsafe {
+        match foo {
+            Foo {
+                pizza: Pizza {
+                    topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None
+                }
+            } => {},
+        }
+    }
+    // binding to wildcard is okay
+    match foo {
+        Foo { bar: _ } => {},
+    }
+    let Foo { bar: _ } = foo;
+    // MIR unsafeck incorrectly thinks that it is safe to do these
+    unsafe { //[mir]~ WARNING
+        match foo {
+            Foo { zst: () } => {},
+        }
+    }
+    unsafe { //[mir]~ WARNING
+        match foo {
+            Foo { pizza: Pizza { .. } } => {},
+        }
+    }
+    let foo = Foo { bar: 5 };
+    let foo = if let 3 = if let true = true { 3 } else { 4 } { foo } else { foo };
+
+    let (_foo2, _random) = (foo, 42);
+
+    let mut foo_holder = FooHolder { inner_foo: Foo { bar: 5 } };
+    foo_holder.inner_foo.bar = 4;
+    assert_eq!(unsafe { foo_holder.inner_foo.bar }, 4);
+    drop(foo_holder);
+}
diff --git a/src/test/ui/unsafe/union_access_through_block.rs b/src/test/ui/unsafe/union_access_through_block.rs
new file mode 100644 (file)
index 0000000..e4c0976
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+pub struct Foo { a: bool }
+
+pub union Bar {
+    a: Foo,
+    b: u32,
+}
+pub fn baz(mut bar: Bar) {
+    unsafe {
+        { bar.a }.a = true;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/union_destructure.mir.stderr b/src/test/ui/unsafe/union_destructure.mir.stderr
new file mode 100644 (file)
index 0000000..818f5ce
--- /dev/null
@@ -0,0 +1,16 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/union_destructure.rs:35:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+   |
+   = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+  --> $DIR/union_destructure.rs:41:5
+   |
+LL |     unsafe {
+   |     ^^^^^^ unnecessary `unsafe` block
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/unsafe/union_destructure.rs b/src/test/ui/unsafe/union_destructure.rs
new file mode 100644 (file)
index 0000000..6c88344
--- /dev/null
@@ -0,0 +1,51 @@
+// run-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+#[allow(dead_code)]
+struct Pie {
+    slices: u8,
+    size: u8,
+}
+
+union Foo {
+    #[allow(dead_code)]
+    bar: i8,
+    baz: Pie
+}
+
+fn main() {
+    let u = Foo { bar: 5 };
+    let (Some(Foo { bar: _ }) | None) = Some(u);
+    let u = Foo { bar: 6 };
+    let (Some(Foo { bar: _ }) | Some(Foo { bar: _ }) | None) = Some(u);
+    unsafe {
+        let u = Foo { bar: 7 };
+        let (Foo { bar } | Foo { bar }) = u;
+        assert_eq!(bar, 7)
+    }
+    let u = Foo { bar: 8 };
+    match Some(u) {
+        Some(Foo { bar: _ }) => 3,
+        None => 4,
+    };
+
+    let u = Foo { bar: 9 };
+    unsafe { //[mir]~ WARNING unnecessary `unsafe` block
+        match u {
+            Foo { baz: Pie { .. } } => {},
+        };
+    }
+    let u = Foo { bar: 10 };
+    unsafe { //[mir]~ WARNING unnecessary `unsafe` block
+        match u {
+            Foo { baz: Pie { slices: _, size: _ } } => {},
+        };
+    }
+
+    let u = Foo { bar: 11 };
+    match u {
+        Foo { baz: _ } => {},
+    };
+}
diff --git a/src/test/ui/unsafe/union_wild_or_wild.rs b/src/test/ui/unsafe/union_wild_or_wild.rs
new file mode 100644 (file)
index 0000000..52a0a7a
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+union X { a: i8 }
+
+fn main() {
+    let x = X { a: 5 };
+    match x {
+        X { a: _ | _ } => {},
+    }
+}