Auto merge of #129076 - matthiaskrgr:rollup-rg8mi2x, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #128410 (Migrate `remap-path-prefix-dwarf` `run-make` test to rmake)
 - #128759 (alloc: add ToString specialization for `&&str`)
 - #128873 (Add windows-targets crate to std's sysroot)
 - #129001 (chore(lib): Enhance documentation for core::fmt::Formatter's write_fm…)
 - #129061 (Use `is_lang_item` more)
 - #129062 (Remove a no-longer-true assert)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-08-14 04:17:13 +00:00
commit 9859bf27fd
38 changed files with 543 additions and 261 deletions

View File

@ -160,15 +160,11 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.demand_suptype(span, ret_ty, actual_return_ty);
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
if let Some(panic_impl_did) = tcx.lang_items().panic_impl()
&& panic_impl_did == fn_def_id.to_def_id()
{
check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig);
if tcx.is_lang_item(fn_def_id.to_def_id(), LangItem::PanicImpl) {
check_panic_info_fn(tcx, fn_def_id, fn_sig);
}
if let Some(lang_start_defid) = tcx.lang_items().start_fn()
&& lang_start_defid == fn_def_id.to_def_id()
{
if tcx.is_lang_item(fn_def_id.to_def_id(), LangItem::Start) {
check_lang_start_fn(tcx, fn_sig, fn_def_id);
}

View File

@ -1,5 +1,5 @@
use hir::{Expr, Pat};
use rustc_hir as hir;
use rustc_hir::{self as hir, LangItem};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty;
@ -126,7 +126,10 @@ fn extract_iterator_next_call<'tcx>(
) -> Option<&'tcx Expr<'tcx>> {
// This won't work for `Iterator::next(iter)`, is this an issue?
if let hir::ExprKind::MethodCall(_, recv, _, _) = expr.kind
&& cx.typeck_results().type_dependent_def_id(expr.hir_id) == cx.tcx.lang_items().next_fn()
&& cx
.typeck_results()
.type_dependent_def_id(expr.hir_id)
.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::IteratorNext))
{
Some(recv)
} else {

View File

@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
for (bound, modifier) in &bounds[..] {
let def_id = bound.trait_ref.trait_def_id();
if cx.tcx.lang_items().drop_trait() == def_id
if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop))
&& *modifier != hir::TraitBoundModifier::Maybe
{
let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };

View File

@ -6,10 +6,9 @@ use std::ops::ControlFlow;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{into_diag_arg_using_display, Applicability, Diag, DiagArgValue, IntoDiagArg};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{PredicateOrigin, WherePredicate};
use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicate};
use rustc_span::{BytePos, Span};
use rustc_type_ir::TyKind::*;
@ -290,8 +289,9 @@ pub fn suggest_constraining_type_params<'a>(
let Some(param) = param else { return false };
{
let mut sized_constraints =
constraints.extract_if(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
let mut sized_constraints = constraints.extract_if(|(_, def_id)| {
def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized))
});
if let Some((_, def_id)) = sized_constraints.next() {
applicability = Applicability::MaybeIncorrect;

View File

@ -838,7 +838,7 @@ impl<'tcx> Instance<'tcx> {
return None;
};
if tcx.lang_items().get(coroutine_callable_item) == Some(trait_item_id) {
if tcx.is_lang_item(trait_item_id, coroutine_callable_item) {
let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
else {
bug!()

View File

@ -1145,7 +1145,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
let term = if let Some(ty) = term.skip_binder().as_type()
&& let ty::Alias(ty::Projection, proj) = ty.kind()
&& let Some(assoc) = tcx.opt_associated_item(proj.def_id)
&& assoc.trait_container(tcx) == tcx.lang_items().coroutine_trait()
&& assoc
.trait_container(tcx)
.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine))
&& assoc.name == rustc_span::sym::Return
{
if let ty::Coroutine(_, args) = args.type_at(0).kind() {

View File

@ -1916,7 +1916,7 @@ impl<'tcx> Ty<'tcx> {
pub fn is_c_void(self, tcx: TyCtxt<'_>) -> bool {
match self.kind() {
ty::Adt(adt, _) => tcx.lang_items().get(LangItem::CVoid) == Some(adt.did()),
ty::Adt(adt, _) => tcx.is_lang_item(adt.did(), LangItem::CVoid),
_ => false,
}
}

View File

@ -702,10 +702,12 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
&& adt.is_enum()
&& let Constructor::Variant(variant_index) = witness_1.ctor()
{
let variant = adt.variant(*variant_index);
let inhabited = variant.inhabited_predicate(self.tcx, *adt).instantiate(self.tcx, args);
assert!(inhabited.apply(self.tcx, cx.param_env, cx.module));
!inhabited.apply_ignore_module(self.tcx, cx.param_env)
let variant_inhabited = adt
.variant(*variant_index)
.inhabited_predicate(self.tcx, *adt)
.instantiate(self.tcx, args);
variant_inhabited.apply(self.tcx, cx.param_env, cx.module)
&& !variant_inhabited.apply_ignore_module(self.tcx, cx.param_env)
} else {
false
};

View File

@ -648,7 +648,9 @@ fn characteristic_def_id_of_mono_item<'tcx>(
if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
if tcx.sess.opts.incremental.is_some()
&& tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait()
&& tcx
.trait_id_of_impl(impl_def_id)
.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Drop))
{
// Put `Drop::drop` into the same cgu as `drop_in_place`
// since `drop_in_place` is the only thing that can

View File

@ -4,6 +4,7 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::print::{FmtPrinter, Printer};
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
use rustc_span::def_id::DefId;
@ -313,11 +314,15 @@ impl<T> Trait<T> for X {
(ty::Dynamic(t, _, ty::DynKind::Dyn), _)
if let Some(def_id) = t.principal_def_id() =>
{
let mut impl_def_ids = vec![];
let mut has_matching_impl = false;
tcx.for_each_relevant_impl(def_id, values.found, |did| {
impl_def_ids.push(did)
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
{
has_matching_impl = true;
}
});
if let [_] = &impl_def_ids[..] {
if has_matching_impl {
let trait_name = tcx.item_name(def_id);
diag.help(format!(
"`{}` implements `{trait_name}` so you could box the found value \
@ -330,11 +335,15 @@ impl<T> Trait<T> for X {
(_, ty::Dynamic(t, _, ty::DynKind::Dyn))
if let Some(def_id) = t.principal_def_id() =>
{
let mut impl_def_ids = vec![];
let mut has_matching_impl = false;
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
impl_def_ids.push(did)
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
.types_may_unify(values.expected, tcx.type_of(did).skip_binder())
{
has_matching_impl = true;
}
});
if let [_] = &impl_def_ids[..] {
if has_matching_impl {
let trait_name = tcx.item_name(def_id);
diag.help(format!(
"`{}` implements `{trait_name}` so you could change the expected \
@ -346,11 +355,15 @@ impl<T> Trait<T> for X {
(ty::Dynamic(t, _, ty::DynKind::DynStar), _)
if let Some(def_id) = t.principal_def_id() =>
{
let mut impl_def_ids = vec![];
let mut has_matching_impl = false;
tcx.for_each_relevant_impl(def_id, values.found, |did| {
impl_def_ids.push(did)
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
{
has_matching_impl = true;
}
});
if let [_] = &impl_def_ids[..] {
if has_matching_impl {
let trait_name = tcx.item_name(def_id);
diag.help(format!(
"`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \

View File

@ -230,8 +230,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
post_message,
);
let (err_msg, safe_transmute_explanation) = if Some(main_trait_ref.def_id())
== self.tcx.lang_items().transmute_trait()
let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_ref.def_id(), LangItem::TransmuteTrait)
{
// Recompute the safe transmute reason and use that for the error reporting
match self.get_safe_transmute_error_and_reason(

View File

@ -2831,7 +2831,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// Do not suggest relaxing if there is an explicit `Sized` obligation.
&& !bounds.iter()
.filter_map(|bound| bound.trait_ref())
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
.any(|tr| tr.trait_def_id().is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized)))
{
let (span, separator) = if let [.., last] = bounds {
(last.span().shrink_to_hi(), " +")

View File

@ -1,3 +1,4 @@
use rustc_hir::LangItem;
use rustc_infer::traits::Obligation;
pub use rustc_middle::traits::query::type_op::ProvePredicate;
use rustc_middle::traits::query::NoSolution;
@ -20,8 +21,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
// such cases.
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
key.value.predicate.kind().skip_binder()
&& let Some(sized_def_id) = tcx.lang_items().sized_trait()
&& trait_ref.def_id() == sized_def_id
&& tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized)
&& trait_ref.self_ty().is_trivially_sized(tcx)
{
return Some(());

View File

@ -621,7 +621,7 @@ fn fn_abi_new_uncached<'tcx>(
let rust_abi = matches!(sig.abi, RustIntrinsic | Rust | RustCall);
let is_drop_in_place =
fn_def_id.is_some() && fn_def_id == cx.tcx.lang_items().drop_in_place_fn();
fn_def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::DropInPlace));
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
let span = tracing::debug_span!("arg_of");

View File

@ -339,6 +339,7 @@ dependencies = [
"std_detect",
"unwind",
"wasi",
"windows-targets 0.0.0",
]
[[package]]
@ -421,9 +422,13 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
"windows-targets 0.52.5",
]
[[package]]
name = "windows-targets"
version = "0.0.0"
[[package]]
name = "windows-targets"
version = "0.52.5"

View File

@ -8,6 +8,7 @@ members = [
exclude = [
# stdarch has its own Cargo workspace
"stdarch",
"windows_targets"
]
[profile.release.package.compiler_builtins]

View File

@ -2643,14 +2643,54 @@ impl ToString for i8 {
}
}
#[doc(hidden)]
// Generic/generated code can sometimes have multiple, nested references
// for strings, including `&&&str`s that would never be written
// by hand. This macro generates twelve layers of nested `&`-impl
// for primitive strings.
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "str_to_string_specialization", since = "1.9.0")]
impl ToString for str {
#[inline]
fn to_string(&self) -> String {
String::from(self)
}
macro_rules! to_string_str_wrap_in_ref {
{x $($x:ident)*} => {
&to_string_str_wrap_in_ref! { $($x)* }
};
{} => { str };
}
#[cfg(not(no_global_oom_handling))]
macro_rules! to_string_expr_wrap_in_deref {
{$self:expr ; x $($x:ident)*} => {
*(to_string_expr_wrap_in_deref! { $self ; $($x)* })
};
{$self:expr ;} => { $self };
}
#[cfg(not(no_global_oom_handling))]
macro_rules! to_string_str {
{$($($x:ident)*),+} => {
$(
#[doc(hidden)]
#[stable(feature = "str_to_string_specialization", since = "1.9.0")]
impl ToString for to_string_str_wrap_in_ref!($($x)*) {
#[inline]
fn to_string(&self) -> String {
String::from(to_string_expr_wrap_in_deref!(self ; $($x)*))
}
}
)+
};
}
#[cfg(not(no_global_oom_handling))]
to_string_str! {
x x x x x x x x x x x x,
x x x x x x x x x x x,
x x x x x x x x x x,
x x x x x x x x x,
x x x x x x x x,
x x x x x x x,
x x x x x x,
x x x x x,
x x x x,
x x x,
x x,
x,
}
#[doc(hidden)]

View File

@ -1626,6 +1626,11 @@ impl<'a> Formatter<'a> {
self.buf.write_str(data)
}
/// Glue for usage of the [`write!`] macro with implementors of this trait.
///
/// This method should generally not be invoked manually, but rather through
/// the [`write!`] macro itself.
///
/// Writes some formatted information into this instance.
///
/// # Examples

View File

@ -57,6 +57,9 @@ object = { version = "0.36.0", default-features = false, optional = true, featur
'archive',
] }
[target.'cfg(windows)'.dependencies.windows-targets]
path = "../windows_targets"
[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
rand_xorshift = "0.3.0"
@ -116,7 +119,7 @@ std_detect_env_override = ["std_detect/std_detect_env_override"]
# Enable using raw-dylib for Windows imports.
# This will eventually be the default.
windows_raw_dylib = []
windows_raw_dylib = ["windows-targets/windows_raw_dylib"]
[package.metadata.fortanix-sgx]
# Maximum possible number of threads when testing

View File

@ -4,7 +4,7 @@ use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ffi::c_void;
use crate::ptr;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys::c::{self, windows_targets};
use crate::sys::c;
use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};
#[cfg(test)]

View File

@ -8,8 +8,6 @@
use core::ffi::{c_uint, c_ulong, c_ushort, c_void, CStr};
use core::{mem, ptr};
pub(super) mod windows_targets;
mod windows_sys;
pub use windows_sys::*;

View File

@ -3317,4 +3317,3 @@ pub struct WSADATA {
#[cfg(target_arch = "arm")]
pub enum CONTEXT {}
// ignore-tidy-filelength
use super::windows_targets;

View File

@ -0,0 +1,10 @@
[package]
name = "windows-targets"
description = "A drop-in replacement for the real windows-targets crate for use in std only."
version = "0.0.0"
edition = "2021"
[features]
# Enable using raw-dylib for Windows imports.
# This will eventually be the default.
windows_raw_dylib = []

View File

@ -2,6 +2,10 @@
//!
//! This is a simple wrapper around an `extern` block with a `#[link]` attribute.
//! It's very roughly equivalent to the windows-targets crate.
#![no_std]
#![no_core]
#![feature(decl_macro)]
#![feature(no_core)]
#[cfg(feature = "windows_raw_dylib")]
pub macro link {

View File

@ -35,7 +35,6 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut f = std::fs::File::options().append(true).open("windows_sys.rs")?;
f.write_all(ARM32_SHIM.as_bytes())?;
writeln!(&mut f, "// ignore-tidy-filelength")?;
writeln!(&mut f, "use super::windows_targets;")?;
Ok(())
}

View File

@ -48,6 +48,12 @@ pub fn llvm_bcanalyzer() -> LlvmBcanalyzer {
LlvmBcanalyzer::new()
}
/// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available
/// at `$LLVM_BIN_DIR/llvm-dwarfdump`.
pub fn llvm_dwarfdump() -> LlvmDwarfdump {
LlvmDwarfdump::new()
}
/// A `llvm-readobj` invocation builder.
#[derive(Debug)]
#[must_use]
@ -97,6 +103,13 @@ pub struct LlvmBcanalyzer {
cmd: Command,
}
/// A `llvm-dwarfdump` invocation builder.
#[derive(Debug)]
#[must_use]
pub struct LlvmDwarfdump {
cmd: Command,
}
crate::macros::impl_common_helpers!(LlvmReadobj);
crate::macros::impl_common_helpers!(LlvmProfdata);
crate::macros::impl_common_helpers!(LlvmFilecheck);
@ -104,6 +117,7 @@ crate::macros::impl_common_helpers!(LlvmObjdump);
crate::macros::impl_common_helpers!(LlvmAr);
crate::macros::impl_common_helpers!(LlvmNm);
crate::macros::impl_common_helpers!(LlvmBcanalyzer);
crate::macros::impl_common_helpers!(LlvmDwarfdump);
/// Generate the path to the bin directory of LLVM.
#[must_use]
@ -317,3 +331,19 @@ impl LlvmBcanalyzer {
self
}
}
impl LlvmDwarfdump {
/// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available
/// at `$LLVM_BIN_DIR/llvm-dwarfdump`.
pub fn new() -> Self {
let llvm_dwarfdump = llvm_bin_dir().join("llvm-dwarfdump");
let cmd = Command::new(llvm_dwarfdump);
Self { cmd }
}
/// Provide an input file.
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg(path.as_ref());
self
}
}

View File

@ -49,8 +49,9 @@ pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_nativ
pub use clang::{clang, Clang};
pub use htmldocck::htmldocck;
pub use llvm::{
llvm_ar, llvm_bcanalyzer, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj,
LlvmAr, LlvmBcanalyzer, LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj,
llvm_ar, llvm_bcanalyzer, llvm_dwarfdump, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata,
llvm_readobj, LlvmAr, LlvmBcanalyzer, LlvmDwarfdump, LlvmFilecheck, LlvmNm, LlvmObjdump,
LlvmProfdata, LlvmReadobj,
};
pub use python::python_command;
pub use rustc::{aux_build, bare_rustc, rustc, Rustc};

View File

@ -16,7 +16,6 @@ run-make/macos-deployment-target/Makefile
run-make/min-global-align/Makefile
run-make/native-link-modifier-bundle/Makefile
run-make/no-alloc-shim/Makefile
run-make/remap-path-prefix-dwarf/Makefile
run-make/reproducible-build/Makefile
run-make/rlib-format-packed-bundled-libs/Makefile
run-make/split-debuginfo/Makefile

View File

@ -36,6 +36,7 @@ use crate::walk::{filter_dirs, walk};
// Paths that may contain platform-specific code.
const EXCEPTION_PATHS: &[&str] = &[
"library/windows_targets",
"library/panic_abort",
"library/panic_unwind",
"library/unwind",

View File

@ -0,0 +1,36 @@
//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled
#![crate_type = "lib"]
//! Make sure str::to_string is specialized not to use fmt machinery.
// CHECK-LABEL: define {{(dso_local )?}}void @one_ref
#[no_mangle]
pub fn one_ref(input: &str) -> String {
// CHECK-NOT: {{(call|invoke).*}}fmt
input.to_string()
}
// CHECK-LABEL: define {{(dso_local )?}}void @two_ref
#[no_mangle]
pub fn two_ref(input: &&str) -> String {
// CHECK-NOT: {{(call|invoke).*}}fmt
input.to_string()
}
// CHECK-LABEL: define {{(dso_local )?}}void @thirteen_ref
#[no_mangle]
pub fn thirteen_ref(input: &&&&&&&&&&&&&str) -> String {
// CHECK-NOT: {{(call|invoke).*}}fmt
input.to_string()
}
// This is a known performance cliff because of the macro-generated
// specialized impl. If this test suddenly starts failing,
// consider removing the `to_string_str!` macro in `alloc/str/string.rs`.
//
// CHECK-LABEL: define {{(dso_local )?}}void @fourteen_ref
#[no_mangle]
pub fn fourteen_ref(input: &&&&&&&&&&&&&&str) -> String {
// CHECK: {{(call|invoke).*}}fmt
input.to_string()
}

View File

@ -1,112 +0,0 @@
# This test makes sure that --remap-path-prefix has the expected effects on paths in debuginfo.
# It tests several cases, each of them has a detailed description attached to it.
# ignore-windows
include ../tools.mk
SRC_DIR := $(abspath .)
SRC_DIR_PARENT := $(abspath ..)
ifeq ($(UNAME),Darwin)
DEBUGINFOOPTS := -Csplit-debuginfo=off
else
DEBUGINFOOPTS :=
endif
all: \
abs_input_outside_working_dir \
rel_input_remap_working_dir \
rel_input_remap_working_dir_scope \
rel_input_remap_working_dir_parent \
rel_input_remap_working_dir_child \
rel_input_remap_working_dir_diagnostics \
abs_input_inside_working_dir \
abs_input_inside_working_dir_scope \
abs_input_outside_working_dir
# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within
# the working directory of the compiler. We are remapping the path that contains `src`.
abs_input_inside_working_dir:
# We explicitly switch to a directory that *is* a prefix of the directory our
# source code is contained in.
cd $(SRC_DIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_inside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED
# We expect the path to the main source file to be remapped.
"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs"
# No weird duplication of remapped components (see #78479)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within
# the working directory of the compiler. We are remapping the path that contains `src`.
abs_input_inside_working_dir_scope:
# We explicitly switch to a directory that *is* a prefix of the directory our
# source code is contained in.
cd $(SRC_DIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_inside_working_dir_scope.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED -Zremap-path-scope=object $(DEBUGINFOOPTS)
# We expect the path to the main source file to be remapped.
"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir_scope.rlib | $(CGREP) "REMAPPED/src/quux.rs"
# No weird duplication of remapped components (see #78479)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir_scope.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path is *not* within
# the working directory of the compiler. We are remapping both the path that contains `src` and
# the working directory to the same thing. This setup corresponds to a workaround that is needed
# when trying to remap everything to something that looks like a local path.
# Relative paths are interpreted as relative to the compiler's working directory (e.g. in
# debuginfo). If we also remap the working directory, the compiler strip it from other paths so
# that the final outcome is the desired one again.
abs_input_outside_working_dir:
# We explicitly switch to a directory that is *not* a prefix of the directory our
# source code is contained in.
cd $(TMPDIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_outside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED --remap-path-prefix $(TMPDIR)=REMAPPED
"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs"
# No weird duplication of remapped components (see #78479)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
# The compiler is called with a *RELATIVE PATH* as input. We are remapping the working directory of
# the compiler, which naturally is an implicit prefix of our relative input path. Debuginfo will
# expand the relative path to an absolute path and we expect the working directory to be remapped
# in that expansion.
rel_input_remap_working_dir:
cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED"
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) "REMAPPED/src/quux.rs"
# No weird duplication of remapped components (see #78479)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
# The compiler is called with a *RELATIVE PATH* as input. We are remapping the working directory of
# the compiler, which naturally is an implicit prefix of our relative input path. Debuginfo will
# expand the relative path to an absolute path and we expect the working directory to be remapped
# in that expansion.
rel_input_remap_working_dir_scope:
cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED" -Zremap-path-scope=object $(DEBUGINFOOPTS)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" | $(CGREP) "REMAPPED/src/quux.rs"
# No weird duplication of remapped components (see #78479)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
rel_input_remap_working_dir_diagnostics:
cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED" -Zremap-path-scope=diagnostics $(DEBUGINFOOPTS)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" | $(CGREP) -v "REMAPPED/src/quux.rs"
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_scope.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *SUB-DIRECTORY* of the
# compiler's working directory. This test makes sure that that directory is remapped even though it
# won't actually show up in this form in the compiler's SourceMap and instead is only constructed
# on demand during debuginfo generation.
rel_input_remap_working_dir_child:
cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)/src=REMAPPED"
# We expect `src/quux.rs` to have been remapped to `REMAPPED/quux.rs`.
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) "REMAPPED/quux.rs"
# We don't want to find the path that we just remapped anywhere in the DWARF
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "$(SRC_DIR)/src"
# No weird duplication of remapped components (see #78479)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *PARENT DIRECTORY* of
# the compiler's working directory.
rel_input_remap_working_dir_parent:
cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR_PARENT)=REMAPPED"
# We expect `src/quux.rs` to have been remapped to `REMAPPED/remap-path-prefix-dwarf/src/quux.rs`.
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) "REMAPPED/remap-path-prefix-dwarf/src/quux.rs"
# We don't want to find the path that we just remapped anywhere in the DWARF
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "$(SRC_DIR_PARENT)"
# No weird duplication of remapped components (see #78479)
"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"

View File

@ -0,0 +1,202 @@
// This test makes sure that --remap-path-prefix has the expected effects on paths in debuginfo.
// We explicitly switch to a directory that *is* a prefix of the directory our
// source code is contained in.
// It tests several cases, each of them has a detailed description attached to it.
// See https://github.com/rust-lang/rust/pull/96867
//@ ignore-windows
// Reason: the remap path prefix is not printed in the dwarf dump.
use run_make_support::{cwd, is_darwin, llvm_dwarfdump, rust_lib_name, rustc};
fn main() {
// The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within
// the working directory of the compiler. We are remapping the path that contains `src`.
check_dwarf(DwarfTest {
lib_name: "abs_input_inside_working_dir",
input_path: PathType::Absolute,
scope: None,
remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())),
dwarf_test: DwarfDump::ContainsSrcPath,
});
check_dwarf(DwarfTest {
lib_name: "abs_input_inside_working_dir_scope",
input_path: PathType::Absolute,
scope: Some(ScopeType::Object),
remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())),
dwarf_test: DwarfDump::ContainsSrcPath,
});
// The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path is *not*
// within the working directory of the compiler. We are remapping both the path that contains
// `src` and the working directory to the same thing. This setup corresponds to a workaround
// that is needed when trying to remap everything to something that looks like a local
// path. Relative paths are interpreted as relative to the compiler's working directory (e.g.
// in debuginfo). If we also remap the working directory, the compiler strip it from other
// paths so that the final outcome is the desired one again.
check_dwarf(DwarfTest {
lib_name: "abs_input_outside_working_dir",
input_path: PathType::Absolute,
scope: None,
remap_path_prefix: PrefixType::Dual((
format!("{}=REMAPPED", cwd().display()),
"rmake_out=REMAPPED".to_owned(),
)),
dwarf_test: DwarfDump::ContainsSrcPath,
});
// The compiler is called with a *RELATIVE PATH* as input. We are remapping the working
// directory of the compiler, which naturally is an implicit prefix of our relative input path.
// Debuginfo will expand the relative path to an absolute path and we expect the working
// directory to be remapped in that expansion.
check_dwarf(DwarfTest {
lib_name: "rel_input_remap_working_dir",
input_path: PathType::Relative,
scope: None,
remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())),
dwarf_test: DwarfDump::ContainsSrcPath,
});
check_dwarf(DwarfTest {
lib_name: "rel_input_remap_working_dir_scope",
input_path: PathType::Relative,
scope: Some(ScopeType::Object),
remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())),
dwarf_test: DwarfDump::ContainsSrcPath,
});
check_dwarf(DwarfTest {
lib_name: "rel_input_remap_working_dir_scope",
input_path: PathType::Relative,
scope: Some(ScopeType::Diagnostics),
remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())),
dwarf_test: DwarfDump::AvoidSrcPath,
});
// The compiler is called with a *RELATIVE PATH* as input. We are remapping a *SUB-DIRECTORY*
// of the compiler's working directory. This test makes sure that that directory is remapped
// even though it won't actually show up in this form in the compiler's SourceMap and instead
// is only constructed on demand during debuginfo generation.
check_dwarf(DwarfTest {
lib_name: "rel_input_remap_working_dir_child",
input_path: PathType::Relative,
scope: None,
remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().join("src").display())),
dwarf_test: DwarfDump::ChildTest,
});
// The compiler is called with a *RELATIVE PATH* as input. We are remapping a
// *PARENT DIRECTORY* of the compiler's working directory.
check_dwarf(DwarfTest {
lib_name: "rel_input_remap_working_dir_parent",
input_path: PathType::Relative,
scope: None,
remap_path_prefix: PrefixType::Regular(format!(
"{}=REMAPPED",
cwd().parent().unwrap().display()
)),
dwarf_test: DwarfDump::ParentTest,
});
}
#[track_caller]
fn check_dwarf(test: DwarfTest) {
let mut rustc = rustc();
match test.input_path {
PathType::Absolute => rustc.input(cwd().join("src/quux.rs")),
PathType::Relative => rustc.input("src/quux.rs"),
};
rustc.output(rust_lib_name(test.lib_name));
rustc.arg("-Cdebuginfo=2");
if let Some(scope) = test.scope {
match scope {
ScopeType::Object => rustc.arg("-Zremap-path-scope=object"),
ScopeType::Diagnostics => rustc.arg("-Zremap-path-scope=diagnostics"),
};
if is_darwin() {
rustc.arg("-Csplit-debuginfo=off");
}
}
match test.remap_path_prefix {
PrefixType::Regular(prefix) => {
// We explicitly switch to a directory that *is* a prefix of the directory our
// source code is contained in.
rustc.arg("--remap-path-prefix");
rustc.arg(prefix);
}
PrefixType::Dual((prefix1, prefix2)) => {
// We explicitly switch to a directory that is *not* a prefix of the directory our
// source code is contained in.
rustc.arg("--remap-path-prefix");
rustc.arg(prefix1);
rustc.arg("--remap-path-prefix");
rustc.arg(prefix2);
}
}
rustc.run();
match test.dwarf_test {
DwarfDump::ContainsSrcPath => {
llvm_dwarfdump()
.input(rust_lib_name(test.lib_name))
.run()
// We expect the path to the main source file to be remapped.
.assert_stdout_contains("REMAPPED/src/quux.rs")
// No weird duplication of remapped components (see #78479)
.assert_stdout_not_contains("REMAPPED/REMAPPED");
}
DwarfDump::AvoidSrcPath => {
llvm_dwarfdump()
.input(rust_lib_name(test.lib_name))
.run()
.assert_stdout_not_contains("REMAPPED/src/quux.rs")
.assert_stdout_not_contains("REMAPPED/REMAPPED");
}
DwarfDump::ChildTest => {
llvm_dwarfdump()
.input(rust_lib_name(test.lib_name))
.run()
// We expect `src/quux.rs` to have been remapped to `REMAPPED/quux.rs`.
.assert_stdout_contains("REMAPPED/quux.rs")
// We don't want to find the path that we just remapped anywhere in the DWARF
.assert_stdout_not_contains(cwd().join("src").to_str().unwrap())
// No weird duplication of remapped components (see #78479)
.assert_stdout_not_contains("REMAPPED/REMAPPED");
}
DwarfDump::ParentTest => {
llvm_dwarfdump()
.input(rust_lib_name(test.lib_name))
.run()
// We expect `src/quux.rs` to have been remapped to
// `REMAPPED/remap-path-prefix-dwarf/src/quux.rs`.
.assert_stdout_contains("REMAPPED/rmake_out/src/quux.rs")
// We don't want to find the path that we just remapped anywhere in the DWARF
.assert_stdout_not_contains(cwd().parent().unwrap().to_str().unwrap())
// No weird duplication of remapped components (see #78479)
.assert_stdout_not_contains("REMAPPED/REMAPPED");
}
};
}
struct DwarfTest {
lib_name: &'static str,
input_path: PathType,
scope: Option<ScopeType>,
remap_path_prefix: PrefixType,
dwarf_test: DwarfDump,
}
enum PathType {
Absolute,
Relative,
}
enum ScopeType {
Object,
Diagnostics,
}
enum DwarfDump {
ContainsSrcPath,
AvoidSrcPath,
ChildTest,
ParentTest,
}
enum PrefixType {
Regular(String),
Dual((String, String)),
}

View File

@ -14,6 +14,7 @@ LL | let y: *const dyn Trait<Y> = x as _;
|
= note: expected trait object `dyn Trait<X>`
found trait object `dyn Trait<Y>`
= help: `dyn Trait<Y>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
error[E0308]: mismatched types
--> $DIR/ptr-to-trait-obj-different-args.rs:27:34
@ -25,6 +26,7 @@ LL | let _: *const dyn Trait<T> = x as _;
|
= note: expected trait object `dyn Trait<X>`
found trait object `dyn Trait<T>`
= help: `dyn Trait<T>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
error[E0308]: mismatched types
--> $DIR/ptr-to-trait-obj-different-args.rs:28:34
@ -37,6 +39,7 @@ LL | let _: *const dyn Trait<X> = t as _;
|
= note: expected trait object `dyn Trait<T>`
found trait object `dyn Trait<X>`
= help: `dyn Trait<X>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
error[E0308]: mismatched types
--> $DIR/ptr-to-trait-obj-different-args.rs:36:5

View File

@ -42,6 +42,7 @@ LL | let _ = type_ascribe!(Box::new( if true { false } else { true }), Box<d
|
= note: expected struct `Box<dyn Debug>`
found struct `Box<bool>`
= help: `bool` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:16:27
@ -51,6 +52,7 @@ LL | let _ = type_ascribe!(Box::new( match true { true => 'a', false => 'b'
|
= note: expected struct `Box<dyn Debug>`
found struct `Box<char>`
= help: `char` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:18:27
@ -96,6 +98,7 @@ LL | let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug);
|
= note: expected reference `&dyn Debug`
found reference `&bool`
= help: `bool` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:24:27
@ -105,6 +108,7 @@ LL | let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn D
|
= note: expected reference `&dyn Debug`
found reference `&char`
= help: `char` implements `Debug` so you could box the found value and coerce it to the trait object `Box<dyn Debug>`, you will have to change the expected type as well
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:26:27

View File

@ -254,7 +254,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:279:9
--> $DIR/empty-types.rs:281:9
|
LL | _ => {}
| ^
@ -262,7 +262,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:282:9
--> $DIR/empty-types.rs:284:9
|
LL | (_, _) => {}
| ^^^^^^
@ -270,7 +270,7 @@ LL | (_, _) => {}
= note: this pattern matches no values because `(!, !)` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:285:9
--> $DIR/empty-types.rs:287:9
|
LL | Ok(_) => {}
| ^^^^^
@ -278,7 +278,7 @@ LL | Ok(_) => {}
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:286:9
--> $DIR/empty-types.rs:288:9
|
LL | Err(_) => {}
| ^^^^^^
@ -286,7 +286,7 @@ LL | Err(_) => {}
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
--> $DIR/empty-types.rs:318:11
--> $DIR/empty-types.rs:327:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
@ -300,7 +300,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: `&[]` not covered
--> $DIR/empty-types.rs:329:11
--> $DIR/empty-types.rs:338:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[]` not covered
@ -313,7 +313,7 @@ LL + &[] => todo!()
|
error[E0004]: non-exhaustive patterns: `&[]` not covered
--> $DIR/empty-types.rs:343:11
--> $DIR/empty-types.rs:352:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[]` not covered
@ -327,7 +327,7 @@ LL + &[] => todo!()
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
--> $DIR/empty-types.rs:350:11
--> $DIR/empty-types.rs:359:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
@ -341,7 +341,7 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:359:9
--> $DIR/empty-types.rs:368:9
|
LL | _ => {}
| ^
@ -349,7 +349,7 @@ LL | _ => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:362:9
--> $DIR/empty-types.rs:371:9
|
LL | [_, _, _] => {}
| ^^^^^^^^^
@ -357,7 +357,7 @@ LL | [_, _, _] => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:365:9
--> $DIR/empty-types.rs:374:9
|
LL | [_, ..] => {}
| ^^^^^^^
@ -365,7 +365,7 @@ LL | [_, ..] => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
--> $DIR/empty-types.rs:379:11
--> $DIR/empty-types.rs:388:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
@ -379,7 +379,7 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:386:9
--> $DIR/empty-types.rs:395:9
|
LL | [] => {}
| -- matches all the values already
@ -387,7 +387,7 @@ LL | _ => {}
| ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `[]` not covered
--> $DIR/empty-types.rs:388:11
--> $DIR/empty-types.rs:397:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
@ -401,7 +401,7 @@ LL + [] => todo!()
|
error: unreachable pattern
--> $DIR/empty-types.rs:407:9
--> $DIR/empty-types.rs:416:9
|
LL | Some(_) => {}
| ^^^^^^^
@ -409,7 +409,7 @@ LL | Some(_) => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:412:9
--> $DIR/empty-types.rs:421:9
|
LL | Some(_a) => {}
| ^^^^^^^^
@ -417,7 +417,7 @@ LL | Some(_a) => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:417:9
--> $DIR/empty-types.rs:426:9
|
LL | None => {}
| ---- matches all the values already
@ -426,7 +426,7 @@ LL | _ => {}
| ^ unreachable pattern
error: unreachable pattern
--> $DIR/empty-types.rs:422:9
--> $DIR/empty-types.rs:431:9
|
LL | None => {}
| ---- matches all the values already
@ -435,7 +435,7 @@ LL | _a => {}
| ^^ unreachable pattern
error: unreachable pattern
--> $DIR/empty-types.rs:594:9
--> $DIR/empty-types.rs:603:9
|
LL | _ => {}
| ^
@ -443,7 +443,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:597:9
--> $DIR/empty-types.rs:606:9
|
LL | _x => {}
| ^^
@ -451,7 +451,7 @@ LL | _x => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:600:9
--> $DIR/empty-types.rs:609:9
|
LL | _ if false => {}
| ^
@ -459,7 +459,7 @@ LL | _ if false => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:603:9
--> $DIR/empty-types.rs:612:9
|
LL | _x if false => {}
| ^^

View File

@ -296,7 +296,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:279:9
--> $DIR/empty-types.rs:281:9
|
LL | _ => {}
| ^
@ -304,7 +304,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:282:9
--> $DIR/empty-types.rs:284:9
|
LL | (_, _) => {}
| ^^^^^^
@ -312,7 +312,7 @@ LL | (_, _) => {}
= note: this pattern matches no values because `(!, !)` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:285:9
--> $DIR/empty-types.rs:287:9
|
LL | Ok(_) => {}
| ^^^^^
@ -320,15 +320,29 @@ LL | Ok(_) => {}
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:286:9
--> $DIR/empty-types.rs:288:9
|
LL | Err(_) => {}
| ^^^^^^
|
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error[E0005]: refutable pattern in local binding
--> $DIR/empty-types.rs:297:13
|
LL | let Ok(_) = *ptr_result_never_err;
| ^^^^^ pattern `Err(!)` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `Result<u8, !>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | if let Ok(_) = *ptr_result_never_err { todo!() };
| ++ +++++++++++
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:307:11
--> $DIR/empty-types.rs:316:11
|
LL | match *x {}
| ^^
@ -342,7 +356,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
--> $DIR/empty-types.rs:309:11
--> $DIR/empty-types.rs:318:11
|
LL | match *x {}
| ^^
@ -356,7 +370,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: `Ok(!)` and `Err(!)` not covered
--> $DIR/empty-types.rs:311:11
--> $DIR/empty-types.rs:320:11
|
LL | match *x {}
| ^^ patterns `Ok(!)` and `Err(!)` not covered
@ -378,7 +392,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
--> $DIR/empty-types.rs:313:11
--> $DIR/empty-types.rs:322:11
|
LL | match *x {}
| ^^
@ -392,7 +406,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
--> $DIR/empty-types.rs:318:11
--> $DIR/empty-types.rs:327:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
@ -406,7 +420,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: `&[!, ..]` not covered
--> $DIR/empty-types.rs:320:11
--> $DIR/empty-types.rs:329:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[!, ..]` not covered
@ -420,7 +434,7 @@ LL + &[!, ..]
|
error[E0004]: non-exhaustive patterns: `&[]`, `&[!]` and `&[!, !]` not covered
--> $DIR/empty-types.rs:329:11
--> $DIR/empty-types.rs:338:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]`, `&[!]` and `&[!, !]` not covered
@ -433,7 +447,7 @@ LL + &[] | &[!] | &[!, !] => todo!()
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[!, ..]` not covered
--> $DIR/empty-types.rs:343:11
--> $DIR/empty-types.rs:352:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]` and `&[!, ..]` not covered
@ -447,7 +461,7 @@ LL + &[] | &[!, ..] => todo!()
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
--> $DIR/empty-types.rs:350:11
--> $DIR/empty-types.rs:359:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
@ -461,7 +475,7 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:359:9
--> $DIR/empty-types.rs:368:9
|
LL | _ => {}
| ^
@ -469,7 +483,7 @@ LL | _ => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:362:9
--> $DIR/empty-types.rs:371:9
|
LL | [_, _, _] => {}
| ^^^^^^^^^
@ -477,7 +491,7 @@ LL | [_, _, _] => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:365:9
--> $DIR/empty-types.rs:374:9
|
LL | [_, ..] => {}
| ^^^^^^^
@ -485,7 +499,7 @@ LL | [_, ..] => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
--> $DIR/empty-types.rs:379:11
--> $DIR/empty-types.rs:388:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
@ -499,7 +513,7 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:386:9
--> $DIR/empty-types.rs:395:9
|
LL | [] => {}
| -- matches all the values already
@ -507,7 +521,7 @@ LL | _ => {}
| ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `[]` not covered
--> $DIR/empty-types.rs:388:11
--> $DIR/empty-types.rs:397:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
@ -521,7 +535,7 @@ LL + [] => todo!()
|
error: unreachable pattern
--> $DIR/empty-types.rs:407:9
--> $DIR/empty-types.rs:416:9
|
LL | Some(_) => {}
| ^^^^^^^
@ -529,7 +543,7 @@ LL | Some(_) => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:412:9
--> $DIR/empty-types.rs:421:9
|
LL | Some(_a) => {}
| ^^^^^^^^
@ -537,7 +551,7 @@ LL | Some(_a) => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:417:9
--> $DIR/empty-types.rs:426:9
|
LL | None => {}
| ---- matches all the values already
@ -546,7 +560,7 @@ LL | _ => {}
| ^ unreachable pattern
error: unreachable pattern
--> $DIR/empty-types.rs:422:9
--> $DIR/empty-types.rs:431:9
|
LL | None => {}
| ---- matches all the values already
@ -555,7 +569,7 @@ LL | _a => {}
| ^^ unreachable pattern
error[E0004]: non-exhaustive patterns: `&Some(!)` not covered
--> $DIR/empty-types.rs:442:11
--> $DIR/empty-types.rs:451:11
|
LL | match ref_opt_never {
| ^^^^^^^^^^^^^ pattern `&Some(!)` not covered
@ -574,7 +588,7 @@ LL + &Some(!)
|
error[E0004]: non-exhaustive patterns: `Some(!)` not covered
--> $DIR/empty-types.rs:483:11
--> $DIR/empty-types.rs:492:11
|
LL | match *ref_opt_never {
| ^^^^^^^^^^^^^^ pattern `Some(!)` not covered
@ -593,7 +607,7 @@ LL + Some(!)
|
error[E0004]: non-exhaustive patterns: `Err(!)` not covered
--> $DIR/empty-types.rs:531:11
--> $DIR/empty-types.rs:540:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(!)` not covered
@ -612,7 +626,7 @@ LL + Err(!)
|
error[E0004]: non-exhaustive patterns: `Err(!)` not covered
--> $DIR/empty-types.rs:542:11
--> $DIR/empty-types.rs:551:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(!)` not covered
@ -631,7 +645,7 @@ LL + Err(!)
|
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:561:11
--> $DIR/empty-types.rs:570:11
|
LL | match *ref_tuple_half_never {}
| ^^^^^^^^^^^^^^^^^^^^^
@ -645,7 +659,7 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:594:9
--> $DIR/empty-types.rs:603:9
|
LL | _ => {}
| ^
@ -653,7 +667,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:597:9
--> $DIR/empty-types.rs:606:9
|
LL | _x => {}
| ^^
@ -661,7 +675,7 @@ LL | _x => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:600:9
--> $DIR/empty-types.rs:609:9
|
LL | _ if false => {}
| ^
@ -669,7 +683,7 @@ LL | _ if false => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:603:9
--> $DIR/empty-types.rs:612:9
|
LL | _x if false => {}
| ^^
@ -677,7 +691,7 @@ LL | _x if false => {}
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: `&!` not covered
--> $DIR/empty-types.rs:628:11
--> $DIR/empty-types.rs:637:11
|
LL | match ref_never {
| ^^^^^^^^^ pattern `&!` not covered
@ -693,7 +707,7 @@ LL + &!
|
error[E0004]: non-exhaustive patterns: `Ok(!)` not covered
--> $DIR/empty-types.rs:644:11
--> $DIR/empty-types.rs:653:11
|
LL | match *ref_result_never {
| ^^^^^^^^^^^^^^^^^ pattern `Ok(!)` not covered
@ -712,7 +726,7 @@ LL + Ok(!)
|
error[E0004]: non-exhaustive patterns: `Some(!)` not covered
--> $DIR/empty-types.rs:664:11
--> $DIR/empty-types.rs:673:11
|
LL | match *x {
| ^^ pattern `Some(!)` not covered
@ -730,7 +744,7 @@ LL ~ None => {},
LL + Some(!)
|
error: aborting due to 64 previous errors; 1 warning emitted
error: aborting due to 65 previous errors; 1 warning emitted
Some errors have detailed explanations: E0004, E0005.
For more information about an error, try `rustc --explain E0004`.

View File

@ -287,7 +287,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:279:9
--> $DIR/empty-types.rs:281:9
|
LL | _ => {}
| ^
@ -295,7 +295,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:282:9
--> $DIR/empty-types.rs:284:9
|
LL | (_, _) => {}
| ^^^^^^
@ -303,7 +303,7 @@ LL | (_, _) => {}
= note: this pattern matches no values because `(!, !)` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:285:9
--> $DIR/empty-types.rs:287:9
|
LL | Ok(_) => {}
| ^^^^^
@ -311,15 +311,29 @@ LL | Ok(_) => {}
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:286:9
--> $DIR/empty-types.rs:288:9
|
LL | Err(_) => {}
| ^^^^^^
|
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error[E0005]: refutable pattern in local binding
--> $DIR/empty-types.rs:297:13
|
LL | let Ok(_) = *ptr_result_never_err;
| ^^^^^ pattern `Err(_)` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `Result<u8, !>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | if let Ok(_) = *ptr_result_never_err { todo!() };
| ++ +++++++++++
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:307:11
--> $DIR/empty-types.rs:316:11
|
LL | match *x {}
| ^^
@ -333,7 +347,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
--> $DIR/empty-types.rs:309:11
--> $DIR/empty-types.rs:318:11
|
LL | match *x {}
| ^^
@ -347,7 +361,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
--> $DIR/empty-types.rs:311:11
--> $DIR/empty-types.rs:320:11
|
LL | match *x {}
| ^^ patterns `Ok(_)` and `Err(_)` not covered
@ -369,7 +383,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
--> $DIR/empty-types.rs:313:11
--> $DIR/empty-types.rs:322:11
|
LL | match *x {}
| ^^
@ -383,7 +397,7 @@ LL ~ }
|
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
--> $DIR/empty-types.rs:318:11
--> $DIR/empty-types.rs:327:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
@ -397,7 +411,7 @@ LL + }
|
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
--> $DIR/empty-types.rs:320:11
--> $DIR/empty-types.rs:329:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[_, ..]` not covered
@ -411,7 +425,7 @@ LL + &[_, ..] => todo!()
|
error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered
--> $DIR/empty-types.rs:329:11
--> $DIR/empty-types.rs:338:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered
@ -424,7 +438,7 @@ LL + &[] | &[_] | &[_, _] => todo!()
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
--> $DIR/empty-types.rs:343:11
--> $DIR/empty-types.rs:352:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
@ -438,7 +452,7 @@ LL + &[] | &[_, ..] => todo!()
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
--> $DIR/empty-types.rs:350:11
--> $DIR/empty-types.rs:359:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
@ -452,7 +466,7 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:359:9
--> $DIR/empty-types.rs:368:9
|
LL | _ => {}
| ^
@ -460,7 +474,7 @@ LL | _ => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:362:9
--> $DIR/empty-types.rs:371:9
|
LL | [_, _, _] => {}
| ^^^^^^^^^
@ -468,7 +482,7 @@ LL | [_, _, _] => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:365:9
--> $DIR/empty-types.rs:374:9
|
LL | [_, ..] => {}
| ^^^^^^^
@ -476,7 +490,7 @@ LL | [_, ..] => {}
= note: this pattern matches no values because `[!; 3]` is uninhabited
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
--> $DIR/empty-types.rs:379:11
--> $DIR/empty-types.rs:388:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
@ -490,7 +504,7 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:386:9
--> $DIR/empty-types.rs:395:9
|
LL | [] => {}
| -- matches all the values already
@ -498,7 +512,7 @@ LL | _ => {}
| ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `[]` not covered
--> $DIR/empty-types.rs:388:11
--> $DIR/empty-types.rs:397:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
@ -512,7 +526,7 @@ LL + [] => todo!()
|
error: unreachable pattern
--> $DIR/empty-types.rs:407:9
--> $DIR/empty-types.rs:416:9
|
LL | Some(_) => {}
| ^^^^^^^
@ -520,7 +534,7 @@ LL | Some(_) => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:412:9
--> $DIR/empty-types.rs:421:9
|
LL | Some(_a) => {}
| ^^^^^^^^
@ -528,7 +542,7 @@ LL | Some(_a) => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:417:9
--> $DIR/empty-types.rs:426:9
|
LL | None => {}
| ---- matches all the values already
@ -537,7 +551,7 @@ LL | _ => {}
| ^ unreachable pattern
error: unreachable pattern
--> $DIR/empty-types.rs:422:9
--> $DIR/empty-types.rs:431:9
|
LL | None => {}
| ---- matches all the values already
@ -546,7 +560,7 @@ LL | _a => {}
| ^^ unreachable pattern
error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
--> $DIR/empty-types.rs:442:11
--> $DIR/empty-types.rs:451:11
|
LL | match ref_opt_never {
| ^^^^^^^^^^^^^ pattern `&Some(_)` not covered
@ -565,7 +579,7 @@ LL + &Some(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:483:11
--> $DIR/empty-types.rs:492:11
|
LL | match *ref_opt_never {
| ^^^^^^^^^^^^^^ pattern `Some(_)` not covered
@ -584,7 +598,7 @@ LL + Some(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/empty-types.rs:531:11
--> $DIR/empty-types.rs:540:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@ -603,7 +617,7 @@ LL + Err(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/empty-types.rs:542:11
--> $DIR/empty-types.rs:551:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@ -622,7 +636,7 @@ LL + Err(_) => todo!()
|
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
--> $DIR/empty-types.rs:561:11
--> $DIR/empty-types.rs:570:11
|
LL | match *ref_tuple_half_never {}
| ^^^^^^^^^^^^^^^^^^^^^
@ -636,7 +650,7 @@ LL + }
|
error: unreachable pattern
--> $DIR/empty-types.rs:594:9
--> $DIR/empty-types.rs:603:9
|
LL | _ => {}
| ^
@ -644,7 +658,7 @@ LL | _ => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:597:9
--> $DIR/empty-types.rs:606:9
|
LL | _x => {}
| ^^
@ -652,7 +666,7 @@ LL | _x => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:600:9
--> $DIR/empty-types.rs:609:9
|
LL | _ if false => {}
| ^
@ -660,7 +674,7 @@ LL | _ if false => {}
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
--> $DIR/empty-types.rs:603:9
--> $DIR/empty-types.rs:612:9
|
LL | _x if false => {}
| ^^
@ -668,7 +682,7 @@ LL | _x if false => {}
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: `&_` not covered
--> $DIR/empty-types.rs:628:11
--> $DIR/empty-types.rs:637:11
|
LL | match ref_never {
| ^^^^^^^^^ pattern `&_` not covered
@ -684,7 +698,7 @@ LL + &_ => todo!()
|
error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
--> $DIR/empty-types.rs:644:11
--> $DIR/empty-types.rs:653:11
|
LL | match *ref_result_never {
| ^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@ -703,7 +717,7 @@ LL + Ok(_) => todo!()
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/empty-types.rs:664:11
--> $DIR/empty-types.rs:673:11
|
LL | match *x {
| ^^ pattern `Some(_)` not covered
@ -721,7 +735,7 @@ LL ~ None => {},
LL + Some(_) => todo!()
|
error: aborting due to 64 previous errors
error: aborting due to 65 previous errors
Some errors have detailed explanations: E0004, E0005.
For more information about an error, try `rustc --explain E0004`.

View File

@ -17,7 +17,7 @@
#[derive(Copy, Clone)]
enum Void {}
/// A bunch of never situations that can't be normally constructed.
/// A bunch of never situations that can't be normally constructed so we take them as argument.
#[derive(Copy, Clone)]
struct NeverBundle {
never: !,
@ -272,6 +272,8 @@ fn nested_validity_tracking(bundle: NeverBundle) {
let ref_never: &! = &never;
let tuple_never: (!, !) = bundle.tuple_never;
let result_never: Result<!, !> = bundle.result_never;
let result_never_err: Result<u8, !> = Ok(0);
let ptr_result_never_err: *const Result<u8, !> = &result_never_err as *const _;
let union_never = Uninit::<!>::new();
// These should be considered known_valid and warn unreachable.
@ -287,6 +289,13 @@ fn nested_validity_tracking(bundle: NeverBundle) {
}
// These should be considered !known_valid and not warn unreachable.
unsafe {
match *ptr_result_never_err {
Ok(_) => {}
Err(_) => {}
}
let Ok(_) = *ptr_result_never_err; //[normal,never_pats]~ ERROR refutable pattern
}
match ref_never {
&_ => {}
}