name = "error_index_generator"
version = "0.0.0"
dependencies = [
- "rustdoc",
+ "mdbook",
]
[[package]]
"rustc-std-workspace-core",
]
+[[package]]
+name = "libffi"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
+dependencies = [
+ "libc",
+ "libffi-sys",
+]
+
+[[package]]
+name = "libffi-sys"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "libgit2-sys"
version = "0.14.0+1.5.0"
"getrandom 0.2.0",
"lazy_static",
"libc",
+ "libffi",
"libloading",
"log",
"measureme",
"rustc_macros",
"rustc_serialize",
"rustc_span",
+ "rustc_target",
"serde",
"serde_json",
"termcolor",
ast::ItemKind::GlobalAsm(ref asm) => {
self.head(visibility_qualified(&item.vis, "global_asm!"));
self.print_inline_asm(asm);
+ self.word(";");
+ self.end();
self.end();
}
ast::ItemKind::TyAlias(box ast::TyAlias {
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
+/// The version placeholder that recently stabilized features contain inside the
+/// `since` field of the `#[stable]` attribute.
+///
+/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
+pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
+
pub fn is_builtin_attr(attr: &Attribute) -> bool {
attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
}
}
}
+ if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
+ let version = option_env!("CFG_VERSION").unwrap_or("<current>");
+ let version = version.split(' ').next().unwrap();
+ since = Some(Symbol::intern(&version));
+ }
+
match (feature, since) {
(Some(feature), Some(since)) => {
let level = Stable { since, allowed_through_unstable_modules: false };
use rustc_hir::LangItem;
use rustc_middle::ty::subst::GenericArg;
use rustc_middle::ty::AssocKind;
-use rustc_session::config::EntryFnType;
+use rustc_session::config::{sigpipe, EntryFnType};
use rustc_span::symbol::Ident;
use crate::prelude::*;
is_jit: bool,
is_primary_cgu: bool,
) {
- let (main_def_id, is_main_fn) = match tcx.entry_fn(()) {
+ let (main_def_id, (is_main_fn, sigpipe)) = match tcx.entry_fn(()) {
Some((def_id, entry_ty)) => (
def_id,
match entry_ty {
- EntryFnType::Main => true,
- EntryFnType::Start => false,
+ EntryFnType::Main { sigpipe } => (true, sigpipe),
+ EntryFnType::Start => (false, sigpipe::DEFAULT),
},
),
None => return,
return;
}
- create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn);
+ create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn, sigpipe);
fn create_entry_fn(
tcx: TyCtxt<'_>,
rust_main_def_id: DefId,
ignore_lang_start_wrapper: bool,
is_main_fn: bool,
+ sigpipe: u8,
) {
let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
// Given that `main()` has no arguments,
bcx.switch_to_block(block);
let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type());
let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());
+ let arg_sigpipe = bcx.ins().iconst(types::I8, sigpipe as i64);
let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);
let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);
let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
- let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]);
+ let call_inst =
+ bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv, arg_sigpipe]);
bcx.inst_results(call_inst)[0]
} else {
// using user-defined start fn
// only the linker flavor is known; use the default linker for the selected flavor
(None, Some(flavor)) => Some((
PathBuf::from(match flavor {
- LinkerFlavor::Em => {
- if cfg!(windows) {
- "emcc.bat"
- } else {
- "emcc"
- }
- }
LinkerFlavor::Gcc => {
if cfg!(any(target_os = "solaris", target_os = "illumos")) {
// On historical Solaris systems, "cc" may have
}
}
LinkerFlavor::Ld => "ld",
- LinkerFlavor::Msvc => "link.exe",
LinkerFlavor::Lld(_) => "lld",
- LinkerFlavor::PtxLinker => "rust-ptx-linker",
- LinkerFlavor::BpfLinker => "bpf-linker",
- LinkerFlavor::L4Bender => "l4-bender",
+ LinkerFlavor::Msvc => "link.exe",
+ LinkerFlavor::EmCc => {
+ if cfg!(windows) {
+ "emcc.bat"
+ } else {
+ "emcc"
+ }
+ }
+ LinkerFlavor::Bpf => "bpf-linker",
+ LinkerFlavor::Ptx => "rust-ptx-linker",
}),
flavor,
)),
});
let flavor = if stem == "emcc" {
- LinkerFlavor::Em
+ LinkerFlavor::EmCc
} else if stem == "gcc"
|| stem.ends_with("-gcc")
|| stem == "clang"
// linker and linker flavor specified via command line have precedence over what the target
// specification specifies
- if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), sess.opts.cg.linker_flavor) {
+ let linker_flavor = sess.opts.cg.linker_flavor.map(LinkerFlavor::from_cli);
+ if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) {
return ret;
}
});
}
- if flavor == LinkerFlavor::PtxLinker {
+ if flavor == LinkerFlavor::Ptx {
// Provide the linker with fallback to internal `target-cpu`.
cmd.arg("--fallback-arch");
cmd.arg(&codegen_results.crate_info.target_cpu);
- } else if flavor == LinkerFlavor::BpfLinker {
+ } else if flavor == LinkerFlavor::Bpf {
cmd.arg("--cpu");
cmd.arg(&codegen_results.crate_info.target_cpu);
cmd.arg("--cpu-features");
if let LinkerFlavor::Gcc = flavor {
match ld_impl {
LdImpl::Lld => {
- let tools_path = sess.get_tools_search_paths(false);
- let gcc_ld_dir = tools_path
- .into_iter()
- .map(|p| p.join("gcc-ld"))
- .find(|p| {
- p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists()
- })
- .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
- cmd.arg({
- let mut arg = OsString::from("-B");
- arg.push(gcc_ld_dir);
- arg
- });
- cmd.arg(format!("-Wl,-rustc-lld-flavor={}", sess.target.lld_flavor.as_str()));
+ // Implement the "self-contained" part of -Zgcc-ld
+ // by adding rustc distribution directories to the tool search path.
+ for path in sess.get_tools_search_paths(false) {
+ cmd.arg({
+ let mut arg = OsString::from("-B");
+ arg.push(path.join("gcc-ld"));
+ arg
+ });
+ }
+ // Implement the "linker flavor" part of -Zgcc-ld
+ // by asking cc to use some kind of lld.
+ cmd.arg("-fuse-ld=lld");
+ if sess.target.lld_flavor != LldFlavor::Ld {
+ // Tell clang to use a non-default LLD flavor.
+ // Gcc doesn't understand the target option, but we currently assume
+ // that gcc is not used for Apple and Wasm targets (#97402).
+ cmd.arg(format!("--target={}", sess.target.llvm_target));
+ }
}
}
} else {
// to the linker args construction.
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
match flavor {
- LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
- Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
- }
- LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::Gcc => {
Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false })
as Box<dyn Linker>
}
-
+ LinkerFlavor::Ld if sess.target.os == "l4re" => {
+ Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
+ }
LinkerFlavor::Lld(LldFlavor::Ld)
| LinkerFlavor::Lld(LldFlavor::Ld64)
| LinkerFlavor::Ld => {
Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true })
as Box<dyn Linker>
}
-
+ LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
+ Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
+ }
LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
-
- LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
-
- LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
-
- LinkerFlavor::L4Bender => Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>,
+ LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
+ LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
+ LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
}
}
let main_llfn = cx.get_fn_addr(instance);
- let use_start_lang_item = EntryFnType::Start != entry_type;
- let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item);
+ let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, entry_type);
return Some(entry_fn);
fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
rust_main: Bx::Value,
rust_main_def_id: DefId,
- use_start_lang_item: bool,
+ entry_type: EntryFnType,
) -> Bx::Function {
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
// depending on whether the target needs `argc` and `argv` to be passed in.
let i8pp_ty = cx.type_ptr_to(cx.type_i8p());
let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
- let (start_fn, start_ty, args) = if use_start_lang_item {
+ let (start_fn, start_ty, args) = if let EntryFnType::Main { sigpipe } = entry_type {
let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
let start_fn = cx.get_fn_addr(
ty::Instance::resolve(
.unwrap()
.unwrap(),
);
- let start_ty = cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty], isize_ty);
- (start_fn, start_ty, vec![rust_main, arg_argc, arg_argv])
+
+ let i8_ty = cx.type_i8();
+ let arg_sigpipe = bx.const_u8(sigpipe);
+
+ let start_ty =
+ cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty, i8_ty], isize_ty);
+ (start_fn, start_ty, vec![rust_main, arg_argc, arg_argv, arg_sigpipe])
} else {
debug!("using user-defined start fn");
let start_ty = cx.type_func(&[isize_ty, i8pp_ty], isize_ty);
//! to be const-safe.
use std::convert::TryFrom;
-use std::fmt::Write;
+use std::fmt::{Display, Write};
use std::num::NonZeroUsize;
use rustc_ast::Mutability;
fn read_immediate(
&self,
op: &OpTy<'tcx, M::Provenance>,
- expected: &str,
+ expected: impl Display,
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
Ok(try_validation!(
self.ecx.read_immediate(op),
fn read_scalar(
&self,
op: &OpTy<'tcx, M::Provenance>,
- expected: &str,
+ expected: impl Display,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
Ok(self.read_immediate(op, expected)?.to_scalar())
}
value: &OpTy<'tcx, M::Provenance>,
kind: &str,
) -> InterpResult<'tcx> {
- let place = self.ecx.ref_to_mplace(&self.read_immediate(value, &format!("a {kind}"))?)?;
+ let place =
+ self.ecx.ref_to_mplace(&self.read_immediate(value, format_args!("a {kind}"))?)?;
// Handle wide pointers.
// Check metadata early, for better diagnostics
if place.layout.is_unsized() {
if (src, dest).has_opaque_types() {
return true;
}
- // Normalize projections and things like that.
- let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
- let src = self.tcx.normalize_erasing_regions(param_env, src);
- let dest = self.tcx.normalize_erasing_regions(param_env, dest);
+ // Normalize projections and things like that.
// Type-changing assignments can happen when subtyping is used. While
// all normal lifetimes are erased, higher-ranked types with their
// late-bound lifetimes are still around and can lead to type
// differences. So we compare ignoring lifetimes.
- equal_up_to_regions(self.tcx, param_env, src, dest)
+
+ // First, try with reveal_all. This might not work in some cases, as the predicates
+ // can be cleared in reveal_all mode. We try the reveal first anyways as it is used
+ // by some other passes like inlining as well.
+ let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
+ if equal_up_to_regions(self.tcx, param_env, src, dest) {
+ return true;
+ }
+
+ // If this fails, we can try it without the reveal.
+ equal_up_to_regions(self.tcx, self.param_env, src, dest)
}
}
.suggestion = consider restricting its visibility
.help = or consider exporting it for use by other crates
+lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
+ .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
+
+lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
+ .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
+
lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
--- /dev/null
+metadata_rlib_required =
+ crate `{$crate_name}` required to be available in rlib format, but was not found in this form
+
+metadata_lib_required =
+ crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+
+metadata_crate_dep_multiple =
+ cannot satisfy dependencies so `{$crate_name}` only shows up once
+ .help = having upstream crates all available in one format will likely make this go away
+
+metadata_two_panic_runtimes =
+ cannot link together two panic runtimes: {$prev_name} and {$cur_name}
+
+metadata_bad_panic_strategy =
+ the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
+
+metadata_required_panic_strategy =
+ the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_incompatible_panic_in_drop_strategy =
+ the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_multiple_names_in_link =
+ multiple `name` arguments in a single `#[link]` attribute
+
+metadata_multiple_kinds_in_link =
+ multiple `kind` arguments in a single `#[link]` attribute
+
+metadata_link_name_form =
+ link name must be of the form `name = "string"`
+
+metadata_link_kind_form =
+ link kind must be of the form `kind = "string"`
+
+metadata_link_modifiers_form =
+ link modifiers must be of the form `modifiers = "string"`
+
+metadata_link_cfg_form =
+ link cfg must be of the form `cfg(/* predicate */)`
+
+metadata_wasm_import_form =
+ wasm import module must be of the form `wasm_import_module = "string"`
+
+metadata_empty_link_name =
+ link name must not be empty
+ .label = empty link name
+
+metadata_link_framework_apple =
+ link kind `framework` is only supported on Apple targets
+
+metadata_framework_only_windows =
+ link kind `raw-dylib` is only supported on Windows targets
+
+metadata_unknown_link_kind =
+ unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
+ .label = unknown link kind
+
+metadata_multiple_link_modifiers =
+ multiple `modifiers` arguments in a single `#[link]` attribute
+
+metadata_multiple_cfgs =
+ multiple `cfg` arguments in a single `#[link]` attribute
+
+metadata_link_cfg_single_predicate =
+ link cfg must have a single predicate argument
+
+metadata_multiple_wasm_import =
+ multiple `wasm_import_module` arguments in a single `#[link]` attribute
+
+metadata_unexpected_link_arg =
+ unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
+
+metadata_invalid_link_modifier =
+ invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_multiple_modifiers =
+ multiple `{$modifier}` modifiers in a single `modifiers` argument
+
+metadata_bundle_needs_static =
+ linking modifier `bundle` is only compatible with `static` linking kind
+
+metadata_whole_archive_needs_static =
+ linking modifier `whole-archive` is only compatible with `static` linking kind
+
+metadata_as_needed_compatibility =
+ linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
+
+metadata_unknown_link_modifier =
+ unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_incompatible_wasm_link =
+ `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+
+metadata_link_requires_name =
+ `#[link]` attribute requires a `name = "string"` argument
+ .label = missing `name` argument
+
+metadata_raw_dylib_no_nul =
+ link name must not contain NUL characters if link kind is `raw-dylib`
+
+metadata_link_ordinal_raw_dylib =
+ `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+
+metadata_lib_framework_apple =
+ library kind `framework` is only supported on Apple targets
+
+metadata_empty_renaming_target =
+ an empty renaming target was specified for library `{$lib_name}`
+
+metadata_renaming_no_link =
+ renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+
+metadata_multiple_renamings =
+ multiple renamings were specified for library `{$lib_name}`
+
+metadata_no_link_mod_override =
+ overriding linking modifiers from command line is not supported
+
+metadata_unsupported_abi_i686 =
+ ABI not supported by `#[link(kind = "raw-dylib")]` on i686
+
+metadata_unsupported_abi =
+ ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+
+metadata_fail_create_file_encoder =
+ failed to create file encoder: {$err}
+
+metadata_fail_seek_file =
+ failed to seek the file: {$err}
+
+metadata_fail_write_file =
+ failed to write to the file: {$err}
+
+metadata_crate_not_panic_runtime =
+ the crate `{$crate_name}` is not a panic runtime
+
+metadata_no_panic_strategy =
+ the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
+
+metadata_profiler_builtins_needs_core =
+ `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+
+metadata_not_profiler_runtime =
+ the crate `{$crate_name}` is not a profiler runtime
+
+metadata_no_multiple_global_alloc =
+ cannot define multiple global allocators
+ .label = cannot define a new global allocator
+
+metadata_prev_global_alloc =
+ previous global allocator defined here
+
+metadata_conflicting_global_alloc =
+ the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
+
+metadata_global_alloc_required =
+ no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+
+metadata_no_transitive_needs_dep =
+ the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
+
+metadata_failed_write_error =
+ failed to write {$filename}: {$err}
+
+metadata_failed_create_tempdir =
+ couldn't create a temp dir: {$err}
+
+metadata_failed_create_file =
+ failed to create the file {$filename}: {$err}
+
+metadata_failed_create_encoded_metadata =
+ failed to create encoded metadata from file: {$err}
+
+metadata_non_ascii_name =
+ cannot load a crate with a non-ascii name `{$crate_name}`
+
+metadata_extern_location_not_exist =
+ extern location for {$crate_name} does not exist: {$location}
+
+metadata_extern_location_not_file =
+ extern location for {$crate_name} is not a file: {$location}
+
+metadata_multiple_candidates =
+ multiple {$flavor} candidates for `{$crate_name}` found
+
+metadata_multiple_matching_crates =
+ multiple matching crates for `{$crate_name}`
+ .note = candidates:{$candidates}
+
+metadata_symbol_conflicts_current =
+ the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
+
+metadata_symbol_conflicts_others =
+ found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two.
+
+metadata_stable_crate_id_collision =
+ found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
+
+metadata_dl_error =
+ {$err}
+
+metadata_newer_crate_version =
+ found possibly newer version of crate `{$crate_name}`{$add_info}
+ .note = perhaps that crate needs to be recompiled?
+
+metadata_found_crate_versions =
+ the following crate versions were found:{$found_crates}
+
+metadata_no_crate_with_triple =
+ couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
+
+metadata_found_staticlib =
+ found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
+ .help = please recompile that crate using --crate-type lib
+
+metadata_incompatible_rustc =
+ found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
+ .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
+
+metadata_invalid_meta_files =
+ found invalid metadata files for crate `{$crate_name}`{$add_info}
+
+metadata_cannot_find_crate =
+ can't find crate for `{$crate_name}`{$add_info}
+
+metadata_no_dylib_plugin =
+ plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+
+metadata_target_not_installed =
+ the `{$locator_triple}` target may not be installed
+
+metadata_target_no_std_support =
+ the `{$locator_triple}` target may not support the standard library
+
+metadata_consider_downloading_target =
+ consider downloading the target with `rustup target add {$locator_triple}`
+
+metadata_std_required =
+ `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
+
+metadata_consider_building_std =
+ consider building the standard library from source with `cargo build -Zbuild-std`
+
+metadata_compiler_missing_profiler =
+ the compiler may have been built without the profiler runtime
+
+metadata_install_missing_components =
+ maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
+
+metadata_cant_find_crate =
+ can't find crate
+
+metadata_crate_location_unknown_type =
+ extern location for {$crate_name} is of an unknown type: {$path}
+
+metadata_lib_filename_form =
+ file name should be lib*.rlib or {dll_prefix}*.{dll_suffix}
+
+metadata_multiple_import_name_type =
+ multiple `import_name_type` arguments in a single `#[link]` attribute
+
+metadata_import_name_type_form =
+ import name type must be of the form `import_name_type = "string"`
+
+metadata_import_name_type_x86 =
+ import name type is only supported on x86
+
+metadata_unknown_import_name_type =
+ unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
+
+metadata_import_name_type_raw =
+ import name type can only be used with link kind `raw-dylib`
.label = can't leak {$vis_descr} {$kind}
.visibility_label = `{$descr}` declared as {$vis_descr}
+privacy_report_access_level = {$descr}
+
privacy_from_private_dep_in_public_interface =
{$kind} `{$descr}` from private dependency '{$krate}' in public interface
--- /dev/null
+trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
+
+trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
+
+trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
+ .label = deref recursion limit reached
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
+ .label = empty on-clause here
+
+trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
+ .label = invalid on-clause here
+
+trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
+ .label = expected value here
+ .note = eg `#[rustc_on_unimplemented(message="foo")]`
+
+trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
+ [none] {""}
+ *[default] {" "}for type `{$self_desc}`
+ }:
+ .negative_implementation_here = negative implementation here
+ .negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}`
+ .positive_implementation_here = positive implementation here
+ .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`
infer => "../locales/en-US/infer.ftl",
lint => "../locales/en-US/lint.ftl",
monomorphize => "../locales/en-US/monomorphize.ftl",
+ metadata => "../locales/en-US/metadata.ftl",
parser => "../locales/en-US/parser.ftl",
passes => "../locales/en-US/passes.ftl",
plugin_impl => "../locales/en-US/plugin_impl.ftl",
privacy => "../locales/en-US/privacy.ftl",
query_system => "../locales/en-US/query_system.ftl",
+ trait_selection => "../locales/en-US/trait_selection.ftl",
save_analysis => "../locales/en-US/save_analysis.ftl",
ty_utils => "../locales/en-US/ty_utils.ftl",
typeck => "../locales/en-US/typeck.ftl",
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hir = { path = "../rustc_hir" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
+rustc_target = { path = "../rustc_target" }
unicode-width = "0.1.4"
atty = "0.2"
termcolor = "1.0"
annotate-snippets = "0.9"
termize = "0.1.1"
-serde = { version = "1.0.125", features = ["derive"] }
+serde = { version = "1.0.125", features = [ "derive" ] }
serde_json = "1.0.59"
[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3", features = ["handleapi", "synchapi", "winbase"] }
+winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] }
use rustc_span::edition::LATEST_STABLE_EDITION;
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
use rustc_span::{edition::Edition, Span, DUMMY_SP};
+use rustc_target::spec::PanicStrategy;
use std::borrow::Cow;
use std::fmt;
use std::hash::{Hash, Hasher};
}
}
+impl IntoDiagnosticArg for PanicStrategy {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
+ }
+}
+
impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
fn into(self) -> FluentValue<'source> {
match self {
/// Allows creation of instances of a struct by moving fields that have
/// not changed from prior instances of the same struct (RFC #2528)
(active, type_changing_struct_update, "1.58.0", Some(86555), None),
+ /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
+ (active, unix_sigpipe, "CURRENT_RUSTC_VERSION", Some(97889), None),
/// Allows unsized fn parameters.
(active, unsized_fn_params, "1.49.0", Some(48055), None),
/// Allows unsized rvalues at arguments and parameters.
),
// Entry point:
+ gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)),
ungated!(start, Normal, template!(Word), WarnFollowing),
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),
// Internal attributes, Testing:
// ==========================================================================
+ rustc_attr!(TEST, rustc_access_level, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
use rustc_span::edition::{Edition, DEFAULT_EDITION};
use rustc_span::symbol::sym;
use rustc_span::SourceFileHashAlgorithm;
-use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
-use rustc_target::spec::{
- RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel,
-};
+use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
+use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator;
untracked!(link_args, vec![String::from("abc"), String::from("def")]);
untracked!(link_self_contained, Some(true));
untracked!(linker, Some(PathBuf::from("linker")));
- untracked!(linker_flavor, Some(LinkerFlavor::Gcc));
+ untracked!(linker_flavor, Some(LinkerFlavorCli::Gcc));
untracked!(no_stack_check, true);
untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")]));
untracked!(rpath, true);
}
}
}
+
+pub use rustc_session::lint::builtin::UNEXPECTED_CFGS;
+
+declare_lint_pass!(UnexpectedCfgs => [UNEXPECTED_CFGS]);
+
+impl EarlyLintPass for UnexpectedCfgs {
+ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
+ let cfg = &cx.sess().parse_sess.config;
+ let check_cfg = &cx.sess().parse_sess.check_config;
+ for &(name, value) in cfg {
+ if let Some(names_valid) = &check_cfg.names_valid {
+ if !names_valid.contains(&name) {
+ cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
+ diag.build(fluent::lint::builtin_unexpected_cli_config_name)
+ .help(fluent::lint::help)
+ .set_arg("name", name)
+ .emit();
+ });
+ }
+ }
+ if let Some(value) = value {
+ if let Some(values) = &check_cfg.values_valid.get(&name) {
+ if !values.contains(&value) {
+ cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
+ diag.build(fluent::lint::builtin_unexpected_cli_config_value)
+ .help(fluent::lint::help)
+ .set_arg("name", name)
+ .set_arg("value", value)
+ .emit();
+ });
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+use crate::{LateContext, LateLintPass, LintContext};
+use rustc_errors::{Applicability, LintDiagnosticBuilder, MultiSpan};
+use rustc_hir as hir;
+use rustc_middle::ty;
+use rustc_span::Symbol;
+
+declare_lint! {
+ /// The `let_underscore_drop` lint checks for statements which don't bind
+ /// an expression which has a non-trivial Drop implementation to anything,
+ /// causing the expression to be dropped immediately instead of at end of
+ /// scope.
+ ///
+ /// ### Example
+ /// ```
+ /// struct SomeStruct;
+ /// impl Drop for SomeStruct {
+ /// fn drop(&mut self) {
+ /// println!("Dropping SomeStruct");
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// #[warn(let_underscore_drop)]
+ /// // SomeStuct is dropped immediately instead of at end of scope,
+ /// // so "Dropping SomeStruct" is printed before "end of main".
+ /// // The order of prints would be reversed if SomeStruct was bound to
+ /// // a name (such as "_foo").
+ /// let _ = SomeStruct;
+ /// println!("end of main");
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Statements which assign an expression to an underscore causes the
+ /// expression to immediately drop instead of extending the expression's
+ /// lifetime to the end of the scope. This is usually unintended,
+ /// especially for types like `MutexGuard`, which are typically used to
+ /// lock a mutex for the duration of an entire scope.
+ ///
+ /// If you want to extend the expression's lifetime to the end of the scope,
+ /// assign an underscore-prefixed name (such as `_foo`) to the expression.
+ /// If you do actually want to drop the expression immediately, then
+ /// calling `std::mem::drop` on the expression is clearer and helps convey
+ /// intent.
+ pub LET_UNDERSCORE_DROP,
+ Allow,
+ "non-binding let on a type that implements `Drop`"
+}
+
+declare_lint! {
+ /// The `let_underscore_lock` lint checks for statements which don't bind
+ /// a mutex to anything, causing the lock to be released immediately instead
+ /// of at end of scope, which is typically incorrect.
+ ///
+ /// ### Example
+ /// ```compile_fail
+ /// use std::sync::{Arc, Mutex};
+ /// use std::thread;
+ /// let data = Arc::new(Mutex::new(0));
+ ///
+ /// thread::spawn(move || {
+ /// // The lock is immediately released instead of at the end of the
+ /// // scope, which is probably not intended.
+ /// let _ = data.lock().unwrap();
+ /// println!("doing some work");
+ /// let mut lock = data.lock().unwrap();
+ /// *lock += 1;
+ /// });
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Statements which assign an expression to an underscore causes the
+ /// expression to immediately drop instead of extending the expression's
+ /// lifetime to the end of the scope. This is usually unintended,
+ /// especially for types like `MutexGuard`, which are typically used to
+ /// lock a mutex for the duration of an entire scope.
+ ///
+ /// If you want to extend the expression's lifetime to the end of the scope,
+ /// assign an underscore-prefixed name (such as `_foo`) to the expression.
+ /// If you do actually want to drop the expression immediately, then
+ /// calling `std::mem::drop` on the expression is clearer and helps convey
+ /// intent.
+ pub LET_UNDERSCORE_LOCK,
+ Deny,
+ "non-binding let on a synchronization lock"
+}
+
+declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK]);
+
+const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [
+ rustc_span::sym::MutexGuard,
+ rustc_span::sym::RwLockReadGuard,
+ rustc_span::sym::RwLockWriteGuard,
+];
+
+impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
+ fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
+ if !matches!(local.pat.kind, hir::PatKind::Wild) {
+ return;
+ }
+ if let Some(init) = local.init {
+ let init_ty = cx.typeck_results().expr_ty(init);
+ // If the type has a trivial Drop implementation, then it doesn't
+ // matter that we drop the value immediately.
+ if !init_ty.needs_drop(cx.tcx, cx.param_env) {
+ return;
+ }
+ let is_sync_lock = match init_ty.kind() {
+ ty::Adt(adt, _) => SYNC_GUARD_SYMBOLS
+ .iter()
+ .any(|guard_symbol| cx.tcx.is_diagnostic_item(*guard_symbol, adt.did())),
+ _ => false,
+ };
+
+ if is_sync_lock {
+ let mut span = MultiSpan::from_spans(vec![local.pat.span, init.span]);
+ span.push_span_label(
+ local.pat.span,
+ "this lock is not assigned to a binding and is immediately dropped".to_string(),
+ );
+ span.push_span_label(
+ init.span,
+ "this binding will immediately drop the value assigned to it".to_string(),
+ );
+ cx.struct_span_lint(LET_UNDERSCORE_LOCK, span, |lint| {
+ build_and_emit_lint(
+ lint,
+ local,
+ init.span,
+ "non-binding let on a synchronization lock",
+ )
+ })
+ } else {
+ cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
+ build_and_emit_lint(
+ lint,
+ local,
+ init.span,
+ "non-binding let on a type that implements `Drop`",
+ );
+ })
+ }
+ }
+ }
+}
+
+fn build_and_emit_lint(
+ lint: LintDiagnosticBuilder<'_, ()>,
+ local: &hir::Local<'_>,
+ init_span: rustc_span::Span,
+ msg: &str,
+) {
+ lint.build(msg)
+ .span_suggestion_verbose(
+ local.pat.span,
+ "consider binding to an unused variable to avoid immediately dropping the value",
+ "_unused",
+ Applicability::MachineApplicable,
+ )
+ .multipart_suggestion(
+ "consider immediately dropping the value",
+ vec![
+ (local.span.until(init_span), "drop(".to_string()),
+ (init_span.shrink_to_hi(), ")".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ )
+ .emit();
+}
pub mod hidden_unicode_codepoints;
mod internal;
mod late;
+mod let_underscore;
mod levels;
mod methods;
mod non_ascii_idents;
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
use hidden_unicode_codepoints::*;
use internal::*;
+use let_underscore::*;
use methods::*;
use non_ascii_idents::*;
use non_fmt_panic::NonPanicFmt;
IncompleteFeatures: IncompleteFeatures,
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
+ UnexpectedCfgs: UnexpectedCfgs,
]
);
};
VariantSizeDifferences: VariantSizeDifferences,
BoxPointers: BoxPointers,
PathStatements: PathStatements,
+ LetUnderscore: LetUnderscore,
// Depends on referenced function signatures in expressions
UnusedResults: UnusedResults,
NonUpperCaseGlobals: NonUpperCaseGlobals,
REDUNDANT_SEMICOLONS
);
+ add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK);
+
add_lint_group!(
"rust_2018_idioms",
BARE_TRAIT_OBJECTS,
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
DUPLICATE_MACRO_ATTRIBUTES,
SUSPICIOUS_AUTO_TRAIT_IMPLS,
- UNEXPECTED_CFGS,
DEPRECATED_WHERE_CLAUSE_LOCATION,
TEST_UNSTABLE_LINT,
FFI_UNWIND_CALLS,
use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;
-use syn::{spanned::Spanned, Meta, MetaList, MetaNameValue, NestedMeta, Path};
+use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path};
use synstructure::{BindingInfo, Structure, VariantInfo};
/// Which kind of suggestion is being created?
Verbose,
}
+impl FromStr for SubdiagnosticSuggestionKind {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "" => Ok(SubdiagnosticSuggestionKind::Normal),
+ "_short" => Ok(SubdiagnosticSuggestionKind::Short),
+ "_hidden" => Ok(SubdiagnosticSuggestionKind::Hidden),
+ "_verbose" => Ok(SubdiagnosticSuggestionKind::Verbose),
+ _ => Err(()),
+ }
+ }
+}
+
+impl SubdiagnosticSuggestionKind {
+ pub fn to_suggestion_style(&self) -> TokenStream {
+ match self {
+ SubdiagnosticSuggestionKind::Normal => {
+ quote! { rustc_errors::SuggestionStyle::ShowCode }
+ }
+ SubdiagnosticSuggestionKind::Short => {
+ quote! { rustc_errors::SuggestionStyle::HideCodeInline }
+ }
+ SubdiagnosticSuggestionKind::Hidden => {
+ quote! { rustc_errors::SuggestionStyle::HideCodeAlways }
+ }
+ SubdiagnosticSuggestionKind::Verbose => {
+ quote! { rustc_errors::SuggestionStyle::ShowAlways }
+ }
+ }
+ }
+}
+
/// Which kind of subdiagnostic is being created from a variant?
-#[derive(Clone, Copy)]
+#[derive(Clone)]
enum SubdiagnosticKind {
/// `#[label(...)]`
Label,
/// `#[warning(...)]`
Warn,
/// `#[suggestion{,_short,_hidden,_verbose}]`
- Suggestion(SubdiagnosticSuggestionKind),
-}
-
-impl FromStr for SubdiagnosticKind {
- type Err = ();
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- match s {
- "label" => Ok(SubdiagnosticKind::Label),
- "note" => Ok(SubdiagnosticKind::Note),
- "help" => Ok(SubdiagnosticKind::Help),
- "warning" => Ok(SubdiagnosticKind::Warn),
- "suggestion" => Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Normal)),
- "suggestion_short" => {
- Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Short))
- }
- "suggestion_hidden" => {
- Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Hidden))
- }
- "suggestion_verbose" => {
- Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Verbose))
- }
- _ => Err(()),
- }
- }
+ Suggestion { suggestion_kind: SubdiagnosticSuggestionKind, code: TokenStream },
+ /// `#[multipart_suggestion{,_short,_hidden,_verbose}]`
+ MultipartSuggestion { suggestion_kind: SubdiagnosticSuggestionKind },
}
impl quote::IdentFragment for SubdiagnosticKind {
SubdiagnosticKind::Note => write!(f, "note"),
SubdiagnosticKind::Help => write!(f, "help"),
SubdiagnosticKind::Warn => write!(f, "warn"),
- SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Normal) => {
- write!(f, "suggestion")
- }
- SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Short) => {
- write!(f, "suggestion_short")
- }
- SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Hidden) => {
- write!(f, "suggestion_hidden")
- }
- SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Verbose) => {
- write!(f, "suggestion_verbose")
+ SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"),
+ SubdiagnosticKind::MultipartSuggestion { .. } => {
+ write!(f, "multipart_suggestion_with_style")
}
}
}
variant,
span,
fields: fields_map,
- kinds: Vec::new(),
- slugs: Vec::new(),
- code: None,
span_field: None,
applicability: None,
+ has_suggestion_parts: false,
};
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
});
/// derive builder.
fields: HashMap<String, TokenStream>,
- /// Subdiagnostic kind of the type/variant.
- kinds: Vec<(SubdiagnosticKind, proc_macro::Span)>,
-
- /// Slugs of the subdiagnostic - corresponds to the Fluent identifier for the message - from the
- /// `#[kind(slug)]` attribute on the type or variant.
- slugs: Vec<(Path, proc_macro::Span)>,
- /// If a suggestion, the code to suggest as a replacement - from the `#[kind(code = "...")]`
- /// attribute on the type or variant.
- code: Option<(TokenStream, proc_macro::Span)>,
-
/// Identifier for the binding to the `#[primary_span]` field.
span_field: Option<(proc_macro2::Ident, proc_macro::Span)>,
/// If a suggestion, the identifier for the binding to the `#[applicability]` field or a
/// `rustc_errors::Applicability::*` variant directly.
applicability: Option<(TokenStream, proc_macro::Span)>,
+
+ /// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
+ /// during finalization if still `false`.
+ has_suggestion_parts: bool,
}
impl<'a> HasFieldMap for SessionSubdiagnosticDeriveBuilder<'a> {
}
}
+/// Provides frequently-needed information about the diagnostic kinds being derived for this type.
+#[derive(Clone, Copy, Debug)]
+struct KindsStatistics {
+ has_multipart_suggestion: bool,
+ all_multipart_suggestions: bool,
+ has_normal_suggestion: bool,
+}
+
+impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
+ fn from_iter<T: IntoIterator<Item = &'a SubdiagnosticKind>>(kinds: T) -> Self {
+ let mut ret = Self {
+ has_multipart_suggestion: false,
+ all_multipart_suggestions: true,
+ has_normal_suggestion: false,
+ };
+ for kind in kinds {
+ if let SubdiagnosticKind::MultipartSuggestion { .. } = kind {
+ ret.has_multipart_suggestion = true;
+ } else {
+ ret.all_multipart_suggestions = false;
+ }
+
+ if let SubdiagnosticKind::Suggestion { .. } = kind {
+ ret.has_normal_suggestion = true;
+ }
+ }
+ ret
+ }
+}
+
impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
- fn identify_kind(&mut self) -> Result<(), DiagnosticDeriveError> {
- for (i, attr) in self.variant.ast().attrs.iter().enumerate() {
+ fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
+ let mut kind_slugs = vec![];
+
+ for attr in self.variant.ast().attrs {
let span = attr.span().unwrap();
let name = attr.path.segments.last().unwrap().ident.to_string();
let name = name.as_str();
let meta = attr.parse_meta()?;
- let kind = match meta {
- Meta::List(MetaList { ref nested, .. }) => {
- let mut nested_iter = nested.into_iter();
- if let Some(nested_attr) = nested_iter.next() {
- match nested_attr {
- NestedMeta::Meta(Meta::Path(path)) => {
- self.slugs.push((path.clone(), span));
- }
- NestedMeta::Meta(meta @ Meta::NameValue(_))
- if matches!(
- meta.path().segments.last().unwrap().ident.to_string().as_str(),
- "code" | "applicability"
- ) =>
- {
- // don't error for valid follow-up attributes
- }
- nested_attr => {
- throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- diag.help(
- "first argument of the attribute should be the diagnostic \
- slug",
- )
- })
- }
- };
- }
+ let Meta::List(MetaList { ref nested, .. }) = meta else {
+ throw_invalid_attr!(attr, &meta);
+ };
- for nested_attr in nested_iter {
- let meta = match nested_attr {
- NestedMeta::Meta(ref meta) => meta,
- _ => throw_invalid_nested_attr!(attr, &nested_attr),
- };
-
- let span = meta.span().unwrap();
- let nested_name = meta.path().segments.last().unwrap().ident.to_string();
- let nested_name = nested_name.as_str();
-
- match meta {
- Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
- match nested_name {
- "code" => {
- let formatted_str = self.build_format(&s.value(), s.span());
- self.code.set_once((formatted_str, span));
- }
- "applicability" => {
- let value = match Applicability::from_str(&s.value()) {
- Ok(v) => v,
- Err(()) => {
- span_err(span, "invalid applicability").emit();
- Applicability::Unspecified
- }
- };
- self.applicability.set_once((quote! { #value }, span));
- }
- _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- diag.help(
- "only `code` and `applicability` are valid nested \
- attributes",
- )
- }),
- }
- }
- _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- if matches!(meta, Meta::Path(_)) {
- diag.help(
- "a diagnostic slug must be the first argument to the \
- attribute",
- )
- } else {
- diag
- }
- }),
- }
+ let mut kind = match name {
+ "label" => SubdiagnosticKind::Label,
+ "note" => SubdiagnosticKind::Note,
+ "help" => SubdiagnosticKind::Help,
+ "warning" => SubdiagnosticKind::Warn,
+ _ => {
+ if let Some(suggestion_kind) =
+ name.strip_prefix("suggestion").and_then(|s| s.parse().ok())
+ {
+ SubdiagnosticKind::Suggestion { suggestion_kind, code: TokenStream::new() }
+ } else if let Some(suggestion_kind) =
+ name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok())
+ {
+ SubdiagnosticKind::MultipartSuggestion { suggestion_kind }
+ } else {
+ throw_invalid_attr!(attr, &meta);
}
-
- let Ok(kind) = SubdiagnosticKind::from_str(name) else {
- throw_invalid_attr!(attr, &meta)
- };
-
- kind
}
- _ => throw_invalid_attr!(attr, &meta),
};
- if matches!(
- kind,
- SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note
- ) && self.code.is_some()
- {
- throw_span_err!(
- span,
- &format!("`code` is not a valid nested attribute of a `{}` attribute", name)
- );
+ let mut slug = None;
+ let mut code = None;
+
+ let mut nested_iter = nested.into_iter();
+ if let Some(nested_attr) = nested_iter.next() {
+ match nested_attr {
+ NestedMeta::Meta(Meta::Path(path)) => {
+ slug.set_once((path.clone(), span));
+ }
+ NestedMeta::Meta(meta @ Meta::NameValue(_))
+ if matches!(
+ meta.path().segments.last().unwrap().ident.to_string().as_str(),
+ "code" | "applicability"
+ ) =>
+ {
+ // Don't error for valid follow-up attributes.
+ }
+ nested_attr => {
+ throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+ diag.help(
+ "first argument of the attribute should be the diagnostic \
+ slug",
+ )
+ })
+ }
+ };
}
- if matches!(
- kind,
- SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note
- ) && self.applicability.is_some()
- {
- throw_span_err!(
- span,
- &format!(
- "`applicability` is not a valid nested attribute of a `{}` attribute",
- name
- )
- );
+ for nested_attr in nested_iter {
+ let meta = match nested_attr {
+ NestedMeta::Meta(ref meta) => meta,
+ _ => throw_invalid_nested_attr!(attr, &nested_attr),
+ };
+
+ let span = meta.span().unwrap();
+ let nested_name = meta.path().segments.last().unwrap().ident.to_string();
+ let nested_name = nested_name.as_str();
+
+ let value = match meta {
+ Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value,
+ Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+ diag.help("a diagnostic slug must be the first argument to the attribute")
+ }),
+ _ => throw_invalid_nested_attr!(attr, &nested_attr),
+ };
+
+ match nested_name {
+ "code" => {
+ if matches!(kind, SubdiagnosticKind::Suggestion { .. }) {
+ let formatted_str = self.build_format(&value.value(), value.span());
+ code.set_once((formatted_str, span));
+ } else {
+ span_err(
+ span,
+ &format!(
+ "`code` is not a valid nested attribute of a `{}` attribute",
+ name
+ ),
+ )
+ .emit();
+ }
+ }
+ "applicability" => {
+ if matches!(
+ kind,
+ SubdiagnosticKind::Suggestion { .. }
+ | SubdiagnosticKind::MultipartSuggestion { .. }
+ ) {
+ let value =
+ Applicability::from_str(&value.value()).unwrap_or_else(|()| {
+ span_err(span, "invalid applicability").emit();
+ Applicability::Unspecified
+ });
+ self.applicability.set_once((quote! { #value }, span));
+ } else {
+ span_err(
+ span,
+ &format!(
+ "`applicability` is not a valid nested attribute of a `{}` attribute",
+ name
+ )
+ ).emit();
+ }
+ }
+ _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+ diag.help("only `code` and `applicability` are valid nested attributes")
+ }),
+ }
}
- if self.slugs.len() != i + 1 {
+ let Some((slug, _)) = slug else {
throw_span_err!(
span,
&format!(
name
)
);
+ };
+
+ match kind {
+ SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => {
+ let Some((code, _)) = code else {
+ throw_span_err!(span, "suggestion without `code = \"...\"`");
+ };
+ *code_field = code;
+ }
+ SubdiagnosticKind::Label
+ | SubdiagnosticKind::Note
+ | SubdiagnosticKind::Help
+ | SubdiagnosticKind::Warn
+ | SubdiagnosticKind::MultipartSuggestion { .. } => {}
}
- self.kinds.push((kind, span));
+ kind_slugs.push((kind, slug))
}
- Ok(())
+ Ok(kind_slugs)
}
- fn generate_field_code(
+ /// Generates the code for a field with no attributes.
+ fn generate_field_set_arg(&mut self, binding: &BindingInfo<'_>) -> TokenStream {
+ let ast = binding.ast();
+ assert_eq!(ast.attrs.len(), 0, "field with attribute used as diagnostic arg");
+
+ let diag = &self.diag;
+ let ident = ast.ident.as_ref().unwrap();
+ quote! {
+ #diag.set_arg(
+ stringify!(#ident),
+ #binding
+ );
+ }
+ }
+
+ /// Generates the necessary code for all attributes on a field.
+ fn generate_field_attr_code(
&mut self,
binding: &BindingInfo<'_>,
- have_suggestion: bool,
- ) -> Result<TokenStream, DiagnosticDeriveError> {
+ kind_stats: KindsStatistics,
+ ) -> TokenStream {
let ast = binding.ast();
+ assert!(ast.attrs.len() > 0, "field without attributes generating attr code");
+ // Abstract over `Vec<T>` and `Option<T>` fields using `FieldInnerTy`, which will
+ // apply the generated code on each element in the `Vec` or `Option`.
let inner_ty = FieldInnerTy::from_type(&ast.ty);
- let info = FieldInfo {
- binding: binding,
- ty: inner_ty.inner_type().unwrap_or(&ast.ty),
- span: &ast.span(),
- };
+ ast.attrs
+ .iter()
+ .map(|attr| {
+ let info = FieldInfo {
+ binding,
+ ty: inner_ty.inner_type().unwrap_or(&ast.ty),
+ span: &ast.span(),
+ };
- for attr in &ast.attrs {
- let name = attr.path.segments.last().unwrap().ident.to_string();
- let name = name.as_str();
- let span = attr.span().unwrap();
+ let generated = self
+ .generate_field_code_inner(kind_stats, attr, info)
+ .unwrap_or_else(|v| v.to_compile_error());
- let meta = attr.parse_meta()?;
- match meta {
- Meta::Path(_) => match name {
- "primary_span" => {
- report_error_if_not_applied_to_span(attr, &info)?;
- self.span_field.set_once((binding.binding.clone(), span));
- return Ok(quote! {});
- }
- "applicability" if have_suggestion => {
- report_error_if_not_applied_to_applicability(attr, &info)?;
- let binding = binding.binding.clone();
- self.applicability.set_once((quote! { #binding }, span));
- return Ok(quote! {});
- }
- "applicability" => {
- span_err(span, "`#[applicability]` is only valid on suggestions").emit();
- return Ok(quote! {});
- }
- "skip_arg" => {
- return Ok(quote! {});
- }
- _ => throw_invalid_attr!(attr, &meta, |diag| {
+ inner_ty.with(binding, generated)
+ })
+ .collect()
+ }
+
+ fn generate_field_code_inner(
+ &mut self,
+ kind_stats: KindsStatistics,
+ attr: &Attribute,
+ info: FieldInfo<'_>,
+ ) -> Result<TokenStream, DiagnosticDeriveError> {
+ let meta = attr.parse_meta()?;
+ match meta {
+ Meta::Path(path) => self.generate_field_code_inner_path(kind_stats, attr, info, path),
+ Meta::List(list @ MetaList { .. }) => {
+ self.generate_field_code_inner_list(kind_stats, attr, info, list)
+ }
+ _ => throw_invalid_attr!(attr, &meta),
+ }
+ }
+
+ /// Generates the code for a `[Meta::Path]`-like attribute on a field (e.g. `#[primary_span]`).
+ fn generate_field_code_inner_path(
+ &mut self,
+ kind_stats: KindsStatistics,
+ attr: &Attribute,
+ info: FieldInfo<'_>,
+ path: Path,
+ ) -> Result<TokenStream, DiagnosticDeriveError> {
+ let span = attr.span().unwrap();
+ let ident = &path.segments.last().unwrap().ident;
+ let name = ident.to_string();
+ let name = name.as_str();
+
+ match name {
+ "skip_arg" => Ok(quote! {}),
+ "primary_span" => {
+ if kind_stats.has_multipart_suggestion {
+ throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
diag.help(
- "only `primary_span`, `applicability` and `skip_arg` are valid field \
- attributes",
+ "multipart suggestions use one or more `#[suggestion_part]`s rather \
+ than one `#[primary_span]`",
)
- }),
- },
- _ => throw_invalid_attr!(attr, &meta),
+ })
+ }
+
+ report_error_if_not_applied_to_span(attr, &info)?;
+
+ let binding = info.binding.binding.clone();
+ self.span_field.set_once((binding, span));
+
+ Ok(quote! {})
}
+ "suggestion_part" => {
+ self.has_suggestion_parts = true;
+
+ if kind_stats.has_multipart_suggestion {
+ span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
+ .emit();
+ Ok(quote! {})
+ } else {
+ throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+ diag.help(
+ "`#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead",
+ )
+ });
+ }
+ }
+ "applicability" => {
+ if kind_stats.has_multipart_suggestion || kind_stats.has_normal_suggestion {
+ report_error_if_not_applied_to_applicability(attr, &info)?;
+
+ let binding = info.binding.binding.clone();
+ self.applicability.set_once((quote! { #binding }, span));
+ } else {
+ span_err(span, "`#[applicability]` is only valid on suggestions").emit();
+ }
+
+ Ok(quote! {})
+ }
+ _ => throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+ let mut span_attrs = vec![];
+ if kind_stats.has_multipart_suggestion {
+ span_attrs.push("suggestion_part");
+ }
+ if !kind_stats.all_multipart_suggestions {
+ span_attrs.push("primary_span")
+ }
+ diag.help(format!(
+ "only `{}`, `applicability` and `skip_arg` are valid field attributes",
+ span_attrs.join(", ")
+ ))
+ }),
}
+ }
- let ident = ast.ident.as_ref().unwrap();
+ /// Generates the code for a `[Meta::List]`-like attribute on a field (e.g.
+ /// `#[suggestion_part(code = "...")]`).
+ fn generate_field_code_inner_list(
+ &mut self,
+ kind_stats: KindsStatistics,
+ attr: &Attribute,
+ info: FieldInfo<'_>,
+ list: MetaList,
+ ) -> Result<TokenStream, DiagnosticDeriveError> {
+ let span = attr.span().unwrap();
+ let ident = &list.path.segments.last().unwrap().ident;
+ let name = ident.to_string();
+ let name = name.as_str();
+
+ match name {
+ "suggestion_part" => {
+ if !kind_stats.has_multipart_suggestion {
+ throw_invalid_attr!(attr, &Meta::List(list), |diag| {
+ diag.help(
+ "`#[suggestion_part(...)]` is only valid in multipart suggestions",
+ )
+ })
+ }
- let diag = &self.diag;
- let generated = quote! {
- #diag.set_arg(
- stringify!(#ident),
- #binding
- );
- };
+ self.has_suggestion_parts = true;
+
+ report_error_if_not_applied_to_span(attr, &info)?;
+
+ let mut code = None;
+ for nested_attr in list.nested.iter() {
+ let NestedMeta::Meta(ref meta) = nested_attr else {
+ throw_invalid_nested_attr!(attr, &nested_attr);
+ };
+
+ let span = meta.span().unwrap();
+ let nested_name = meta.path().segments.last().unwrap().ident.to_string();
+ let nested_name = nested_name.as_str();
- Ok(inner_ty.with(binding, generated))
+ let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) = meta else {
+ throw_invalid_nested_attr!(attr, &nested_attr);
+ };
+
+ match nested_name {
+ "code" => {
+ let formatted_str = self.build_format(&value.value(), value.span());
+ code.set_once((formatted_str, span));
+ }
+ _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+ diag.help("`code` is the only valid nested attribute")
+ }),
+ }
+ }
+
+ let Some((code, _)) = code else {
+ span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
+ .emit();
+ return Ok(quote! {});
+ };
+ let binding = info.binding;
+
+ Ok(quote! { suggestions.push((#binding, #code)); })
+ }
+ _ => throw_invalid_attr!(attr, &Meta::List(list), |diag| {
+ let mut span_attrs = vec![];
+ if kind_stats.has_multipart_suggestion {
+ span_attrs.push("suggestion_part");
+ }
+ if !kind_stats.all_multipart_suggestions {
+ span_attrs.push("primary_span")
+ }
+ diag.help(format!(
+ "only `{}`, `applicability` and `skip_arg` are valid field attributes",
+ span_attrs.join(", ")
+ ))
+ }),
+ }
}
- fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
- self.identify_kind()?;
- if self.kinds.is_empty() {
+ pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
+ let kind_slugs = self.identify_kind()?;
+ if kind_slugs.is_empty() {
throw_span_err!(
self.variant.ast().ident.span().unwrap(),
"subdiagnostic kind not specified"
);
};
- let have_suggestion =
- self.kinds.iter().any(|(k, _)| matches!(k, SubdiagnosticKind::Suggestion(_)));
- let mut args = TokenStream::new();
- for binding in self.variant.bindings() {
- let arg = self
- .generate_field_code(binding, have_suggestion)
- .unwrap_or_else(|v| v.to_compile_error());
- args.extend(arg);
- }
- let mut tokens = TokenStream::new();
- for ((kind, _), (slug, _)) in self.kinds.iter().zip(&self.slugs) {
- let code = match self.code.as_ref() {
- Some((code, _)) => Some(quote! { #code }),
- None if have_suggestion => {
- span_err(self.span, "suggestion without `code = \"...\"`").emit();
- Some(quote! { /* macro error */ "..." })
- }
- None => None,
- };
- let span_field = self.span_field.as_ref().map(|(span, _)| span);
- let applicability = match self.applicability.clone() {
- Some((applicability, _)) => Some(applicability),
- None if have_suggestion => {
- span_err(self.span, "suggestion without `applicability`").emit();
- Some(quote! { rustc_errors::Applicability::Unspecified })
- }
- None => None,
- };
+ let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
+
+ let init = if kind_stats.has_multipart_suggestion {
+ quote! { let mut suggestions = Vec::new(); }
+ } else {
+ quote! {}
+ };
+
+ let attr_args: TokenStream = self
+ .variant
+ .bindings()
+ .iter()
+ .filter(|binding| !binding.ast().attrs.is_empty())
+ .map(|binding| self.generate_field_attr_code(binding, kind_stats))
+ .collect();
+
+ let span_field = self.span_field.as_ref().map(|(span, _)| span);
+ let applicability = self.applicability.take().map_or_else(
+ || quote! { rustc_errors::Applicability::Unspecified },
+ |(applicability, _)| applicability,
+ );
- let diag = &self.diag;
+ let diag = &self.diag;
+ let mut calls = TokenStream::new();
+ for (kind, slug) in kind_slugs {
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
let message = quote! { rustc_errors::fluent::#slug };
- let call = if matches!(kind, SubdiagnosticKind::Suggestion(..)) {
- if let Some(span) = span_field {
- quote! { #diag.#name(#span, #message, #code, #applicability); }
- } else {
- span_err(self.span, "suggestion without `#[primary_span]` field").emit();
- quote! { unreachable!(); }
+ let call = match kind {
+ SubdiagnosticKind::Suggestion { suggestion_kind, code } => {
+ if let Some(span) = span_field {
+ let style = suggestion_kind.to_suggestion_style();
+
+ quote! { #diag.#name(#span, #message, #code, #applicability, #style); }
+ } else {
+ span_err(self.span, "suggestion without `#[primary_span]` field").emit();
+ quote! { unreachable!(); }
+ }
}
- } else if matches!(kind, SubdiagnosticKind::Label) {
- if let Some(span) = span_field {
- quote! { #diag.#name(#span, #message); }
- } else {
- span_err(self.span, "label without `#[primary_span]` field").emit();
- quote! { unreachable!(); }
+ SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => {
+ if !self.has_suggestion_parts {
+ span_err(
+ self.span,
+ "multipart suggestion without any `#[suggestion_part(...)]` fields",
+ )
+ .emit();
+ }
+
+ let style = suggestion_kind.to_suggestion_style();
+
+ quote! { #diag.#name(#message, suggestions, #applicability, #style); }
}
- } else {
- if let Some(span) = span_field {
- quote! { #diag.#name(#span, #message); }
- } else {
- quote! { #diag.#name(#message); }
+ SubdiagnosticKind::Label => {
+ if let Some(span) = span_field {
+ quote! { #diag.#name(#span, #message); }
+ } else {
+ span_err(self.span, "label without `#[primary_span]` field").emit();
+ quote! { unreachable!(); }
+ }
+ }
+ _ => {
+ if let Some(span) = span_field {
+ quote! { #diag.#name(#span, #message); }
+ } else {
+ quote! { #diag.#name(#message); }
+ }
}
};
- tokens.extend(quote! {
- #call
- #args
- });
+ calls.extend(call);
}
- Ok(tokens)
+ let plain_args: TokenStream = self
+ .variant
+ .bindings()
+ .iter()
+ .filter(|binding| binding.ast().attrs.is_empty())
+ .map(|binding| self.generate_field_set_arg(binding))
+ .collect();
+
+ Ok(quote! {
+ #init
+ #attr_args
+ #calls
+ #plain_args
+ })
}
}
//! Validates all used crates and extern libraries and loads their metadata
+use crate::errors::{
+ ConflictingGlobalAlloc, CrateNotPanicRuntime, GlobalAllocRequired, NoMultipleGlobalAlloc,
+ NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
+};
use crate::locator::{CrateError, CrateLocator, CratePaths};
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
// Sanity check the loaded crate to ensure it is indeed a panic runtime
// and the panic strategy is indeed what we thought it was.
if !data.is_panic_runtime() {
- self.sess.err(&format!("the crate `{}` is not a panic runtime", name));
+ self.sess.emit_err(CrateNotPanicRuntime { crate_name: name });
}
if data.required_panic_strategy() != Some(desired_strategy) {
- self.sess.err(&format!(
- "the crate `{}` does not have the panic \
- strategy `{}`",
- name,
- desired_strategy.desc()
- ));
+ self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy });
}
self.cstore.injected_panic_runtime = Some(cnum);
let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
- self.sess.err(
- "`profiler_builtins` crate (required by compiler options) \
- is not compatible with crate attribute `#![no_core]`",
- );
+ self.sess.emit_err(ProfilerBuiltinsNeedsCore);
}
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
if !data.is_profiler_runtime() {
- self.sess.err(&format!("the crate `{}` is not a profiler runtime", name));
+ self.sess.emit_err(NotProfilerRuntime { crate_name: name });
}
}
fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) {
[span1, span2, ..] => {
- self.sess
- .struct_span_err(*span2, "cannot define multiple global allocators")
- .span_label(*span2, "cannot define a new global allocator")
- .span_label(*span1, "previous global allocator defined here")
- .emit();
+ self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
if data.has_global_allocator() {
match global_allocator {
Some(other_crate) => {
- self.sess.err(&format!(
- "the `#[global_allocator]` in {} conflicts with global allocator in: {}",
- other_crate,
- data.name()
- ));
+ self.sess.emit_err(ConflictingGlobalAlloc {
+ crate_name: data.name(),
+ other_crate_name: other_crate,
+ });
}
None => global_allocator = Some(data.name()),
}
if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator)
&& !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
{
- self.sess.err(
- "no global memory allocator found but one is required; link to std or add \
- `#[global_allocator]` to a static item that implements the GlobalAlloc trait",
- );
+ self.sess.emit_err(GlobalAllocRequired);
}
self.cstore.allocator_kind = Some(AllocatorKind::Default);
}
for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
let data = self.cstore.get_crate_data(dep);
if needs_dep(&data) {
- self.sess.err(&format!(
- "the crate `{}` cannot depend \
- on a crate that needs {}, but \
- it depends on `{}`",
- self.cstore.get_crate_data(krate).name(),
- what,
- data.name()
- ));
+ self.sess.emit_err(NoTransitiveNeedsDep {
+ crate_name: self.cstore.get_crate_data(krate).name(),
+ needs_crate_name: what,
+ deps_crate_name: data.name(),
+ });
}
}
//! than finding a number of solutions (there are normally quite a few).
use crate::creader::CStore;
+use crate::errors::{
+ BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
+ RequiredPanicStrategy, RlibRequired, TwoPanicRuntimes,
+};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::CrateNum;
if src.rlib.is_some() {
continue;
}
- sess.err(&format!(
- "crate `{}` required to be available in rlib format, \
- but was not found in this form",
- tcx.crate_name(cnum)
- ));
+ sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
}
return Vec::new();
}
Linkage::Static => "rlib",
_ => "dylib",
};
- sess.err(&format!(
- "crate `{}` required to be available in {} format, \
- but was not found in this form",
- tcx.crate_name(cnum),
- kind
- ));
+ sess.emit_err(LibRequired { crate_name: tcx.crate_name(cnum), kind: kind });
}
}
}
// This error is probably a little obscure, but I imagine that it
// can be refined over time.
if link2 != link || link == RequireStatic {
- tcx.sess
- .struct_err(&format!(
- "cannot satisfy dependencies so `{}` only \
- shows up once",
- tcx.crate_name(cnum)
- ))
- .help(
- "having upstream crates all available in one format \
- will likely make this go away",
- )
- .emit();
+ tcx.sess.emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum) });
}
}
None => {
if let Some((prev, _)) = panic_runtime {
let prev_name = tcx.crate_name(prev);
let cur_name = tcx.crate_name(cnum);
- sess.err(&format!(
- "cannot link together two \
- panic runtimes: {} and {}",
- prev_name, cur_name
- ));
+ sess.emit_err(TwoPanicRuntimes { prev_name, cur_name });
}
panic_runtime = Some((
cnum,
// First up, validate that our selected panic runtime is indeed exactly
// our same strategy.
if found_strategy != desired_strategy {
- sess.err(&format!(
- "the linked panic runtime `{}` is \
- not compiled with this crate's \
- panic strategy `{}`",
- tcx.crate_name(runtime_cnum),
- desired_strategy.desc()
- ));
+ sess.emit_err(BadPanicStrategy {
+ runtime: tcx.crate_name(runtime_cnum),
+ strategy: desired_strategy,
+ });
}
// Next up, verify that all other crates are compatible with this panic
}
if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy {
- sess.err(&format!(
- "the crate `{}` requires \
- panic strategy `{}` which is \
- incompatible with this crate's \
- strategy of `{}`",
- tcx.crate_name(cnum),
- found_strategy.desc(),
- desired_strategy.desc()
- ));
+ sess.emit_err(RequiredPanicStrategy {
+ crate_name: tcx.crate_name(cnum),
+ found_strategy,
+ desired_strategy});
}
let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
- sess.err(&format!(
- "the crate `{}` is compiled with the \
- panic-in-drop strategy `{}` which is \
- incompatible with this crate's \
- strategy of `{}`",
- tcx.crate_name(cnum),
- found_drop_strategy.desc(),
- tcx.sess.opts.unstable_opts.panic_in_drop.desc()
- ));
+ sess.emit_err(IncompatiblePanicInDropStrategy {
+ crate_name: tcx.crate_name(cnum),
+ found_strategy: found_drop_strategy,
+ desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
+ });
}
}
}
--- /dev/null
+use std::{
+ io::Error,
+ path::{Path, PathBuf},
+};
+
+use rustc_errors::{error_code, ErrorGuaranteed};
+use rustc_macros::SessionDiagnostic;
+use rustc_session::{config, SessionDiagnostic};
+use rustc_span::{sym, Span, Symbol};
+use rustc_target::spec::{PanicStrategy, TargetTriple};
+
+use crate::locator::CrateFlavor;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::rlib_required)]
+pub struct RlibRequired {
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_required)]
+pub struct LibRequired<'a> {
+ pub crate_name: Symbol,
+ pub kind: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_dep_multiple)]
+#[help]
+pub struct CrateDepMultiple {
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::two_panic_runtimes)]
+pub struct TwoPanicRuntimes {
+ pub prev_name: Symbol,
+ pub cur_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::bad_panic_strategy)]
+pub struct BadPanicStrategy {
+ pub runtime: Symbol,
+ pub strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::required_panic_strategy)]
+pub struct RequiredPanicStrategy {
+ pub crate_name: Symbol,
+ pub found_strategy: PanicStrategy,
+ pub desired_strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_panic_in_drop_strategy)]
+pub struct IncompatiblePanicInDropStrategy {
+ pub crate_name: Symbol,
+ pub found_strategy: PanicStrategy,
+ pub desired_strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_names_in_link)]
+pub struct MultipleNamesInLink {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_kinds_in_link)]
+pub struct MultipleKindsInLink {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_name_form)]
+pub struct LinkNameForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_kind_form)]
+pub struct LinkKindForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_modifiers_form)]
+pub struct LinkModifiersForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_cfg_form)]
+pub struct LinkCfgForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::wasm_import_form)]
+pub struct WasmImportForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::empty_link_name, code = "E0454")]
+pub struct EmptyLinkName {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_framework_apple, code = "E0455")]
+pub struct LinkFrameworkApple {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::framework_only_windows, code = "E0455")]
+pub struct FrameworkOnlyWindows {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_link_kind, code = "E0458")]
+pub struct UnknownLinkKind<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub kind: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_link_modifiers)]
+pub struct MultipleLinkModifiers {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_cfgs)]
+pub struct MultipleCfgs {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_cfg_single_predicate)]
+pub struct LinkCfgSinglePredicate {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_wasm_import)]
+pub struct MultipleWasmImport {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unexpected_link_arg)]
+pub struct UnexpectedLinkArg {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::invalid_link_modifier)]
+pub struct InvalidLinkModifier {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_modifiers)]
+pub struct MultipleModifiers<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub modifier: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::bundle_needs_static)]
+pub struct BundleNeedsStatic {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::whole_archive_needs_static)]
+pub struct WholeArchiveNeedsStatic {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::as_needed_compatibility)]
+pub struct AsNeededCompatibility {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_link_modifier)]
+pub struct UnknownLinkModifier<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub modifier: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_wasm_link)]
+pub struct IncompatibleWasmLink {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_requires_name, code = "E0459")]
+pub struct LinkRequiresName {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::raw_dylib_no_nul)]
+pub struct RawDylibNoNul {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_ordinal_raw_dylib)]
+pub struct LinkOrdinalRawDylib {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_framework_apple)]
+pub struct LibFrameworkApple;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::empty_renaming_target)]
+pub struct EmptyRenamingTarget<'a> {
+ pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::renaming_no_link)]
+pub struct RenamingNoLink<'a> {
+ pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_renamings)]
+pub struct MultipleRenamings<'a> {
+ pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_link_mod_override)]
+pub struct NoLinkModOverride {
+ #[primary_span]
+ pub span: Option<Span>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unsupported_abi_i686)]
+pub struct UnsupportedAbiI686 {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unsupported_abi)]
+pub struct UnsupportedAbi {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_create_file_encoder)]
+pub struct FailCreateFileEncoder {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_seek_file)]
+pub struct FailSeekFile {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_write_file)]
+pub struct FailWriteFile {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_not_panic_runtime)]
+pub struct CrateNotPanicRuntime {
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_panic_strategy)]
+pub struct NoPanicStrategy {
+ pub crate_name: Symbol,
+ pub strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::profiler_builtins_needs_core)]
+pub struct ProfilerBuiltinsNeedsCore;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::not_profiler_runtime)]
+pub struct NotProfilerRuntime {
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_multiple_global_alloc)]
+pub struct NoMultipleGlobalAlloc {
+ #[primary_span]
+ #[label]
+ pub span2: Span,
+ #[label(metadata::prev_global_alloc)]
+ pub span1: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::conflicting_global_alloc)]
+pub struct ConflictingGlobalAlloc {
+ pub crate_name: Symbol,
+ pub other_crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::global_alloc_required)]
+pub struct GlobalAllocRequired;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_transitive_needs_dep)]
+pub struct NoTransitiveNeedsDep<'a> {
+ pub crate_name: Symbol,
+ pub needs_crate_name: &'a str,
+ pub deps_crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_write_error)]
+pub struct FailedWriteError {
+ pub filename: PathBuf,
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_tempdir)]
+pub struct FailedCreateTempdir {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_file)]
+pub struct FailedCreateFile<'a> {
+ pub filename: &'a Path,
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_encoded_metadata)]
+pub struct FailedCreateEncodedMetadata {
+ pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::non_ascii_name)]
+pub struct NonAsciiName {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::extern_location_not_exist)]
+pub struct ExternLocationNotExist<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub location: &'a Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::extern_location_not_file)]
+pub struct ExternLocationNotFile<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub location: &'a Path,
+}
+
+pub(crate) struct MultipleCandidates {
+ pub span: Span,
+ pub flavor: CrateFlavor,
+ pub crate_name: Symbol,
+ pub candidates: Vec<PathBuf>,
+}
+
+impl SessionDiagnostic<'_> for MultipleCandidates {
+ fn into_diagnostic(
+ self,
+ sess: &'_ rustc_session::parse::ParseSess,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates);
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("flavor", self.flavor);
+ diag.code(error_code!(E0465));
+ diag.set_span(self.span);
+ for (i, candidate) in self.candidates.iter().enumerate() {
+ diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display()));
+ }
+ diag
+ }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_matching_crates, code = "E0464")]
+#[note]
+pub struct MultipleMatchingCrates {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub candidates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::symbol_conflicts_current, code = "E0519")]
+pub struct SymbolConflictsCurrent {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::symbol_conflicts_others, code = "E0523")]
+pub struct SymbolConflictsOthers {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::stable_crate_id_collision)]
+pub struct StableCrateIdCollision {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name0: Symbol,
+ pub crate_name1: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::dl_error)]
+pub struct DlError {
+ #[primary_span]
+ pub span: Span,
+ pub err: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::newer_crate_version, code = "E0460")]
+#[note]
+#[note(metadata::found_crate_versions)]
+pub struct NewerCrateVersion {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_crate_with_triple, code = "E0461")]
+#[note(metadata::found_crate_versions)]
+pub struct NoCrateWithTriple<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub locator_triple: &'a str,
+ pub add_info: String,
+ pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::found_staticlib, code = "E0462")]
+#[note(metadata::found_crate_versions)]
+#[help]
+pub struct FoundStaticlib {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_rustc, code = "E0514")]
+#[note(metadata::found_crate_versions)]
+#[help]
+pub struct IncompatibleRustc {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub found_crates: String,
+ pub rustc_version: String,
+}
+
+pub struct InvalidMetadataFiles {
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub crate_rejections: Vec<String>,
+}
+
+impl SessionDiagnostic<'_> for InvalidMetadataFiles {
+ fn into_diagnostic(
+ self,
+ sess: &'_ rustc_session::parse::ParseSess,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files);
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("add_info", self.add_info);
+ diag.code(error_code!(E0786));
+ diag.set_span(self.span);
+ for crate_rejection in self.crate_rejections {
+ diag.note(crate_rejection);
+ }
+ diag
+ }
+}
+
+pub struct CannotFindCrate {
+ pub span: Span,
+ pub crate_name: Symbol,
+ pub add_info: String,
+ pub missing_core: bool,
+ pub current_crate: String,
+ pub is_nightly_build: bool,
+ pub profiler_runtime: Symbol,
+ pub locator_triple: TargetTriple,
+}
+
+impl SessionDiagnostic<'_> for CannotFindCrate {
+ fn into_diagnostic(
+ self,
+ sess: &'_ rustc_session::parse::ParseSess,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate);
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("add_info", self.add_info);
+ diag.set_arg("locator_triple", self.locator_triple.triple());
+ diag.code(error_code!(E0463));
+ diag.set_span(self.span);
+ if (self.crate_name == sym::std || self.crate_name == sym::core)
+ && self.locator_triple != TargetTriple::from_triple(config::host_triple())
+ {
+ if self.missing_core {
+ diag.note(rustc_errors::fluent::metadata::target_not_installed);
+ } else {
+ diag.note(rustc_errors::fluent::metadata::target_no_std_support);
+ }
+ // NOTE: this suggests using rustup, even though the user may not have it installed.
+ // That's because they could choose to install it; or this may give them a hint which
+ // target they need to install from their distro.
+ if self.missing_core {
+ diag.help(rustc_errors::fluent::metadata::consider_downloading_target);
+ }
+ // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
+ // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
+ // If it's not a dummy, that means someone added `extern crate std` explicitly and
+ // `#![no_std]` won't help.
+ if !self.missing_core && self.span.is_dummy() {
+ diag.note(rustc_errors::fluent::metadata::std_required);
+ }
+ if self.is_nightly_build {
+ diag.help(rustc_errors::fluent::metadata::consider_building_std);
+ }
+ } else if self.crate_name == self.profiler_runtime {
+ diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler);
+ } else if self.crate_name.as_str().starts_with("rustc_") {
+ diag.help(rustc_errors::fluent::metadata::install_missing_components);
+ }
+ diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate);
+ diag
+ }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_dylib_plugin, code = "E0457")]
+pub struct NoDylibPlugin {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_location_unknown_type)]
+pub struct CrateLocationUnknownType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub path: &'a Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_filename_form)]
+pub struct LibFilenameForm<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub dll_prefix: &'a str,
+ pub dll_suffix: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_import_name_type)]
+pub struct MultipleImportNameType {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_form)]
+pub struct ImportNameTypeForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_x86)]
+pub struct ImportNameTypeX86 {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_import_name_type)]
+pub struct UnknownImportNameType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub import_name_type: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_raw)]
+pub struct ImportNameTypeRaw {
+ #[primary_span]
+ pub span: Span,
+}
+use crate::errors::{
+ FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError,
+};
use crate::{encode_metadata, EncodedMetadata};
use rustc_data_structures::temp_dir::MaybeTempDir;
let out_filename = tmpdir.as_ref().join(METADATA_FILENAME);
let result = fs::write(&out_filename, metadata);
- if let Err(e) = result {
- sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
+ if let Err(err) = result {
+ sess.emit_fatal(FailedWriteError { filename: out_filename, err });
}
out_filename
let metadata_tmpdir = TempFileBuilder::new()
.prefix("rmeta")
.tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new("")))
- .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
+ .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err }));
let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME);
// This simplifies the creation of the output `out_filename` when requested.
match metadata_kind {
MetadataKind::None => {
- std::fs::File::create(&metadata_filename).unwrap_or_else(|e| {
- tcx.sess.fatal(&format!(
- "failed to create the file {}: {}",
- metadata_filename.display(),
- e
- ))
+ std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
+ tcx.sess.emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
});
}
MetadataKind::Uncompressed | MetadataKind::Compressed => {
// this file always exists.
let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
let (metadata_filename, metadata_tmpdir) = if need_metadata_file {
- if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) {
- tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
+ if let Err(err) = non_durable_rename(&metadata_filename, &out_filename) {
+ tcx.sess.emit_fatal(FailedWriteError { filename: out_filename, err });
}
if tcx.sess.opts.json_artifact_notifications {
tcx.sess
// Load metadata back to memory: codegen may need to include it in object files.
let metadata =
- EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| {
- tcx.sess.fatal(&format!("failed to create encoded metadata from file: {}", e))
+ EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
+ tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err });
});
let need_metadata_module = metadata_kind == MetadataKind::Compressed;
#![feature(never_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
extern crate proc_macro;
mod rmeta;
pub mod creader;
+pub mod errors;
pub mod fs;
pub mod locator;
//! metadata::locator or metadata::creader for all the juicy details!
use crate::creader::Library;
+use crate::errors::{
+ CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist,
+ ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles,
+ LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion,
+ NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent,
+ SymbolConflictsOthers,
+};
use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::owning_ref::OwningRef;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
-use rustc_errors::{struct_span_err, FatalError};
+use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
use rustc_session::config::{self, CrateType};
use rustc_session::cstore::{CrateSource, MetadataLoader};
use rustc_session::filesearch::FileSearch;
use rustc_session::search_paths::PathKind;
use rustc_session::utils::CanonicalizedPath;
use rustc_session::Session;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::spec::{Target, TargetTriple};
use snap::read::FrameDecoder;
+use std::borrow::Cow;
use std::fmt::Write as _;
use std::io::{Read, Result as IoResult, Write};
use std::path::{Path, PathBuf};
}
}
+impl IntoDiagnosticArg for CrateFlavor {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ match self {
+ CrateFlavor::Rlib => DiagnosticArgValue::Str(Cow::Borrowed("rlib")),
+ CrateFlavor::Rmeta => DiagnosticArgValue::Str(Cow::Borrowed("rmeta")),
+ CrateFlavor::Dylib => DiagnosticArgValue::Str(Cow::Borrowed("dylib")),
+ }
+ }
+}
+
impl<'a> CrateLocator<'a> {
pub(crate) fn new(
sess: &'a Session,
impl CrateError {
pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
- let mut diag = match self {
- CrateError::NonAsciiName(crate_name) => sess.struct_span_err(
- span,
- &format!("cannot load a crate with a non-ascii name `{}`", crate_name),
- ),
- CrateError::ExternLocationNotExist(crate_name, loc) => sess.struct_span_err(
- span,
- &format!("extern location for {} does not exist: {}", crate_name, loc.display()),
- ),
- CrateError::ExternLocationNotFile(crate_name, loc) => sess.struct_span_err(
- span,
- &format!("extern location for {} is not a file: {}", crate_name, loc.display()),
- ),
+ match self {
+ CrateError::NonAsciiName(crate_name) => {
+ sess.emit_err(NonAsciiName { span, crate_name });
+ }
+ CrateError::ExternLocationNotExist(crate_name, loc) => {
+ sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc });
+ }
+ CrateError::ExternLocationNotFile(crate_name, loc) => {
+ sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc });
+ }
CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
- let mut err = struct_span_err!(
- sess,
- span,
- E0465,
- "multiple {} candidates for `{}` found",
- flavor,
- crate_name,
- );
- for (i, candidate) in candidates.iter().enumerate() {
- err.span_note(span, &format!("candidate #{}: {}", i + 1, candidate.display()));
- }
- err
+ sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates });
}
CrateError::MultipleMatchingCrates(crate_name, libraries) => {
- let mut err = struct_span_err!(
- sess,
- span,
- E0464,
- "multiple matching crates for `{}`",
- crate_name
- );
let mut libraries: Vec<_> = libraries.into_values().collect();
// Make ordering of candidates deterministic.
// This has to `clone()` to work around lifetime restrictions with `sort_by_key()`.
s
})
.collect::<String>();
- err.note(&format!("candidates:{}", candidates));
- err
+ sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates });
+ }
+ CrateError::SymbolConflictsCurrent(root_name) => {
+ sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name });
+ }
+ CrateError::SymbolConflictsOthers(root_name) => {
+ sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
}
- CrateError::SymbolConflictsCurrent(root_name) => struct_span_err!(
- sess,
- span,
- E0519,
- "the current crate is indistinguishable from one of its dependencies: it has the \
- same crate-name `{}` and was compiled with the same `-C metadata` arguments. \
- This will result in symbol conflicts between the two.",
- root_name,
- ),
- CrateError::SymbolConflictsOthers(root_name) => struct_span_err!(
- sess,
- span,
- E0523,
- "found two different crates with name `{}` that are not distinguished by differing \
- `-C metadata`. This will result in symbol conflicts between the two.",
- root_name,
- ),
CrateError::StableCrateIdCollision(crate_name0, crate_name1) => {
- let msg = format!(
- "found crates (`{}` and `{}`) with colliding StableCrateId values.",
- crate_name0, crate_name1
- );
- sess.struct_span_err(span, &msg)
+ sess.emit_err(StableCrateIdCollision {
+ span,
+ crate_name0: crate_name0,
+ crate_name1: crate_name1,
+ });
+ }
+ CrateError::DlOpen(s) | CrateError::DlSym(s) => {
+ sess.emit_err(DlError { span, err: s });
}
- CrateError::DlOpen(s) | CrateError::DlSym(s) => sess.struct_span_err(span, &s),
CrateError::LocatorCombined(locator) => {
let crate_name = locator.crate_name;
- let add = match &locator.root {
+ let add_info = match &locator.root {
None => String::new(),
Some(r) => format!(" which `{}` depends on", r.name),
};
- let mut msg = "the following crate versions were found:".to_string();
- let mut err = if !locator.crate_rejections.via_hash.is_empty() {
- let mut err = struct_span_err!(
- sess,
- span,
- E0460,
- "found possibly newer version of crate `{}`{}",
- crate_name,
- add,
- );
- err.note("perhaps that crate needs to be recompiled?");
+ // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm
+ if !locator.crate_rejections.via_filename.is_empty() {
+ let mismatches = locator.crate_rejections.via_filename.iter();
+ for CrateMismatch { path, .. } in mismatches {
+ sess.emit_err(CrateLocationUnknownType { span, path: &path });
+ sess.emit_err(LibFilenameForm {
+ span,
+ dll_prefix: &locator.dll_prefix,
+ dll_suffix: &locator.dll_suffix,
+ });
+ }
+ }
+ let mut found_crates = String::new();
+ if !locator.crate_rejections.via_hash.is_empty() {
let mismatches = locator.crate_rejections.via_hash.iter();
for CrateMismatch { path, .. } in mismatches {
- msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
+ found_crates.push_str(&format!(
+ "\ncrate `{}`: {}",
+ crate_name,
+ path.display()
+ ));
}
if let Some(r) = locator.root {
for path in r.source.paths() {
- msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display()));
+ found_crates.push_str(&format!(
+ "\ncrate `{}`: {}",
+ r.name,
+ path.display()
+ ));
}
}
- err.note(&msg);
- err
- } else if !locator.crate_rejections.via_triple.is_empty() {
- let mut err = struct_span_err!(
- sess,
+ sess.emit_err(NewerCrateVersion {
span,
- E0461,
- "couldn't find crate `{}` with expected target triple {}{}",
- crate_name,
- locator.triple,
- add,
- );
+ crate_name: crate_name,
+ add_info,
+ found_crates,
+ });
+ } else if !locator.crate_rejections.via_triple.is_empty() {
let mismatches = locator.crate_rejections.via_triple.iter();
for CrateMismatch { path, got } in mismatches {
- msg.push_str(&format!(
+ found_crates.push_str(&format!(
"\ncrate `{}`, target triple {}: {}",
crate_name,
got,
path.display(),
));
}
- err.note(&msg);
- err
- } else if !locator.crate_rejections.via_kind.is_empty() {
- let mut err = struct_span_err!(
- sess,
+ sess.emit_err(NoCrateWithTriple {
span,
- E0462,
- "found staticlib `{}` instead of rlib or dylib{}",
- crate_name,
- add,
- );
- err.help("please recompile that crate using --crate-type lib");
+ crate_name: crate_name,
+ locator_triple: locator.triple.triple(),
+ add_info,
+ found_crates,
+ });
+ } else if !locator.crate_rejections.via_kind.is_empty() {
let mismatches = locator.crate_rejections.via_kind.iter();
for CrateMismatch { path, .. } in mismatches {
- msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
+ found_crates.push_str(&format!(
+ "\ncrate `{}`: {}",
+ crate_name,
+ path.display()
+ ));
}
- err.note(&msg);
- err
+ sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates });
} else if !locator.crate_rejections.via_version.is_empty() {
- let mut err = struct_span_err!(
- sess,
- span,
- E0514,
- "found crate `{}` compiled by an incompatible version of rustc{}",
- crate_name,
- add,
- );
- err.help(&format!(
- "please recompile that crate using this compiler ({}) \
- (consider running `cargo clean` first)",
- rustc_version(),
- ));
let mismatches = locator.crate_rejections.via_version.iter();
for CrateMismatch { path, got } in mismatches {
- msg.push_str(&format!(
+ found_crates.push_str(&format!(
"\ncrate `{}` compiled by {}: {}",
crate_name,
got,
path.display(),
));
}
- err.note(&msg);
- err
- } else if !locator.crate_rejections.via_invalid.is_empty() {
- let mut err = struct_span_err!(
- sess,
+ sess.emit_err(IncompatibleRustc {
span,
- E0786,
- "found invalid metadata files for crate `{}`{}",
crate_name,
- add,
- );
+ add_info,
+ found_crates,
+ rustc_version: rustc_version(),
+ });
+ } else if !locator.crate_rejections.via_invalid.is_empty() {
+ let mut crate_rejections = Vec::new();
for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
- err.note(&got);
+ crate_rejections.push(got);
}
- err
+ sess.emit_err(InvalidMetadataFiles {
+ span,
+ crate_name,
+ add_info,
+ crate_rejections,
+ });
} else {
- let mut err = struct_span_err!(
- sess,
+ sess.emit_err(CannotFindCrate {
span,
- E0463,
- "can't find crate for `{}`{}",
crate_name,
- add,
- );
-
- if (crate_name == sym::std || crate_name == sym::core)
- && locator.triple != TargetTriple::from_triple(config::host_triple())
- {
- if missing_core {
- err.note(&format!(
- "the `{}` target may not be installed",
- locator.triple
- ));
- } else {
- err.note(&format!(
- "the `{}` target may not support the standard library",
- locator.triple
- ));
- }
- // NOTE: this suggests using rustup, even though the user may not have it installed.
- // That's because they could choose to install it; or this may give them a hint which
- // target they need to install from their distro.
- if missing_core {
- err.help(&format!(
- "consider downloading the target with `rustup target add {}`",
- locator.triple
- ));
- }
- // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
- // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
- // If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help.
- if !missing_core && span.is_dummy() {
- let current_crate =
- sess.opts.crate_name.as_deref().unwrap_or("<unknown>");
- err.note(&format!(
- "`std` is required by `{}` because it does not declare `#![no_std]`",
- current_crate
- ));
- }
- if sess.is_nightly_build() {
- err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
- }
- } else if crate_name
- == Symbol::intern(&sess.opts.unstable_opts.profiler_runtime)
- {
- err.note("the compiler may have been built without the profiler runtime");
- } else if crate_name.as_str().starts_with("rustc_") {
- err.help(
- "maybe you need to install the missing components with: \
- `rustup component add rust-src rustc-dev llvm-tools-preview`",
- );
- }
- err.span_label(span, "can't find crate");
- err
- };
-
- if !locator.crate_rejections.via_filename.is_empty() {
- let mismatches = locator.crate_rejections.via_filename.iter();
- for CrateMismatch { path, .. } in mismatches {
- err.note(&format!(
- "extern location for {} is of an unknown type: {}",
- crate_name,
- path.display(),
- ))
- .help(&format!(
- "file name should be lib*.rlib or {}*.{}",
- locator.dll_prefix, locator.dll_suffix
- ));
- }
+ add_info,
+ missing_core,
+ current_crate: sess
+ .opts
+ .crate_name
+ .clone()
+ .unwrap_or("<unknown>".to_string()),
+ is_nightly_build: sess.is_nightly_build(),
+ profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime),
+ locator_triple: locator.triple,
+ });
}
- err
}
- CrateError::NonDylibPlugin(crate_name) => struct_span_err!(
- sess,
- span,
- E0457,
- "plugin `{}` only found in rlib format, but must be available in dylib format",
- crate_name,
- ),
- };
-
- diag.emit();
+ CrateError::NonDylibPlugin(crate_name) => {
+ sess.emit_err(NoDylibPlugin { span, crate_name });
+ }
+ }
}
}
use rustc_ast::{NestedMetaItem, CRATE_NODE_ID};
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;
+use crate::errors::{
+ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget,
+ FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86,
+ IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm,
+ LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm,
+ LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleImportNameType,
+ MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink,
+ MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink,
+ UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi,
+ UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic,
+};
+
pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
let mut collector = Collector { tcx, libs: Vec::new() };
for id in tcx.hir().items() {
match item.name_or_empty() {
sym::name => {
if name.is_some() {
- let msg = "multiple `name` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleNamesInLink { span: item.span() });
continue;
}
let Some(link_name) = item.value_str() else {
- let msg = "link name must be of the form `name = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkNameForm { span: item.span() });
continue;
};
let span = item.name_value_literal_span().unwrap();
if link_name.is_empty() {
- struct_span_err!(sess, span, E0454, "link name must not be empty")
- .span_label(span, "empty link name")
- .emit();
+ sess.emit_err(EmptyLinkName { span });
}
name = Some((link_name, span));
}
sym::kind => {
if kind.is_some() {
- let msg = "multiple `kind` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleKindsInLink { span: item.span() });
continue;
}
let Some(link_kind) = item.value_str() else {
- let msg = "link kind must be of the form `kind = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkKindForm { span: item.span() });
continue;
};
"dylib" => NativeLibKind::Dylib { as_needed: None },
"framework" => {
if !sess.target.is_like_osx {
- struct_span_err!(
- sess,
- span,
- E0455,
- "link kind `framework` is only supported on Apple targets"
- )
- .emit();
+ sess.emit_err(LinkFrameworkApple { span });
}
NativeLibKind::Framework { as_needed: None }
}
"raw-dylib" => {
if !sess.target.is_like_windows {
- struct_span_err!(
- sess,
- span,
- E0455,
- "link kind `raw-dylib` is only supported on Windows targets"
- )
- .emit();
+ sess.emit_err(FrameworkOnlyWindows { span });
} else if !features.raw_dylib {
feature_err(
&sess.parse_sess,
NativeLibKind::RawDylib
}
kind => {
- let msg = format!(
- "unknown link kind `{kind}`, expected one of: \
- static, dylib, framework, raw-dylib"
- );
- struct_span_err!(sess, span, E0458, "{}", msg)
- .span_label(span, "unknown link kind")
- .emit();
+ sess.emit_err(UnknownLinkKind { span, kind });
continue;
}
};
}
sym::modifiers => {
if modifiers.is_some() {
- let msg =
- "multiple `modifiers` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleLinkModifiers { span: item.span() });
continue;
}
let Some(link_modifiers) = item.value_str() else {
- let msg = "link modifiers must be of the form `modifiers = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkModifiersForm { span: item.span() });
continue;
};
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
}
sym::cfg => {
if cfg.is_some() {
- let msg = "multiple `cfg` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleCfgs { span: item.span() });
continue;
}
let Some(link_cfg) = item.meta_item_list() else {
- let msg = "link cfg must be of the form `cfg(/* predicate */)`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkCfgForm { span: item.span() });
continue;
};
let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else {
- let msg = "link cfg must have a single predicate argument";
- sess.span_err(item.span(), msg);
+ sess.emit_err(LinkCfgSinglePredicate { span: item.span() });
continue;
};
if !features.link_cfg {
}
sym::wasm_import_module => {
if wasm_import_module.is_some() {
- let msg = "multiple `wasm_import_module` arguments \
- in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleWasmImport { span: item.span() });
continue;
}
let Some(link_wasm_import_module) = item.value_str() else {
- let msg = "wasm import module must be of the form \
- `wasm_import_module = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(WasmImportForm { span: item.span() });
continue;
};
wasm_import_module = Some((link_wasm_import_module, item.span()));
}
sym::import_name_type => {
if import_name_type.is_some() {
- let msg = "multiple `import_name_type` arguments in a single `#[link]` attribute";
- sess.span_err(item.span(), msg);
+ sess.emit_err(MultipleImportNameType { span: item.span() });
continue;
}
let Some(link_import_name_type) = item.value_str() else {
- let msg = "import name type must be of the form `import_name_type = \"string\"`";
- sess.span_err(item.span(), msg);
+ sess.emit_err(ImportNameTypeForm { span: item.span() });
continue;
};
if self.tcx.sess.target.arch != "x86" {
- let msg = "import name type is only supported on x86";
- sess.span_err(item.span(), msg);
+ sess.emit_err(ImportNameTypeX86 { span: item.span() });
continue;
}
"noprefix" => PeImportNameType::NoPrefix,
"undecorated" => PeImportNameType::Undecorated,
import_name_type => {
- let msg = format!(
- "unknown import name type `{import_name_type}`, expected one of: \
- decorated, noprefix, undecorated"
- );
- sess.span_err(item.span(), msg);
+ sess.emit_err(UnknownImportNameType {
+ span: item.span(),
+ import_name_type,
+ });
continue;
}
};
import_name_type = Some((link_import_name_type, item.span()));
}
_ => {
- let msg = "unexpected `#[link]` argument, expected one of: \
- name, kind, modifiers, cfg, wasm_import_module, import_name_type";
- sess.span_err(item.span(), msg);
+ sess.emit_err(UnexpectedLinkArg { span: item.span() });
}
}
}
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => {
- sess.span_err(
- span,
- "invalid linking modifier syntax, expected '+' or '-' prefix \
- before one of: bundle, verbatim, whole-archive, as-needed",
- );
+ sess.emit_err(InvalidLinkModifier { span });
continue;
}
};
}
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
- let msg = format!(
- "multiple `{modifier}` modifiers in a single `modifiers` argument"
- );
- sess.span_err(span, &msg);
+ sess.emit_err(MultipleModifiers { span, modifier });
} else {
*dst = Some(value);
}
assign_modifier(bundle)
}
("bundle", _) => {
- sess.span_err(
- span,
- "linking modifier `bundle` is only compatible with \
- `static` linking kind",
- );
+ sess.emit_err(BundleNeedsStatic { span });
}
("verbatim", _) => {
assign_modifier(whole_archive)
}
("whole-archive", _) => {
- sess.span_err(
- span,
- "linking modifier `whole-archive` is only compatible with \
- `static` linking kind",
- );
+ sess.emit_err(WholeArchiveNeedsStatic { span });
}
("as-needed", Some(NativeLibKind::Dylib { as_needed }))
assign_modifier(as_needed)
}
("as-needed", _) => {
- sess.span_err(
- span,
- "linking modifier `as-needed` is only compatible with \
- `dylib` and `framework` linking kinds",
- );
+ sess.emit_err(AsNeededCompatibility { span });
}
_ => {
- sess.span_err(
- span,
- format!(
- "unknown linking modifier `{modifier}`, expected one of: \
- bundle, verbatim, whole-archive, as-needed"
- ),
- );
+ sess.emit_err(UnknownLinkModifier { span, modifier });
}
}
}
if let Some((_, span)) = wasm_import_module {
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
- let msg = "`wasm_import_module` is incompatible with \
- other arguments in `#[link]` attributes";
- sess.span_err(span, msg);
+ sess.emit_err(IncompatibleWasmLink { span });
}
} else if name.is_none() {
- struct_span_err!(
- sess,
- m.span,
- E0459,
- "`#[link]` attribute requires a `name = \"string\"` argument"
- )
- .span_label(m.span, "missing `name` argument")
- .emit();
+ sess.emit_err(LinkRequiresName { span: m.span });
}
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
if let Some((_, span)) = import_name_type {
if kind != Some(NativeLibKind::RawDylib) {
- let msg = "import name type can only be used with link kind `raw-dylib`";
- sess.span_err(span, msg);
+ sess.emit_err(ImportNameTypeRaw { span });
}
}
let dll_imports = match kind {
Some(NativeLibKind::RawDylib) => {
if let Some((name, span)) = name && name.as_str().contains('\0') {
- sess.span_err(
- span,
- "link name must not contain NUL characters if link kind is `raw-dylib`",
- );
+ sess.emit_err(RawDylibNoNul { span });
}
foreign_mod_items
.iter()
.iter()
.find(|a| a.has_name(sym::link_ordinal))
.unwrap();
- sess.span_err(
- link_ordinal_attr.span,
- "`#[link_ordinal]` is only supported if link kind is `raw-dylib`",
- );
+ sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span });
}
}
for lib in &self.tcx.sess.opts.libs {
if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx {
// Cannot check this when parsing options because the target is not yet available.
- self.tcx.sess.err("library kind `framework` is only supported on Apple targets");
+ self.tcx.sess.emit_err(LibFrameworkApple);
}
if let Some(ref new_name) = lib.new_name {
let any_duplicate = self
.filter_map(|lib| lib.name.as_ref())
.any(|n| n.as_str() == lib.name);
if new_name.is_empty() {
- self.tcx.sess.err(format!(
- "an empty renaming target was specified for library `{}`",
- lib.name
- ));
+ self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name });
} else if !any_duplicate {
- self.tcx.sess.err(format!(
- "renaming of the library `{}` was specified, \
- however this crate contains no `#[link(...)]` \
- attributes referencing this library",
- lib.name
- ));
+ self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name });
} else if !renames.insert(&lib.name) {
- self.tcx.sess.err(format!(
- "multiple renamings were \
- specified for library `{}`",
- lib.name
- ));
+ self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name });
}
}
}
// involved or not, library reordering and kind overriding without
// explicit `:rename` in particular.
if lib.has_modifiers() || passed_lib.has_modifiers() {
- let msg = "overriding linking modifiers from command line is not supported";
match lib.foreign_module {
- Some(def_id) => self.tcx.sess.span_err(self.tcx.def_span(def_id), msg),
- None => self.tcx.sess.err(msg),
+ Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride {
+ span: Some(self.tcx.def_span(def_id)),
+ }),
+ None => {
+ self.tcx.sess.emit_err(NoLinkModOverride { span: None })
+ }
};
}
if passed_lib.kind != NativeLibKind::Unspecified {
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
}
_ => {
- self.tcx.sess.span_fatal(
- item.span,
- r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#,
- );
+ self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span });
}
}
} 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"#,
- );
+ self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span });
}
}
};
+use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile};
use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
use crate::rmeta::table::TableBuilder;
use crate::rmeta::*;
if should_encode_type(tcx, local_id, def_kind) {
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
}
- if let DefKind::TyParam | DefKind::ConstParam = def_kind {
- if let Some(default) = self.tcx.object_lifetime_default(def_id) {
- record!(self.tables.object_lifetime_default[def_id] <- default);
- }
+ if let DefKind::TyParam = def_kind {
+ let default = self.tcx.object_lifetime_default(def_id);
+ record!(self.tables.object_lifetime_default[def_id] <- default);
}
if let DefKind::Trait | DefKind::TraitAlias = def_kind {
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
let mut encoder = opaque::FileEncoder::new(path)
- .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to create file encoder: {}", err)));
+ .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err }));
encoder.emit_raw_bytes(METADATA_HEADER);
// Will be filled with the root position after encoding everything.
// Encode the root position.
let header = METADATA_HEADER.len();
file.seek(std::io::SeekFrom::Start(header as u64))
- .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to seek the file: {}", err)));
+ .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err }));
let pos = root.position.get();
file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])
- .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to write to the file: {}", err)));
+ .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err }));
// Return to the position where we are before writing the root position.
file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap();
[decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>,
[decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>,
- [] dep_kind: rustc_middle::dep_graph::DepKindStruct,
+ [] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>,
]);
)
}
/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
/// jump table instead of large matches.
-pub struct DepKindStruct {
+pub struct DepKindStruct<'tcx> {
/// Anonymous queries cannot be replayed from one compiler invocation to the next.
/// When their result is needed, it is recomputed. They are useful for fine-grained
/// dependency tracking, and caching within one compiler invocation.
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
/// `DefId` in `tcx.def_path_hash_to_def_id`.
- pub force_from_dep_node: Option<fn(tcx: TyCtxt<'_>, dep_node: DepNode) -> bool>,
+ pub force_from_dep_node: Option<fn(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool>,
/// Invoke a query to put the on-disk cached value in memory.
- pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'_>, DepNode)>,
+ pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'tcx>, DepNode)>,
}
impl DepKind {
Some(def_kind)
}
+ /// Finds the id of the parent node to this one.
+ ///
+ /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
pub fn find_parent_node(self, id: HirId) -> Option<HirId> {
if id.local_id == ItemLocalId::from_u32(0) {
Some(self.tcx.hir_owner_parent(id.owner))
query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxIndexSet<LocalDefId>> {
desc { "testing if a region is late bound" }
}
- /// For a given item (like a struct), gets the default lifetimes to be used
+ /// For a given item's generic parameter, gets the default lifetimes to be used
/// for each parameter if a trait object were to be passed for that parameter.
- /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`.
- /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`.
- query object_lifetime_default(key: DefId) -> Option<ObjectLifetimeDefault> {
- desc { "looking up lifetime defaults for generic parameter `{:?}`", key }
+ /// For example, for `T` in `struct Foo<'a, T>`, this would be `'static`.
+ /// For `T` in `struct Foo<'a, T: 'a>`, this would instead be `'a`.
+ /// This query will panic if passed something that is not a type parameter.
+ query object_lifetime_default(key: DefId) -> ObjectLifetimeDefault {
+ desc { "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(key) }
separate_provide_extern
}
query late_bound_vars_map(_: LocalDefId)
/// `let <PAT> = ...`
///
/// If a type annotation is included, it is added as an ascription pattern.
- pattern: Pat<'tcx>,
+ pattern: Box<Pat<'tcx>>,
/// `let pat: ty = <INIT>`
initializer: Option<ExprId>,
},
Let {
expr: ExprId,
- pat: Pat<'tcx>,
+ pat: Box<Pat<'tcx>>,
},
/// A `match` expression.
Match {
/// A `match` arm.
#[derive(Clone, Debug, HashStable)]
pub struct Arm<'tcx> {
- pub pattern: Pat<'tcx>,
+ pub pattern: Box<Pat<'tcx>>,
pub guard: Option<Guard<'tcx>>,
pub body: ExprId,
pub lint_level: LintLevel,
#[derive(Clone, Debug, HashStable)]
pub enum Guard<'tcx> {
If(ExprId),
- IfLet(Pat<'tcx>, ExprId),
+ IfLet(Box<Pat<'tcx>>, ExprId),
}
#[derive(Copy, Clone, Debug, HashStable)]
#[derive(Clone, Debug, HashStable)]
pub struct FieldPat<'tcx> {
pub field: Field,
- pub pattern: Pat<'tcx>,
+ pub pattern: Box<Pat<'tcx>>,
}
#[derive(Clone, Debug, HashStable)]
pub struct Pat<'tcx> {
pub ty: Ty<'tcx>,
pub span: Span,
- pub kind: Box<PatKind<'tcx>>,
+ pub kind: PatKind<'tcx>,
}
impl<'tcx> Pat<'tcx> {
pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
- Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
+ Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
}
}
AscribeUserType {
ascription: Ascription<'tcx>,
- subpattern: Pat<'tcx>,
+ subpattern: Box<Pat<'tcx>>,
},
/// `x`, `ref x`, `x @ P`, etc.
mode: BindingMode,
var: LocalVarId,
ty: Ty<'tcx>,
- subpattern: Option<Pat<'tcx>>,
+ subpattern: Option<Box<Pat<'tcx>>>,
/// Is this the leftmost occurrence of the binding, i.e., is `var` the
/// `HirId` of this pattern?
is_primary: bool,
/// `box P`, `&P`, `&mut P`, etc.
Deref {
- subpattern: Pat<'tcx>,
+ subpattern: Box<Pat<'tcx>>,
},
/// One of the following:
value: mir::ConstantKind<'tcx>,
},
- Range(PatRange<'tcx>),
+ Range(Box<PatRange<'tcx>>),
/// Matches against a slice, checking the length and extracting elements.
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
/// e.g., `&[ref xs @ ..]`.
Slice {
- prefix: Vec<Pat<'tcx>>,
- slice: Option<Pat<'tcx>>,
- suffix: Vec<Pat<'tcx>>,
+ prefix: Box<[Box<Pat<'tcx>>]>,
+ slice: Option<Box<Pat<'tcx>>>,
+ suffix: Box<[Box<Pat<'tcx>>]>,
},
/// Fixed match against an array; irrefutable.
Array {
- prefix: Vec<Pat<'tcx>>,
- slice: Option<Pat<'tcx>>,
- suffix: Vec<Pat<'tcx>>,
+ prefix: Box<[Box<Pat<'tcx>>]>,
+ slice: Option<Box<Pat<'tcx>>>,
+ suffix: Box<[Box<Pat<'tcx>>]>,
},
/// An or-pattern, e.g. `p | q`.
/// Invariant: `pats.len() >= 2`.
Or {
- pats: Vec<Pat<'tcx>>,
+ pats: Box<[Box<Pat<'tcx>>]>,
},
}
-#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
+#[derive(Clone, Debug, PartialEq, HashStable)]
pub struct PatRange<'tcx> {
pub lo: mir::ConstantKind<'tcx>,
pub hi: mir::ConstantKind<'tcx>,
};
let mut start_or_comma = || start_or_continue(", ");
- match *self.kind {
+ match self.kind {
PatKind::Wild => write!(f, "_"),
PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
Ok(())
}
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
- let variant = match *self.kind {
+ let variant = match self.kind {
PatKind::Variant { adt_def, variant_index, .. } => {
Some(adt_def.variant(variant_index))
}
let mut printed = 0;
for p in subpatterns {
- if let PatKind::Wild = *p.pattern.kind {
+ if let PatKind::Wild = p.pattern.kind {
continue;
}
let name = variant.fields[p.field.index()].name;
write!(f, "{}", subpattern)
}
PatKind::Constant { value } => write!(f, "{}", value),
- PatKind::Range(PatRange { lo, hi, end }) => {
+ PatKind::Range(box PatRange { lo, hi, end }) => {
write!(f, "{}", lo)?;
write!(f, "{}", end)?;
write!(f, "{}", hi)
PatKind::Slice { ref prefix, ref slice, ref suffix }
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
write!(f, "[")?;
- for p in prefix {
+ for p in prefix.iter() {
write!(f, "{}{}", start_or_comma(), p)?;
}
if let Some(ref slice) = *slice {
write!(f, "{}", start_or_comma())?;
- match *slice.kind {
+ match slice.kind {
PatKind::Wild => {}
_ => write!(f, "{}", slice)?,
}
write!(f, "..")?;
}
- for p in suffix {
+ for p in suffix.iter() {
write!(f, "{}{}", start_or_comma(), p)?;
}
write!(f, "]")
}
PatKind::Or { ref pats } => {
- for pat in pats {
+ for pat in pats.iter() {
write!(f, "{}{}", start_or_continue(" | "), pat)?;
}
Ok(())
static_assert_size!(Block, 56);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
- static_assert_size!(Pat<'_>, 24);
- static_assert_size!(PatKind<'_>, 112);
- static_assert_size!(Stmt<'_>, 72);
- static_assert_size!(StmtKind<'_>, 64);
+ static_assert_size!(Pat<'_>, 72);
+ static_assert_size!(PatKind<'_>, 56);
+ static_assert_size!(Stmt<'_>, 56);
+ static_assert_size!(StmtKind<'_>, 48);
}
pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
use PatKind::*;
- match pat.kind.as_ref() {
+ match &pat.kind {
AscribeUserType { subpattern, ascription: _ }
| Deref { subpattern }
| Binding {
Constant { value: _ } => {}
Range(_) => {}
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
- for subpattern in prefix {
+ for subpattern in prefix.iter() {
visitor.visit_pat(&subpattern);
}
if let Some(pat) = slice {
- visitor.visit_pat(pat);
+ visitor.visit_pat(&pat);
}
- for subpattern in suffix {
+ for subpattern in suffix.iter() {
visitor.visit_pat(&subpattern);
}
}
Or { pats } => {
- for pat in pats {
+ for pat in pats.iter() {
visitor.visit_pat(&pat);
}
}
pub promoted: P,
}
+impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ format!("{:?}", self).into_diagnostic_arg()
+ }
+}
+
impl<'tcx> Unevaluated<'tcx> {
#[inline]
pub fn shrink(self) -> Unevaluated<'tcx, ()> {
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct CanonicalUserTypeAnnotation<'tcx> {
- pub user_ty: CanonicalUserType<'tcx>,
+ pub user_ty: Box<CanonicalUserType<'tcx>>,
pub span: Span,
pub inferred_ty: Ty<'tcx>,
}
pub queries: &'tcx dyn query::QueryEngine<'tcx>,
pub query_caches: query::QueryCaches<'tcx>,
- query_kinds: &'tcx [DepKindStruct],
+ query_kinds: &'tcx [DepKindStruct<'tcx>],
// Internal caches for metadata decoding. No need to track deps on this.
pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
dep_graph: DepGraph,
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
queries: &'tcx dyn query::QueryEngine<'tcx>,
- query_kinds: &'tcx [DepKindStruct],
+ query_kinds: &'tcx [DepKindStruct<'tcx>],
crate_name: &str,
output_filenames: OutputFilenames,
) -> GlobalCtxt<'tcx> {
}
}
- pub(crate) fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct {
+ pub(crate) fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct<'tcx> {
&self.query_kinds[k as usize]
}
}
}
+impl rustc_errors::IntoDiagnosticArg for PolyTraitRef<'_> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
/// An existential reference to a trait, where `Self` is erased.
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
/// ```ignore (illustrative)
lint_level,
else_block,
} => {
- let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
+ let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
// Enter the remainder scope, i.e., the bindings' destruction scope.
ArmHasGuard(false),
Some((None, initializer_span)),
);
- this.expr_into_pattern(block, pattern.clone(), init) // irrefutable pattern
+ this.expr_into_pattern(block, pattern, init) // irrefutable pattern
}
})
},
Constant { span, user_ty: None, literal }
}
ExprKind::NonHirLiteral { lit, ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|box user_ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
Constant { span, user_ty: user_ty, literal }
}
ExprKind::ZstLiteral { ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|box user_ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
Constant { span, user_ty: user_ty, literal }
}
ExprKind::NamedConst { def_id, substs, ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|box user_ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
fake_borrow_temps,
)
);
- if let Some(box user_ty) = user_ty {
+ if let Some(user_ty) = user_ty {
let annotation_index =
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: expr.ty,
});
let source = &this.thir[source];
let temp =
unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
- if let Some(box user_ty) = user_ty {
+ if let Some(user_ty) = user_ty {
let annotation_index =
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: expr.ty,
});
this.cfg.push(
};
let inferred_ty = expr.ty;
- let user_ty = user_ty.as_ref().map(|box user_ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty: *user_ty,
+ user_ty: user_ty.clone(),
inferred_ty,
})
});
pub(super) fn expr_into_pattern(
&mut self,
mut block: BasicBlock,
- irrefutable_pat: Pat<'tcx>,
+ irrefutable_pat: &Pat<'tcx>,
initializer: &Expr<'tcx>,
) -> BlockAnd<()> {
- match *irrefutable_pat.kind {
+ match irrefutable_pat.kind {
// Optimize the case of `let x = ...` to write directly into `x`
PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => {
let place =
// broken.
PatKind::AscribeUserType {
subpattern:
- Pat {
+ box Pat {
kind:
- box PatKind::Binding {
- mode: BindingMode::ByValue,
- var,
- subpattern: None,
- ..
+ PatKind::Binding {
+ mode: BindingMode::ByValue, var, subpattern: None, ..
},
..
},
- ascription: thir::Ascription { annotation, variance: _ },
+ ascription: thir::Ascription { ref annotation, variance: _ },
} => {
let place =
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
let ty_source_info = self.source_info(annotation.span);
- let base = self.canonical_user_type_annotations.push(annotation);
+ let base = self.canonical_user_type_annotations.push(annotation.clone());
self.cfg.push(
block,
Statement {
pub(crate) fn place_into_pattern(
&mut self,
block: BasicBlock,
- irrefutable_pat: Pat<'tcx>,
+ irrefutable_pat: &Pat<'tcx>,
initializer: PlaceBuilder<'tcx>,
set_match_place: bool,
) -> BlockAnd<()> {
"visit_primary_bindings: pattern={:?} pattern_user_ty={:?}",
pattern, pattern_user_ty
);
- match *pattern.kind {
+ match pattern.kind {
PatKind::Binding {
mutability,
name,
| PatKind::Slice { ref prefix, ref slice, ref suffix } => {
let from = u64::try_from(prefix.len()).unwrap();
let to = u64::try_from(suffix.len()).unwrap();
- for subpattern in prefix {
+ for subpattern in prefix.iter() {
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
}
for subpattern in slice {
f,
);
}
- for subpattern in suffix {
+ for subpattern in suffix.iter() {
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
}
}
// may not all be in the leftmost subpattern. For example in
// `let (x | y) = ...`, the primary binding of `y` occurs in
// the right subpattern
- for subpattern in pats {
+ for subpattern in pats.iter() {
self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f);
}
}
},
/// Test whether the value falls within an inclusive or exclusive range
- Range(PatRange<'tcx>),
+ Range(Box<PatRange<'tcx>>),
/// Test that the length of the slice is equal to `len`.
Len { len: u64, op: BinOp },
// All of the or-patterns have been sorted to the end, so if the first
// pattern is an or-pattern we only have or-patterns.
- match *first_candidate.match_pairs[0].pattern.kind {
+ match first_candidate.match_pairs[0].pattern.kind {
PatKind::Or { .. } => (),
_ => {
self.test_candidates(
let mut otherwise = None;
for match_pair in match_pairs {
- let PatKind::Or { ref pats } = &*match_pair.pattern.kind else {
+ let PatKind::Or { ref pats } = &match_pair.pattern.kind else {
bug!("Or-patterns should have been sorted to the end");
};
let or_span = match_pair.pattern.span;
&mut self,
candidate: &mut Candidate<'pat, 'tcx>,
otherwise: &mut Option<BasicBlock>,
- pats: &'pat [Pat<'tcx>],
+ pats: &'pat [Box<Pat<'tcx>>],
or_span: Span,
place: PlaceBuilder<'tcx>,
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
let else_block_span = self.thir[else_block].span;
let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| {
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
- let pat = Pat { ty: init.ty, span: else_block_span, kind: Box::new(PatKind::Wild) };
+ let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild };
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
this.declare_bindings(
visibility_scope,
loop {
let match_pairs = mem::take(&mut candidate.match_pairs);
- if let [MatchPair { pattern: Pat { kind: box PatKind::Or { pats }, .. }, place }] =
+ if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] =
&*match_pairs
{
existing_bindings.extend_from_slice(&new_bindings);
// late as possible.
candidate
.match_pairs
- .sort_by_key(|pair| matches!(*pair.pattern.kind, PatKind::Or { .. }));
+ .sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
debug!(simplified = ?candidate, "simplify_candidate");
return false; // if we were not able to simplify any, done.
}
&mut self,
candidate: &Candidate<'pat, 'tcx>,
place: PlaceBuilder<'tcx>,
- pats: &'pat [Pat<'tcx>],
+ pats: &'pat [Box<Pat<'tcx>>],
) -> Vec<Candidate<'pat, 'tcx>> {
pats.iter()
- .map(|pat| {
+ .map(|box pat| {
let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard);
self.simplify_candidate(&mut candidate);
candidate
candidate: &mut Candidate<'pat, 'tcx>,
) -> Result<(), MatchPair<'pat, 'tcx>> {
let tcx = self.tcx;
- match *match_pair.pattern.kind {
+ match match_pair.pattern.kind {
PatKind::AscribeUserType {
ref subpattern,
ascription: thir::Ascription { ref annotation, variance },
Err(match_pair)
}
- PatKind::Range(PatRange { lo, hi, end }) => {
+ PatKind::Range(box PatRange { lo, hi, end }) => {
let (range, bias) = match *lo.ty().kind() {
ty::Char => {
(Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0)
&mut candidate.match_pairs,
&match_pair.place,
prefix,
- slice.as_ref(),
+ slice,
suffix,
);
Ok(())
&mut candidate.match_pairs,
&match_pair.place,
prefix,
- slice.as_ref(),
+ slice,
suffix,
);
Ok(())
///
/// It is a bug to call this with a not-fully-simplified pattern.
pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
- match *match_pair.pattern.kind {
+ match match_pair.pattern.kind {
PatKind::Variant { adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
span: match_pair.pattern.span,
kind: TestKind::Switch {
kind: TestKind::Eq { value, ty: match_pair.pattern.ty },
},
- PatKind::Range(range) => {
+ PatKind::Range(ref range) => {
assert_eq!(range.lo.ty(), match_pair.pattern.ty);
assert_eq!(range.hi.ty(), match_pair.pattern.ty);
- Test { span: match_pair.pattern.span, kind: TestKind::Range(range) }
+ Test { span: match_pair.pattern.span, kind: TestKind::Range(range.clone()) }
}
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
return false;
};
- match *match_pair.pattern.kind {
+ match match_pair.pattern.kind {
PatKind::Constant { value } => {
options
.entry(value)
PatKind::Variant { .. } => {
panic!("you should have called add_variants_to_switch instead!");
}
- PatKind::Range(range) => {
+ PatKind::Range(ref range) => {
// Check that none of the switch values are in the range.
- self.values_not_contained_in_range(range, options).unwrap_or(false)
+ self.values_not_contained_in_range(&*range, options).unwrap_or(false)
}
PatKind::Slice { .. }
| PatKind::Array { .. }
return false;
};
- match *match_pair.pattern.kind {
+ match match_pair.pattern.kind {
PatKind::Variant { adt_def: _, variant_index, .. } => {
// We have a pattern testing for variant `variant_index`
// set the corresponding index to true
}
}
- TestKind::Range(PatRange { lo, hi, ref end }) => {
+ TestKind::Range(box PatRange { lo, hi, ref end }) => {
let lower_bound_success = self.cfg.start_new_block();
let target_blocks = make_target_blocks(self);
let (match_pair_index, match_pair) =
candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?;
- match (&test.kind, &*match_pair.pattern.kind) {
+ match (&test.kind, &match_pair.pattern.kind) {
// If we are performing a variant switch, then this
// informs variant patterns, but nothing else.
(
Some(index)
}
- (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(range)) => {
+ (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(ref range)) => {
let not_contained =
- self.values_not_contained_in_range(range, options).unwrap_or(false);
+ self.values_not_contained_in_range(&*range, options).unwrap_or(false);
if not_contained {
// No switch values are contained in the pattern range,
match_pair_index,
candidate,
prefix,
- slice.as_ref(),
+ slice,
suffix,
);
Some(0)
match_pair_index,
candidate,
prefix,
- slice.as_ref(),
+ slice,
suffix,
);
Some(0)
}
}
- (&TestKind::Range(test), &PatKind::Range(pat)) => {
+ (&TestKind::Range(ref test), &PatKind::Range(ref pat)) => {
use std::cmp::Ordering::*;
if test == pat {
no_overlap
}
- (&TestKind::Range(range), &PatKind::Constant { value }) => {
- if let Some(false) = self.const_range_contains(range, value) {
+ (&TestKind::Range(ref range), &PatKind::Constant { value }) => {
+ if let Some(false) = self.const_range_contains(&*range, value) {
// `value` is not contained in the testing range,
// so `value` can be matched only if this test fails.
Some(1)
// However, at this point we can still encounter or-patterns that were extracted
// from previous calls to `sort_candidate`, so we need to manually address that
// case to avoid panicking in `self.test()`.
- if let PatKind::Or { .. } = &*match_pair.pattern.kind {
+ if let PatKind::Or { .. } = &match_pair.pattern.kind {
return None;
}
&mut self,
match_pair_index: usize,
candidate: &mut Candidate<'pat, 'tcx>,
- prefix: &'pat [Pat<'tcx>],
- opt_slice: Option<&'pat Pat<'tcx>>,
- suffix: &'pat [Pat<'tcx>],
+ prefix: &'pat [Box<Pat<'tcx>>],
+ opt_slice: &'pat Option<Box<Pat<'tcx>>>,
+ suffix: &'pat [Box<Pat<'tcx>>],
) {
let removed_place = candidate.match_pairs.remove(match_pair_index).place;
self.prefix_slice_suffix(
fn const_range_contains(
&self,
- range: PatRange<'tcx>,
+ range: &PatRange<'tcx>,
value: ConstantKind<'tcx>,
) -> Option<bool> {
use std::cmp::Ordering::*;
fn values_not_contained_in_range(
&self,
- range: PatRange<'tcx>,
+ range: &PatRange<'tcx>,
options: &FxIndexMap<ConstantKind<'tcx>, u128>,
) -> Option<bool> {
for &val in options.keys() {
&mut self,
match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
place: &PlaceBuilder<'tcx>,
- prefix: &'pat [Pat<'tcx>],
- opt_slice: Option<&'pat Pat<'tcx>>,
- suffix: &'pat [Pat<'tcx>],
+ prefix: &'pat [Box<Pat<'tcx>>],
+ opt_slice: &'pat Option<Box<Pat<'tcx>>>,
+ suffix: &'pat [Box<Pat<'tcx>>],
) {
let tcx = self.tcx;
let (min_length, exact_size) = if let Ok(place_resolved) =
let original_source_scope = self.source_scope;
let span = pattern.span;
self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
- match *pattern.kind {
+ match pattern.kind {
// Don't introduce extra copies for simple bindings
PatKind::Binding {
mutability,
Some((Some(&place), span)),
);
let place_builder = PlaceBuilder::from(local);
- unpack!(block = self.place_into_pattern(block, pattern, place_builder, false));
+ unpack!(
+ block =
+ self.place_into_pattern(block, pattern.as_ref(), place_builder, false)
+ );
}
}
self.source_scope = original_source_scope;
fn visit_pat(&mut self, pat: &Pat<'tcx>) {
if self.in_union_destructure {
- match *pat.kind {
+ match pat.kind {
// binding to a variable allows getting stuff out of variable
PatKind::Binding { .. }
// match is conditional on having this value
}
};
- match &*pat.kind {
+ match &pat.kind {
PatKind::Leaf { .. } => {
if let ty::Adt(adt_def, ..) = pat.ty.kind() {
if adt_def.is_union() {
{
debug!("mirror_stmts: user_ty={:?}", user_ty);
let annotation = CanonicalUserTypeAnnotation {
- user_ty,
+ user_ty: Box::new(user_ty),
span: ty.span,
inferred_ty: self.typeck_results.node_type(ty.hir_id),
};
- pattern = Pat {
+ pattern = Box::new(Pat {
ty: pattern.ty,
span: pattern.span,
- kind: Box::new(PatKind::AscribeUserType {
+ kind: PatKind::AscribeUserType {
ascription: Ascription {
annotation,
variance: ty::Variance::Covariant,
},
subpattern: pattern,
- }),
- };
+ },
+ });
}
}
}
#[instrument(level = "debug", skip(self))]
- pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
+ pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box<Pat<'tcx>> {
let p = match self.tcx.hir().get(p.hir_id) {
Node::Pat(p) => p,
node => bug!("pattern became {:?}", node),
id: hir::HirId,
span: Span,
mir_structural_match_violation: bool,
- ) -> Pat<'tcx> {
+ ) -> Box<Pat<'tcx>> {
self.tcx.infer_ctxt().enter(|infcx| {
let mut convert = ConstToPat::new(self, id, span, infcx);
convert.to_pat(cv, mir_structural_match_violation)
&mut self,
cv: mir::ConstantKind<'tcx>,
mir_structural_match_violation: bool,
- ) -> Pat<'tcx> {
+ ) -> Box<Pat<'tcx>> {
trace!(self.treat_byte_string_as_slice);
// This method is just a wrapper handling a validity check; the heavy lifting is
// performed by the recursive `recur` method, which is not meant to be
// level of indirection can be eliminated
let inlined_const_as_pat =
- self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| Pat {
- span: self.span,
- ty: cv.ty(),
- kind: Box::new(PatKind::Constant { value: cv }),
+ self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| {
+ Box::new(Pat {
+ span: self.span,
+ ty: cv.ty(),
+ kind: PatKind::Constant { value: cv },
+ })
});
if self.include_lint_checks && !self.saw_const_match_error.get() {
&self,
cv: mir::ConstantKind<'tcx>,
mir_structural_match_violation: bool,
- ) -> Result<Pat<'tcx>, FallbackToConstRef> {
+ ) -> Result<Box<Pat<'tcx>>, FallbackToConstRef> {
let id = self.id;
let span = self.span;
let tcx = self.tcx();
.map(|val| self.recur(*val, false))
.collect::<Result<_, _>>()?,
slice: None,
- suffix: Vec::new(),
+ suffix: Box::new([]),
},
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
// These are not allowed and will error elsewhere anyway.
let old = self.behind_reference.replace(true);
let array = tcx.deref_mir_constant(self.param_env.and(cv));
let val = PatKind::Deref {
- subpattern: Pat {
- kind: Box::new(PatKind::Array {
+ subpattern: Box::new(Pat {
+ kind: PatKind::Array {
prefix: tcx
.destructure_mir_constant(param_env, array)
.fields
.map(|val| self.recur(*val, false))
.collect::<Result<_, _>>()?,
slice: None,
- suffix: vec![],
- }),
+ suffix: Box::new([]),
+ },
span,
ty: *pointee_ty,
- },
+ }),
};
self.behind_reference.set(old);
val
let old = self.behind_reference.replace(true);
let array = tcx.deref_mir_constant(self.param_env.and(cv));
let val = PatKind::Deref {
- subpattern: Pat {
- kind: Box::new(PatKind::Slice {
+ subpattern: Box::new(Pat {
+ kind: PatKind::Slice {
prefix: tcx
.destructure_mir_constant(param_env, array)
.fields
.map(|val| self.recur(*val, false))
.collect::<Result<_, _>>()?,
slice: None,
- suffix: vec![],
- }),
+ suffix: Box::new([]),
+ },
span,
ty: tcx.mk_slice(elem_ty),
- },
+ }),
};
self.behind_reference.set(old);
val
);
}
- Ok(Pat { span, ty: cv.ty(), kind: Box::new(kind) })
+ Ok(Box::new(Pat { span, ty: cv.ty(), kind }))
}
}
/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) {
- if let PatKind::Or { pats } = pat.kind.as_ref() {
- for pat in pats {
- expand(pat, vec);
+ if let PatKind::Or { pats } = &pat.kind {
+ for pat in pats.iter() {
+ expand(&pat, vec);
}
} else {
vec.push(pat)
let kind = if lo == hi {
PatKind::Constant { value: lo_const }
} else {
- PatKind::Range(PatRange { lo: lo_const, hi: hi_const, end: RangeEnd::Included })
+ PatKind::Range(Box::new(PatRange {
+ lo: lo_const,
+ hi: hi_const,
+ end: RangeEnd::Included,
+ }))
};
- Pat { ty, span: DUMMY_SP, kind: Box::new(kind) }
+ Pat { ty, span: DUMMY_SP, kind }
}
/// Lint on likely incorrect range patterns (#63987)
let mkpat = |pat| DeconstructedPat::from_pat(cx, pat);
let ctor;
let fields;
- match pat.kind.as_ref() {
+ match &pat.kind {
PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern),
PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat),
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
fields = Fields::singleton(cx, pat);
}
ty::Adt(adt, _) => {
- ctor = match pat.kind.as_ref() {
+ ctor = match pat.kind {
PatKind::Leaf { .. } => Single,
- PatKind::Variant { variant_index, .. } => Variant(*variant_index),
+ PatKind::Variant { variant_index, .. } => Variant(variant_index),
_ => bug!(),
};
let variant = &adt.variant(ctor.variant_index_for_adt(*adt));
}
}
}
- &PatKind::Range(PatRange { lo, hi, end }) => {
+ &PatKind::Range(box PatRange { lo, hi, end }) => {
let ty = lo.ty();
ctor = if let Some(int_range) = IntRange::from_range(
cx.tcx,
FixedLen(prefix.len() + suffix.len())
};
ctor = Slice(Slice::new(array_len, kind));
- fields = Fields::from_iter(cx, prefix.iter().chain(suffix).map(mkpat));
+ fields =
+ Fields::from_iter(cx, prefix.iter().chain(suffix.iter()).map(|p| mkpat(&*p)));
}
PatKind::Or { .. } => {
ctor = Or;
pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> {
let is_wildcard = |pat: &Pat<'_>| {
- matches!(*pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
+ matches!(pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
};
- let mut subpatterns = self.iter_fields().map(|p| p.to_pat(cx));
- let pat = match &self.ctor {
+ let mut subpatterns = self.iter_fields().map(|p| Box::new(p.to_pat(cx)));
+ let kind = match &self.ctor {
Single | Variant(_) => match self.ty.kind() {
ty::Tuple(..) => PatKind::Leaf {
subpatterns: subpatterns
.enumerate()
- .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p })
+ .map(|(i, pattern)| FieldPat { field: Field::new(i), pattern })
.collect(),
},
ty::Adt(adt_def, _) if adt_def.is_box() => {
FixedLen(_) => PatKind::Slice {
prefix: subpatterns.collect(),
slice: None,
- suffix: vec![],
+ suffix: Box::new([]),
},
VarLen(prefix, _) => {
let mut subpatterns = subpatterns.peekable();
subpatterns.next();
}
}
- let suffix: Vec<_> = subpatterns.collect();
+ let suffix: Box<[_]> = subpatterns.collect();
let wild = Pat::wildcard_from_ty(self.ty);
- PatKind::Slice { prefix, slice: Some(wild), suffix }
+ PatKind::Slice {
+ prefix: prefix.into_boxed_slice(),
+ slice: Some(Box::new(wild)),
+ suffix,
+ }
}
}
}
&Str(value) => PatKind::Constant { value },
- &FloatRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }),
+ &FloatRange(lo, hi, end) => PatKind::Range(Box::new(PatRange { lo, hi, end })),
IntRange(range) => return range.to_pat(cx.tcx, self.ty),
Wildcard | NonExhaustive => PatKind::Wild,
Missing { .. } => bug!(
}
};
- Pat { ty: self.ty, span: DUMMY_SP, kind: Box::new(pat) }
+ Pat { ty: self.ty, span: DUMMY_SP, kind }
}
pub(super) fn is_or_pat(&self) -> bool {
param_env: ty::ParamEnv<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
pat: &'tcx hir::Pat<'tcx>,
-) -> Pat<'tcx> {
+) -> Box<Pat<'tcx>> {
let mut pcx = PatCtxt::new(tcx, param_env, typeck_results);
let result = pcx.lower_pattern(pat);
if !pcx.errors.is_empty() {
self
}
- pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+ pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
// When implicit dereferences have been inserted in this pattern, the unadjusted lowered
// pattern has the type that results *after* dereferencing. For example, in this code:
//
let unadjusted_pat = self.lower_pattern_unadjusted(pat);
self.typeck_results.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold(
unadjusted_pat,
- |pat, ref_ty| {
+ |pat: Box<_>, ref_ty| {
debug!("{:?}: wrapping pattern with type {:?}", pat, ref_ty);
- Pat {
+ Box::new(Pat {
span: pat.span,
ty: *ref_ty,
- kind: Box::new(PatKind::Deref { subpattern: pat }),
- }
+ kind: PatKind::Deref { subpattern: pat },
+ })
},
)
}
expr: &'tcx hir::Expr<'tcx>,
) -> (PatKind<'tcx>, Option<Ascription<'tcx>>) {
match self.lower_lit(expr) {
- PatKind::AscribeUserType { ascription, subpattern: Pat { kind: box kind, .. } } => {
+ PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
(kind, Some(ascription))
}
kind => (kind, None),
match (end, cmp) {
// `x..y` where `x < y`.
// Non-empty because the range includes at least `x`.
- (RangeEnd::Excluded, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+ (RangeEnd::Excluded, Some(Ordering::Less)) => {
+ PatKind::Range(Box::new(PatRange { lo, hi, end }))
+ }
// `x..y` where `x >= y`. The range is empty => error.
(RangeEnd::Excluded, _) => {
struct_span_err!(
// `x..=y` where `x == y`.
(RangeEnd::Included, Some(Ordering::Equal)) => PatKind::Constant { value: lo },
// `x..=y` where `x < y`.
- (RangeEnd::Included, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+ (RangeEnd::Included, Some(Ordering::Less)) => {
+ PatKind::Range(Box::new(PatRange { lo, hi, end }))
+ }
// `x..=y` where `x > y` hence the range is empty => error.
(RangeEnd::Included, _) => {
let mut err = struct_span_err!(
}
}
- fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
let mut ty = self.typeck_results.node_type(pat.hir_id);
let kind = match pat.kind {
// constants somewhere. Have them on the range pattern.
for end in &[lo, hi] {
if let Some((_, Some(ascription))) = end {
- let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
+ let subpattern = Box::new(Pat { span: pat.span, ty, kind });
kind =
PatKind::AscribeUserType { ascription: ascription.clone(), subpattern };
}
hir::PatKind::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) },
};
- Pat { span: pat.span, ty, kind: Box::new(kind) }
+ Box::new(Pat { span: pat.span, ty, kind })
}
fn lower_tuple_subpats(
.collect()
}
- fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec<Pat<'tcx>> {
+ fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Box<Pat<'tcx>>]> {
pats.iter().map(|p| self.lower_pattern(p)).collect()
}
- fn lower_opt_pattern(&mut self, pat: &'tcx Option<&'tcx hir::Pat<'tcx>>) -> Option<Pat<'tcx>> {
+ fn lower_opt_pattern(
+ &mut self,
+ pat: &'tcx Option<&'tcx hir::Pat<'tcx>>,
+ ) -> Option<Box<Pat<'tcx>>> {
pat.as_ref().map(|p| self.lower_pattern(p))
}
if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
let annotation = CanonicalUserTypeAnnotation {
- user_ty,
+ user_ty: Box::new(user_ty),
span,
inferred_ty: self.typeck_results.node_type(hir_id),
};
kind = PatKind::AscribeUserType {
- subpattern: Pat { span, ty, kind: Box::new(kind) },
+ subpattern: Box::new(Pat { span, ty, kind }),
ascription: Ascription { annotation, variance: ty::Variance::Covariant },
};
}
/// it to `const_to_pat`. Any other path (like enum variants without fields)
/// is converted to the corresponding pattern via `lower_variant_or_leaf`.
#[instrument(skip(self), level = "debug")]
- fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Pat<'tcx> {
+ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Box<Pat<'tcx>> {
let ty = self.typeck_results.node_type(id);
let res = self.typeck_results.qpath_res(qpath, id);
- let pat_from_kind = |kind| Pat { span, ty, kind: Box::new(kind) };
+ let pat_from_kind = |kind| Box::new(Pat { span, ty, kind });
let (def_id, is_associated_const) = match res {
Res::Def(DefKind::Const, def_id) => (def_id, false),
let user_provided_types = self.typeck_results().user_provided_types();
if let Some(&user_ty) = user_provided_types.get(id) {
let annotation = CanonicalUserTypeAnnotation {
- user_ty,
+ user_ty: Box::new(user_ty),
span,
inferred_ty: self.typeck_results().node_type(id),
};
- Pat {
+ Box::new(Pat {
span,
- kind: Box::new(PatKind::AscribeUserType {
+ kind: PatKind::AscribeUserType {
subpattern: pattern,
ascription: Ascription {
annotation,
/// `variance` field documentation for details.
variance: ty::Variance::Contravariant,
},
- }),
+ },
ty: const_.ty(),
- }
+ })
} else {
pattern
}
_ => bug!("Expected either ConstKind::Param or ConstKind::Unevaluated"),
}
}
- mir::ConstantKind::Val(_, _) => *self.const_to_pat(value, id, span, false).kind,
+ mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
}
}
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
let (lit, neg) = match expr.kind {
hir::ExprKind::Path(ref qpath) => {
- return *self.lower_path(qpath, expr.hir_id, expr.span).kind;
+ return self.lower_path(qpath, expr.hir_id, expr.span).kind;
}
hir::ExprKind::ConstBlock(ref anon_const) => {
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
let lit_input =
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) {
- Ok(constant) => *self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
+ Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
Err(LitToConstError::Reported) => PatKind::Wild,
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
}
}
}
+impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<[T]> {
+ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
+ self.iter().map(|t| t.fold_with(folder)).collect()
+ }
+}
+
impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
self.as_ref().map(|t| t.fold_with(folder))
PatKind::Deref { subpattern: subpattern.fold_with(folder) }
}
PatKind::Constant { value } => PatKind::Constant { value },
- PatKind::Range(range) => PatKind::Range(range),
+ PatKind::Range(ref range) => PatKind::Range(range.clone()),
PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice {
prefix: prefix.fold_with(folder),
slice: slice.fold_with(folder),
/// the return type of `main`. This is not needed when
/// the user writes their own `start` manually.
fn push_extra_entry_roots(&mut self) {
- let Some((main_def_id, EntryFnType::Main)) = self.entry_fn else {
+ let Some((main_def_id, EntryFnType::Main { .. })) = self.entry_fn else {
return;
};
// Prepend `self.attrs` to `attrs`.
// FIXME: require passing an NT to prevent misuse of this method
pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) {
- let mut self_attrs = self.attrs.clone();
+ let mut self_attrs = self.attrs;
std::mem::swap(attrs, &mut self_attrs);
attrs.extend(self_attrs);
}
sym::no_implicit_prelude => {
self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
}
- sym::rustc_object_lifetime_default => {
- self.check_object_lifetime_default(hir_id, span)
- }
+ sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
_ => {}
}
}
/// Debugging aid for `object_lifetime_default` query.
- fn check_object_lifetime_default(&self, hir_id: HirId, span: Span) {
+ fn check_object_lifetime_default(&self, hir_id: HirId) {
let tcx = self.tcx;
if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) {
- let object_lifetime_default_reprs: String = generics
- .params
- .iter()
- .filter_map(|p| {
- let param_id = tcx.hir().local_def_id(p.hir_id);
- let default = tcx.object_lifetime_default(param_id)?;
- Some(match default {
- ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
- ObjectLifetimeDefault::Static => "'static".to_owned(),
- ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
- ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
- })
- })
- .collect::<Vec<String>>()
- .join(",");
-
- tcx.sess.span_err(span, &object_lifetime_default_reprs);
+ for p in generics.params {
+ let hir::GenericParamKind::Type { .. } = p.kind else { continue };
+ let param_id = tcx.hir().local_def_id(p.hir_id);
+ let default = tcx.object_lifetime_default(param_id);
+ let repr = match default {
+ ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
+ ObjectLifetimeDefault::Static => "'static".to_owned(),
+ ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
+ ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
+ };
+ tcx.sess.span_err(p.span, &repr);
+ }
}
}
sym::automatically_derived,
sym::start,
sym::rustc_main,
+ sym::unix_sigpipe,
sym::derive,
sym::test,
sym::test_case,
-use rustc_ast::{entry::EntryPointType, Attribute};
+use rustc_ast::entry::EntryPointType;
use rustc_errors::struct_span_err;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{DefIdTree, TyCtxt};
-use rustc_session::config::{CrateType, EntryFnType};
+use rustc_session::config::{sigpipe, CrateType, EntryFnType};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol, DUMMY_SP};
}
}
-fn err_if_attr_found(ctxt: &EntryContext<'_>, attrs: &[Attribute], sym: Symbol) {
+fn err_if_attr_found(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol, details: &str) {
+ let attrs = ctxt.tcx.hir().attrs(id.hir_id());
if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym) {
ctxt.tcx
.sess
- .struct_span_err(
- attr.span,
- &format!("`{}` attribute can only be used on functions", sym),
- )
+ .struct_span_err(attr.span, &format!("`{}` attribute {}", sym, details))
.emit();
}
}
let at_root = ctxt.tcx.opt_local_parent(id.def_id) == Some(CRATE_DEF_ID);
match entry_point_type(ctxt, id, at_root) {
- EntryPointType::None => (),
+ EntryPointType::None => {
+ err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
+ }
_ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => {
- let attrs = ctxt.tcx.hir().attrs(id.hir_id());
- err_if_attr_found(ctxt, attrs, sym::start);
- err_if_attr_found(ctxt, attrs, sym::rustc_main);
+ err_if_attr_found(ctxt, id, sym::start, "can only be used on functions");
+ err_if_attr_found(ctxt, id, sym::rustc_main, "can only be used on functions");
}
EntryPointType::MainNamed => (),
EntryPointType::OtherMain => {
+ err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on root `fn main()`");
ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id));
}
EntryPointType::RustcMainAttr => {
}
}
EntryPointType::Start => {
+ err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id())));
} else {
fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
if let Some((def_id, _)) = visitor.start_fn {
Some((def_id.to_def_id(), EntryFnType::Start))
- } else if let Some((def_id, _)) = visitor.attr_main_fn {
- Some((def_id.to_def_id(), EntryFnType::Main))
+ } else if let Some((local_def_id, _)) = visitor.attr_main_fn {
+ let def_id = local_def_id.to_def_id();
+ Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }))
} else {
if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() {
// non-local main imports are handled below
)
.emit();
}
- return Some((def_id, EntryFnType::Main));
+ return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }));
}
no_main_err(tcx, visitor);
None
}
}
+fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
+ if let Some(attr) = tcx.get_attr(def_id, sym::unix_sigpipe) {
+ match (attr.value_str(), attr.meta_item_list()) {
+ (Some(sym::inherit), None) => sigpipe::INHERIT,
+ (Some(sym::sig_ign), None) => sigpipe::SIG_IGN,
+ (Some(sym::sig_dfl), None) => sigpipe::SIG_DFL,
+ (_, Some(_)) => {
+ // Keep going so that `fn emit_malformed_attribute()` can print
+ // an excellent error message
+ sigpipe::DEFAULT
+ }
+ _ => {
+ tcx.sess
+ .struct_span_err(
+ attr.span,
+ "valid values for `#[unix_sigpipe = \"...\"]` are `inherit`, `sig_ign`, or `sig_dfl`",
+ )
+ .emit();
+ sigpipe::DEFAULT
+ }
+ }
+ } else {
+ sigpipe::DEFAULT
+ }
+}
+
fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
let sp = tcx.def_span(CRATE_DEF_ID);
if *tcx.sess.parse_sess.reached_eof.borrow() {
//! collect them instead.
use rustc_ast::{Attribute, MetaItemKind};
+use rustc_attr::VERSION_PLACEHOLDER;
use rustc_errors::struct_span_err;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
}
}
}
- const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
let version = option_env!("CFG_VERSION").unwrap_or("<current>");
pub vis_span: Span,
}
+#[derive(SessionDiagnostic)]
+#[diag(privacy::report_access_level)]
+pub struct ReportAccessLevel {
+ #[primary_span]
+ pub span: Span,
+ pub descr: String,
+}
+
#[derive(LintDiagnostic)]
#[diag(privacy::from_private_dep_in_public_interface)]
pub struct FromPrivateDependencyInPublicInterface<'a> {
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use std::marker::PhantomData;
use errors::{
FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
- InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, UnnamedItemIsPrivate,
+ InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportAccessLevel,
+ UnnamedItemIsPrivate,
};
////////////////////////////////////////////////////////////////////////////////
}
}
+////////////////////////////////////////////////////////////////////////////////
+/// Visitor, used for AccessLevels table checking
+////////////////////////////////////////////////////////////////////////////////
+pub struct TestReachabilityVisitor<'tcx, 'a> {
+ tcx: TyCtxt<'tcx>,
+ access_levels: &'a AccessLevels,
+}
+
+impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
+ fn access_level_diagnostic(&mut self, def_id: LocalDefId) {
+ if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_access_level) {
+ let access_level = format!("{:?}", self.access_levels.map.get(&def_id));
+ let span = self.tcx.def_span(def_id.to_def_id());
+ self.tcx.sess.emit_err(ReportAccessLevel { span, descr: access_level });
+ }
+ }
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
+ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
+ self.access_level_diagnostic(item.def_id);
+
+ match item.kind {
+ hir::ItemKind::Enum(ref def, _) => {
+ for variant in def.variants.iter() {
+ let variant_id = self.tcx.hir().local_def_id(variant.id);
+ self.access_level_diagnostic(variant_id);
+ for field in variant.data.fields() {
+ let def_id = self.tcx.hir().local_def_id(field.hir_id);
+ self.access_level_diagnostic(def_id);
+ }
+ }
+ }
+ hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
+ for field in def.fields() {
+ let def_id = self.tcx.hir().local_def_id(field.hir_id);
+ self.access_level_diagnostic(def_id);
+ }
+ }
+ _ => {}
+ }
+ }
+
+ fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
+ self.access_level_diagnostic(item.def_id);
+ }
+ fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
+ self.access_level_diagnostic(item.def_id);
+ }
+ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
+ self.access_level_diagnostic(item.def_id);
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////////////
/// Name privacy visitor, checks privacy and reports violations.
/// Most of name privacy checks are performed during the main resolution phase,
}
}
+ let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels };
+ tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor);
+
tcx.arena.alloc(visitor.access_levels)
}
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lock;
use rustc_errors::{Diagnostic, Handler};
-use rustc_middle::dep_graph::{self, DepKind, DepNodeIndex, SerializedDepNodeIndex};
+use rustc_middle::dep_graph::{
+ self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
+};
use rustc_middle::ty::tls::{self, ImplicitCtxt};
use rustc_middle::ty::{self, TyCtxt};
-use rustc_query_system::dep_graph::HasDepContext;
+use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{
- QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame,
+ force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap,
+ QuerySideEffects, QueryStackFrame,
};
use std::any::Any;
use std::num::NonZeroU64;
QueryStackFrame::new(name, description, span, def_kind, hash)
}
+fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode)
+where
+ Q: QueryDescription<QueryCtxt<'tcx>>,
+ Q::Key: DepNodeParams<TyCtxt<'tcx>>,
+{
+ debug_assert!(tcx.dep_graph.is_green(&dep_node));
+
+ let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
+ panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
+ });
+ if Q::cache_on_disk(tcx, &key) {
+ let _ = Q::execute_query(tcx, key);
+ }
+}
+
+fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
+where
+ Q: QueryDescription<QueryCtxt<'tcx>>,
+ Q::Key: DepNodeParams<TyCtxt<'tcx>>,
+{
+ if let Some(key) = Q::Key::recover(tcx, &dep_node) {
+ #[cfg(debug_assertions)]
+ let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
+ let tcx = QueryCtxt::from_tcx(tcx);
+ force_query::<Q, _>(tcx, key, dep_node);
+ true
+ } else {
+ false
+ }
+}
+
+pub(crate) fn query_callback<'tcx, Q: QueryConfig>(
+ is_anon: bool,
+ is_eval_always: bool,
+) -> DepKindStruct<'tcx>
+where
+ Q: QueryDescription<QueryCtxt<'tcx>>,
+ Q::Key: DepNodeParams<TyCtxt<'tcx>>,
+{
+ let fingerprint_style = Q::Key::fingerprint_style();
+
+ if is_anon || !fingerprint_style.reconstructible() {
+ return DepKindStruct {
+ is_anon,
+ is_eval_always,
+ fingerprint_style,
+ force_from_dep_node: None,
+ try_load_from_on_disk_cache: None,
+ };
+ }
+
+ DepKindStruct {
+ is_anon,
+ is_eval_always,
+ fingerprint_style,
+ force_from_dep_node: Some(force_from_dep_node::<Q>),
+ try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache::<Q>),
+ }
+}
+
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
// invoked by `rustc_query_append`.
macro_rules! define_queries {
input: ($(([$($modifiers)*] [$($attr)*] [$name]))*)
}
- mod make_query {
- use super::*;
-
- // Create an eponymous constructor for each query.
- $(#[allow(nonstandard_style)] $(#[$attr])*
- pub fn $name<'tcx>(tcx: QueryCtxt<'tcx>, key: <queries::$name<'tcx> as QueryConfig>::Key) -> QueryStackFrame {
- let kind = dep_graph::DepKind::$name;
- let name = stringify!($name);
- $crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
- })*
- }
-
#[allow(nonstandard_style)]
mod queries {
use std::marker::PhantomData;
try_load_from_disk: Self::TRY_LOAD_FROM_DISK,
}
}
+
+ fn execute_query(tcx: TyCtxt<'tcx>, k: Self::Key) -> Self::Stored {
+ tcx.$name(k)
+ }
})*
#[allow(nonstandard_style)]
mod query_callbacks {
use super::*;
- use rustc_middle::dep_graph::DepNode;
- use rustc_query_system::dep_graph::DepNodeParams;
- use rustc_query_system::query::{force_query, QueryDescription};
use rustc_query_system::dep_graph::FingerprintStyle;
// We use this for most things when incr. comp. is turned off.
- pub fn Null() -> DepKindStruct {
+ pub fn Null<'tcx>() -> DepKindStruct<'tcx> {
DepKindStruct {
is_anon: false,
is_eval_always: false,
}
// We use this for the forever-red node.
- pub fn Red() -> DepKindStruct {
+ pub fn Red<'tcx>() -> DepKindStruct<'tcx> {
DepKindStruct {
is_anon: false,
is_eval_always: false,
}
}
- pub fn TraitSelect() -> DepKindStruct {
+ pub fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
DepKindStruct {
is_anon: true,
is_eval_always: false,
}
}
- pub fn CompileCodegenUnit() -> DepKindStruct {
+ pub fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> {
DepKindStruct {
is_anon: false,
is_eval_always: false,
}
}
- pub fn CompileMonoItem() -> DepKindStruct {
+ pub fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> {
DepKindStruct {
is_anon: false,
is_eval_always: false,
}
}
- $(pub(crate) fn $name()-> DepKindStruct {
- let is_anon = is_anon!([$($modifiers)*]);
- let is_eval_always = is_eval_always!([$($modifiers)*]);
-
- let fingerprint_style =
- <<queries::$name<'_> as QueryConfig>::Key as DepNodeParams<TyCtxt<'_>>>::fingerprint_style();
-
- if is_anon || !fingerprint_style.reconstructible() {
- return DepKindStruct {
- is_anon,
- is_eval_always,
- fingerprint_style,
- force_from_dep_node: None,
- try_load_from_on_disk_cache: None,
- }
- }
-
- #[inline(always)]
- fn recover<'tcx>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> Option<<queries::$name<'tcx> as QueryConfig>::Key> {
- <<queries::$name<'_> as QueryConfig>::Key as DepNodeParams<TyCtxt<'_>>>::recover(tcx, &dep_node)
- }
-
- fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: DepNode) -> bool {
- if let Some(key) = recover(tcx, dep_node) {
- #[cfg(debug_assertions)]
- let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
- let tcx = QueryCtxt::from_tcx(tcx);
- force_query::<queries::$name<'_>, _>(tcx, key, dep_node);
- true
- } else {
- false
- }
- }
-
- fn try_load_from_on_disk_cache(tcx: TyCtxt<'_>, dep_node: DepNode) {
- debug_assert!(tcx.dep_graph.is_green(&dep_node));
-
- let key = recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash));
- if queries::$name::cache_on_disk(tcx, &key) {
- let _ = tcx.$name(key);
- }
- }
-
- DepKindStruct {
- is_anon,
- is_eval_always,
- fingerprint_style,
- force_from_dep_node: Some(force_from_dep_node),
- try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache),
- }
+ $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
+ $crate::plumbing::query_callback::<queries::$name<'tcx>>(
+ is_anon!([$($modifiers)*]),
+ is_eval_always!([$($modifiers)*]),
+ )
})*
}
- pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct] {
+ pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
}
}
let mut jobs = QueryMap::default();
$(
+ let make_query = |tcx, key| {
+ let kind = dep_graph::DepKind::$name;
+ let name = stringify!($name);
+ $crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
+ };
self.$name.try_collect_active_jobs(
tcx,
- make_query::$name,
+ make_query,
&mut jobs,
)?;
)*
fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVTable<CTX, Self::Key, Self::Value>;
fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool;
+
+ // Don't use this method to compute query results, instead use the methods on TyCtxt
+ fn execute_query(tcx: CTX::DepContext, k: Self::Key) -> Self::Stored;
}
+use crate::imports::ImportKind;
+use crate::NameBinding;
+use crate::NameBindingKind;
+use crate::Resolver;
use rustc_ast::ast;
use rustc_ast::visit;
use rustc_ast::visit::Visitor;
use rustc_ast::Crate;
use rustc_ast::EnumDef;
-use rustc_ast::ForeignMod;
use rustc_ast::NodeId;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_middle::middle::privacy::AccessLevel;
-use rustc_middle::ty::Visibility;
+use rustc_middle::ty::DefIdTree;
use rustc_span::sym;
-use crate::imports::ImportKind;
-use crate::BindingKey;
-use crate::NameBinding;
-use crate::NameBindingKind;
-use crate::Resolver;
-
pub struct AccessLevelsVisitor<'r, 'a> {
r: &'r mut Resolver<'a>,
- prev_level: Option<AccessLevel>,
changed: bool,
}
/// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
/// need access to a TyCtxt for that.
pub fn compute_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
- let mut visitor =
- AccessLevelsVisitor { r, changed: false, prev_level: Some(AccessLevel::Public) };
+ let mut visitor = AccessLevelsVisitor { r, changed: false };
visitor.set_access_level_def_id(CRATE_DEF_ID, Some(AccessLevel::Public));
- visitor.set_exports_access_level(CRATE_DEF_ID);
+ visitor.set_bindings_access_level(CRATE_DEF_ID);
while visitor.changed {
visitor.reset();
fn reset(&mut self) {
self.changed = false;
- self.prev_level = Some(AccessLevel::Public);
}
- /// Update the access level of the exports of the given module accordingly. The module access
+ /// Update the access level of the bindings in the given module accordingly. The module access
/// level has to be Exported or Public.
/// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level).
- fn set_exports_access_level(&mut self, module_id: LocalDefId) {
+ fn set_bindings_access_level(&mut self, module_id: LocalDefId) {
assert!(self.r.module_map.contains_key(&&module_id.to_def_id()));
-
+ let module_level = self.r.access_levels.map.get(&module_id).copied();
+ if !module_level.is_some() {
+ return;
+ }
// Set the given binding access level to `AccessLevel::Public` and
// sets the rest of the `use` chain to `AccessLevel::Exported` until
// we hit the actual exported item.
}
};
- let module_level = self.r.access_levels.map.get(&module_id).copied();
- assert!(module_level >= Some(AccessLevel::Exported));
-
- if let Some(exports) = self.r.reexport_map.get(&module_id) {
- let pub_exports = exports
- .iter()
- .filter(|ex| ex.vis == Visibility::Public)
- .cloned()
- .collect::<Vec<_>>();
-
- let module = self.r.get_module(module_id.to_def_id()).unwrap();
- for export in pub_exports.into_iter() {
- if let Some(export_def_id) = export.res.opt_def_id().and_then(|id| id.as_local()) {
- self.set_access_level_def_id(export_def_id, Some(AccessLevel::Exported));
- }
-
- if let Some(ns) = export.res.ns() {
- let key = BindingKey { ident: export.ident, ns, disambiguator: 0 };
- let name_res = self.r.resolution(module, key);
- if let Some(binding) = name_res.borrow().binding() {
- set_import_binding_access_level(self, binding, module_level)
- }
+ let module = self.r.get_module(module_id.to_def_id()).unwrap();
+ let resolutions = self.r.resolutions(module);
+
+ for (.., name_resolution) in resolutions.borrow().iter() {
+ if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() {
+ let access_level = match binding.is_import() {
+ true => {
+ set_import_binding_access_level(self, binding, module_level);
+ Some(AccessLevel::Exported)
+ },
+ false => module_level,
+ };
+ if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
+ self.set_access_level_def_id(def_id, access_level);
}
}
}
impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> {
fn visit_item(&mut self, item: &'ast ast::Item) {
- let inherited_item_level = match item.kind {
+ let def_id = self.r.local_def_id(item.id);
+ // Set access level of nested items.
+ // If it's a mod, also make the visitor walk all of its items
+ match item.kind {
// Resolved in rustc_privacy when types are available
ast::ItemKind::Impl(..) => return,
- // Only exported `macro_rules!` items are public, but they always are
- ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => {
- let is_macro_export =
- item.attrs.iter().any(|attr| attr.has_name(sym::macro_export));
- if is_macro_export { Some(AccessLevel::Public) } else { None }
- }
-
- // Foreign modules inherit level from parents.
- ast::ItemKind::ForeignMod(..) => self.prev_level,
-
- // Other `pub` items inherit levels from parents.
- ast::ItemKind::ExternCrate(..)
- | ast::ItemKind::Use(..)
- | ast::ItemKind::Static(..)
- | ast::ItemKind::Const(..)
- | ast::ItemKind::Fn(..)
- | ast::ItemKind::Mod(..)
- | ast::ItemKind::GlobalAsm(..)
- | ast::ItemKind::TyAlias(..)
- | ast::ItemKind::Enum(..)
- | ast::ItemKind::Struct(..)
- | ast::ItemKind::Union(..)
- | ast::ItemKind::Trait(..)
- | ast::ItemKind::TraitAlias(..)
- | ast::ItemKind::MacroDef(..) => {
- if item.vis.kind.is_pub() {
- self.prev_level
- } else {
- None
- }
- }
-
// Should be unreachable at this stage
ast::ItemKind::MacCall(..) => panic!(
"ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
),
- };
- let access_level = self.set_access_level(item.id, inherited_item_level);
+ // Foreign modules inherit level from parents.
+ ast::ItemKind::ForeignMod(..) => {
+ let parent_level =
+ self.r.access_levels.map.get(&self.r.local_parent(def_id)).copied();
+ self.set_access_level(item.id, parent_level);
+ }
- // Set access level of nested items.
- // If it's a mod, also make the visitor walk all of its items
- match item.kind {
- ast::ItemKind::Mod(..) => {
- if access_level.is_some() {
- self.set_exports_access_level(self.r.local_def_id(item.id));
+ // Only exported `macro_rules!` items are public, but they always are
+ ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => {
+ if item.attrs.iter().any(|attr| attr.has_name(sym::macro_export)) {
+ self.set_access_level(item.id, Some(AccessLevel::Public));
}
+ }
- let orig_level = std::mem::replace(&mut self.prev_level, access_level);
+ ast::ItemKind::Mod(..) => {
+ self.set_bindings_access_level(def_id);
visit::walk_item(self, item);
- self.prev_level = orig_level;
}
- ast::ItemKind::ForeignMod(ForeignMod { ref items, .. }) => {
- for nested in items {
- if nested.vis.kind.is_pub() {
- self.set_access_level(nested.id, access_level);
- }
- }
- }
ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
+ self.set_bindings_access_level(def_id);
for variant in variants {
- let variant_level = self.set_access_level(variant.id, access_level);
- if let Some(ctor_id) = variant.data.ctor_id() {
- self.set_access_level(ctor_id, access_level);
- }
-
+ let variant_def_id = self.r.local_def_id(variant.id);
+ let variant_level = self.r.access_levels.map.get(&variant_def_id).copied();
for field in variant.data.fields() {
self.set_access_level(field.id, variant_level);
}
}
}
- ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
- if let Some(ctor_id) = def.ctor_id() {
- self.set_access_level(ctor_id, access_level);
- }
+ ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
+ let inherited_level = self.r.access_levels.map.get(&def_id).copied();
for field in def.fields() {
if field.vis.kind.is_pub() {
- self.set_access_level(field.id, access_level);
+ self.set_access_level(field.id, inherited_level);
}
}
}
- ast::ItemKind::Trait(ref trait_kind) => {
- for nested in trait_kind.items.iter() {
- self.set_access_level(nested.id, access_level);
- }
+
+ ast::ItemKind::Trait(..) => {
+ self.set_bindings_access_level(def_id);
}
ast::ItemKind::ExternCrate(..)
| ast::ItemKind::TraitAlias(..)
| ast::ItemKind::MacroDef(..)
| ast::ItemKind::Fn(..) => return,
-
- // Unreachable kinds
- ast::ItemKind::Impl(..) | ast::ItemKind::MacCall(..) => unreachable!(),
}
}
}
if let Some(def_id) = module.opt_def_id() {
let mut reexports = Vec::new();
- module.for_each_child(self.r, |_, ident, _, binding| {
- // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules`
- // into the crate root to actual `NameBindingKind::Import`.
- if binding.is_import()
- || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true))
- {
- let res = binding.res().expect_non_local();
- // Ambiguous imports are treated as errors at this point and are
- // not exposed to other crates (see #36837 for more details).
- if res != def::Res::Err && !binding.is_ambiguity() {
- reexports.push(ModChild {
- ident,
- res,
- vis: binding.vis,
- span: binding.span,
- macro_rules: false,
- });
- }
+ module.for_each_child(self.r, |this, ident, _, binding| {
+ if let Some(res) = this.is_reexport(binding) {
+ reexports.push(ModChild {
+ ident,
+ res,
+ vis: binding.vis,
+ span: binding.span,
+ macro_rules: false,
+ });
}
});
}
}
-fn object_lifetime_default<'tcx>(
- tcx: TyCtxt<'tcx>,
- param_def_id: DefId,
-) -> Option<ObjectLifetimeDefault> {
+fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> ObjectLifetimeDefault {
+ debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
let param_def_id = param_def_id.expect_local();
let parent_def_id = tcx.local_parent(param_def_id);
- let generics = tcx.hir().get_generics(parent_def_id)?;
+ let generics = tcx.hir().get_generics(parent_def_id).unwrap();
let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
- let param = generics.params.iter().find(|p| p.hir_id == param_hir_id)?;
+ let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
// Scan the bounds and where-clauses on parameters to extract bounds
// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
// for each type parameter.
match param.kind {
- GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;
}
}
- Some(match set {
+ match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
}
_ => ObjectLifetimeDefault::Ambiguous,
- })
+ }
}
- GenericParamKind::Const { .. } => {
- // Generic consts don't impose any constraints.
- //
- // We still store a dummy value here to allow generic parameters
- // in an arbitrary order.
- Some(ObjectLifetimeDefault::Empty)
+ _ => {
+ bug!("object_lifetime_default_raw must only be called on a type parameter")
}
}
}
generics
.params
.iter()
- .filter_map(|param| self.tcx.object_lifetime_default(param.def_id))
+ .filter_map(|param| {
+ match self.tcx.def_kind(param.def_id) {
+ // Generic consts don't impose any constraints.
+ //
+ // We still store a dummy value here to allow generic parameters
+ // in an arbitrary order.
+ DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
+ DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
+ // We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
+ // works. Ignore it because it can't have a meaningful lifetime default.
+ DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
+ dk => bug!("unexpected def_kind {:?}", dk),
+ }
+ })
.map(set_to_region)
.collect()
});
}
self.main_def = Some(MainDefinition { res, is_import, span });
}
+
+ // Items that go to reexport table encoded to metadata and visible through it to other crates.
+ fn is_reexport(&self, binding: &NameBinding<'a>) -> Option<def::Res<!>> {
+ // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules`
+ // into the crate root to actual `NameBindingKind::Import`.
+ if binding.is_import()
+ || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true))
+ {
+ let res = binding.res().expect_non_local();
+ // Ambiguous imports are treated as errors at this point and are
+ // not exposed to other crates (see #36837 for more details).
+ if res != def::Res::Err && !binding.is_ambiguity() {
+ return Some(res);
+ }
+ }
+
+ return None;
+ }
}
fn names_to_string(names: &[Symbol]) -> String {
use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_target::abi::{Align, TargetDataLayout};
-use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings};
-use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS};
+use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
+use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
use crate::parse::{CrateCheckConfig, CrateConfig};
use rustc_feature::UnstableFeatures;
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
+pub mod sigpipe;
+
/// The different settings that the `-C strip` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum Strip {
// The type of entry function, so users can have their own entry functions
#[derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic)]
pub enum EntryFnType {
- Main,
+ Main {
+ /// Specifies what to do with `SIGPIPE` before calling `fn main()`.
+ ///
+ /// What values that are valid and what they mean must be in sync
+ /// across rustc and libstd, but we don't want it public in libstd,
+ /// so we take a bit of an unusual approach with simple constants
+ /// and an `include!()`.
+ sigpipe: u8,
+ },
Start,
}
sess.fatal(&err);
});
- let mut ret = FxHashSet::default();
+ let mut ret = CrateConfig::default();
ret.reserve(7); // the minimum number of insertions
// Target bindings.
ret.insert((sym::target_os, Some(Symbol::intern(os))));
}
}
- if cg.linker_flavor == Some(LinkerFlavor::L4Bender)
- && !nightly_options::is_unstable_enabled(matches)
- {
- early_error(
- error_format,
- "`l4-bender` linker flavor is unstable, `-Z unstable-options` \
- flag must also be passed to explicitly use it",
- );
- }
-
let prints = collect_print_requests(&mut cg, &mut unstable_opts, matches, error_format);
let cg = cg;
--- /dev/null
+//! NOTE: Keep these constants in sync with `library/std/src/sys/unix/mod.rs`!
+
+/// Do not touch `SIGPIPE`. Use whatever the parent process uses.
+#[allow(dead_code)]
+pub const INHERIT: u8 = 1;
+
+/// Change `SIGPIPE` to `SIG_IGN` so that failed writes results in `EPIPE`
+/// that are eventually converted to `ErrorKind::BrokenPipe`.
+#[allow(dead_code)]
+pub const SIG_IGN: u8 = 2;
+
+/// Change `SIGPIPE` to `SIG_DFL` so that the process is killed when trying
+/// to write to a closed pipe. This is usually the desired behavior for CLI
+/// apps that produce textual output that you want to pipe to other programs
+/// such as `head -n 1`.
+#[allow(dead_code)]
+pub const SIG_DFL: u8 = 3;
+
+/// `SIG_IGN` has been the Rust default since 2014. See
+/// <https://github.com/rust-lang/rust/issues/62569>.
+#[allow(dead_code)]
+pub const DEFAULT: u8 = SIG_IGN;
use crate::search_paths::SearchPath;
use crate::utils::NativeLib;
use rustc_errors::LanguageIdentifier;
-use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
+use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet};
use rustc_target::spec::{
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
};
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)";
pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
- pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
+ pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
pub const parse_optimization_fuel: &str = "crate=integer";
pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
pub const parse_instrument_coverage: &str =
true
}
- pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
- match v.and_then(LinkerFlavor::from_str) {
+ pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool {
+ match v.and_then(LinkerFlavorCli::from_str) {
Some(lf) => *slot = Some(lf),
_ => return false,
}
on C toolchain installed in the system"),
linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"system linker to link outputs with"),
- linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
+ linker_flavor: Option<LinkerFlavorCli> = (None, parse_linker_flavor, [UNTRACKED],
"linker flavor"),
linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
parse_linker_plugin_lto, [TRACKED],
};
use crate::SessionDiagnostic;
use rustc_ast::node_id::NodeId;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
use rustc_errors::{
/// The set of keys (and, optionally, values) that define the compilation
/// environment of the crate, used to drive conditional compilation.
-pub type CrateConfig = FxHashSet<(Symbol, Option<Symbol>)>;
+pub type CrateConfig = FxIndexSet<(Symbol, Option<Symbol>)>;
pub type CrateCheckConfig = CheckCfg<Symbol>;
/// Collected spans during parsing for places where a certain feature was
Self {
span_diagnostic: handler,
unstable_features: UnstableFeatures::from_environment(None),
- config: FxHashSet::default(),
+ config: FxIndexSet::default(),
check_config: CrateCheckConfig::default(),
edition: ExpnId::root().expn_data().edition,
raw_identifier_spans: Lock::new(Vec::new()),
}
}
+impl rustc_errors::IntoDiagnosticArg for Limit {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct Limits {
/// The maximum recursion limit for potentially infinitely recursive
LinkedList,
LintPass,
Mutex,
+ MutexGuard,
N,
NonZeroI128,
NonZeroI16,
Rust,
RustcDecodable,
RustcEncodable,
+ RwLockReadGuard,
+ RwLockWriteGuard,
Send,
SeqCst,
SessionDiagnostic,
infer_outlives_requirements,
infer_static_outlives_requirements,
inherent_associated_types,
+ inherit,
inlateout,
inline,
inline_const,
rust_eh_unregister_frames,
rust_oom,
rustc,
+ rustc_access_level,
rustc_allocator,
rustc_allocator_nounwind,
rustc_allocator_zeroed,
should_panic,
shr,
shr_assign,
+ sig_dfl,
+ sig_ign,
simd,
simd_add,
simd_and,
unit,
universal_impl_trait,
unix,
+ unix_sigpipe,
unlikely,
unmarked_api,
unpin,
pub fn target() -> Target {
let mut target = wasm32_unknown_emscripten::target();
- target.add_post_link_args(LinkerFlavor::Em, &["-sWASM=0", "--memory-init-file", "0"]);
+ target.add_post_link_args(LinkerFlavor::EmCc, &["-sWASM=0", "--memory-init-file", "0"]);
target
}
TargetOptions {
allow_asm: true,
endian,
- linker_flavor: LinkerFlavor::BpfLinker,
+ linker_flavor: LinkerFlavor::Bpf,
atomic_cas: false,
dynamic_linking: true,
no_builtins: true,
TargetOptions {
os: "l4re".into(),
env: "uclibc".into(),
- linker_flavor: LinkerFlavor::L4Bender,
+ linker_flavor: LinkerFlavor::Ld,
panic_strategy: PanicStrategy::Abort,
linker: Some("l4-bender".into()),
linker_is_gnu: false,
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum LinkerFlavor {
- Em,
Gcc,
- L4Bender,
Ld,
+ Lld(LldFlavor),
Msvc,
+ EmCc,
+ Bpf,
+ Ptx,
+}
+
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum LinkerFlavorCli {
+ Gcc,
+ Ld,
Lld(LldFlavor),
- PtxLinker,
+ Msvc,
+ Em,
BpfLinker,
+ PtxLinker,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
}
}
-impl ToJson for LinkerFlavor {
- fn to_json(&self) -> Json {
- self.desc().to_json()
+impl LinkerFlavor {
+ pub fn from_cli(cli: LinkerFlavorCli) -> LinkerFlavor {
+ match cli {
+ LinkerFlavorCli::Gcc => LinkerFlavor::Gcc,
+ LinkerFlavorCli::Ld => LinkerFlavor::Ld,
+ LinkerFlavorCli::Lld(lld_flavor) => LinkerFlavor::Lld(lld_flavor),
+ LinkerFlavorCli::Msvc => LinkerFlavor::Msvc,
+ LinkerFlavorCli::Em => LinkerFlavor::EmCc,
+ LinkerFlavorCli::BpfLinker => LinkerFlavor::Bpf,
+ LinkerFlavorCli::PtxLinker => LinkerFlavor::Ptx,
+ }
+ }
+
+ fn to_cli(self) -> LinkerFlavorCli {
+ match self {
+ LinkerFlavor::Gcc => LinkerFlavorCli::Gcc,
+ LinkerFlavor::Ld => LinkerFlavorCli::Ld,
+ LinkerFlavor::Lld(lld_flavor) => LinkerFlavorCli::Lld(lld_flavor),
+ LinkerFlavor::Msvc => LinkerFlavorCli::Msvc,
+ LinkerFlavor::EmCc => LinkerFlavorCli::Em,
+ LinkerFlavor::Bpf => LinkerFlavorCli::BpfLinker,
+ LinkerFlavor::Ptx => LinkerFlavorCli::PtxLinker,
+ }
}
}
-macro_rules! flavor_mappings {
- ($((($($flavor:tt)*), $string:expr),)*) => (
- impl LinkerFlavor {
+
+macro_rules! linker_flavor_cli_impls {
+ ($(($($flavor:tt)*) $string:literal)*) => (
+ impl LinkerFlavorCli {
pub const fn one_of() -> &'static str {
concat!("one of: ", $($string, " ",)*)
}
- pub fn from_str(s: &str) -> Option<Self> {
+ pub fn from_str(s: &str) -> Option<LinkerFlavorCli> {
Some(match s {
$($string => $($flavor)*,)*
_ => return None,
)
}
-flavor_mappings! {
- ((LinkerFlavor::Em), "em"),
- ((LinkerFlavor::Gcc), "gcc"),
- ((LinkerFlavor::L4Bender), "l4-bender"),
- ((LinkerFlavor::Ld), "ld"),
- ((LinkerFlavor::Msvc), "msvc"),
- ((LinkerFlavor::PtxLinker), "ptx-linker"),
- ((LinkerFlavor::BpfLinker), "bpf-linker"),
- ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
- ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
- ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
- ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
+linker_flavor_cli_impls! {
+ (LinkerFlavorCli::Gcc) "gcc"
+ (LinkerFlavorCli::Ld) "ld"
+ (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
+ (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
+ (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
+ (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
+ (LinkerFlavorCli::Msvc) "msvc"
+ (LinkerFlavorCli::Em) "em"
+ (LinkerFlavorCli::BpfLinker) "bpf-linker"
+ (LinkerFlavorCli::PtxLinker) "ptx-linker"
+}
+
+impl ToJson for LinkerFlavorCli {
+ fn to_json(&self) -> Json {
+ self.desc().to_json()
+ }
}
#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
}
pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
+pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
/// Which kind of debuginfo does the target use?
///
pub abi: StaticCow<str>,
/// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
pub vendor: StaticCow<str>,
- /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
- /// on the command line. Defaults to `LinkerFlavor::Gcc`.
- pub linker_flavor: LinkerFlavor,
/// Linker to invoke
pub linker: Option<StaticCow<str>>,
-
+ /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
+ /// on the command line. Defaults to `LinkerFlavor::Gcc`.
+ pub linker_flavor: LinkerFlavor,
+ linker_flavor_json: LinkerFlavorCli,
/// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
/// without clarifying its flavor in any way.
+ /// FIXME: Merge this into `LinkerFlavor`.
pub lld_flavor: LldFlavor,
+ /// Whether the linker support GNU-like arguments such as -O. Defaults to true.
+ /// FIXME: Merge this into `LinkerFlavor`.
+ pub linker_is_gnu: bool,
- /// Linker arguments that are passed *before* any user-defined libraries.
- pub pre_link_args: LinkArgs,
/// Objects to link before and after all other object code.
pub pre_link_objects: CrtObjects,
pub post_link_objects: CrtObjects,
pub post_link_objects_self_contained: CrtObjects,
pub link_self_contained: LinkSelfContainedDefault,
+ /// Linker arguments that are passed *before* any user-defined libraries.
+ pub pre_link_args: LinkArgs,
+ pre_link_args_json: LinkArgsCli,
/// Linker arguments that are unconditionally passed after any
/// user-defined but before post-link objects. Standard platform
/// libraries that should be always be linked to, usually go here.
pub late_link_args: LinkArgs,
+ late_link_args_json: LinkArgsCli,
/// Linker arguments used in addition to `late_link_args` if at least one
/// Rust dependency is dynamically linked.
pub late_link_args_dynamic: LinkArgs,
+ late_link_args_dynamic_json: LinkArgsCli,
/// Linker arguments used in addition to `late_link_args` if all Rust
/// dependencies are statically linked.
pub late_link_args_static: LinkArgs,
+ late_link_args_static_json: LinkArgsCli,
/// Linker arguments that are unconditionally passed *after* any
/// user-defined libraries.
pub post_link_args: LinkArgs,
+ post_link_args_json: LinkArgsCli,
+
/// Optional link script applied to `dylib` and `executable` crate types.
/// This is a string containing the script, not a path. Can only be applied
/// to linkers where `linker_is_gnu` is true.
pub link_script: Option<StaticCow<str>>,
-
/// Environment variables to be set for the linker invocation.
pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
/// Environment variables to be removed for the linker invocation.
/// Default supported version of DWARF on this platform.
/// Useful because some platforms (osx, bsd) only want up to DWARF2.
pub default_dwarf_version: u32,
- /// Whether the linker support GNU-like arguments such as -O. Defaults to true.
- pub linker_is_gnu: bool,
/// The MinGW toolchain has a known issue that prevents it from correctly
/// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
/// symbol needs its own COMDAT section, weak linkage implies a large
LinkerFlavor::Lld(lld_flavor) => {
panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor)
}
- LinkerFlavor::Gcc
- | LinkerFlavor::Em
- | LinkerFlavor::L4Bender
- | LinkerFlavor::BpfLinker
- | LinkerFlavor::PtxLinker => {}
+ LinkerFlavor::Gcc | LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => {}
}
}
fn add_post_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
add_link_args(&mut self.post_link_args, flavor, args);
}
+
+ fn update_from_cli(&mut self) {
+ self.linker_flavor = LinkerFlavor::from_cli(self.linker_flavor_json);
+ for (args, args_json) in [
+ (&mut self.pre_link_args, &self.pre_link_args_json),
+ (&mut self.late_link_args, &self.late_link_args_json),
+ (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
+ (&mut self.late_link_args_static, &self.late_link_args_static_json),
+ (&mut self.post_link_args, &self.post_link_args_json),
+ ] {
+ *args = args_json
+ .iter()
+ .map(|(flavor, args)| (LinkerFlavor::from_cli(*flavor), args.clone()))
+ .collect();
+ }
+ }
+
+ fn update_to_cli(&mut self) {
+ self.linker_flavor_json = self.linker_flavor.to_cli();
+ for (args, args_json) in [
+ (&self.pre_link_args, &mut self.pre_link_args_json),
+ (&self.late_link_args, &mut self.late_link_args_json),
+ (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
+ (&self.late_link_args_static, &mut self.late_link_args_static_json),
+ (&self.post_link_args, &mut self.post_link_args_json),
+ ] {
+ *args_json =
+ args.iter().map(|(flavor, args)| (flavor.to_cli(), args.clone())).collect();
+ }
+ }
}
impl Default for TargetOptions {
env: "".into(),
abi: "".into(),
vendor: "unknown".into(),
- linker_flavor: LinkerFlavor::Gcc,
linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
+ linker_flavor: LinkerFlavor::Gcc,
+ linker_flavor_json: LinkerFlavorCli::Gcc,
lld_flavor: LldFlavor::Ld,
- pre_link_args: LinkArgs::new(),
- post_link_args: LinkArgs::new(),
+ linker_is_gnu: true,
link_script: None,
asm_args: cvs![],
cpu: "generic".into(),
is_like_msvc: false,
is_like_wasm: false,
default_dwarf_version: 4,
- linker_is_gnu: true,
allows_weak_linkage: true,
has_rpath: false,
no_default_libraries: true,
pre_link_objects_self_contained: Default::default(),
post_link_objects_self_contained: Default::default(),
link_self_contained: LinkSelfContainedDefault::False,
+ pre_link_args: LinkArgs::new(),
+ pre_link_args_json: LinkArgsCli::new(),
late_link_args: LinkArgs::new(),
+ late_link_args_json: LinkArgsCli::new(),
late_link_args_dynamic: LinkArgs::new(),
+ late_link_args_dynamic_json: LinkArgsCli::new(),
late_link_args_static: LinkArgs::new(),
+ late_link_args_static_json: LinkArgsCli::new(),
+ post_link_args: LinkArgs::new(),
+ post_link_args_json: LinkArgsCli::new(),
link_env: cvs![],
link_env_remove: cvs![],
archive_format: "gnu".into(),
Some(Ok(()))
})).unwrap_or(Ok(()))
} );
- ($key_name:ident, LinkerFlavor) => ( {
- let name = (stringify!($key_name)).replace("_", "-");
- obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
- match LinkerFlavor::from_str(s) {
+ ($key_name:ident = $json_name:expr, LinkerFlavor) => ( {
+ let name = $json_name;
+ obj.remove(name).and_then(|o| o.as_str().and_then(|s| {
+ match LinkerFlavorCli::from_str(s) {
Some(linker_flavor) => base.$key_name = linker_flavor,
_ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
- Use {}", s, LinkerFlavor::one_of()))),
+ Use {}", s, LinkerFlavorCli::one_of()))),
}
Some(Ok(()))
})).unwrap_or(Ok(()))
base.$key_name = args;
}
} );
- ($key_name:ident, link_args) => ( {
- let name = (stringify!($key_name)).replace("_", "-");
- if let Some(val) = obj.remove(&name) {
+ ($key_name:ident = $json_name:expr, link_args) => ( {
+ let name = $json_name;
+ if let Some(val) = obj.remove(name) {
let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
JSON object with fields per linker-flavor.", name))?;
- let mut args = LinkArgs::new();
+ let mut args = LinkArgsCli::new();
for (k, v) in obj {
- let flavor = LinkerFlavor::from_str(&k).ok_or_else(|| {
+ let flavor = LinkerFlavorCli::from_str(&k).ok_or_else(|| {
format!("{}: '{}' is not a valid value for linker-flavor. \
Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
})?;
key!(env);
key!(abi);
key!(vendor);
- key!(linker_flavor, LinkerFlavor)?;
key!(linker, optional);
+ key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?;
key!(lld_flavor, LldFlavor)?;
+ key!(linker_is_gnu, bool);
key!(pre_link_objects = "pre-link-objects", link_objects);
key!(post_link_objects = "post-link-objects", link_objects);
key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects);
key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects);
key!(link_self_contained = "crt-objects-fallback", link_self_contained)?;
- key!(pre_link_args, link_args);
- key!(late_link_args, link_args);
- key!(late_link_args_dynamic, link_args);
- key!(late_link_args_static, link_args);
- key!(post_link_args, link_args);
+ key!(pre_link_args_json = "pre-link-args", link_args);
+ key!(late_link_args_json = "late-link-args", link_args);
+ key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args);
+ key!(late_link_args_static_json = "late-link-args-static", link_args);
+ key!(post_link_args_json = "post-link-args", link_args);
key!(link_script, optional);
key!(link_env, env);
key!(link_env_remove, list);
key!(is_like_msvc, bool);
key!(is_like_wasm, bool);
key!(default_dwarf_version, u32);
- key!(linker_is_gnu, bool);
key!(allows_weak_linkage, bool);
key!(has_rpath, bool);
key!(no_default_libraries, bool);
// This can cause unfortunate ICEs later down the line.
return Err("may not set is_builtin for targets not built-in".into());
}
+ base.update_from_cli();
+
// Each field should have been read using `Json::remove` so any keys remaining are unused.
let remaining_keys = obj.keys();
Ok((
fn to_json(&self) -> Json {
let mut d = serde_json::Map::new();
let default: TargetOptions = Default::default();
+ let mut target = self.clone();
+ target.update_to_cli();
macro_rules! target_val {
($attr:ident) => {{
let name = (stringify!($attr)).replace("_", "-");
- d.insert(name, self.$attr.to_json());
+ d.insert(name, target.$attr.to_json());
}};
}
macro_rules! target_option_val {
($attr:ident) => {{
let name = (stringify!($attr)).replace("_", "-");
- if default.$attr != self.$attr {
- d.insert(name, self.$attr.to_json());
+ if default.$attr != target.$attr {
+ d.insert(name, target.$attr.to_json());
}
}};
- ($attr:ident, $key_name:expr) => {{
- let name = $key_name;
- if default.$attr != self.$attr {
- d.insert(name.into(), self.$attr.to_json());
+ ($attr:ident, $json_name:expr) => {{
+ let name = $json_name;
+ if default.$attr != target.$attr {
+ d.insert(name.into(), target.$attr.to_json());
}
}};
- (link_args - $attr:ident) => {{
- let name = (stringify!($attr)).replace("_", "-");
- if default.$attr != self.$attr {
- let obj = self
+ (link_args - $attr:ident, $json_name:expr) => {{
+ let name = $json_name;
+ if default.$attr != target.$attr {
+ let obj = target
.$attr
.iter()
.map(|(k, v)| (k.desc().to_string(), v.clone()))
.collect::<BTreeMap<_, _>>();
- d.insert(name, obj.to_json());
+ d.insert(name.to_string(), obj.to_json());
}
}};
(env - $attr:ident) => {{
let name = (stringify!($attr)).replace("_", "-");
- if default.$attr != self.$attr {
- let obj = self
+ if default.$attr != target.$attr {
+ let obj = target
.$attr
.iter()
.map(|&(ref k, ref v)| format!("{k}={v}"))
target_option_val!(env);
target_option_val!(abi);
target_option_val!(vendor);
- target_option_val!(linker_flavor);
target_option_val!(linker);
+ target_option_val!(linker_flavor_json, "linker-flavor");
target_option_val!(lld_flavor);
+ target_option_val!(linker_is_gnu);
target_option_val!(pre_link_objects);
target_option_val!(post_link_objects);
target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback");
target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback");
target_option_val!(link_self_contained, "crt-objects-fallback");
- target_option_val!(link_args - pre_link_args);
- target_option_val!(link_args - late_link_args);
- target_option_val!(link_args - late_link_args_dynamic);
- target_option_val!(link_args - late_link_args_static);
- target_option_val!(link_args - post_link_args);
+ target_option_val!(link_args - pre_link_args_json, "pre-link-args");
+ target_option_val!(link_args - late_link_args_json, "late-link-args");
+ target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic");
+ target_option_val!(link_args - late_link_args_static_json, "late-link-args-static");
+ target_option_val!(link_args - post_link_args_json, "post-link-args");
target_option_val!(link_script);
target_option_val!(env - link_env);
target_option_val!(link_env_remove);
target_option_val!(is_like_msvc);
target_option_val!(is_like_wasm);
target_option_val!(default_dwarf_version);
- target_option_val!(linker_is_gnu);
target_option_val!(allows_weak_linkage);
target_option_val!(has_rpath);
target_option_val!(no_default_libraries);
options: TargetOptions {
os: "cuda".into(),
vendor: "nvidia".into(),
- linker_flavor: LinkerFlavor::PtxLinker,
+ linker_flavor: LinkerFlavor::Ptx,
// The linker can be installed from `crates.io`.
linker: Some("rust-ptx-linker".into()),
linker_is_gnu: false,
use std::assert_matches::assert_matches;
// Test target self-consistency and JSON encoding/decoding roundtrip.
-pub(super) fn test_target(target: Target, triple: &str) {
+pub(super) fn test_target(mut target: Target, triple: &str) {
+ let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j);
+ target.update_to_cli();
target.check_consistency(triple);
- assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target));
+ assert_eq!(recycled_target, Ok(target));
}
impl Target {
assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64));
assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link));
assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm));
- assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender));
- assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em));
- assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker));
- assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker));
+ assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc));
+ assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf));
+ assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx));
for args in [
&self.pre_link_args,
LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc
)
}
- (LinkerFlavor::L4Bender, LldFlavor::Ld) => {
- assert_matches!(flavor, LinkerFlavor::L4Bender)
+ (LinkerFlavor::EmCc, LldFlavor::Wasm) => {
+ assert_matches!(flavor, LinkerFlavor::EmCc)
}
- (LinkerFlavor::Em, LldFlavor::Wasm) => {
- assert_matches!(flavor, LinkerFlavor::Em)
+ (LinkerFlavor::Bpf, LldFlavor::Ld) => {
+ assert_matches!(flavor, LinkerFlavor::Bpf)
}
- (LinkerFlavor::BpfLinker, LldFlavor::Ld) => {
- assert_matches!(flavor, LinkerFlavor::BpfLinker)
- }
- (LinkerFlavor::PtxLinker, LldFlavor::Ld) => {
- assert_matches!(flavor, LinkerFlavor::PtxLinker)
+ (LinkerFlavor::Ptx, LldFlavor::Ld) => {
+ assert_matches!(flavor, LinkerFlavor::Ptx)
}
flavors => unreachable!("unexpected flavor combination: {:?}", flavors),
}
// Reset flags for non-Em flavors back to empty to satisfy sanity checking tests.
let pre_link_args = LinkArgs::new();
let post_link_args = TargetOptions::link_args(
- LinkerFlavor::Em,
+ LinkerFlavor::EmCc,
&["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"],
);
let opts = TargetOptions {
os: "emscripten".into(),
- linker_flavor: LinkerFlavor::Em,
+ linker_flavor: LinkerFlavor::EmCc,
// emcc emits two files - a .js file to instantiate the wasm and supply platform
// functionality, and a .wasm file.
exe_suffix: ".js".into(),
+use crate::errors::AutoDerefReachedRecursionLimit;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{self, TraitEngine};
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
Limit(0) => Limit(2),
limit => limit * 2,
};
- struct_span_err!(
- tcx.sess,
+ tcx.sess.emit_err(AutoDerefReachedRecursionLimit {
span,
- E0055,
- "reached the recursion limit while auto-dereferencing `{:?}`",
- ty
- )
- .span_label(span, "deref recursion limit reached")
- .help(&format!(
- "consider increasing the recursion limit by adding a \
- `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
+ ty,
suggested_limit,
- tcx.crate_name(LOCAL_CRATE),
- ))
- .emit();
+ crate_name: tcx.crate_name(LOCAL_CRATE),
+ });
}
--- /dev/null
+use rustc_errors::{fluent, ErrorGuaranteed};
+use rustc_macros::SessionDiagnostic;
+use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated};
+use rustc_session::{parse::ParseSess, Limit, SessionDiagnostic};
+use rustc_span::{Span, Symbol};
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::dump_vtable_entries)]
+pub struct DumpVTableEntries<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub trait_ref: PolyTraitRef<'a>,
+ pub entries: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::unable_to_construct_constant_value)]
+pub struct UnableToConstructConstantValue<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub unevaluated: Unevaluated<'a>,
+}
+
+#[derive(SessionDiagnostic)]
+#[help]
+#[diag(trait_selection::auto_deref_reached_recursion_limit, code = "E0055")]
+pub struct AutoDerefReachedRecursionLimit<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub ty: Ty<'a>,
+ pub suggested_limit: Limit,
+ pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+pub struct EmptyOnClauseInOnUnimplemented {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+pub struct InvalidOnClauseInOnUnimplemented {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::no_value_in_rustc_on_unimplemented, code = "E0232")]
+#[note]
+pub struct NoValueInOnUnimplemented {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+pub struct NegativePositiveConflict<'a> {
+ pub impl_span: Span,
+ pub trait_desc: &'a str,
+ pub self_desc: &'a Option<String>,
+ pub negative_impl_span: Result<Span, Symbol>,
+ pub positive_impl_span: Result<Span, Symbol>,
+}
+
+impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> {
+ fn into_diagnostic(
+ self,
+ sess: &ParseSess,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = sess.struct_err(fluent::trait_selection::negative_positive_conflict);
+ diag.set_arg("trait_desc", self.trait_desc);
+ diag.set_arg(
+ "self_desc",
+ self.self_desc.clone().map_or_else(|| String::from("none"), |ty| ty),
+ );
+ diag.set_span(self.impl_span);
+ diag.code(rustc_errors::error_code!(E0751));
+ match self.negative_impl_span {
+ Ok(span) => {
+ diag.span_label(span, fluent::trait_selection::negative_implementation_here);
+ }
+ Err(cname) => {
+ diag.note(fluent::trait_selection::negative_implementation_in_crate);
+ diag.set_arg("negative_impl_cname", cname.to_string());
+ }
+ }
+ match self.positive_impl_span {
+ Ok(span) => {
+ diag.span_label(span, fluent::trait_selection::positive_implementation_here);
+ }
+ Err(cname) => {
+ diag.note(fluent::trait_selection::positive_implementation_in_crate);
+ diag.set_arg("positive_impl_cname", cname.to_string());
+ }
+ }
+ diag
+ }
+}
extern crate smallvec;
pub mod autoderef;
+pub mod errors;
pub mod infer;
pub mod traits;
use super::*;
+use crate::errors::UnableToConstructConstantValue;
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxt;
use crate::traits::project::ProjectAndUnifyResult;
Ok(None) => {
let tcx = self.tcx;
let def_id = unevaluated.def.did;
- let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();
-
+ let reported =
+ tcx.sess.emit_err(UnableToConstructConstantValue {
+ span: tcx.def_span(def_id),
+ unevaluated,
+ });
Err(ErrorHandled::Reported(reported))
}
Err(err) => Err(err),
{
"consider using `()`, or a `Result`".to_owned()
} else {
- format!(
- "{}the trait `{}` is not implemented for `{}`",
- pre_message,
- trait_predicate.print_modifiers_and_trait_path(),
- trait_ref.skip_binder().self_ty(),
- )
+ let ty_desc = match trait_ref.skip_binder().self_ty().kind() {
+ ty::FnDef(_, _) => Some("fn item"),
+ ty::Closure(_, _) => Some("closure"),
+ _ => None,
+ };
+
+ match ty_desc {
+ Some(desc) => format!(
+ "{}the trait `{}` is not implemented for {} `{}`",
+ pre_message,
+ trait_predicate.print_modifiers_and_trait_path(),
+ desc,
+ trait_ref.skip_binder().self_ty(),
+ ),
+ None => format!(
+ "{}the trait `{}` is not implemented for `{}`",
+ pre_message,
+ trait_predicate.print_modifiers_and_trait_path(),
+ trait_ref.skip_binder().self_ty(),
+ ),
+ }
};
if self.suggest_add_reference_to_arg(
return false;
}
if candidates.len() == 1 {
+ let ty_desc = match candidates[0].self_ty().kind() {
+ ty::FnPtr(_) => Some("fn pointer"),
+ _ => None,
+ };
+ let the_desc = match ty_desc {
+ Some(desc) => format!(" implemented for {} `", desc),
+ None => " implemented for `".to_string(),
+ };
err.highlighted_help(vec![
(
format!("the trait `{}` ", candidates[0].print_only_trait_path()),
Style::NoStyle,
),
("is".to_string(), Style::Highlight),
- (" implemented for `".to_string(), Style::NoStyle),
+ (the_desc, Style::NoStyle),
(candidates[0].self_ty().to_string(), Style::Highlight),
("`".to_string(), Style::NoStyle),
]);
mod util;
pub mod wf;
+use crate::errors::DumpVTableEntries;
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::error_reporting::InferCtxtExt as _;
trait_ref: ty::PolyTraitRef<'tcx>,
entries: &[VtblEntry<'tcx>],
) {
- let msg = format!("vtable entries for `{}`: {:#?}", trait_ref, entries);
- tcx.sess.struct_span_err(sp, &msg).emit();
+ tcx.sess.emit_err(DumpVTableEntries {
+ span: sp,
+ trait_ref,
+ entries: format!("{:#?}", entries),
+ });
}
fn own_existential_vtable_entries<'tcx>(
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
+use crate::errors::{
+ EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
+};
+
#[derive(Clone, Debug)]
pub struct OnUnimplementedFormatString(Symbol);
pub append_const_msg: Option<Option<Symbol>>,
}
-fn parse_error(
- tcx: TyCtxt<'_>,
- span: Span,
- message: &str,
- label: &str,
- note: Option<&str>,
-) -> ErrorGuaranteed {
- let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message);
- diag.span_label(span, label);
- if let Some(note) = note {
- diag.note(note);
- }
- diag.emit()
-}
-
impl<'tcx> OnUnimplementedDirective {
fn parse(
tcx: TyCtxt<'tcx>,
} else {
let cond = item_iter
.next()
- .ok_or_else(|| {
- parse_error(
- tcx,
- span,
- "empty `on`-clause in `#[rustc_on_unimplemented]`",
- "empty on-clause here",
- None,
- )
- })?
+ .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))?
.meta_item()
- .ok_or_else(|| {
- parse_error(
- tcx,
- span,
- "invalid `on`-clause in `#[rustc_on_unimplemented]`",
- "invalid on-clause here",
- None,
- )
- })?;
+ .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
errored = Some(guar);
}
// nothing found
- parse_error(
- tcx,
- item.span(),
- "this attribute must have a valid value",
- "expected value here",
- Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#),
- );
+ tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
if let Some(reported) = errored {
pub mod specialization_graph;
use specialization_graph::GraphExt;
+use crate::errors::NegativePositiveConflict;
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
positive_impl_def_id: DefId,
sg: &mut specialization_graph::Graph,
) {
- let impl_span = tcx.def_span(local_impl_def_id);
-
- let mut err = struct_span_err!(
- tcx.sess,
- impl_span,
- E0751,
- "found both positive and negative implementation of trait `{}`{}:",
- overlap.trait_desc,
- overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty))
- );
-
- match tcx.span_of_impl(negative_impl_def_id) {
- Ok(span) => {
- err.span_label(span, "negative implementation here");
- }
- Err(cname) => {
- err.note(&format!("negative implementation in crate `{}`", cname));
- }
- }
-
- match tcx.span_of_impl(positive_impl_def_id) {
- Ok(span) => {
- err.span_label(span, "positive implementation here");
- }
- Err(cname) => {
- err.note(&format!("positive implementation in crate `{}`", cname));
- }
- }
-
+ let mut err = tcx.sess.create_err(NegativePositiveConflict {
+ impl_span: tcx.def_span(local_impl_def_id),
+ trait_desc: &overlap.trait_desc,
+ self_desc: &overlap.self_desc,
+ negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
+ positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
+ });
sg.has_errored = Some(err.emit());
}
return true;
}
- match pat.kind.as_ref() {
+ match pat.kind {
thir::PatKind::Constant { value } => value.has_param_types_or_consts(),
- thir::PatKind::Range(thir::PatRange { lo, hi, .. }) => {
+ thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
lo.has_param_types_or_consts() || hi.has_param_types_or_consts()
}
_ => false,
// We just want to check sizedness, so instead of introducing
// placeholder lifetimes with probing, we just replace higher lifetimes
// with fresh vars.
- let arg_span = args.get(i).map(|a| a.span);
- let span = arg_span.unwrap_or(expr.span);
+ let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
let input = self.replace_bound_vars_with_fresh_vars(
span,
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.input(i),
);
- self.require_type_is_sized(
- self.normalize_associated_types_in(span, input),
+ self.require_type_is_sized_deferred(
+ input,
span,
- traits::SizedArgumentType(arg_span),
+ traits::SizedArgumentType(None),
);
}
}
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.output(),
);
- self.require_type_is_sized(
- self.normalize_associated_types_in(expr.span, output),
- expr.span,
- traits::SizedReturnType,
- );
+ self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType);
}
// We always require that the type provided as the value for
}
}
+ pub fn require_type_is_sized_deferred(
+ &self,
+ ty: Ty<'tcx>,
+ span: Span,
+ code: traits::ObligationCauseCode<'tcx>,
+ ) {
+ if !ty.references_error() {
+ self.deferred_sized_obligations.borrow_mut().push((ty, span, code));
+ }
+ }
+
pub fn register_bound(
&self,
ty: Ty<'tcx>,
};
if let Some(suggestion_text) = suggestion_text {
let source_map = self.sess().source_map();
- let mut suggestion = format!(
- "{}(",
- source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| fn_def_id
- .map_or("".to_string(), |fn_def_id| tcx.item_name(fn_def_id).to_string()))
- );
+ let (mut suggestion, suggestion_span) =
+ if let Some(call_span) = full_call_span.find_ancestor_inside(error_span) {
+ ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
+ } else {
+ (
+ format!(
+ "{}(",
+ source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
+ fn_def_id.map_or("".to_string(), |fn_def_id| {
+ tcx.item_name(fn_def_id).to_string()
+ })
+ })
+ ),
+ error_span,
+ )
+ };
let mut needs_comma = false;
for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
if needs_comma {
}
suggestion += ")";
err.span_suggestion_verbose(
- error_span,
+ suggestion_span,
&suggestion_text,
suggestion,
Applicability::HasPlaceholders,
}) {
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
} else {
- debug!("parent_node: {:?}", self.fcx.tcx.hir().find_parent_node(expr.hir_id));
- match self.fcx.tcx.hir().find_parent_node(expr.hir_id) {
+ let parent_expr = self
+ .fcx
+ .tcx
+ .hir()
+ .parent_iter(expr.hir_id)
+ .find(|(_, node)| matches!(node, hir::Node::Expr(_)))
+ .map(|(id, _)| id);
+ debug!("parent_expr: {:?}", parent_expr);
+ match parent_expr {
Some(parent) => Some(Scope { id: parent.local_id, data: ScopeData::Node }),
None => {
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
bk: rustc_middle::ty::BorrowKind,
) {
debug!(
- "borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \
- borrow_kind={bk:?}"
+ "borrow: place_with_id = {place_with_id:#?}, diag_expr_id={diag_expr_id:#?}, \
+ borrow_kind={bk:#?}"
);
self.borrow_place(place_with_id);
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
+ // Some additional `Sized` obligations badly affect type inference.
+ // These obligations are added in a later stage of typeck.
+ // Removing these may also cause additional complications, see #101066.
+ pub(super) deferred_sized_obligations:
+ RefCell<Vec<(Ty<'tcx>, Span, traits::ObligationCauseCode<'tcx>)>>,
+
// When we process a call like `c()` where `c` is a closure type,
// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
// `FnOnce` closure. In that case, we defer full resolution of the
infcx,
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
locals: RefCell::new(Default::default()),
+ deferred_sized_obligations: RefCell::new(Vec::new()),
deferred_call_resolutions: RefCell::new(Default::default()),
deferred_cast_checks: RefCell::new(Vec::new()),
deferred_transmute_checks: RefCell::new(Vec::new()),
use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::print::with_crate_prefix;
-use rustc_middle::ty::ToPolyTraitRef;
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol;
use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
use std::cmp::Ordering;
use std::iter;
-use super::probe::{Mode, ProbeScope};
+use super::probe::{IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
+ self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
+
return Some(err);
}
}
}
+ fn check_for_deref_method(
+ &self,
+ err: &mut Diagnostic,
+ self_source: SelfSource<'tcx>,
+ rcvr_ty: Ty<'tcx>,
+ item_name: Ident,
+ ) {
+ let SelfSource::QPath(ty) = self_source else { return; };
+ for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
+ if let Ok(pick) = self.probe_for_name(
+ ty.span,
+ Mode::Path,
+ item_name,
+ IsSuggestion(true),
+ deref_ty,
+ ty.hir_id,
+ ProbeScope::TraitsInScope,
+ ) {
+ if deref_ty.is_suggestable(self.tcx, true)
+ // If this method receives `&self`, then the provided
+ // argument _should_ coerce, so it's valid to suggest
+ // just changing the path.
+ && pick.item.fn_has_self_parameter
+ && let Some(self_ty) =
+ self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
+ && self_ty.is_ref()
+ {
+ let suggested_path = match deref_ty.kind() {
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Adt(_, _)
+ | ty::Str
+ | ty::Projection(_)
+ | ty::Param(_) => format!("{deref_ty}"),
+ _ => format!("<{deref_ty}>"),
+ };
+ err.span_suggestion_verbose(
+ ty.span,
+ format!("the function `{item_name}` is implemented on `{deref_ty}`"),
+ suggested_path,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.span_note(
+ ty.span,
+ format!("the function `{item_name}` is implemented on `{deref_ty}`"),
+ );
+ }
+ return;
+ }
+ }
+ }
+
/// Print out the type for use in value namespace.
fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
match ty.kind() {
fcx.resolve_rvalue_scopes(def_id.to_def_id());
fcx.resolve_generator_interiors(def_id.to_def_id());
+ for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
+ let ty = fcx.normalize_ty(span, ty);
+ fcx.require_type_is_sized(ty, span, code);
+ }
+
fcx.select_all_obligations_or_error();
if !fcx.infcx.is_tainted_by_errors() {
fn check_for_entry_fn(tcx: TyCtxt<'_>) {
match tcx.entry_fn(()) {
- Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
+ Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
_ => {}
}
-Subproject commit 4e5a3f72929f152752d5659e95bb15c8f6b41eff
+Subproject commit 07872f28cd8a65c3c7428811548dc85f1f2fb05b
/// impl Provider for SomeConcreteType {
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
/// demand.provide_ref::<str>(&self.field)
- /// .provide_value::<i32>(|| self.num_field);
+ /// .provide_value::<i32>(self.num_field);
/// }
/// }
/// ```
///
/// # Examples
///
+ /// Provides an `u8`.
+ ///
+ /// ```rust
+ /// #![feature(provide_any)]
+ ///
+ /// use std::any::{Provider, Demand};
+ /// # struct SomeConcreteType { field: u8 }
+ ///
+ /// impl Provider for SomeConcreteType {
+ /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ /// demand.provide_value::<u8>(self.field);
+ /// }
+ /// }
+ /// ```
+ #[unstable(feature = "provide_any", issue = "96024")]
+ pub fn provide_value<T>(&mut self, value: T) -> &mut Self
+ where
+ T: 'static,
+ {
+ self.provide::<tags::Value<T>>(value)
+ }
+
+ /// Provide a value or other type with only static lifetimes computed using a closure.
+ ///
+ /// # Examples
+ ///
/// Provides a `String` by cloning.
///
/// ```rust
- /// # #![feature(provide_any)]
+ /// #![feature(provide_any)]
+ ///
/// use std::any::{Provider, Demand};
/// # struct SomeConcreteType { field: String }
///
/// impl Provider for SomeConcreteType {
/// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
- /// demand.provide_value::<String>(|| self.field.clone());
+ /// demand.provide_value_with::<String>(|| self.field.clone());
/// }
/// }
/// ```
#[unstable(feature = "provide_any", issue = "96024")]
- pub fn provide_value<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
+ pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
where
T: 'static,
{
self.provide_with::<tags::Value<T>>(fulfil)
}
- /// Provide a reference, note that the referee type must be bounded by `'static`,
+ /// Provide a reference. The referee type must be bounded by `'static`,
/// but may be unsized.
///
/// # Examples
/// Provides a reference to a field as a `&str`.
///
/// ```rust
- /// # #![feature(provide_any)]
+ /// #![feature(provide_any)]
+ ///
/// use std::any::{Provider, Demand};
/// # struct SomeConcreteType { field: String }
///
self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value)
}
+ /// Provide a reference computed using a closure. The referee type
+ /// must be bounded by `'static`, but may be unsized.
+ ///
+ /// # Examples
+ ///
+ /// Provides a reference to a field as a `&str`.
+ ///
+ /// ```rust
+ /// #![feature(provide_any)]
+ ///
+ /// use std::any::{Provider, Demand};
+ /// # struct SomeConcreteType { business: String, party: String }
+ /// # fn today_is_a_weekday() -> bool { true }
+ ///
+ /// impl Provider for SomeConcreteType {
+ /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ /// demand.provide_ref_with::<str>(|| {
+ /// if today_is_a_weekday() {
+ /// &self.business
+ /// } else {
+ /// &self.party
+ /// }
+ /// });
+ /// }
+ /// }
+ /// ```
+ #[unstable(feature = "provide_any", issue = "96024")]
+ pub fn provide_ref_with<T: ?Sized + 'static>(
+ &mut self,
+ fulfil: impl FnOnce() -> &'a T,
+ ) -> &mut Self {
+ self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil)
+ }
+
/// Provide a value with the given `Type` tag.
fn provide<I>(&mut self, value: I::Reified) -> &mut Self
where
}
self
}
+
+ /// Check if the `Demand` would be satisfied if provided with a
+ /// value of the specified type. If the type does not match or has
+ /// already been provided, returns false.
+ ///
+ /// # Examples
+ ///
+ /// Check if an `u8` still needs to be provided and then provides
+ /// it.
+ ///
+ /// ```rust
+ /// #![feature(provide_any)]
+ ///
+ /// use std::any::{Provider, Demand};
+ ///
+ /// struct Parent(Option<u8>);
+ ///
+ /// impl Provider for Parent {
+ /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ /// if let Some(v) = self.0 {
+ /// demand.provide_value::<u8>(v);
+ /// }
+ /// }
+ /// }
+ ///
+ /// struct Child {
+ /// parent: Parent,
+ /// }
+ ///
+ /// impl Child {
+ /// // Pretend that this takes a lot of resources to evaluate.
+ /// fn an_expensive_computation(&self) -> Option<u8> {
+ /// Some(99)
+ /// }
+ /// }
+ ///
+ /// impl Provider for Child {
+ /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ /// // In general, we don't know if this call will provide
+ /// // an `u8` value or not...
+ /// self.parent.provide(demand);
+ ///
+ /// // ...so we check to see if the `u8` is needed before
+ /// // we run our expensive computation.
+ /// if demand.would_be_satisfied_by_value_of::<u8>() {
+ /// if let Some(v) = self.an_expensive_computation() {
+ /// demand.provide_value::<u8>(v);
+ /// }
+ /// }
+ ///
+ /// // The demand will be satisfied now, regardless of if
+ /// // the parent provided the value or we did.
+ /// assert!(!demand.would_be_satisfied_by_value_of::<u8>());
+ /// }
+ /// }
+ ///
+ /// let parent = Parent(Some(42));
+ /// let child = Child { parent };
+ /// assert_eq!(Some(42), std::any::request_value::<u8>(&child));
+ ///
+ /// let parent = Parent(None);
+ /// let child = Child { parent };
+ /// assert_eq!(Some(99), std::any::request_value::<u8>(&child));
+ /// ```
+ #[unstable(feature = "provide_any", issue = "96024")]
+ pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
+ where
+ T: 'static,
+ {
+ self.would_be_satisfied_by::<tags::Value<T>>()
+ }
+
+ /// Check if the `Demand` would be satisfied if provided with a
+ /// reference to a value of the specified type. If the type does
+ /// not match or has already been provided, returns false.
+ ///
+ /// # Examples
+ ///
+ /// Check if a `&str` still needs to be provided and then provides
+ /// it.
+ ///
+ /// ```rust
+ /// #![feature(provide_any)]
+ ///
+ /// use std::any::{Provider, Demand};
+ ///
+ /// struct Parent(Option<String>);
+ ///
+ /// impl Provider for Parent {
+ /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ /// if let Some(v) = &self.0 {
+ /// demand.provide_ref::<str>(v);
+ /// }
+ /// }
+ /// }
+ ///
+ /// struct Child {
+ /// parent: Parent,
+ /// name: String,
+ /// }
+ ///
+ /// impl Child {
+ /// // Pretend that this takes a lot of resources to evaluate.
+ /// fn an_expensive_computation(&self) -> Option<&str> {
+ /// Some(&self.name)
+ /// }
+ /// }
+ ///
+ /// impl Provider for Child {
+ /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ /// // In general, we don't know if this call will provide
+ /// // a `str` reference or not...
+ /// self.parent.provide(demand);
+ ///
+ /// // ...so we check to see if the `&str` is needed before
+ /// // we run our expensive computation.
+ /// if demand.would_be_satisfied_by_ref_of::<str>() {
+ /// if let Some(v) = self.an_expensive_computation() {
+ /// demand.provide_ref::<str>(v);
+ /// }
+ /// }
+ ///
+ /// // The demand will be satisfied now, regardless of if
+ /// // the parent provided the reference or we did.
+ /// assert!(!demand.would_be_satisfied_by_ref_of::<str>());
+ /// }
+ /// }
+ ///
+ /// let parent = Parent(Some("parent".into()));
+ /// let child = Child { parent, name: "child".into() };
+ /// assert_eq!(Some("parent"), std::any::request_ref::<str>(&child));
+ ///
+ /// let parent = Parent(None);
+ /// let child = Child { parent, name: "child".into() };
+ /// assert_eq!(Some("child"), std::any::request_ref::<str>(&child));
+ /// ```
+ #[unstable(feature = "provide_any", issue = "96024")]
+ pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool
+ where
+ T: ?Sized + 'static,
+ {
+ self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>()
+ }
+
+ fn would_be_satisfied_by<I>(&self) -> bool
+ where
+ I: tags::Type<'a>,
+ {
+ matches!(self.0.downcast::<I>(), Some(TaggedOption(None)))
+ }
}
#[unstable(feature = "provide_any", issue = "96024")]
/// Returns some reference to the dynamic value if it is tagged with `I`,
/// or `None` otherwise.
#[inline]
+ fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>>
+ where
+ I: tags::Type<'a>,
+ {
+ if self.tag_id() == TypeId::of::<I>() {
+ // SAFETY: Just checked whether we're pointing to an I.
+ Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() })
+ } else {
+ None
+ }
+ }
+
+ /// Returns some mutable reference to the dynamic value if it is tagged with `I`,
+ /// or `None` otherwise.
+ #[inline]
fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>>
where
I: tags::Type<'a>,
impl<T> Bound<T> {
/// Converts from `&Bound<T>` to `Bound<&T>`.
#[inline]
- #[unstable(feature = "bound_as_ref", issue = "80996")]
+ #[stable(feature = "bound_as_ref_shared", since = "CURRENT_RUSTC_VERSION")]
pub fn as_ref(&self) -> Bound<&T> {
match *self {
Included(ref x) => Included(x),
demand
.provide_ref::<String>(&self.some_string)
.provide_ref::<str>(&self.some_string)
- .provide_value::<String>(|| "bye".to_owned());
+ .provide_value_with::<String>(|| "bye".to_owned());
}
}
///
/// If the returned iterator is dropped before being fully consumed, it
/// drops the remaining elements. The returned iterator keeps a mutable
- /// borrow on the vector to optimize its implementation.
+ /// borrow on the set to optimize its implementation.
///
/// # Examples
///
// Runs before `main`.
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+//
+// # The `sigpipe` parameter
+//
+// Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to
+// `SIG_IGN`. Applications have good reasons to want a different behavior
+// though, so there is a `#[unix_sigpipe = "..."]` attribute on `fn main()` that
+// can be used to select how `SIGPIPE` shall be setup (if changed at all) before
+// `fn main()` is called. See <https://github.com/rust-lang/rust/issues/97889>
+// for more info.
+//
+// The `sigpipe` parameter to this function gets its value via the code that
+// rustc generates to invoke `fn lang_start()`. The reason we have `sigpipe` for
+// all platforms and not only Unix, is because std is not allowed to have `cfg`
+// directives as this high level. See the module docs in
+// `src/tools/tidy/src/pal.rs` for more info. On all other platforms, `sigpipe`
+// has a value, but its value is ignored.
+//
+// Even though it is an `u8`, it only ever has 3 values. These are documented in
+// `compiler/rustc_session/src/config/sigpipe.rs`.
#[cfg_attr(test, allow(dead_code))]
-unsafe fn init(argc: isize, argv: *const *const u8) {
+unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
unsafe {
- sys::init(argc, argv);
+ sys::init(argc, argv, sigpipe);
let main_guard = sys::thread::guard::init();
// Next, set up the current Thread with the guard information we just
main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
argc: isize,
argv: *const *const u8,
+ sigpipe: u8,
) -> Result<isize, !> {
use crate::{mem, panic};
let rt_abort = move |e| {
// prevent libstd from accidentally introducing a panic to these functions. Another is from
// user code from `main` or, more nefariously, as described in e.g. issue #86030.
// SAFETY: Only called once during runtime initialization.
- panic::catch_unwind(move || unsafe { init(argc, argv) }).map_err(rt_abort)?;
+ panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) }).map_err(rt_abort)?;
let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
.map_err(move |e| {
mem::forget(e);
main: fn() -> T,
argc: isize,
argv: *const *const u8,
+ #[cfg(not(bootstrap))] sigpipe: u8,
) -> isize {
let Ok(v) = lang_start_internal(
&move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
argc,
argv,
+ #[cfg(bootstrap)]
+ 2, // Temporary inlining of sigpipe::DEFAULT until bootstrap stops being special
+ #[cfg(not(bootstrap))]
+ sigpipe,
);
v
}
and cause Futures to not implement `Send`"]
#[stable(feature = "rust1", since = "1.0.0")]
#[clippy::has_significant_drop]
+#[cfg_attr(not(test), rustc_diagnostic_item = "MutexGuard")]
pub struct MutexGuard<'a, T: ?Sized + 'a> {
lock: &'a Mutex<T>,
poison: poison::Guard,
and cause Futures to not implement `Send`"]
#[stable(feature = "rust1", since = "1.0.0")]
#[clippy::has_significant_drop]
+#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockReadGuard")]
pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
// NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a
// `Ref` argument doesn't hold immutability for its whole scope, only until it drops.
and cause Future's to not implement `Send`"]
#[stable(feature = "rust1", since = "1.0.0")]
#[clippy::has_significant_drop]
+#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockWriteGuard")]
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
lock: &'a RwLock<T>,
poison: poison::Guard,
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
let _ = net::init();
args::init(argc, argv);
}
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
unsafe {
args::init(argc, argv);
}
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
// SAFETY: must be called only once during runtime cleanup.
pub unsafe fn cleanup() {}
pub mod time;
#[cfg(target_os = "espidf")]
-pub fn init(argc: isize, argv: *const *const u8) {}
+pub fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {}
#[cfg(not(target_os = "espidf"))]
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+// See `fn init()` in `library/std/src/rt.rs` for docs on `sigpipe`.
+pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// The standard streams might be closed on application startup. To prevent
// std::io::{stdin, stdout,stderr} objects from using other unrelated file
// resources opened later, we reopen standards streams when they are closed.
// want!
//
// Hence, we set SIGPIPE to ignore when the program starts up in order
- // to prevent this problem.
- reset_sigpipe();
+ // to prevent this problem. Add `#[unix_sigpipe = "..."]` above `fn main()` to
+ // alter this behavior.
+ reset_sigpipe(sigpipe);
stack_overflow::init();
args::init(argc, argv);
}
}
- unsafe fn reset_sigpipe() {
+ unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
#[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
- rtassert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
+ {
+ // We don't want to add this as a public type to libstd, nor do we
+ // want to `include!` a file from the compiler (which would break
+ // Miri and xargo for example), so we choose to duplicate these
+ // constants from `compiler/rustc_session/src/config/sigpipe.rs`.
+ // See the other file for docs. NOTE: Make sure to keep them in
+ // sync!
+ mod sigpipe {
+ pub const INHERIT: u8 = 1;
+ pub const SIG_IGN: u8 = 2;
+ pub const SIG_DFL: u8 = 3;
+ }
+
+ let handler = match sigpipe {
+ sigpipe::INHERIT => None,
+ sigpipe::SIG_IGN => Some(libc::SIG_IGN),
+ sigpipe::SIG_DFL => Some(libc::SIG_DFL),
+ _ => unreachable!(),
+ };
+ if let Some(handler) = handler {
+ rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR);
+ }
+ }
}
}
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
status >= 0
}
-pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
+pub const BCRYPT_RNG_ALG_HANDLE: usize = 0x81;
#[repr(C)]
pub struct UNICODE_STRING {
MaximumFileInfoByHandlesClass,
}
+#[repr(C)]
+pub struct FILE_ATTRIBUTE_TAG_INFO {
+ pub FileAttributes: DWORD,
+ pub ReparseTag: DWORD,
+}
+
#[repr(C)]
pub struct FILE_DISPOSITION_INFO {
pub DeleteFile: BOOLEAN,
cvt(c::GetFileInformationByHandle(self.handle.as_raw_handle(), &mut info))?;
let mut reparse_tag = 0;
if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
- let mut b =
- Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
- if let Ok((_, buf)) = self.reparse_point(&mut b) {
- reparse_tag = (*buf).ReparseTag;
+ let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
+ cvt(c::GetFileInformationByHandleEx(
+ self.handle.as_raw_handle(),
+ c::FileAttributeTagInfo,
+ ptr::addr_of_mut!(attr_tag).cast(),
+ mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
+ ))?;
+ if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+ reparse_tag = attr_tag.ReparseTag;
}
}
Ok(FileAttr {
attr.file_size = info.AllocationSize as u64;
attr.number_of_links = Some(info.NumberOfLinks);
if attr.file_type().is_reparse_point() {
- let mut b =
- Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
- if let Ok((_, buf)) = self.reparse_point(&mut b) {
- attr.reparse_tag = (*buf).ReparseTag;
+ let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
+ cvt(c::GetFileInformationByHandleEx(
+ self.handle.as_raw_handle(),
+ c::FileAttributeTagInfo,
+ ptr::addr_of_mut!(attr_tag).cast(),
+ mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
+ ))?;
+ if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+ reparse_tag = attr_tag.ReparseTag;
}
}
Ok(attr)
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {
stack_overflow::init();
// Normally, `thread::spawn` will call `Thread::set_name` but since this thread already
+//! # Random key generation
+//!
+//! This module wraps the RNG provided by the OS. There are a few different
+//! ways to interface with the OS RNG so it's worth exploring each of the options.
+//! Note that at the time of writing these all go through the (undocumented)
+//! `bcryptPrimitives.dll` but they use different route to get there.
+//!
+//! Originally we were using [`RtlGenRandom`], however that function is
+//! deprecated and warns it "may be altered or unavailable in subsequent versions".
+//!
+//! So we switched to [`BCryptGenRandom`] with the `BCRYPT_USE_SYSTEM_PREFERRED_RNG`
+//! flag to query and find the system configured RNG. However, this change caused a small
+//! but significant number of users to experience panics caused by a failure of
+//! this function. See [#94098].
+//!
+//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE`
+//! [Pseudo-handle], which gets the default RNG algorithm without querying the
+//! system preference thus hopefully avoiding the previous issue.
+//! This is only supported on Windows 10+ so a fallback is used for older versions.
+//!
+//! [#94098]: https://github.com/rust-lang/rust/issues/94098
+//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
+//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles
use crate::io;
use crate::mem;
use crate::ptr;
use crate::sys::c;
+/// Generates high quality secure random keys for use by [`HashMap`].
+///
+/// This is used to seed the default [`RandomState`].
+///
+/// [`HashMap`]: crate::collections::HashMap
+/// [`RandomState`]: crate::collections::hash_map::RandomState
pub fn hashmap_random_keys() -> (u64, u64) {
let mut v = (0, 0);
let ret = unsafe {
+ let size = mem::size_of_val(&v).try_into().unwrap();
c::BCryptGenRandom(
- ptr::null_mut(),
- &mut v as *mut _ as *mut u8,
- mem::size_of_val(&v) as c::ULONG,
- c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
+ // BCRYPT_RNG_ALG_HANDLE is only supported in Windows 10+.
+ // So for Windows 8.1 and Windows 7 we'll need a fallback when this fails.
+ ptr::invalid_mut(c::BCRYPT_RNG_ALG_HANDLE),
+ ptr::addr_of_mut!(v).cast(),
+ size,
+ 0,
)
};
if ret != 0 { fallback_rng() } else { v }
compiler: build_compiler,
target: target_compiler.host,
});
- builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe("ld", target_compiler.host)));
+ for name in crate::LLD_FILE_NAMES {
+ builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(name, target_compiler.host)));
+ }
}
if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
let gcc_lld_src_dir = src_dir.join("gcc-ld");
let gcc_lld_dst_dir = dst_dir.join("gcc-ld");
t!(fs::create_dir(&gcc_lld_dst_dir));
- let exe_name = exe("ld", compiler.host);
- builder.copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
+ for name in crate::LLD_FILE_NAMES {
+ let exe_name = exe(name, compiler.host);
+ builder
+ .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
+ }
}
// Man pages
t!(fs::create_dir_all(&out));
let mut index = tool::ErrorIndex::command(builder);
index.arg("html");
- index.arg(out.join("error-index.html"));
+ index.arg(out);
index.arg(&builder.version);
builder.run(&mut index);
"opt", // used to optimize LLVM bytecode
];
+/// LLD file names for all flavors.
+const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
+
pub const VERSION: usize = 2;
/// Extra --check-cfg to add when building
-FROM ubuntu:16.04
+FROM ubuntu:22.04
+ARG DEBIAN_FRONTEND=noninteractive
COPY scripts/android-base-apt-get.sh /scripts/
RUN sh /scripts/android-base-apt-get.sh
libgl1-mesa-glx \
libpulse0 \
libstdc++6:i386 \
- openjdk-9-jre-headless \
+ openjdk-8-jre-headless \
tzdata \
wget \
python3
ENV TARGETS=arm-linux-androideabi
-# We are intentionally allowing an old toolchain on this builder (and that's
-# incompatible with LLVM downloads today).
-ENV NO_DOWNLOAD_CI_LLVM 1
-
-ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14 \
- --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14
ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target $TARGETS
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
COPY scripts/android-start-emulator.sh /scripts/
ENTRYPOINT ["/scripts/android-start-emulator.sh"]
-FROM ubuntu:16.04
+FROM ubuntu:22.04
COPY scripts/android-base-apt-get.sh /scripts/
RUN sh /scripts/android-base-apt-get.sh
--i686-linux-android-ndk=/android/ndk/x86-14 \
--aarch64-linux-android-ndk=/android/ndk/arm64-21 \
--x86_64-linux-android-ndk=/android/ndk/x86_64-21 \
- --disable-docs \
- --set llvm.allow-old-toolchain
+ --disable-docs
ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
-
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
g++ \
git \
libssl-dev \
+ libncurses5 \
make \
ninja-build \
pkg-config \
The `package` file describes our package's name and version number. Every
package must contain one.
-**`pkg/hello_fuchsia.manifest`**
+**`pkg/hello_fuchsia.manifest` if using cargo**
```txt
-bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia # If using cargo...
-bin/hello_fuchsia=bin/hello_fuchsia # If using rustc...
+bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia
+lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
+lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
+meta/package=pkg/meta/package
+meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
+```
+
+**`pkg/hello_fuchsia.manifest` if using rustc**
+```txt
+bin/hello_fuchsia=bin/hello_fuchsia
lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
meta/package=pkg/meta/package
```sh
${SDK_PATH}/tools/${ARCH}/ffx component run \
+ /core/ffx-laboratory:hello_fuchsia \
fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
```
```sh
${SDK_PATH}/tools/${ARCH}/ffx component run \
--recreate \
+ /core/ffx-laboratory:hello_fuchsia \
fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
```
--- /dev/null
+# `unix_sigpipe`
+
+The tracking issue for this feature is: [#97889]
+
+[#97889]: https://github.com/rust-lang/rust/issues/97889
+
+---
+
+The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants:
+* `#[unix_sigpipe = "inherit"]`
+* `#[unix_sigpipe = "sig_dfl"]`
+* `#[unix_sigpipe = "sig_ign"]`
+
+## `#[unix_sigpipe = "inherit"]`
+
+Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`.
+
+## `#[unix_sigpipe = "sig_dfl"]`
+
+Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output.
+
+### Example
+
+```rust,no_run
+#![feature(unix_sigpipe)]
+#[unix_sigpipe = "sig_dfl"]
+fn main() { loop { println!("hello world"); } }
+```
+
+```bash
+% ./main | head -n 1
+hello world
+```
+
+## `#[unix_sigpipe = "sig_ign"]`
+
+Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers.
+
+This is what libstd has done by default since 2014. Omitting `#[unix_sigpipe = "..."]` is the same as having `#[unix_sigpipe = "sig_ign"]`.
+
+### Example
+
+```rust,no_run
+#![feature(unix_sigpipe)]
+#[unix_sigpipe = "sig_ign"]
+fn main() { loop { println!("hello world"); } }
+```
+
+```bash
+% ./main | head -n 1
+hello world
+thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+```
div.impl-items > div:not(.docblock):not(.item-info),
.content ul.crate a.crate,
a.srclink,
-#main-content > .since,
#help-button > button,
details.rustdoc-toggle.top-doc > summary,
details.rustdoc-toggle.top-doc > summary::before,
margin-bottom: .6em;
}
-.content .impl-items > .item-info {
- margin-left: 40px;
-}
-
-.methods > .item-info, .content .impl-items > .item-info {
- margin-top: -8px;
-}
-
-.impl-items {
- flex-basis: 100%;
-}
-
#main-content > .item-info {
margin-top: 0;
margin-left: 0;
width: 100%;
background-color: var(--button-background-color);
}
+.search-input:focus {
+ border-color: var(--search-input-focused-border-color);
+}
.search-results {
display: none;
float: right;
}
+.rightside:not(a),
+.out-of-band {
+ color: var(--right-side-color);
+}
+
+
.impl-items .srclink, .impl .srclink, .methods .srclink {
/* Override header settings otherwise it's too bold */
font-weight: normal;
.code-attribute {
font-weight: 300;
+ color: var(--code-attribute-color);
}
.item-spacer {
margin-left: 24px;
}
-.toggle-label {
- display: inline-block;
- margin-left: 4px;
- margin-top: 3px;
-}
-
:target > code, :target > .code-header {
opacity: 1;
}
background-color: var(--button-background-color);
}
+#copy-path {
+ color: var(--copy-path-button-color);
+}
+#copy-path > img {
+ filter: var(--copy-path-img-filter);
+}
+#copy-path:hover > img {
+ filter: var(--copy-path-img-hover-filter);
+}
+
@keyframes rotating {
from {
transform: rotate(0deg);
opacity: .5;
}
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+.more-examples-toggle summary, .more-examples-toggle .hide-more {
+ color: var(--toggles-color);
+}
+
/* Screen readers see the text version at the end the line.
Visual readers see the icon at the start of the line, but small and transparent. */
details.rustdoc-toggle > summary::after {
#main-content > div > details.rustdoc-toggle > summary::before {
left: -11px;
}
+
+ /* Align summary-nested and unnested item-info gizmos. */
+ .content .impl-items > .item-info {
+ margin-left: 34px;
+ }
}
@media print {
--headings-border-bottom-color: #5c6773;
--border-color: #5c6773;
--button-background-color: #141920;
+ --right-side-color: grey;
+ --code-attribute-color: #999;
+ --toggles-color: #999;
+ --search-input-focused-border-color: #5c6773; /* Same as `--border-color`. */
+ --copy-path-button-color: #fff;
+ --copy-path-img-filter: invert(70%);
+ --copy-path-img-hover-filter: invert(100%);
}
.slider {
background: #333;
}
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
- color: #999;
-}
-
details.rustdoc-toggle > summary::before {
filter: invert(100%);
}
background: none;
}
-.rightside:not(a),
-.out-of-band {
- color: grey;
-}
-
.result-name .primitive > i, .result-name .keyword > i {
color: #788797;
}
color: #c5c5c5;
}
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
:target {
background: rgba(255, 236, 164, 0.06);
border-right: 3px solid rgba(255, 180, 76, 0.85);
/* FIXME: these rules should be at the bottom of the file but currently must be
above the `@media (max-width: 700px)` rules due to a bug in the css checker */
/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-.search-input:focus {}
.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,
.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {}
.content span.struct,.content a.struct,.block a.current.struct {}
filter: invert(100);
}
-#copy-path {
- color: #fff;
-}
-#copy-path > img {
- filter: invert(70%);
-}
-#copy-path:hover > img {
- filter: invert(100%);
-}
-
#settings-menu > a:hover, #settings-menu > a:focus,
#help-button > button:hover, #help-button > button:focus {
border-color: #e0e0e0;
border-color: white;
color: white;
}
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
- color: #999;
-}
.scraped-example .example-wrap .rust span.highlight {
background: rgb(91, 59, 1);
}
--headings-border-bottom-color: #d2d2d2;
--border-color: #e0e0e0;
--button-background-color: #f0f0f0;
+ --right-side-color: grey;
+ --code-attribute-color: #999;
+ --toggles-color: #999;
+ --search-input-focused-border-color: #008dfd;
+ --copy-path-button-color: #999;
+ --copy-path-img-filter: invert(50%);
+ --copy-path-img-hover-filter: invert(65%);
}
.slider {
background: #333;
}
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
- color: #999;
-}
-
details.rustdoc-toggle > summary::before {
filter: invert(100%);
}
.search-input {
color: #111;
- border-color: #f0f0f0;
}
#crate-search-div::after {
filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);
}
-.search-input:focus {
- border-color: #008dfd;
-}
-
.stab { background: #314559; }
.stab.portability > code {
background: none;
}
-.rightside:not(a),
-.out-of-band {
- color: grey;
-}
-
.line-numbers :target { background-color: transparent; }
/* Code highlighting */
background-color: #4e8bca;
}
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
:target {
background-color: #494a3d;
border-right: 3px solid #bb7410;
border-color: #ffb900;
}
-#copy-path {
- color: #999;
-}
-#copy-path > img {
- filter: invert(50%);
-}
-#copy-path:hover > img {
- filter: invert(65%);
-}
-
.search-results .result-name span.alias {
color: #fff;
}
border-color: white;
color: white;
}
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
- color: #999;
-}
.scraped-example .example-wrap .rust span.highlight {
background: rgb(91, 59, 1);
}
--headings-border-bottom-color: #ddd;
--border-color: #e0e0e0;
--button-background-color: #fff;
+ --right-side-color: grey;
+ --code-attribute-color: #999;
+ --toggles-color: #999;
+ --search-input-focused-border-color: #66afe9;
+ --copy-path-button-color: #999;
+ --copy-path-img-filter: invert(50%);
+ --copy-path-img-hover-filter: invert(35%);
}
.slider {
background: #eee;
}
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
- color: #999;
-}
-
#crate-search-div::after {
/* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
filter: invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);
filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);
}
-.search-input:focus {
- border-color: #66afe9;
-}
-
.stab { background: #FFF5D6; border-color: #FFC600; }
.stab.portability > code { background: none; }
-.rightside:not(a),
-.out-of-band {
- color: grey;
-}
-
.line-numbers :target { background-color: transparent; }
/* Code highlighting */
background-color: #4e8bca;
}
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
:target {
background: #FDFFD3;
border-right: 3px solid #AD7C37;
border-color: #717171;
}
-#copy-path {
- color: #999;
-}
-#copy-path > img {
- filter: invert(50%);
-}
-#copy-path:hover > img {
- filter: invert(35%);
-}
-
.search-results .result-name span.alias {
color: #000;
}
border-color: black;
color: black;
}
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
- color: #999;
-}
.scraped-example .example-wrap .rust span.highlight {
background: #fcffd6;
}
},
QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath {
name: assoc.name.to_string(),
- args: Box::new(assoc.args.clone().into_tcx(tcx)),
+ args: Box::new(assoc.args.into_tcx(tcx)),
self_type: Box::new(self_type.into_tcx(tcx)),
trait_: trait_.into_tcx(tcx),
},
use std::convert::TryFrom;
<[T; N.get()]>::try_from(())
//~^ error: the trait bound
+ //~| error: the trait bound
//~| error: mismatched types
}
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
+
+// FIXME: This test was broken by the derefer change.
// example from #68867
type CSSFloat = f32;
}
// EMIT_MIR early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
-// EMIT_MIR early_otherwise_branch_68867.try_sum EarlyOtherwiseBranch.before SimplifyConstCondition-final.after
#[no_mangle]
pub extern "C" fn try_sum(
x: &ViewportPercentageLength,
+++ /dev/null
-- // MIR for `try_sum` before EarlyOtherwiseBranch
-+ // MIR for `try_sum` after SimplifyConstCondition-final
-
- fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> Result<ViewportPercentageLength, ()> {
- debug x => _1; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+1:5: +1:6
- debug other => _2; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+2:5: +2:10
- let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:+3:6: +3:42
- let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6
- let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
- let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
- let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:21: +6:30
- let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:21: +7:30
- let mut _9: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:23: +8:34
- let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:23: +9:34
- let mut _11: isize; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:11: +6:18
- let _12: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
- let _13: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
- let mut _14: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
- let mut _15: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
- let mut _16: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
- let _17: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
- let _18: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
- let mut _19: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
- let mut _20: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
- let mut _21: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
- let _22: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
- let _23: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
- let mut _24: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
- let mut _25: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
- let mut _26: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
- let _27: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
- let _28: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
- let mut _29: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
- let mut _30: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
- let mut _31: f32; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
- let mut _32: !; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:14: +10:28
- let mut _33: (); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- let mut _34: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _35: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _36: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _37: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _38: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _39: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _40: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _41: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _42: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _43: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _44: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _45: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- let mut _46: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- scope 1 {
-- debug one => _12; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-- debug other => _13; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-+ debug one => _15; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-+ debug other => _16; // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
- }
- scope 2 {
-- debug one => _17; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-- debug other => _18; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-+ debug one => _20; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-+ debug other => _21; // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
- }
- scope 3 {
-- debug one => _22; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-- debug other => _23; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-+ debug one => _25; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-+ debug other => _26; // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
- }
- scope 4 {
-- debug one => _27; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-- debug other => _28; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-+ debug one => _30; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-+ debug other => _31; // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
- }
-
- bb0: {
-- StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6
-- StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-- StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
-- _5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
-+ (_4.0: &ViewportPercentageLength) = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
- StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
- _6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
- Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-- (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
-- StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
- _34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- _11 = discriminant((*_34)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
- }
-
- bb1: {
- _35 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- _7 = discriminant((*_35)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
- }
-
- bb2: {
- StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28
-- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
-- StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
- return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
- }
-
- bb3: {
- _36 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- _8 = discriminant((*_36)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
- }
-
- bb4: {
- _37 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- _9 = discriminant((*_37)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
- }
-
- bb5: {
- _38 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- _10 = discriminant((*_38)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
- }
-
- bb6: {
-- StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
- _39 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-- _12 = (((*_39) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-- StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-+ _15 = (((*_39) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
- _40 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-- _13 = (((*_40) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-- StorageLive(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
-- StorageLive(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
-- _15 = _12; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
-- StorageLive(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
-- _16 = _13; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
-- _14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
-- StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
-- StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
-- Deinit(_3); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-- ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-- discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-- StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-- StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-- StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-+ _16 = (((*_40) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
-+ ((((_0 as Ok).0: ViewportPercentageLength) as Vw).0: f32) = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
-+ Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-+ nop; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
- }
-
- bb7: {
-- StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
- _41 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-- _17 = (((*_41) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-- StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-+ _20 = (((*_41) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
- _42 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-- _18 = (((*_42) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-- StorageLive(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
-- StorageLive(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
-- _20 = _17; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
-- StorageLive(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
-- _21 = _18; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
-- _19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
-- StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
-- StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
-- Deinit(_3); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-- ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-- discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-- StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-- StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-- StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-+ _21 = (((*_42) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
-+ ((((_0 as Ok).0: ViewportPercentageLength) as Vh).0: f32) = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
-+ Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-+ nop; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
- }
-
- bb8: {
-- StorageLive(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
- _43 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-- _22 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-- StorageLive(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-+ _25 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
- _44 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-- _23 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-- StorageLive(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
-- StorageLive(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
-- _25 = _22; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
-- StorageLive(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
-- _26 = _23; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
-- _24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
-- StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
-- StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
-- Deinit(_3); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-- ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-- discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-- StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-- StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-- StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-+ _26 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
-+ ((((_0 as Ok).0: ViewportPercentageLength) as Vmin).0: f32) = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
-+ Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-+ nop; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
- }
-
- bb9: {
-- StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
- _45 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-- _27 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-- StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-+ _30 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
- _46 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-- _28 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-- StorageLive(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
-- StorageLive(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
-- _30 = _27; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
-- StorageLive(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
-- _31 = _28; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
-- _29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
-- StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
-- StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
-- Deinit(_3); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-- ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-- discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-- StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-- StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-- StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-+ _31 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
-+ ((((_0 as Ok).0: ViewportPercentageLength) as Vmax).0: f32) = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
-+ Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-+ discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-+ nop; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
- goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
- }
-
- bb10: {
- Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
-- ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
- discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
-- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
-- StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
-+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
- return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
- }
-
- bb11: {
- unreachable; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
- }
- }
-
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
_34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
_11 = discriminant((*_34)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+ switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
}
bb1: {
bb2: {
StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
+ Deinit(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
+ ((_0 as Err).0: ()) = move _33; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
- return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
+ goto -> bb11; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
}
bb3: {
discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
- return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
+ goto -> bb11; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
}
bb11: {
- unreachable; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
+ return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
}
}
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR issue_73223.main.SimplifyArmIdentity.diff
-// EMIT_MIR issue_73223.main.PreCodegen.diff
+++ /dev/null
-- // MIR for `main` before PreCodegen
-+ // MIR for `main` after PreCodegen
-
- fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14
- let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- let _3: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
- let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _14: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _19: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 1 {
- debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14
- let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
- scope 3 {
- debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14
- let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 4 {
- debug left_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- debug right_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 5 {
- debug kind => _13; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
- }
- }
- }
- scope 2 {
- debug v => _3; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15
- }
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14
- StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
- _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
- _1 = _3; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21
- StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21
- StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7
- StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
- StorageLive(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _6 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
- _7 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_5.0: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_5.1: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _8 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _9 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _10 = Not(move _11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb1: {
- StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _16 = _8; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _18 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _14 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) }
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
- }
-
- bb2: {
- StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2
- StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2
- return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2
- }
- }
-
+++ /dev/null
-- // MIR for `main` before PreCodegen
-+ // MIR for `main` after PreCodegen
-
- fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14
- let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- let _3: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
- let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _14: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _19: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 1 {
- debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14
- let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
- scope 3 {
- debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14
- let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 4 {
- debug left_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- debug right_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 5 {
- debug kind => _13; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
- }
- }
- }
- scope 2 {
- debug v => _3; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15
- }
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14
- StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
- StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
- _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
- _1 = _3; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21
- StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21
- StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7
- StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
- StorageLive(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _6 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
- _7 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_5.0: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_5.1: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _8 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _9 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _10 = Not(move _11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb1: {
- StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _16 = _8; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _18 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _14 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) }
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
- }
-
- bb2: {
- StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2
- StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2
- return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2
- }
- }
-
+++ /dev/null
-- // MIR for `array_bound` before InstCombine
-+ // MIR for `array_bound` after InstCombine
-
- fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
- debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:36: +0:41
- debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:+0:50: +0:55
- let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:+0:70: +0:72
- let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
- let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- _4 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _7 = _2; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- _11 = _7; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
-- _5 = Len((*_11)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- }
-
- bb1: {
- StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
- _8 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-- _9 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ _9 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- }
-
- bb2: {
- _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
- goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6
- }
-
- bb3: {
- _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:11
- goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6
- }
-
- bb4: {
- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+5:5: +5:6
- return; // scope 0 at $DIR/lower_array_len.rs:+6:2: +6:2
- }
- }
-
+++ /dev/null
-- // MIR for `array_bound` before SimplifyLocals
-+ // MIR for `array_bound` after SimplifyLocals
-
- fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
- debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:36: +0:41
- debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:+0:50: +0:55
- let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:+0:70: +0:72
- let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-- let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ let _6: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+ let mut _7: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ let mut _8: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- _4 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
- _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- }
-
- bb1: {
-- StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-- _8 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-- _9 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+ _6 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+ _7 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- }
-
- bb2: {
-- _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
-+ _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
- goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6
- }
-
- bb3: {
- _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:11
- goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6
- }
-
- bb4: {
- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+5:5: +5:6
- return; // scope 0 at $DIR/lower_array_len.rs:+6:2: +6:2
- }
- }
-
+++ /dev/null
-- // MIR for `array_bound_mut` before InstCombine
-+ // MIR for `array_bound_mut` after InstCombine
-
- fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
- debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:40: +0:45
- debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:+0:54: +0:59
- let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:+0:78: +0:80
- let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
- let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
- let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
- let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
- let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- _4 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- _14 = _7; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
-- _5 = Len((*_14)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
- StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- }
-
- bb1: {
- StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
- _8 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-- _9 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ _9 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- }
-
- bb2: {
- _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
- goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6
- }
-
- bb3: {
- StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
- _11 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-- _12 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+ _12 = const N; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
- _13 = Lt(_11, _12); // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
- }
-
- bb4: {
- (*_2)[_11] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22
- StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23
- _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+6:9: +6:11
- goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6
- }
-
- bb5: {
- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+7:5: +7:6
- return; // scope 0 at $DIR/lower_array_len.rs:+8:2: +8:2
- }
- }
-
+++ /dev/null
-- // MIR for `array_bound_mut` before SimplifyLocals
-+ // MIR for `array_bound_mut` after SimplifyLocals
-
- fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
- debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:40: +0:45
- debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:+0:54: +0:59
- let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:+0:78: +0:80
- let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-- let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-- let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-- let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-- let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ let _6: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+ let mut _7: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ let mut _8: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ let _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-+ let mut _10: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+ let mut _11: bool; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- _4 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
- StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
- _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-- StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
- }
-
- bb1: {
-- StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-- _8 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-- _9 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+ _6 = _1; // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+ _7 = const N; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
- }
-
- bb2: {
-- _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-- StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
-+ _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
- goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6
- }
-
- bb3: {
-- StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-- _11 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-- _12 = const N; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-- _13 = Lt(const 0_usize, _12); // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+ StorageLive(_9); // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-+ _9 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-+ _10 = const N; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+ _11 = Lt(const 0_usize, _10); // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+ assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
- }
-
- bb4: {
-- (*_2)[_11] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22
-- StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23
-+ (*_2)[_9] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22
-+ StorageDead(_9); // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23
- _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:+6:9: +6:11
- goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6
- }
-
- bb5: {
- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+7:5: +7:6
- return; // scope 0 at $DIR/lower_array_len.rs:+8:2: +8:2
- }
- }
-
+++ /dev/null
-- // MIR for `array_len` before InstCombine
-+ // MIR for `array_len` after InstCombine
-
- fn array_len(_1: &[u8; N]) -> usize {
- debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:34: +0:37
- let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57
- let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- _3 = &(*_1); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _3 = _1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- _4 = _3; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
-- _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14
- return; // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2
- }
- }
-
+++ /dev/null
-- // MIR for `array_len` before SimplifyLocals
-+ // MIR for `array_len` after SimplifyLocals
-
- fn array_len(_1: &[u8; N]) -> usize {
- debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:34: +0:37
- let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57
-- let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-
- bb0: {
-- StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
- _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14
- return; // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2
- }
- }
-
+++ /dev/null
-- // MIR for `array_len_by_value` before InstCombine
-+ // MIR for `array_len_by_value` after InstCombine
-
- fn array_len_by_value(_1: [u8; N]) -> usize {
- debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:46
- let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65
- let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- _3 = &_1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- _4 = _3; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
-- _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
- StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14
- return; // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2
- }
- }
-
+++ /dev/null
-- // MIR for `array_len_by_value` before SimplifyLocals
-+ // MIR for `array_len_by_value` after SimplifyLocals
-
- fn array_len_by_value(_1: [u8; N]) -> usize {
- debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:46
- let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65
-- let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-
- bb0: {
-- StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
- _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-- StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14
- return; // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2
- }
- }
-
-// compile-flags: -Z mir-opt-level=4
+// unit-test: NormalizeArrayLen
+// compile-flags: -Zmir-enable-passes=+LowerSliceLenCalls
// EMIT_MIR lower_array_len.array_bound.NormalizeArrayLen.diff
-// EMIT_MIR lower_array_len.array_bound.SimplifyLocals.diff
-// EMIT_MIR lower_array_len.array_bound.InstCombine.diff
pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
if index < slice.len() {
slice[index]
}
// EMIT_MIR lower_array_len.array_bound_mut.NormalizeArrayLen.diff
-// EMIT_MIR lower_array_len.array_bound_mut.SimplifyLocals.diff
-// EMIT_MIR lower_array_len.array_bound_mut.InstCombine.diff
pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
if index < slice.len() {
slice[index]
}
// EMIT_MIR lower_array_len.array_len.NormalizeArrayLen.diff
-// EMIT_MIR lower_array_len.array_len.SimplifyLocals.diff
-// EMIT_MIR lower_array_len.array_len.InstCombine.diff
pub fn array_len<const N: usize>(arr: &[u8; N]) -> usize {
arr.len()
}
// EMIT_MIR lower_array_len.array_len_by_value.NormalizeArrayLen.diff
-// EMIT_MIR lower_array_len.array_len_by_value.SimplifyLocals.diff
-// EMIT_MIR lower_array_len.array_len_by_value.InstCombine.diff
pub fn array_len_by_value<const N: usize>(arr: [u8; N]) -> usize {
arr.len()
}
--- /dev/null
+// MIR for `array_bound` after PreCodegen
+
+fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
+ debug index => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:36: +0:41
+ debug slice => _2; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:50: +0:55
+ let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:70: +0:72
+ let mut _3: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ let mut _4: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+ let mut _5: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+ let _6: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+ let mut _7: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ let mut _8: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+
+ bb0: {
+ StorageLive(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ StorageLive(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+ _4 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+ StorageLive(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+ _5 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+ _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ StorageDead(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
+ StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
+ switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ }
+
+ bb1: {
+ StorageLive(_6); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+ _6 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+ _7 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ }
+
+ bb2: {
+ _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ StorageDead(_6); // scope 0 at $DIR/lower_array_len_e2e.rs:+3:5: +3:6
+ goto -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
+ }
+
+ bb3: {
+ _0 = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:11
+ goto -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
+ }
+
+ bb4: {
+ StorageDead(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+5:5: +5:6
+ return; // scope 0 at $DIR/lower_array_len_e2e.rs:+6:2: +6:2
+ }
+}
--- /dev/null
+// MIR for `array_bound_mut` after PreCodegen
+
+fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
+ debug index => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:40: +0:45
+ debug slice => _2; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:54: +0:59
+ let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:78: +0:80
+ let mut _3: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ let mut _4: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+ let mut _5: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+ let _6: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+ let mut _7: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ let mut _8: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ let _9: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
+ let mut _10: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+ let mut _11: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+
+ bb0: {
+ StorageLive(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ StorageLive(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+ _4 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+ StorageLive(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+ _5 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+ _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ StorageDead(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
+ StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
+ switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ }
+
+ bb1: {
+ StorageLive(_6); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+ _6 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+ _7 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ }
+
+ bb2: {
+ _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+ StorageDead(_6); // scope 0 at $DIR/lower_array_len_e2e.rs:+3:5: +3:6
+ goto -> bb5; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
+ }
+
+ bb3: {
+ StorageLive(_9); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
+ _9 = const 0_usize; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
+ _10 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+ _11 = Lt(const 0_usize, _10); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+ assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+ }
+
+ bb4: {
+ (*_2)[_9] = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:22
+ StorageDead(_9); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:22: +4:23
+ _0 = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+6:9: +6:11
+ goto -> bb5; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
+ }
+
+ bb5: {
+ StorageDead(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+7:5: +7:6
+ return; // scope 0 at $DIR/lower_array_len_e2e.rs:+8:2: +8:2
+ }
+}
--- /dev/null
+// MIR for `array_len` after PreCodegen
+
+fn array_len(_1: &[u8; N]) -> usize {
+ debug arr => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:34: +0:37
+ let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:52: +0:57
+
+ bb0: {
+ _0 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
+ return; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
+ }
+}
--- /dev/null
+// MIR for `array_len_by_value` after PreCodegen
+
+fn array_len_by_value(_1: [u8; N]) -> usize {
+ debug arr => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:43: +0:46
+ let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:60: +0:65
+
+ bb0: {
+ _0 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
+ return; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
+ }
+}
--- /dev/null
+// compile-flags: -Z mir-opt-level=4
+
+// EMIT_MIR lower_array_len_e2e.array_bound.PreCodegen.after.mir
+pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
+ if index < slice.len() {
+ slice[index]
+ } else {
+ 42
+ }
+}
+
+// EMIT_MIR lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
+pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
+ if index < slice.len() {
+ slice[index]
+ } else {
+ slice[0] = 42;
+
+ 42
+ }
+}
+
+// EMIT_MIR lower_array_len_e2e.array_len.PreCodegen.after.mir
+pub fn array_len<const N: usize>(arr: &[u8; N]) -> usize {
+ arr.len()
+}
+
+// EMIT_MIR lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
+pub fn array_len_by_value<const N: usize>(arr: [u8; N]) -> usize {
+ arr.len()
+}
+
+fn main() {
+ let _ = array_bound(3, &[0, 1, 2, 3]);
+ let mut tmp = [0, 1, 2, 3, 4];
+ let _ = array_bound_mut(3, &mut [0, 1, 2, 3]);
+ let _ = array_len(&[0]);
+ let _ = array_len_by_value([0, 2]);
+}
bb0: {
- _0 = std::intrinsics::min_align_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:19:5: 19:40
+- // + span: $DIR/lower_intrinsics.rs:21:5: 21:40
- // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::<T>}, val: Value(<ZST>) }
+ _0 = AlignOf(T); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
_3 = &(*_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
- _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:74:5: 74:41
+- // + span: $DIR/lower_intrinsics.rs:49:5: 49:41
- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> <T as DiscriminantKind>::Discriminant {discriminant_value::<T>}, val: Value(<ZST>) }
+ _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
StorageLive(_7); // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
_19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:75:42: 75:44
+ // + span: $DIR/lower_intrinsics.rs:50:42: 50:44
// + literal: Const { ty: &i32, val: Unevaluated(discriminant, [T], Some(promoted[2])) }
_7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
_6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
- _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:75:5: 75:41
+- // + span: $DIR/lower_intrinsics.rs:50:5: 50:41
- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> <i32 as DiscriminantKind>::Discriminant {discriminant_value::<i32>}, val: Value(<ZST>) }
+ _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
+ goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
StorageLive(_11); // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
_18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:76:42: 76:45
+ // + span: $DIR/lower_intrinsics.rs:51:42: 51:45
// + literal: Const { ty: &(), val: Unevaluated(discriminant, [T], Some(promoted[1])) }
_11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
_10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:76:5: 76:41
+- // + span: $DIR/lower_intrinsics.rs:51:5: 51:41
- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value(<ZST>) }
+ _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
+ goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
StorageLive(_15); // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
_17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:77:42: 77:47
+ // + span: $DIR/lower_intrinsics.rs:52:42: 52:47
// + literal: Const { ty: &E, val: Unevaluated(discriminant, [T], Some(promoted[0])) }
_15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
_14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
- _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:77:5: 77:41
+- // + span: $DIR/lower_intrinsics.rs:52:5: 52:41
- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> <E as DiscriminantKind>::Discriminant {discriminant_value::<E>}, val: Value(<ZST>) }
+ _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
+ goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
StorageDead(_15); // scope 0 at $DIR/lower_intrinsics.rs:+4:48: +4:49
StorageDead(_13); // scope 0 at $DIR/lower_intrinsics.rs:+4:48: +4:49
_0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:+0:30: +5:2
- drop(_1) -> bb5; // scope 0 at $DIR/lower_intrinsics.rs:+5:1: +5:2
+ drop(_1) -> [return: bb5, unwind: bb6]; // scope 0 at $DIR/lower_intrinsics.rs:+5:1: +5:2
}
bb5: {
return; // scope 0 at $DIR/lower_intrinsics.rs:+5:2: +5:2
}
+
+ bb6 (cleanup): {
+ resume; // scope 0 at $DIR/lower_intrinsics.rs:+0:1: +5:2
+ }
}
+++ /dev/null
-// MIR for `f_u64` before PreCodegen
-
-fn f_u64() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:16: +0:16
- let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
- scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
- debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:44:22: 44:23
- let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
- let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
- scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:45:8: 45:32
- }
- }
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
- _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
- StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
- StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
- _3 = move _1; // scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
- _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:48:9: 48:18
- // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(<ZST>) }
- }
-
- bb1: {
- StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:48:20: 48:21
- StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:48:21: 48:22
- StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
- return; // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
- }
-}
+++ /dev/null
-// MIR for `f_unit` before PreCodegen
-
-fn f_unit() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:17: +0:17
- let mut _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:+1:16: +1:18
- scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
- debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:44:22: 44:23
- let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
- let mut _3: (); // in scope 1 at $DIR/lower_intrinsics.rs:46:15: 46:16
- scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:45:8: 45:32
- }
- }
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:16: +1:18
- StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
- StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:46:15: 46:16
- _2 = f_zst::<()>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:46:9: 46:14
- // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(<ZST>) }
- }
-
- bb1: {
- StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:46:16: 46:17
- StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:46:17: 46:18
- StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:18: +1:19
- return; // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
- }
-}
_2 = move _1; // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
- _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:24:5: 24:29
+- // + span: $DIR/lower_intrinsics.rs:26:5: 26:29
- // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::<T>}, val: Value(<ZST>) }
+ _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+2:9: +2:18
_1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:+2:21: +2:51
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:62:21: 62:51
+ // + span: $DIR/lower_intrinsics.rs:37:21: 37:51
// + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(<ZST>) }
StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14
_2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14
-// compile-flags: -Cpanic=abort
+// unit-test: LowerIntrinsics
+// ignore-wasm32 compiled with panic=abort by default
+
#![feature(core_intrinsics)]
#![crate_type = "lib"]
unsafe { core::intrinsics::unreachable() };
}
-// EMIT_MIR lower_intrinsics.f_unit.PreCodegen.before.mir
-pub fn f_unit() {
- f_dispatch(());
-}
-
-
-// EMIT_MIR lower_intrinsics.f_u64.PreCodegen.before.mir
-pub fn f_u64() {
- f_dispatch(0u64);
-}
-
-#[inline(always)]
-pub fn f_dispatch<T>(t: T) {
- if std::mem::size_of::<T>() == 0 {
- f_zst(t);
- } else {
- f_non_zst(t);
- }
-}
-
-#[inline(never)]
-pub fn f_zst<T>(_t: T) {
-}
-
-#[inline(never)]
-pub fn f_non_zst<T>(_t: T) {}
-
// EMIT_MIR lower_intrinsics.non_const.LowerIntrinsics.diff
pub fn non_const<T>() -> usize {
// Check that lowering works with non-const operand as a func.
bb0: {
- _0 = std::intrinsics::size_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:14:5: 14:35
+- // + span: $DIR/lower_intrinsics.rs:16:5: 16:35
- // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(<ZST>) }
+ _0 = SizeOf(T); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
- _3 = std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:29:14: 29:43
+- // + span: $DIR/lower_intrinsics.rs:31:14: 31:43
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(<ZST>) }
+ unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
}
_5 = _2; // scope 0 at $DIR/lower_intrinsics.rs:+1:48: +1:49
- _3 = wrapping_add::<i32>(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:7:14: 7:44
+- // + span: $DIR/lower_intrinsics.rs:9:14: 9:44
- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_add::<i32>}, val: Value(<ZST>) }
+ _3 = Add(move _4, move _5); // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
_8 = _2; // scope 1 at $DIR/lower_intrinsics.rs:+2:48: +2:49
- _6 = wrapping_sub::<i32>(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:8:14: 8:44
+- // + span: $DIR/lower_intrinsics.rs:10:14: 10:44
- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_sub::<i32>}, val: Value(<ZST>) }
+ _6 = Sub(move _7, move _8); // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
+ goto -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
_11 = _2; // scope 2 at $DIR/lower_intrinsics.rs:+3:48: +3:49
- _9 = wrapping_mul::<i32>(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:9:14: 9:44
+- // + span: $DIR/lower_intrinsics.rs:11:14: 11:44
- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_mul::<i32>}, val: Value(<ZST>) }
+ _9 = Mul(move _10, move _11); // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
+ goto -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
--- /dev/null
+// MIR for `f_u64` after PreCodegen
+
+fn f_u64() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics_e2e.rs:+0:16: +0:16
+ let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
+ scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics_e2e.rs:15:5: 15:21
+ debug t => _1; // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23
+ let _2: (); // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+ let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20
+ scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics_e2e.rs:20:8: 20:32
+ }
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
+ _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
+ StorageLive(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+ StorageLive(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20
+ _3 = move _1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20
+ _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+ // mir::Constant
+ // + span: $DIR/lower_intrinsics_e2e.rs:23:9: 23:18
+ // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:20: 23:21
+ StorageDead(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:21: 23:22
+ StorageDead(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
+ return; // scope 0 at $DIR/lower_intrinsics_e2e.rs:+2:2: +2:2
+ }
+}
--- /dev/null
+// MIR for `f_unit` after PreCodegen
+
+fn f_unit() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics_e2e.rs:+0:17: +0:17
+ let mut _1: (); // in scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:16: +1:18
+ scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics_e2e.rs:9:5: 9:19
+ debug t => _1; // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23
+ let _2: (); // in scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
+ let mut _3: (); // in scope 1 at $DIR/lower_intrinsics_e2e.rs:21:15: 21:16
+ scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics_e2e.rs:20:8: 20:32
+ }
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:16: +1:18
+ StorageLive(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
+ StorageLive(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:15: 21:16
+ _2 = f_zst::<()>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
+ // mir::Constant
+ // + span: $DIR/lower_intrinsics_e2e.rs:21:9: 21:14
+ // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:16: 21:17
+ StorageDead(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:17: 21:18
+ StorageDead(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:18: +1:19
+ return; // scope 0 at $DIR/lower_intrinsics_e2e.rs:+2:2: +2:2
+ }
+}
--- /dev/null
+// Checks that we do not have any branches in the MIR for the two tested functions.
+
+// compile-flags: -Cpanic=abort
+#![feature(core_intrinsics)]
+#![crate_type = "lib"]
+
+// EMIT_MIR lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
+pub fn f_unit() {
+ f_dispatch(());
+}
+
+
+// EMIT_MIR lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
+pub fn f_u64() {
+ f_dispatch(0u64);
+}
+
+#[inline(always)]
+pub fn f_dispatch<T>(t: T) {
+ if std::mem::size_of::<T>() == 0 {
+ f_zst(t);
+ } else {
+ f_non_zst(t);
+ }
+}
+
+#[inline(never)]
+pub fn f_zst<T>(_t: T) {
+}
+
+#[inline(never)]
+pub fn f_non_zst<T>(_t: T) {}
- _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22
- _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22
- _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21
-- nop; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
+- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- }
-
+ _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21
_4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22
_5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21
-- nop; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
+ Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- }
-
- _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22
- _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22
- _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21
-- nop; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
+- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- }
-
+ _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21
_4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22
_5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21
-- nop; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
+ Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- }
-
fn foo(_1: Option<()>) -> () {
debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11
let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25
- let mut _2: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26
-+ let mut _3: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26
++ let mut _4: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
bb0: {
- _2 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
-- switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-- }
--
-- bb1: {
+ StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
+- switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ StorageLive(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ _4 = move _3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ _2 = Eq(_4, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ StorageDead(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ }
+
+ bb1: {
+- _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb2: {
+- _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb3: {
-+ StorageLive(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+ _3 = move _2; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+ StorageDead(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+- }
+-
+- bb4: {
+ Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
+- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+ }
+
+- bb5: {
++ bb2: {
+ _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:+3:6: +3:6
+- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+ }
+
+- bb6: {
++ bb3: {
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+3:5: +3:6
return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2
}
}
fn foo(_1: Option<()>) -> () {
debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11
let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25
- let mut _2: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26
-+ let mut _3: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26
++ let mut _4: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
bb0: {
- _2 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
-- switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-- }
--
-- bb1: {
+ StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
+- switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ StorageLive(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ _4 = move _3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ _2 = Eq(_4, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ StorageDead(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ }
+
+ bb1: {
+- _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb2: {
+- _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb3: {
-+ StorageLive(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+ _3 = move _2; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+ StorageDead(_3); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+- }
+-
+- bb4: {
+ Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
+- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+ }
+
+- bb5: {
++ bb2: {
+ _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:+3:6: +3:6
+- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+ }
+
+- bb6: {
++ bb3: {
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+3:5: +3:6
return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2
}
}
+++ /dev/null
-// MIR for `foo` before PreCodegen
-
-fn foo(_1: Option<()>) -> () {
- debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11
- let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25
-
- bb0: {
- return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2
- }
-}
+++ /dev/null
-// MIR for `foo` before PreCodegen
-
-fn foo(_1: Option<()>) -> () {
- debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11
- let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25
-
- bb0: {
- return; // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2
- }
-}
fn match_nested_if() -> bool {
let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:29
let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
- let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-+ let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+ let mut _2: (); // in scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+ let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+ let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+ let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ let mut _8: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++ let mut _9: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++ let mut _10: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
scope 1 {
debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
- StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+ StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+ StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+ StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+ StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+ _6 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+- switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
- }
-
- bb1: {
-+ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-+ _3 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
-- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
-- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+- _5 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:31: +2:35
+- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
- }
-
- bb2: {
-- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
-- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
-- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+- _5 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
+- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
- }
-
- bb3: {
-+ _1 = Ne(_3, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
-+ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ _7 = move _6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ _5 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
++ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+ StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
+- switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+- }
+-
+- bb4: {
+- _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:55: +2:59
+- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+- }
+-
+- bb5: {
+- _4 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
+- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+- }
+-
+- bb6: {
++ StorageLive(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++ _8 = move _5; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++ _4 = Ne(_8, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
++ StorageDead(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+ StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76
+- switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+- }
+-
+- bb7: {
+- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+3:13: +3:17
+- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+- }
+-
+- bb8: {
+- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18
+- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+- }
+-
+- bb9: {
+- switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+- }
+-
+- bb10: {
++ StorageLive(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++ _9 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++ _3 = Ne(_9, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18
++ StorageDead(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++ StorageLive(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
++ _10 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+ StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+- }
+-
+- bb11: {
+- StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+- StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+- }
+-
+- bb12: {
++ _1 = Ne(_10, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
++ StorageDead(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+11:6: +11:7
_0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:+12:5: +12:8
StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+13:1: +13:2
return; // scope 0 at $DIR/matches_reduce_branches.rs:+13:2: +13:2
fn match_nested_if() -> bool {
let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:29
let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
- let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-+ let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+ let mut _2: (); // in scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+ let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+ let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+ let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ let mut _8: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++ let mut _9: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++ let mut _10: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
scope 1 {
debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
- StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+ StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+ StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+ StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+ StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+ _6 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+- switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
- }
-
- bb1: {
-+ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-+ _3 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
-- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
-- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+- _5 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:31: +2:35
+- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
- }
-
- bb2: {
-- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
-- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
-- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+- _5 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
+- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
- }
-
- bb3: {
-+ _1 = Ne(_3, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
-+ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ _7 = move _6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++ _5 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
++ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+ StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
+- switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+- }
+-
+- bb4: {
+- _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:55: +2:59
+- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+- }
+-
+- bb5: {
+- _4 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
+- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+- }
+-
+- bb6: {
++ StorageLive(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++ _8 = move _5; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++ _4 = Ne(_8, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
++ StorageDead(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+ StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76
+- switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+- }
+-
+- bb7: {
+- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+3:13: +3:17
+- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+- }
+-
+- bb8: {
+- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18
+- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+- }
+-
+- bb9: {
+- switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+- }
+-
+- bb10: {
++ StorageLive(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++ _9 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++ _3 = Ne(_9, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18
++ StorageDead(_9); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++ StorageLive(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
++ _10 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+ StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+- }
+-
+- bb11: {
+- StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+- StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+- goto -> bb12; // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+- }
+-
+- bb12: {
++ _1 = Ne(_10, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
++ StorageDead(_10); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+11:6: +11:7
_0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:+12:5: +12:8
StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+13:1: +13:2
return; // scope 0 at $DIR/matches_reduce_branches.rs:+13:2: +13:2
+// unit-test: MatchBranchSimplification
+
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff
-// EMIT_MIR matches_reduce_branches.foo.PreCodegen.before.mir
// EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff
// EMIT_MIR matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
+// unit-test: MatchBranchSimplification
+
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff
// EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
scope 1 {
debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10
scope 2 {
- scope 8 (inlined #[track_caller] <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+ scope 8 (inlined #[track_caller] <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:25:8: 25:10
debug residual => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
let _16: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
let mut _17: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
scope 4 {
}
}
- scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+ scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:25:8: 25:10
debug self => _4; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
let mut _10: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
let _11: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
use std::ops::ControlFlow;
// EMIT_MIR separate_const_switch.too_complex.SeparateConstSwitch.diff
-// EMIT_MIR separate_const_switch.too_complex.ConstProp.diff
-// EMIT_MIR separate_const_switch.too_complex.PreCodegen.after.mir
fn too_complex(x: Result<i32, usize>) -> Option<i32> {
// The pass should break the outer match into
// two blocks that only have one parent each.
}
// EMIT_MIR separate_const_switch.identity.SeparateConstSwitch.diff
-// EMIT_MIR separate_const_switch.identity.ConstProp.diff
-// EMIT_MIR separate_const_switch.identity.PreCodegen.after.mir
fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
Ok(x?)
}
// compile-flags: -Zmir-opt-level=3
// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// This pass is broken since deaggregation changed
+// ignore-test
+
enum Src {
Foo(u8),
Bar,
// EMIT_MIR simplify_arm.id_try.SimplifyArmIdentity.diff
// EMIT_MIR simplify_arm.id_try.SimplifyBranchSame.diff
+// This pass is broken since deaggregation changed
+// ignore-test
+
fn id(o: Option<u8>) -> Option<u8> {
match o {
Some(v) => Some(v),
-// compile-flags: -Zunsound-mir-opts
+// unit-test: SimplifyLocals
fn map(x: Option<Box<()>>) -> Option<Box<()>> {
match x {
+++ /dev/null
-- // MIR for `id` before SimplifyArmIdentity
-+ // MIR for `id` after SimplifyArmIdentity
-
- fn id(_1: Option<u8>) -> Option<u8> {
- debug o => _1; // in scope 0 at $DIR/simplify-arm.rs:+0:7: +0:8
- let mut _0: std::option::Option<u8>; // return place in scope 0 at $DIR/simplify-arm.rs:+0:25: +0:35
- let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:16
- let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
- let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:25: +2:26
- scope 1 {
- debug v => _3; // in scope 1 at $DIR/simplify-arm.rs:+2:14: +2:15
- }
-
- bb0: {
- _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
- switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12
- }
-
- bb1: {
- Deinit(_0); // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
- discriminant(_0) = 0; // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
- }
-
- bb2: {
- unreachable; // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
- }
-
- bb3: {
- StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
- _3 = ((_1 as Some).0: u8); // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
- StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26
- _4 = _3; // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26
- Deinit(_0); // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
- ((_0 as Some).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
- discriminant(_0) = 1; // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
- StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:+2:26: +2:27
- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27
- }
-
- bb4: {
- return; // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2
- }
- }
-
+++ /dev/null
-- // MIR for `id` before SimplifyBranchSame
-+ // MIR for `id` after SimplifyBranchSame
-
- fn id(_1: Option<u8>) -> Option<u8> {
- debug o => _1; // in scope 0 at $DIR/simplify-arm.rs:+0:7: +0:8
- let mut _0: std::option::Option<u8>; // return place in scope 0 at $DIR/simplify-arm.rs:+0:25: +0:35
- let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:16
- let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
- let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:25: +2:26
- scope 1 {
- debug v => _3; // in scope 1 at $DIR/simplify-arm.rs:+2:14: +2:15
- }
-
- bb0: {
- _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
- switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12
- }
-
- bb1: {
- Deinit(_0); // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
- discriminant(_0) = 0; // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
- }
-
- bb2: {
- unreachable; // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
- }
-
- bb3: {
- StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
- _3 = ((_1 as Some).0: u8); // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
- StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26
- _4 = _3; // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26
- Deinit(_0); // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
- ((_0 as Some).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
- discriminant(_0) = 1; // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
- StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:+2:26: +2:27
- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27
- }
-
- bb4: {
- return; // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2
- }
- }
-
+++ /dev/null
-- // MIR for `id_result` before SimplifyArmIdentity
-+ // MIR for `id_result` after SimplifyArmIdentity
-
- fn id_result(_1: Result<u8, i32>) -> Result<u8, i32> {
- debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:+0:14: +0:15
- let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:+0:37: +0:52
- let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:14
- let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
- let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:21: +2:22
- let _5: i32; // in scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
- let mut _6: i32; // in scope 0 at $DIR/simplify-arm.rs:+3:23: +3:24
- scope 1 {
- debug x => _3; // in scope 1 at $DIR/simplify-arm.rs:+2:12: +2:13
- }
- scope 2 {
- debug y => _5; // in scope 2 at $DIR/simplify-arm.rs:+3:13: +3:14
- }
-
- bb0: {
- _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
- switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12
- }
-
- bb1: {
- StorageLive(_5); // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
- _5 = ((_1 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
- StorageLive(_6); // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24
- _6 = _5; // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24
- Deinit(_0); // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
- ((_0 as Err).0: i32) = move _6; // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
- discriminant(_0) = 1; // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
- StorageDead(_6); // scope 2 at $DIR/simplify-arm.rs:+3:24: +3:25
- StorageDead(_5); // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25
- }
-
- bb2: {
- unreachable; // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
- }
-
- bb3: {
- StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
- _3 = ((_1 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
- StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22
- _4 = _3; // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22
- Deinit(_0); // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
- ((_0 as Ok).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
- discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
- StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:+2:22: +2:23
- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23
- }
-
- bb4: {
- return; // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2
- }
- }
-
+++ /dev/null
-- // MIR for `id_result` before SimplifyBranchSame
-+ // MIR for `id_result` after SimplifyBranchSame
-
- fn id_result(_1: Result<u8, i32>) -> Result<u8, i32> {
- debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:+0:14: +0:15
- let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:+0:37: +0:52
- let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:14
- let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
- let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:+2:21: +2:22
- let _5: i32; // in scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
- let mut _6: i32; // in scope 0 at $DIR/simplify-arm.rs:+3:23: +3:24
- scope 1 {
- debug x => _3; // in scope 1 at $DIR/simplify-arm.rs:+2:12: +2:13
- }
- scope 2 {
- debug y => _5; // in scope 2 at $DIR/simplify-arm.rs:+3:13: +3:14
- }
-
- bb0: {
- _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
- switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12
- }
-
- bb1: {
- StorageLive(_5); // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
- _5 = ((_1 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
- StorageLive(_6); // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24
- _6 = _5; // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24
- Deinit(_0); // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
- ((_0 as Err).0: i32) = move _6; // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
- discriminant(_0) = 1; // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
- StorageDead(_6); // scope 2 at $DIR/simplify-arm.rs:+3:24: +3:25
- StorageDead(_5); // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25
- }
-
- bb2: {
- unreachable; // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
- }
-
- bb3: {
- StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
- _3 = ((_1 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
- StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22
- _4 = _3; // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22
- Deinit(_0); // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
- ((_0 as Ok).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
- discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
- StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:+2:22: +2:23
- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23
- }
-
- bb4: {
- return; // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2
- }
- }
-
+++ /dev/null
-- // MIR for `main` before SimplifyArmIdentity
-+ // MIR for `main` after SimplifyArmIdentity
-
- fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +0:11
- let _1: Src; // in scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
- let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:+2:18: +5:6
- let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:+3:9: +3:20
- let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
- scope 1 {
- debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
- let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
- scope 2 {
- }
- scope 3 {
- debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
- }
- }
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
- ((_1 as Foo).0: u8) = const 0_u8; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
- discriminant(_1) = 0; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
- StorageLive(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +5:6
- _3 = const 0_isize; // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25
- goto -> bb3; // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +2:25
- }
-
- bb1: {
- Deinit(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
- ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
- discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
- goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
- }
-
- bb2: {
- unreachable; // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25
- }
-
- bb3: {
- StorageLive(_4); // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
- _4 = ((_1 as Foo).0: u8); // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
- StorageLive(_5); // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
- _5 = _4; // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
- Deinit(_2); // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
- ((_2 as Foo).0: u8) = move _5; // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
- discriminant(_2) = 0; // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
- StorageDead(_5); // scope 3 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
- StorageDead(_4); // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
- goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
- }
-
- bb4: {
- StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+5:6: +5:7
- nop; // scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +6:2
- StorageDead(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+6:1: +6:2
- return; // scope 0 at $DIR/simplify-arm-identity.rs:+6:2: +6:2
- }
- }
-
+++ /dev/null
-- // MIR for `main` before SimplifyArmIdentity
-+ // MIR for `main` after SimplifyArmIdentity
-
- fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +0:11
- let _1: Src; // in scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
- let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:+2:18: +5:6
- let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:+3:9: +3:20
- let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
- scope 1 {
- debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
- let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
- scope 2 {
- }
- scope 3 {
- debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
- }
- }
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
- ((_1 as Foo).0: u8) = const 0_u8; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
- discriminant(_1) = 0; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
- StorageLive(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +5:6
- _3 = const 0_isize; // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25
- goto -> bb3; // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +2:25
- }
-
- bb1: {
- Deinit(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
- ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
- discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
- goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
- }
-
- bb2: {
- unreachable; // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25
- }
-
- bb3: {
- StorageLive(_4); // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
- _4 = ((_1 as Foo).0: u8); // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
- StorageLive(_5); // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
- _5 = _4; // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
- Deinit(_2); // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
- ((_2 as Foo).0: u8) = move _5; // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
- discriminant(_2) = 0; // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
- StorageDead(_5); // scope 3 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
- StorageDead(_4); // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
- goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
- }
-
- bb4: {
- StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:+5:6: +5:7
- nop; // scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +6:2
- StorageDead(_1); // scope 0 at $DIR/simplify-arm-identity.rs:+6:1: +6:2
- return; // scope 0 at $DIR/simplify-arm-identity.rs:+6:2: +6:2
- }
- }
-
debug x => _1; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:8: +0:9
let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:31: +0:46
let mut _2: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:9: +2:13
-- let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
-- let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
+ let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
- let mut _5: bool; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
- let mut _6: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
- let mut _7: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
scope 1 {
- debug x => ((_0 as Some).0: std::boxed::Box<()>); // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ debug x => _3; // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
}
bb0: {
+- _5 = const false; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
+- _5 = const true; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
_2 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12
}
bb1: {
- ((_0 as Some).0: std::boxed::Box<()>) = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
+ _4 = move _3; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
Deinit(_0); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
+ ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
discriminant(_0) = 1; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
+ StorageDead(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
+ StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
goto -> bb4; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
}
}
bb4: {
+- _6 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
return; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2
}
}
debug x => _1; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:8: +0:9
let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:31: +0:46
let mut _2: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:9: +2:13
-- let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
-- let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
+ let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
- let mut _5: bool; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
- let mut _6: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
- let mut _7: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
scope 1 {
- debug x => ((_0 as Some).0: std::boxed::Box<()>); // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ debug x => _3; // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
}
bb0: {
+- _5 = const false; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
+- _5 = const true; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
_2 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12
}
bb1: {
- ((_0 as Some).0: std::boxed::Box<()>) = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+ StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
+ _4 = move _3; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
Deinit(_0); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
+ ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
discriminant(_0) = 1; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
+ StorageDead(_4); // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
+ StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
goto -> bb4; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
}
}
bb4: {
+- _6 = discriminant(_1); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
return; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2
}
}
+++ /dev/null
-// compile-flags: -Zunsound-mir-opts
-// EMIT_MIR simplify_try.try_identity.SimplifyArmIdentity.diff
-// EMIT_MIR simplify_try.try_identity.SimplifyBranchSame.after.mir
-// EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir
-// EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff
-
-
-fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
- r
-}
-
-fn from_error<T, E>(e: E) -> Result<T, E> {
- Err(e)
-}
-
-// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
-// so the relevant desugar is copied inline in order to keep the test testing the same thing.
-// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
-// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
-fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
- let y = match into_result(x) {
- Err(e) => return from_error(From::from(e)),
- Ok(v) => v,
- };
- Ok(y)
-}
-
-fn main() {
- let _ = try_identity(Ok(0));
-}
--- /dev/null
+// MIR for `new` after PreCodegen
+
+fn new(_1: Result<T, E>) -> Result<T, E> {
+ debug x => _1; // in scope 0 at $DIR/try_identity_e2e.rs:+0:14: +0:15
+ let mut _0: std::result::Result<T, E>; // return place in scope 0 at $DIR/try_identity_e2e.rs:+0:34: +0:46
+ let mut _2: T; // in scope 0 at $DIR/try_identity_e2e.rs:+2:9: +10:10
+ let mut _3: std::ops::ControlFlow<E, T>; // in scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+ let mut _4: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:22
+ let _5: T; // in scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+ let mut _6: T; // in scope 0 at $DIR/try_identity_e2e.rs:+4:48: +4:49
+ let _7: E; // in scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
+ let mut _8: E; // in scope 0 at $DIR/try_identity_e2e.rs:+5:46: +5:47
+ let mut _9: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+8:13: +8:37
+ let _10: T; // in scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+ let _11: E; // in scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+ let mut _12: E; // in scope 0 at $DIR/try_identity_e2e.rs:+9:49: +9:50
+ scope 1 {
+ debug v => _5; // in scope 1 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+ }
+ scope 2 {
+ debug e => _7; // in scope 2 at $DIR/try_identity_e2e.rs:+5:21: +5:22
+ }
+ scope 3 {
+ debug v => _10; // in scope 3 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+ }
+ scope 4 {
+ debug e => _11; // in scope 4 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +10:10
+ StorageLive(_3); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+ _4 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20
+ switchInt(move _4) -> [0_isize: bb2, 1_isize: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
+ }
+
+ bb1: {
+ StorageLive(_7); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
+ _7 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
+ StorageLive(_8); // scope 2 at $DIR/try_identity_e2e.rs:+5:46: +5:47
+ _8 = move _7; // scope 2 at $DIR/try_identity_e2e.rs:+5:46: +5:47
+ Deinit(_3); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+ ((_3 as Break).0: E) = move _8; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+ discriminant(_3) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+ StorageDead(_8); // scope 2 at $DIR/try_identity_e2e.rs:+5:47: +5:48
+ StorageDead(_7); // scope 0 at $DIR/try_identity_e2e.rs:+5:47: +5:48
+ _9 = discriminant(_3); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+ switchInt(move _9) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ }
+
+ bb2: {
+ StorageLive(_5); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+ _5 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+ StorageLive(_6); // scope 1 at $DIR/try_identity_e2e.rs:+4:48: +4:49
+ _6 = move _5; // scope 1 at $DIR/try_identity_e2e.rs:+4:48: +4:49
+ Deinit(_3); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+ ((_3 as Continue).0: T) = move _6; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+ discriminant(_3) = 0; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+ StorageDead(_6); // scope 1 at $DIR/try_identity_e2e.rs:+4:49: +4:50
+ StorageDead(_5); // scope 0 at $DIR/try_identity_e2e.rs:+4:49: +4:50
+ _9 = discriminant(_3); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+ switchInt(move _9) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ }
+
+ bb3: {
+ StorageLive(_11); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+ _11 = move ((_3 as Break).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+ StorageLive(_12); // scope 4 at $DIR/try_identity_e2e.rs:+9:49: +9:50
+ _12 = move _11; // scope 4 at $DIR/try_identity_e2e.rs:+9:49: +9:50
+ Deinit(_0); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+ ((_0 as Err).0: E) = move _12; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+ discriminant(_0) = 1; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+ StorageDead(_12); // scope 4 at $DIR/try_identity_e2e.rs:+9:50: +9:51
+ StorageDead(_11); // scope 0 at $DIR/try_identity_e2e.rs:+9:50: +9:51
+ StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+11:5: +11:6
+ StorageDead(_3); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
+ return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
+ }
+
+ bb4: {
+ unreachable; // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+ }
+
+ bb5: {
+ StorageLive(_10); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+ _10 = move ((_3 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+ _2 = move _10; // scope 3 at $DIR/try_identity_e2e.rs:+8:41: +8:42
+ StorageDead(_10); // scope 0 at $DIR/try_identity_e2e.rs:+8:41: +8:42
+ Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+ ((_0 as Ok).0: T) = move _2; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+ discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+ StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+11:5: +11:6
+ StorageDead(_3); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
+ return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
+ }
+}
--- /dev/null
+// MIR for `old` after PreCodegen
+
+fn old(_1: Result<T, E>) -> Result<T, E> {
+ debug x => _1; // in scope 0 at $DIR/try_identity_e2e.rs:+0:14: +0:15
+ let mut _0: std::result::Result<T, E>; // return place in scope 0 at $DIR/try_identity_e2e.rs:+0:34: +0:46
+ let mut _2: T; // in scope 0 at $DIR/try_identity_e2e.rs:+2:9: +5:10
+ let mut _3: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:18
+ let _4: T; // in scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
+ let _5: E; // in scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
+ let mut _6: E; // in scope 0 at $DIR/try_identity_e2e.rs:+4:34: +4:35
+ scope 1 {
+ debug v => _4; // in scope 1 at $DIR/try_identity_e2e.rs:+3:16: +3:17
+ }
+ scope 2 {
+ debug e => _5; // in scope 2 at $DIR/try_identity_e2e.rs:+4:17: +4:18
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +5:10
+ _3 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16
+ switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16
+ }
+
+ bb1: {
+ StorageLive(_5); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
+ _5 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
+ StorageLive(_6); // scope 2 at $DIR/try_identity_e2e.rs:+4:34: +4:35
+ _6 = move _5; // scope 2 at $DIR/try_identity_e2e.rs:+4:34: +4:35
+ Deinit(_0); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+ ((_0 as Err).0: E) = move _6; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+ discriminant(_0) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+ StorageDead(_6); // scope 2 at $DIR/try_identity_e2e.rs:+4:35: +4:36
+ StorageDead(_5); // scope 0 at $DIR/try_identity_e2e.rs:+4:35: +4:36
+ StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+6:5: +6:6
+ return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
+ }
+
+ bb2: {
+ unreachable; // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16
+ }
+
+ bb3: {
+ StorageLive(_4); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
+ _4 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
+ _2 = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+3:22: +3:23
+ StorageDead(_4); // scope 0 at $DIR/try_identity_e2e.rs:+3:22: +3:23
+ Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+ ((_0 as Ok).0: T) = move _2; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+ discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+ StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+6:5: +6:6
+ return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
+ }
+}
--- /dev/null
+// Track the status of MIR optimizations simplifying `Ok(res?)` for both the old and new desugarings
+// of that syntax.
+
+use std::ops::ControlFlow;
+
+// EMIT_MIR try_identity_e2e.new.PreCodegen.after.mir
+fn new<T, E>(x: Result<T, E>) -> Result<T, E> {
+ Ok(
+ match {
+ match x {
+ Ok(v) => ControlFlow::Continue(v),
+ Err(e) => ControlFlow::Break(e),
+ }
+ } {
+ ControlFlow::Continue(v) => v,
+ ControlFlow::Break(e) => return Err(e),
+ }
+ )
+}
+
+// EMIT_MIR try_identity_e2e.old.PreCodegen.after.mir
+fn old<T, E>(x: Result<T, E>) -> Result<T, E> {
+ Ok(
+ match x {
+ Ok(v) => v,
+ Err(e) => return Err(e),
+ }
+ )
+}
+
+fn main() {
+ let _ = new::<(), ()>(Ok(()));
+ let _ = old::<(), ()>(Ok(()));
+}
--- /dev/null
+// This test ensures that the "item-info" looks about the same
+// whether or not it's inside a toggle.
+goto: file://|DOC_PATH|/lib2/struct.ItemInfoAlignmentTest.html
+
+// First, we try it in "desktop" mode.
+size: (1200, 870)
+compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x"))
+// Next, we try it in "mobile" mode (max-width: 700px).
+size: (650, 650)
+compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x"))
assert-css: (
".search-input",
{
- "border-color": "rgb(240, 240, 240)",
+ "border-color": "rgb(224, 224, 224)",
"background-color": "rgb(240, 240, 240)",
"color": "rgb(17, 17, 17)",
},
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
reload:
-assert-css: (".search-input", {"border-color": "rgb(240, 240, 240)"})
+assert-css: (".search-input", {"border-color": "rgb(224, 224, 224)"})
click: ".search-input"
assert-css: (".search-input", {"border-color": "rgb(0, 141, 253)"})
type Output;
fn index(&self, index: Idx) -> &Self::Output;
}
+
+pub struct ItemInfoAlignmentTest;
+
+impl ItemInfoAlignmentTest {
+ /// This method has docs
+ #[deprecated]
+ pub fn foo() {}
+ #[deprecated]
+ pub fn bar() {}
+}
#[derive(SessionSubdiagnostic)]
enum Q {
#[bar]
-//~^ ERROR `#[bar]` is not a valid attribute
-//~^^ ERROR cannot find attribute `bar` in this scope
+ //~^ ERROR `#[bar]` is not a valid attribute
+ //~^^ ERROR cannot find attribute `bar` in this scope
A {
#[primary_span]
span: Span,
#[derive(SessionSubdiagnostic)]
enum R {
#[bar = "..."]
-//~^ ERROR `#[bar = ...]` is not a valid attribute
-//~^^ ERROR cannot find attribute `bar` in this scope
+ //~^ ERROR `#[bar = ...]` is not a valid attribute
+ //~^^ ERROR cannot find attribute `bar` in this scope
A {
#[primary_span]
span: Span,
#[derive(SessionSubdiagnostic)]
enum S {
#[bar = 4]
-//~^ ERROR `#[bar = ...]` is not a valid attribute
-//~^^ ERROR cannot find attribute `bar` in this scope
+ //~^ ERROR `#[bar = ...]` is not a valid attribute
+ //~^^ ERROR cannot find attribute `bar` in this scope
A {
#[primary_span]
span: Span,
#[derive(SessionSubdiagnostic)]
enum T {
#[bar("...")]
-//~^ ERROR `#[bar("...")]` is not a valid attribute
-//~^^ ERROR cannot find attribute `bar` in this scope
+ //~^ ERROR `#[bar(...)]` is not a valid attribute
+ //~^^ ERROR cannot find attribute `bar` in this scope
A {
#[primary_span]
span: Span,
#[derive(SessionSubdiagnostic)]
enum U {
#[label(code = "...")]
-//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
+ //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
A {
#[primary_span]
span: Span,
var: String,
},
B {
-//~^ ERROR subdiagnostic kind not specified
+ //~^ ERROR subdiagnostic kind not specified
#[primary_span]
span: Span,
var: String,
b: u64
}
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+#[label(parser::add_paren)]
+struct AD {
+ #[primary_span]
+ span: Span,
+}
+
#[derive(SessionSubdiagnostic)]
#[label(parser::add_paren, parser::add_paren)]
//~^ ERROR `#[label(parser::add_paren)]` is not a valid attribute
#[label(parser::add_paren)]
struct AF {
#[primary_span]
-//~^ NOTE previously specified here
+ //~^ NOTE previously specified here
span_a: Span,
#[primary_span]
-//~^ ERROR specified multiple times
+ //~^ ERROR specified multiple times
span_b: Span,
}
#[derive(SessionSubdiagnostic)]
struct AG {
-//~^ ERROR subdiagnostic kind not specified
+ //~^ ERROR subdiagnostic kind not specified
#[primary_span]
span: Span,
}
#[primary_span]
span: Span,
#[applicability]
-//~^ NOTE previously specified here
+ //~^ NOTE previously specified here
applicability_a: Applicability,
#[applicability]
-//~^ ERROR specified multiple times
+ //~^ ERROR specified multiple times
applicability_b: Applicability,
}
#[derive(SessionSubdiagnostic)]
#[suggestion(parser::add_paren, code = "...")]
-//~^ ERROR suggestion without `applicability`
struct AL {
#[primary_span]
span: Span,
#[applicability]
-//~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability`
+ //~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability`
applicability: Span,
}
#[derive(SessionSubdiagnostic)]
#[suggestion(parser::add_paren, code = "...")]
-//~^ ERROR suggestion without `applicability`
struct AM {
#[primary_span]
span: Span,
#[derive(SessionSubdiagnostic)]
#[suggestion(parser::add_paren, code = "...")]
-//~^ ERROR suggestion without `applicability`
-//~^^ ERROR suggestion without `#[primary_span]` field
+//~^ ERROR suggestion without `#[primary_span]` field
struct AR {
var: String,
}
#[primary_span]
span: Span,
}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code = "...")]
+//~^ ERROR suggestion without `#[primary_span]` field
+struct BA {
+ #[suggestion_part]
+ //~^ ERROR `#[suggestion_part]` is not a valid attribute
+ span: Span,
+ #[suggestion_part(code = "...")]
+ //~^ ERROR `#[suggestion_part(...)]` is not a valid attribute
+ span2: Span,
+ #[applicability]
+ applicability: Applicability,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
+//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
+//~| ERROR `code` is not a valid nested attribute of a `multipart_suggestion` attribute
+struct BBa {
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BBb {
+ #[suggestion_part]
+ //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+ span1: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BBc {
+ #[suggestion_part()]
+ //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+ span1: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren)]
+//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
+struct BC {
+ #[primary_span]
+ //~^ ERROR `#[primary_span]` is not a valid attribute
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren)]
+struct BD {
+ #[suggestion_part]
+ //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+ span1: Span,
+ #[suggestion_part()]
+ //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+ span2: Span,
+ #[suggestion_part(foo = "bar")]
+ //~^ ERROR `#[suggestion_part(foo = ...)]` is not a valid attribute
+ span4: Span,
+ #[suggestion_part(code = "...")]
+ //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+ s1: String,
+ #[suggestion_part()]
+ //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+ s2: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BE {
+ #[suggestion_part(code = "...", code = ",,,")]
+ //~^ ERROR specified multiple times
+ //~| NOTE previously specified here
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BF {
+ #[suggestion_part(code = "(")]
+ first: Span,
+ #[suggestion_part(code = ")")]
+ second: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren)]
+struct BG {
+ #[applicability]
+ appl: Applicability,
+ #[suggestion_part(code = "(")]
+ first: Span,
+ #[suggestion_part(code = ")")]
+ second: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+//~^ NOTE previously specified here
+struct BH {
+ #[applicability]
+ //~^ ERROR specified multiple times
+ appl: Applicability,
+ #[suggestion_part(code = "(")]
+ first: Span,
+ #[suggestion_part(code = ")")]
+ second: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BI {
+ #[suggestion_part(code = "")]
+ spans: Vec<Span>,
+}
| ^^^^^^^^^^
error: `code` is not a valid nested attribute of a `label` attribute
- --> $DIR/subdiagnostic-derive.rs:137:1
+ --> $DIR/subdiagnostic-derive.rs:137:28
|
LL | #[label(parser::add_paren, code = "...")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^
error: `applicability` is not a valid nested attribute of a `label` attribute
- --> $DIR/subdiagnostic-derive.rs:146:1
+ --> $DIR/subdiagnostic-derive.rs:146:28
|
LL | #[label(parser::add_paren, applicability = "machine-applicable")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: unsupported type attribute for subdiagnostic enum
--> $DIR/subdiagnostic-derive.rs:155:1
LL | #[bar = 4]
| ^^^^^^^^^^
-error: `#[bar("...")]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:205:11
+error: `#[bar(...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:205:5
|
LL | #[bar("...")]
- | ^^^^^
- |
- = help: first argument of the attribute should be the diagnostic slug
+ | ^^^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:217:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
+ |
+ = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: unexpected unsupported untagged union
--> $DIR/subdiagnostic-derive.rs:304:1
| |_^
error: `#[label(parser::add_paren)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:311:28
+ --> $DIR/subdiagnostic-derive.rs:319:28
|
LL | #[label(parser::add_paren, parser::add_paren)]
| ^^^^^^^^^^^^^^^^^
= help: a diagnostic slug must be the first argument to the attribute
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:324:5
+ --> $DIR/subdiagnostic-derive.rs:332:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:321:5
+ --> $DIR/subdiagnostic-derive.rs:329:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: subdiagnostic kind not specified
- --> $DIR/subdiagnostic-derive.rs:330:8
+ --> $DIR/subdiagnostic-derive.rs:338:8
|
LL | struct AG {
| ^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:367:47
+ --> $DIR/subdiagnostic-derive.rs:375:47
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
| ^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:367:33
+ --> $DIR/subdiagnostic-derive.rs:375:33
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
| ^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:385:5
+ --> $DIR/subdiagnostic-derive.rs:393:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:382:5
+ --> $DIR/subdiagnostic-derive.rs:390:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
- --> $DIR/subdiagnostic-derive.rs:396:5
+ --> $DIR/subdiagnostic-derive.rs:403:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
-error: suggestion without `applicability`
- --> $DIR/subdiagnostic-derive.rs:391:1
+error: suggestion without `code = "..."`
+ --> $DIR/subdiagnostic-derive.rs:416:1
|
-LL | / #[suggestion(parser::add_paren, code = "...")]
-LL | |
-LL | | struct AL {
-LL | | #[primary_span]
-... |
-LL | | applicability: Span,
-LL | | }
- | |_^
+LL | #[suggestion(parser::add_paren)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: suggestion without `applicability`
- --> $DIR/subdiagnostic-derive.rs:402:1
+error: invalid applicability
+ --> $DIR/subdiagnostic-derive.rs:426:46
+ |
+LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: suggestion without `#[primary_span]` field
+ --> $DIR/subdiagnostic-derive.rs:444:1
|
LL | / #[suggestion(parser::add_paren, code = "...")]
LL | |
-LL | | struct AM {
-LL | | #[primary_span]
-LL | | span: Span,
+LL | | struct AR {
+LL | | var: String,
LL | | }
| |_^
-error: suggestion without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:410:1
+error: unsupported type attribute for subdiagnostic enum
+ --> $DIR/subdiagnostic-derive.rs:458:1
|
-LL | / #[suggestion(parser::add_paren)]
+LL | #[label]
+ | ^^^^^^^^
+
+error: `var` doesn't refer to a field on this type
+ --> $DIR/subdiagnostic-derive.rs:478:39
+ |
+LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+ | ^^^^^^^
+
+error: `var` doesn't refer to a field on this type
+ --> $DIR/subdiagnostic-derive.rs:497:43
+ |
+LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+ | ^^^^^^^
+
+error: `#[suggestion_part]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:520:5
+ |
+LL | #[suggestion_part]
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
+
+error: `#[suggestion_part(...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:523:5
+ |
+LL | #[suggestion_part(code = "...")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: `#[suggestion_part(...)]` is only valid in multipart suggestions
+
+error: suggestion without `#[primary_span]` field
+ --> $DIR/subdiagnostic-derive.rs:517:1
+ |
+LL | / #[suggestion(parser::add_paren, code = "...")]
LL | |
-LL | | struct AN {
-LL | | #[primary_span]
+LL | | struct BA {
+LL | | #[suggestion_part]
... |
-LL | | applicability: Applicability,
+LL | | var: String,
LL | | }
| |_^
-error: invalid applicability
- --> $DIR/subdiagnostic-derive.rs:420:46
+error: `code` is not a valid nested attribute of a `multipart_suggestion` attribute
+ --> $DIR/subdiagnostic-derive.rs:532:43
|
-LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
+ | ^^^^^^^^^^^^
-error: suggestion without `applicability`
- --> $DIR/subdiagnostic-derive.rs:438:1
+error: multipart suggestion without any `#[suggestion_part(...)]` fields
+ --> $DIR/subdiagnostic-derive.rs:532:1
|
-LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
LL | |
LL | |
-LL | | struct AR {
+LL | | struct BBa {
LL | | var: String,
LL | | }
| |_^
-error: suggestion without `#[primary_span]` field
- --> $DIR/subdiagnostic-derive.rs:438:1
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+ --> $DIR/subdiagnostic-derive.rs:542:5
|
-LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | #[suggestion_part]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+ --> $DIR/subdiagnostic-derive.rs:550:5
+ |
+LL | #[suggestion_part()]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: `#[primary_span]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:559:5
+ |
+LL | #[primary_span]
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
+
+error: multipart suggestion without any `#[suggestion_part(...)]` fields
+ --> $DIR/subdiagnostic-derive.rs:556:1
+ |
+LL | / #[multipart_suggestion(parser::add_paren)]
LL | |
+LL | | struct BC {
+LL | | #[primary_span]
LL | |
-LL | | struct AR {
-LL | | var: String,
+LL | | span: Span,
LL | | }
| |_^
-error: unsupported type attribute for subdiagnostic enum
- --> $DIR/subdiagnostic-derive.rs:453:1
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+ --> $DIR/subdiagnostic-derive.rs:567:5
|
-LL | #[label]
- | ^^^^^^^^
+LL | #[suggestion_part]
+ | ^^^^^^^^^^^^^^^^^^
-error: `var` doesn't refer to a field on this type
- --> $DIR/subdiagnostic-derive.rs:473:39
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+ --> $DIR/subdiagnostic-derive.rs:570:5
|
-LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
- | ^^^^^^^
+LL | #[suggestion_part()]
+ | ^^^^^^^^^^^^^^^^^^^^
-error: `var` doesn't refer to a field on this type
- --> $DIR/subdiagnostic-derive.rs:492:43
+error: `#[suggestion_part(foo = ...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:573:23
|
-LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
- | ^^^^^^^
+LL | #[suggestion_part(foo = "bar")]
+ | ^^^^^^^^^^^
+ |
+ = help: `code` is the only valid nested attribute
+
+error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+ --> $DIR/subdiagnostic-derive.rs:576:5
+ |
+LL | #[suggestion_part(code = "...")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+ --> $DIR/subdiagnostic-derive.rs:579:5
+ |
+LL | #[suggestion_part()]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: specified multiple times
+ --> $DIR/subdiagnostic-derive.rs:587:37
+ |
+LL | #[suggestion_part(code = "...", code = ",,,")]
+ | ^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/subdiagnostic-derive.rs:587:23
+ |
+LL | #[suggestion_part(code = "...", code = ",,,")]
+ | ^^^^^^^^^^^^
+
+error: specified multiple times
+ --> $DIR/subdiagnostic-derive.rs:617:5
+ |
+LL | #[applicability]
+ | ^^^^^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/subdiagnostic-derive.rs:614:43
+ |
+LL | #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: cannot find attribute `foo` in this scope
--> $DIR/subdiagnostic-derive.rs:63:3
LL | #[label(slug)]
| ^^^^ not found in `rustc_errors::fluent`
-error: aborting due to 50 previous errors
+error: aborting due to 63 previous errors
For more information about this error, try `rustc --explain E0425`.
help: remove the extra argument
|
LL | extra();
- | ~~~~~~~
+ | ~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/basic.rs:22:5
help: provide the argument
|
LL | missing(/* u32 */);
- | ~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/basic.rs:23:5
help: swap these arguments
|
LL | swapped(1, "");
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/basic.rs:24:5
help: reorder these arguments
|
LL | permuted(X {}, Y {}, Z {});
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error[E0057]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/basic.rs:27:5
help: provide the argument
|
LL | closure(/* value */);
- | ~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error: aborting due to 6 previous errors
help: did you mean
|
LL | complex(/* u32 */, &"", /* E */, F::X2, G{}, X {}, Y {}, Z {});
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: remove the extra argument
|
LL | t();
- | ~~~
+ | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:7:5
help: remove the extra argument
|
LL | t();
- | ~~~
+ | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:16:5
help: remove the extra argument
|
LL | baz()()
- |
+ | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:22:5
help: remove the extra argument
|
LL | x();
- | ~~~
+ | ~~
error: aborting due to 4 previous errors
help: remove the extra argument
|
LL | empty();
- | ~~~~~~~
+ | ~~
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/extra_arguments.rs:9:3
help: remove the extra argument
|
LL | one_arg(1);
- | ~~~~~~~~~~
+ | ~~~
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/extra_arguments.rs:10:3
help: remove the extra argument
|
LL | one_arg(1);
- | ~~~~~~~~~~
+ | ~~~
error[E0061]: this function takes 1 argument but 3 arguments were supplied
--> $DIR/extra_arguments.rs:11:3
help: remove the extra arguments
|
LL | one_arg(1);
- | ~~~~~~~~~~
+ | ~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:13:3
help: remove the extra argument
|
LL | two_arg_same(1, 1);
- | ~~~~~~~~~~~~~~~~~~
+ | ~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:14:3
help: remove the extra argument
|
LL | two_arg_same(1, 1);
- | ~~~~~~~~~~~~~~~~~~
+ | ~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:16:3
help: remove the extra argument
|
LL | two_arg_diff(1, "");
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:17:3
help: remove the extra argument
|
LL | two_arg_diff(1, "");
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~
error[E0061]: this function takes 2 arguments but 4 arguments were supplied
--> $DIR/extra_arguments.rs:18:3
help: remove the extra arguments
|
LL | two_arg_diff(1, "");
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~
error[E0061]: this function takes 2 arguments but 4 arguments were supplied
--> $DIR/extra_arguments.rs:19:3
help: remove the extra arguments
|
LL | two_arg_diff(1, "");
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:22:3
help: remove the extra argument
|
LL | two_arg_same(1, 1);
- | ~~~~~~~~~~~~~~~~~~
+ | ~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:23:3
help: remove the extra argument
|
LL | two_arg_diff(1, "");
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:24:3
help: remove the extra argument
|
LL | two_arg_same(1, 1);
- | ~~~~~~~~~~~~~~~~~~
+ | ~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/extra_arguments.rs:30:3
help: remove the extra argument
|
LL | two_arg_diff(1, "");
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~
error: aborting due to 14 previous errors
help: provide the argument
|
LL | f(/* usize */, &x, /* usize */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the arguments
|
LL | g((), /* bool */, /* bool */, /* bool */, /* bool */, ());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: remove the extra arguments
|
LL | foo(&&A, D, /* &E */, G);
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | (|_, ()| ())(if true {} else {return;}, ());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | (|_, ()| ())([return, ()], ());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | let _f = f((), main);
- | ~~~~~~~~~~~
+ | ~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | one_arg(/* i32 */);
- | ~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~
error[E0061]: this function takes 2 arguments but 0 arguments were supplied
--> $DIR/missing_arguments.rs:14:3
help: provide the arguments
|
LL | two_same(/* i32 */, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/missing_arguments.rs:15:3
help: provide the argument
|
LL | two_same(1, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~
error[E0061]: this function takes 2 arguments but 0 arguments were supplied
--> $DIR/missing_arguments.rs:16:3
help: provide the arguments
|
LL | two_diff(/* i32 */, /* f32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/missing_arguments.rs:17:3
help: provide the argument
|
LL | two_diff(1, /* f32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/missing_arguments.rs:18:3
help: provide the argument
|
LL | two_diff(/* i32 */, 1.0);
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 0 arguments were supplied
--> $DIR/missing_arguments.rs:21:3
help: provide the arguments
|
LL | three_same(/* i32 */, /* i32 */, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 1 argument was supplied
--> $DIR/missing_arguments.rs:22:3
help: provide the arguments
|
LL | three_same(1, /* i32 */, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
--> $DIR/missing_arguments.rs:23:3
help: provide the argument
|
LL | three_same(1, 1, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
--> $DIR/missing_arguments.rs:26:3
help: provide the argument
|
LL | three_diff(/* i32 */, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
--> $DIR/missing_arguments.rs:27:3
help: provide the argument
|
LL | three_diff(1, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
--> $DIR/missing_arguments.rs:28:3
help: provide the argument
|
LL | three_diff(1, 1.0, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 1 argument was supplied
--> $DIR/missing_arguments.rs:29:3
help: provide the arguments
|
LL | three_diff(/* i32 */, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 1 argument was supplied
--> $DIR/missing_arguments.rs:30:3
help: provide the arguments
|
LL | three_diff(/* i32 */, 1.0, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 1 argument was supplied
--> $DIR/missing_arguments.rs:31:3
help: provide the arguments
|
LL | three_diff(1, /* f32 */, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 4 arguments but 0 arguments were supplied
--> $DIR/missing_arguments.rs:34:3
help: provide the arguments
|
LL | four_repeated(/* i32 */, /* f32 */, /* f32 */, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 4 arguments but 2 arguments were supplied
--> $DIR/missing_arguments.rs:35:3
help: provide the arguments
|
LL | four_repeated(1, /* f32 */, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 5 arguments but 0 arguments were supplied
--> $DIR/missing_arguments.rs:38:3
help: provide the arguments
|
LL | complex(/* i32 */, /* f32 */, /* i32 */, /* f32 */, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 5 arguments but 2 arguments were supplied
--> $DIR/missing_arguments.rs:39:3
help: provide the arguments
|
LL | complex(1, /* f32 */, /* i32 */, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 19 previous errors
help: remove the extra argument
|
LL | two_args(1, /* f32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 4 arguments were supplied
--> $DIR/mixed_cases.rs:11:3
help: did you mean
|
LL | three_args(1, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
--> $DIR/mixed_cases.rs:14:3
help: provide the argument
|
LL | three_args(1, /* f32 */, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/mixed_cases.rs:17:3
help: did you mean
|
LL | three_args(1, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/mixed_cases.rs:20:3
help: swap these arguments
|
LL | three_args(1, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
--> $DIR/mixed_cases.rs:23:3
help: did you mean
|
LL | three_args(1, /* f32 */, "");
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error: aborting due to 6 previous errors
help: reorder these arguments
|
LL | three_args(1, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/permuted_arguments.rs:12:3
help: reorder these arguments
|
LL | many_args(1, 1.0, "", X {}, Y {});
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
help: swap these arguments
|
LL | two_args(1, 1.0);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:9:3
help: swap these arguments
|
LL | three_args(1, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:10:3
help: swap these arguments
|
LL | three_args(1, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:11:3
help: swap these arguments
|
LL | three_args(1, 1.0, "");
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0308]: arguments to this function are incorrect
--> $DIR/swapped_arguments.rs:13:3
help: did you mean
|
LL | four_args(1, 1.0, "", X {});
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~
error: aborting due to 5 previous errors
--- /dev/null
+// check-pass
+// compile-flags: -Zunpretty=expanded
+core::arch::global_asm!("x: .byte 42");
--- /dev/null
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// check-pass
+// compile-flags: -Zunpretty=expanded
+global_asm! ("x: .byte 42");
f1(2u32, 4u32);
//~^ ERROR `u32: Foo` is not satisfied
//~| ERROR `u32: Foo` is not satisfied
+ //~| ERROR `u32: Foo` is not satisfied
}
pub fn f1_uint_int() {
f1(2u32, 4i32);
//~^ ERROR `u32: Foo` is not satisfied
//~| ERROR `u32: Foo` is not satisfied
+ //~| ERROR `u32: Foo` is not satisfied
}
pub fn f2_int() {
LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
| ^^^ required by this bound in `f1`
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+ --> $DIR/associated-types-path-2.rs:29:5
+ |
+LL | f1(2u32, 4u32);
+ | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
+ |
+ = help: the trait `Foo` is implemented for `i32`
+
error[E0277]: the trait bound `u32: Foo` is not satisfied
--> $DIR/associated-types-path-2.rs:29:14
|
= help: the trait `Foo` is implemented for `i32`
error[E0277]: the trait bound `u32: Foo` is not satisfied
- --> $DIR/associated-types-path-2.rs:35:8
+ --> $DIR/associated-types-path-2.rs:36:8
|
LL | f1(2u32, 4i32);
| -- ^^^^ the trait `Foo` is not implemented for `u32`
| ^^^ required by this bound in `f1`
error[E0277]: the trait bound `u32: Foo` is not satisfied
- --> $DIR/associated-types-path-2.rs:35:14
+ --> $DIR/associated-types-path-2.rs:36:5
+ |
+LL | f1(2u32, 4i32);
+ | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
+ |
+ = help: the trait `Foo` is implemented for `i32`
+
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+ --> $DIR/associated-types-path-2.rs:36:14
|
LL | f1(2u32, 4i32);
| ^^^^ the trait `Foo` is not implemented for `u32`
= help: the trait `Foo` is implemented for `i32`
error[E0308]: mismatched types
- --> $DIR/associated-types-path-2.rs:41:18
+ --> $DIR/associated-types-path-2.rs:43:18
|
LL | let _: i32 = f2(2i32);
| --- ^^^^^^^^ expected `i32`, found `u32`
LL | let _: i32 = f2(2i32).try_into().unwrap();
| ++++++++++++++++++++
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
// run-pass
// edition:2018
+// revisions: normal drop-tracking
+// [normal]compile-flags: -Zdrop-tracking=no
+// [drop-tracking]compile-flags: -Zdrop-tracking
#![allow(dead_code)]
use std::future::Future;
LL | (|_| 2333).await;
| ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future
|
- = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
+ = help: the trait `Future` is not implemented for closure `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
= note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited
= note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture`
help: remove the `.await`
--- /dev/null
+#![feature(rustc_private)]
+extern crate libc;
+
+/// So tests don't have to bring libc in scope themselves
+pub enum SignalHandler {
+ Ignore,
+ Default,
+}
+
+/// Helper to assert that [`libc::SIGPIPE`] has the expected signal handler.
+pub fn assert_sigpipe_handler(expected_handler: SignalHandler) {
+ #[cfg(unix)]
+ #[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "horizon",
+ target_os = "android",
+ )))]
+ {
+ let prev = unsafe { libc::signal(libc::SIGPIPE, libc::SIG_IGN) };
+
+ let expected = match expected_handler {
+ SignalHandler::Ignore => libc::SIG_IGN,
+ SignalHandler::Default => libc::SIG_DFL,
+ };
+ assert_eq!(prev, expected);
+
+ // Unlikely to matter, but restore the old value anyway
+ unsafe { libc::signal(libc::SIGPIPE, prev); };
+ }
+}
--- /dev/null
+#![feature(unix_sigpipe)]
+#![unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute cannot be used at crate level
+
+fn main() {}
--- /dev/null
+error: `unix_sigpipe` attribute cannot be used at crate level
+ --> $DIR/unix_sigpipe-crate.rs:2:1
+ |
+LL | #![unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: perhaps you meant to use an outer attribute
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_ign"]
+#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
+fn main() {}
--- /dev/null
+error: multiple `unix_sigpipe` attributes
+ --> $DIR/unix_sigpipe-duplicates.rs:4:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unix_sigpipe-duplicates.rs:3:1
+ |
+LL | #[unix_sigpipe = "sig_ign"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_ign"]
+fn main() {
+ extern crate sigpipe_utils;
+
+ // #[unix_sigpipe = "sig_ign"] is active, so the legacy behavior of ignoring
+ // SIGPIPE shall be in effect
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"]
+fn main() {
+ extern crate sigpipe_utils;
+
+ // #[unix_sigpipe = "inherit"] is active, so SIGPIPE shall NOT be ignored,
+ // instead the default handler shall be installed. (We assume that the
+ // process that runs these tests have the default handler.)
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe(inherit)] //~ error: malformed `unix_sigpipe` attribute input
+fn main() {}
--- /dev/null
+error: malformed `unix_sigpipe` attribute input
+ --> $DIR/unix_sigpipe-list.rs:3:1
+ |
+LL | #[unix_sigpipe(inherit)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: the following are the possible correct uses
+ |
+LL | #[unix_sigpipe = "inherit|sig_ign|sig_dfl"]
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | #[unix_sigpipe]
+ | ~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+fn f() {}
+
+fn main() {}
--- /dev/null
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+ --> $DIR/unix_sigpipe-non-main-fn.rs:3:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+mod m {
+ #[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()`
+ fn main() {}
+}
+
+fn main() {}
--- /dev/null
+error: `unix_sigpipe` attribute can only be used on root `fn main()`
+ --> $DIR/unix_sigpipe-non-root-main.rs:4:5
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+fn main() {
+ extern crate sigpipe_utils;
+
+ // SIGPIPE shall be ignored since #[unix_sigpipe = "..."] is not used
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+fn main() {
+ extern crate sigpipe_utils;
+
+ // Only #![feature(unix_sigpipe)] is enabled, not #[unix_sigpipe = "..."].
+ // This shall not change any behavior, so we still expect SIGPIPE to be
+ // ignored
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+#![feature(rustc_attrs)]
+
+#[unix_sigpipe = "sig_dfl"]
+#[rustc_main]
+fn rustc_main() {
+ extern crate sigpipe_utils;
+
+ // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE handler shall be
+ // SIG_DFL. Note that we have a #[rustc_main], but it should still work.
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
--- /dev/null
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_dfl"]
+fn main() {
+ extern crate sigpipe_utils;
+
+ // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE shall NOT be ignored, instead
+ // the default handler shall be installed
+ sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
--- /dev/null
+#![feature(start)]
+#![feature(unix_sigpipe)]
+
+#[start]
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 }
--- /dev/null
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+ --> $DIR/unix_sigpipe-start.rs:5:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+struct S;
+
+fn main() {}
--- /dev/null
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+ --> $DIR/unix_sigpipe-struct.rs:3:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "wrong"] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+fn main() {}
--- /dev/null
+error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+ --> $DIR/unix_sigpipe-wrong.rs:3:1
+ |
+LL | #[unix_sigpipe = "wrong"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+fn main() {}
--- /dev/null
+error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+ --> $DIR/unix_sigpipe.rs:3:1
+ |
+LL | #[unix_sigpipe]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
LL | assert_eq!(foo, y);
| ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}`
+ = help: the trait `Debug` is not implemented for fn item `for<'r> fn(&'r i32) -> &'r i32 {foo}`
= help: use parentheses to call the function: `foo(s)`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: provide the arguments
|
LL | foo(/* isize */, /* u8 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~
error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
--> $DIR/variadic-ffi-1.rs:21:9
help: provide the argument
|
LL | foo(1, /* u8 */);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:23:56
--- /dev/null
+// This test check that #![allow(unexpected_cfgs)] works with --cfg
+//
+// check-pass
+// compile-flags: --cfg=unexpected --check-cfg=names() -Z unstable-options
+
+#![allow(unexpected_cfgs)]
+
+fn main() {}
|
= note: expected values for `feature` are: full, serde
-warning: 2 warnings emitted
+warning: unexpected condition value `rand` for condition name `feature`
+ |
+ = help: was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+warning: 3 warnings emitted
// we correctly lint on the `cfg!` macro and `cfg_attr` attribute.
//
// check-pass
-// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" -Z unstable-options
+// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" --cfg unknown_name -Z unstable-options
#[cfg(windows)]
fn do_windows_stuff() {}
LL | #[cfg_attr(uu, test)]
| ^^
+warning: unexpected condition value `bar` for condition name `feature`
+ |
+ = help: was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+warning: unexpected `unknown_name` as condition name
+ |
+ = help: was set with `--cfg` but isn't in the `--check-cfg` expected names
+
warning: unexpected `cfg` condition name
--> $DIR/mix.rs:35:10
|
|
= note: expected values for `feature` are: foo
-warning: 25 warnings emitted
+warning: 27 warnings emitted
| |
| required by a bound introduced by this call
|
- = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+ = help: the trait `FnOnce<(&str,)>` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `Option::<T>::map`
--> $SRC_DIR/core/src/option.rs:LL:COL
--- /dev/null
+// check-pass
+
+use std::convert::TryFrom;
+
+pub trait FieldElement {
+ type Integer: TryFrom<usize, Error = std::num::TryFromIntError>;
+
+ fn valid_integer_try_from<N>(i: N) -> Result<Self::Integer, ()>
+ where
+ Self::Integer: TryFrom<N>,
+ {
+ Self::Integer::try_from(i).map_err(|_| ())
+ }
+}
+
+fn main() {}
help: provide the argument
|
LL | let a = f(/* value */);
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/E0057.rs:5:13
help: remove the extra argument
|
LL | let c = f(2);
- | ~~~~
+ | ~~~
error: aborting due to 2 previous errors
help: provide the argument
|
LL | unsafe { printf(/* *const u8 */); }
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: provide the argument
|
LL | f(0, /* &str */);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/E0061.rs:9:5
help: provide the argument
|
LL | f2(/* u16 */);
- | ~~~~~~~~~~~~~
+ | ~~~~~~~~~~~
error: aborting due to 2 previous errors
| |
| required by a bound introduced by this call
|
- = help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}`
+ = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() {f}`
= note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `is_fn`
--> $DIR/extern-wrong-value-type.rs:4:28
--- /dev/null
+#![crate_type = "bin"]
+
+#[unix_sigpipe = "inherit"] //~ the `#[unix_sigpipe]` attribute is an experimental feature
+fn main () {}
--- /dev/null
+error[E0658]: the `#[unix_sigpipe]` attribute is an experimental feature
+ --> $DIR/feature-gate-unix_sigpipe.rs:3:1
+ |
+LL | #[unix_sigpipe = "inherit"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #97889 <https://github.com/rust-lang/rust/issues/97889> for more information
+ = help: add `#![feature(unix_sigpipe)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
| ^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+ = note: all function arguments must have a statically known size
= help: unsized fn params are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
- |
-LL | foo(&*x);
- | +
error: aborting due to 2 previous errors
help: provide the argument
|
LL | f(&[f(/* value */)]);
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error: aborting due to previous error
| |
| required by a bound introduced by this call
|
- = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`
+ = help: the trait `~const FnOnce<()>` is not implemented for closure `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`
note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`, but that implementation is not `const`
--> $DIR/const-eval-select-bad.rs:7:27
|
help: remove the extra argument
|
LL | |t| f();
- | ~~~
+ | ~~
error: aborting due to previous error
help: provide the argument
|
LL | print_x(/* &dyn Foo<Item = bool> */, /* &str */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: remove the extra argument
|
LL | fn main() { foo(5) }
- | ~~~~~~
+ | ~~~
error: aborting due to previous error
LL | assert_eq!(Foo::Bar, i);
| ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+ = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
= help: the following other types implement trait `Debug`:
extern "C" fn() -> Ret
extern "C" fn(A, B) -> Ret
LL | assert_eq!(Foo::Bar, i);
| ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+ = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
= help: the following other types implement trait `Debug`:
extern "C" fn() -> Ret
extern "C" fn(A, B) -> Ret
LL | assert_eq!(a, 0);
| ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for `fn() -> i32 {a}`
+ = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}`
= help: use parentheses to call the function: `a()`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
--- /dev/null
+struct Argument;
+struct Return;
+
+fn function(_: Argument) -> Return { todo!() }
+
+trait Trait {}
+impl Trait for fn(Argument) -> Return {}
+
+fn takes(_: impl Trait) {}
+
+fn main() {
+ takes(function);
+ //~^ ERROR the trait bound
+ takes(|_: Argument| -> Return { todo!() });
+ //~^ ERROR the trait bound
+}
--- /dev/null
+error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied
+ --> $DIR/issue-99875.rs:12:11
+ |
+LL | takes(function);
+ | ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+ --> $DIR/issue-99875.rs:9:18
+ |
+LL | fn takes(_: impl Trait) {}
+ | ^^^^^ required by this bound in `takes`
+
+error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied
+ --> $DIR/issue-99875.rs:14:11
+ |
+LL | takes(|_: Argument| -> Return { todo!() });
+ | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+ --> $DIR/issue-99875.rs:9:18
+ |
+LL | fn takes(_: impl Trait) {}
+ | ^^^^^ required by this bound in `takes`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
fn main() {
let _ = Iterator::next(&mut ());
//~^ ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
for _ in false {}
//~^ ERROR `bool` is not an iterator
let _ = Iterator::next(&mut ());
//~^ ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
other()
}
let _ = Iterator::next(&mut ());
//~^ ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
let _ = Iterator::next(&mut ());
//~^ ERROR `()` is not an iterator
+ //~| ERROR `()` is not an iterator
for _ in false {}
//~^ ERROR `bool` is not an iterator
|
= help: the trait `Iterator` is not implemented for `()`
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:2:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
error[E0277]: `bool` is not an iterator
- --> $DIR/issue-28098.rs:5:14
+ --> $DIR/issue-28098.rs:7:14
|
LL | for _ in false {}
| ^^^^^ `bool` is not an iterator
= note: required for `bool` to implement `IntoIterator`
error[E0277]: `()` is not an iterator
- --> $DIR/issue-28098.rs:8:28
+ --> $DIR/issue-28098.rs:10:28
|
LL | let _ = Iterator::next(&mut ());
| -------------- ^^^^^^^ `()` is not an iterator
= help: the trait `Iterator` is not implemented for `()`
error[E0277]: `()` is not an iterator
- --> $DIR/issue-28098.rs:17:28
+ --> $DIR/issue-28098.rs:10:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:2:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:20:28
|
LL | let _ = Iterator::next(&mut ());
| -------------- ^^^^^^^ `()` is not an iterator
= help: the trait `Iterator` is not implemented for `()`
error[E0277]: `()` is not an iterator
- --> $DIR/issue-28098.rs:20:28
+ --> $DIR/issue-28098.rs:20:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:25:28
|
LL | let _ = Iterator::next(&mut ());
| -------------- ^^^^^^^ `()` is not an iterator
|
= help: the trait `Iterator` is not implemented for `()`
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:25:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
error[E0277]: `bool` is not an iterator
- --> $DIR/issue-28098.rs:23:14
+ --> $DIR/issue-28098.rs:29:14
|
LL | for _ in false {}
| ^^^^^ `bool` is not an iterator
= help: the trait `Iterator` is not implemented for `bool`
= note: required for `bool` to implement `IntoIterator`
-error: aborting due to 6 previous errors
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-28098.rs:20:13
+ |
+LL | let _ = Iterator::next(&mut ());
+ | ^^^^^^^^^^^^^^ `()` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+
+error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0277`.
help: provide the argument
|
LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter(/* &u8 */) }
- | ~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/issue-26638.rs:5:47
--- /dev/null
+// check-pass
+#![warn(let_underscore_drop)]
+
+struct NontrivialDrop;
+
+impl Drop for NontrivialDrop {
+ fn drop(&mut self) {
+ println!("Dropping!");
+ }
+}
+
+fn main() {
+ let _ = NontrivialDrop; //~WARNING non-binding let on a type that implements `Drop`
+}
--- /dev/null
+warning: non-binding let on a type that implements `Drop`
+ --> $DIR/let_underscore_drop.rs:13:5
+ |
+LL | let _ = NontrivialDrop;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/let_underscore_drop.rs:2:9
+ |
+LL | #![warn(let_underscore_drop)]
+ | ^^^^^^^^^^^^^^^^^^^
+help: consider binding to an unused variable to avoid immediately dropping the value
+ |
+LL | let _unused = NontrivialDrop;
+ | ~~~~~~~
+help: consider immediately dropping the value
+ |
+LL | drop(NontrivialDrop);
+ | ~~~~~ +
+
+warning: 1 warning emitted
+
--- /dev/null
+// check-fail
+use std::sync::{Arc, Mutex};
+
+fn main() {
+ let data = Arc::new(Mutex::new(0));
+ let _ = data.lock().unwrap(); //~ERROR non-binding let on a synchronization lock
+}
--- /dev/null
+error: non-binding let on a synchronization lock
+ --> $DIR/let_underscore_lock.rs:6:9
+ |
+LL | let _ = data.lock().unwrap();
+ | ^ ^^^^^^^^^^^^^^^^^^^^ this binding will immediately drop the value assigned to it
+ | |
+ | this lock is not assigned to a binding and is immediately dropped
+ |
+ = note: `#[deny(let_underscore_lock)]` on by default
+help: consider binding to an unused variable to avoid immediately dropping the value
+ |
+LL | let _unused = data.lock().unwrap();
+ | ~~~~~~~
+help: consider immediately dropping the value
+ |
+LL | drop(data.lock().unwrap());
+ | ~~~~~ +
+
+error: aborting due to previous error
+
help: remove the extra argument
|
LL | x.zero()
- | ~~~~~~
+ | ~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/method-call-err-msg.rs:14:7
help: provide the argument
|
LL | .one(/* isize */)
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/method-call-err-msg.rs:15:7
help: provide the argument
|
LL | .two(0, /* isize */);
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error[E0599]: `Foo` is not an iterator
--> $DIR/method-call-err-msg.rs:19:7
help: provide the arguments
|
LL | y.three::<usize>(/* usize */, /* usize */, /* usize */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 5 previous errors
--- /dev/null
+// check-pass
+pub trait Backend {
+ type DescriptorSetLayout;
+}
+
+pub struct Back;
+
+impl Backend for Back {
+ type DescriptorSetLayout = u32;
+}
+
+pub struct HalSetLayouts {
+ vertex_layout: <Back as Backend>::DescriptorSetLayout,
+}
+
+impl HalSetLayouts {
+ pub fn iter<DSL>(self) -> DSL
+ where
+ Back: Backend<DescriptorSetLayout = DSL>,
+ {
+ self.vertex_layout
+ }
+}
+
+fn main() {}
help: provide the argument
|
LL | let ans = s(/* isize */);
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/overloaded-calls-bad.rs:31:15
help: remove the extra argument
|
LL | let ans = s(/* isize */);
- | ~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error: aborting due to 3 previous errors
--> $DIR/namespace-mix.rs:56:11
|
LL | check(m3::TS);
- | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::TS {c::TS}`
| |
| required by a bound introduced by this call
|
--> $DIR/namespace-mix.rs:62:11
|
LL | check(xm3::TS);
- | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
| |
| required by a bound introduced by this call
|
--> $DIR/namespace-mix.rs:122:11
|
LL | check(m9::TV);
- | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::E {c::E::TV}`
| |
| required by a bound introduced by this call
|
--> $DIR/namespace-mix.rs:128:11
|
LL | check(xm9::TV);
- | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
| |
| required by a bound introduced by this call
|
help: provide the argument
|
LL | foo(1, 2, 3, /* isize */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 6 arguments but 3 arguments were supplied
--> $DIR/not-enough-arguments.rs:29:3
help: provide the arguments
|
LL | bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
#![feature(rustc_attrs)]
#[rustc_object_lifetime_default]
-struct A<T>(T); //~ ERROR BaseDefault
+struct A<
+ T, //~ ERROR BaseDefault
+>(T);
#[rustc_object_lifetime_default]
-struct B<'a,T>(&'a (), T); //~ ERROR BaseDefault
+struct B<
+ 'a,
+ T, //~ ERROR BaseDefault
+>(&'a (), T);
#[rustc_object_lifetime_default]
-struct C<'a,T:'a>(&'a T); //~ ERROR 'a
+struct C<
+ 'a,
+ T: 'a, //~ ERROR 'a
+>(&'a T);
#[rustc_object_lifetime_default]
-struct D<'a,'b,T:'a+'b>(&'a T, &'b T); //~ ERROR Ambiguous
+struct D<
+ 'a,
+ 'b,
+ T: 'a + 'b, //~ ERROR Ambiguous
+>(&'a T, &'b T);
#[rustc_object_lifetime_default]
-struct E<'a,'b:'a,T:'b>(&'a T, &'b T); //~ ERROR 'b
+struct E<
+ 'a,
+ 'b: 'a,
+ T: 'b, //~ ERROR 'b
+>(&'a T, &'b T);
#[rustc_object_lifetime_default]
-struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U); //~ ERROR 'a,'b
+struct F<
+ 'a,
+ 'b,
+ T: 'a, //~ ERROR 'a
+ U: 'b, //~ ERROR 'b
+>(&'a T, &'b U);
#[rustc_object_lifetime_default]
-struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U); //~ ERROR 'a,Ambiguous
-
-fn main() { }
+struct G<
+ 'a,
+ 'b,
+ T: 'a, //~ ERROR 'a
+ U: 'a + 'b, //~ ERROR Ambiguous
+>(&'a T, &'b U);
+
+fn main() {}
error: BaseDefault
- --> $DIR/object-lifetime-default.rs:4:1
+ --> $DIR/object-lifetime-default.rs:5:5
|
-LL | struct A<T>(T);
- | ^^^^^^^^^^^^^^^
+LL | T,
+ | ^
error: BaseDefault
- --> $DIR/object-lifetime-default.rs:7:1
+ --> $DIR/object-lifetime-default.rs:11:5
|
-LL | struct B<'a,T>(&'a (), T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | T,
+ | ^
error: 'a
- --> $DIR/object-lifetime-default.rs:10:1
+ --> $DIR/object-lifetime-default.rs:17:5
|
-LL | struct C<'a,T:'a>(&'a T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | T: 'a,
+ | ^
error: Ambiguous
- --> $DIR/object-lifetime-default.rs:13:1
+ --> $DIR/object-lifetime-default.rs:24:5
|
-LL | struct D<'a,'b,T:'a+'b>(&'a T, &'b T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | T: 'a + 'b,
+ | ^
error: 'b
- --> $DIR/object-lifetime-default.rs:16:1
+ --> $DIR/object-lifetime-default.rs:31:5
|
-LL | struct E<'a,'b:'a,T:'b>(&'a T, &'b T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | T: 'b,
+ | ^
-error: 'a,'b
- --> $DIR/object-lifetime-default.rs:19:1
+error: 'a
+ --> $DIR/object-lifetime-default.rs:38:5
+ |
+LL | T: 'a,
+ | ^
+
+error: 'b
+ --> $DIR/object-lifetime-default.rs:39:5
|
-LL | struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | U: 'b,
+ | ^
-error: 'a,Ambiguous
- --> $DIR/object-lifetime-default.rs:22:1
+error: 'a
+ --> $DIR/object-lifetime-default.rs:46:5
+ |
+LL | T: 'a,
+ | ^
+
+error: Ambiguous
+ --> $DIR/object-lifetime-default.rs:47:5
|
-LL | struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | U: 'a + 'b,
+ | ^
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
fn main() {
Index::index(&[] as &[i32], 2u32);
//~^ ERROR E0277
+ //~| ERROR E0277
+ //~| ERROR E0277
Index::index(&[] as &[i32], Foo(2u32));
//~^ ERROR E0277
+ //~| ERROR E0277
+ //~| ERROR E0277
Index::index(&[] as &[i32], Bar(2u32));
//~^ ERROR E0277
+ //~| ERROR E0277
+ //~| ERROR E0277
}
<[i32] as Index<Bar<usize>>>
<[i32] as Index<Foo<usize>>>
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+ --> $DIR/multiple-impls.rs:33:5
+ |
+LL | Index::index(&[] as &[i32], 2u32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message
+ |
+ = help: the trait `Index<u32>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
- --> $DIR/multiple-impls.rs:35:33
+ --> $DIR/multiple-impls.rs:37:33
|
LL | Index::index(&[] as &[i32], Foo(2u32));
| ------------ ^^^^^^^^^ on impl for Foo
<[i32] as Index<Bar<usize>>>
<[i32] as Index<Foo<usize>>>
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+ --> $DIR/multiple-impls.rs:37:5
+ |
+LL | Index::index(&[] as &[i32], Foo(2u32));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo
+ |
+ = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
- --> $DIR/multiple-impls.rs:37:33
+ --> $DIR/multiple-impls.rs:41:33
|
LL | Index::index(&[] as &[i32], Bar(2u32));
| ------------ ^^^^^^^^^ on impl for Bar
<[i32] as Index<Bar<usize>>>
<[i32] as Index<Foo<usize>>>
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+ --> $DIR/multiple-impls.rs:41:5
+ |
+LL | Index::index(&[] as &[i32], Bar(2u32));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar
+ |
+ = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+ --> $DIR/multiple-impls.rs:33:5
+ |
+LL | Index::index(&[] as &[i32], 2u32);
+ | ^^^^^^^^^^^^ trait message
+ |
+ = help: the trait `Index<u32>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+ --> $DIR/multiple-impls.rs:37:5
+ |
+LL | Index::index(&[] as &[i32], Foo(2u32));
+ | ^^^^^^^^^^^^ on impl for Foo
+ |
+ = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+ --> $DIR/multiple-impls.rs:41:5
+ |
+LL | Index::index(&[] as &[i32], Bar(2u32));
+ | ^^^^^^^^^^^^ on impl for Bar
+ |
+ = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+ = help: the following other types implement trait `Index<Idx>`:
+ <[i32] as Index<Bar<usize>>>
+ <[i32] as Index<Foo<usize>>>
+
+error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0277`.
fn main() {
Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
//~^ ERROR E0277
+ //~| ERROR E0277
+ //~| ERROR E0277
}
= help: the trait `Index<u32>` is not implemented for `[i32]`
= help: the trait `Index<usize>` is implemented for `[i32]`
-error: aborting due to previous error
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+ --> $DIR/on-impl.rs:22:5
+ |
+LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+ |
+ = help: the trait `Index<u32>` is not implemented for `[i32]`
+ = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+ --> $DIR/on-impl.rs:22:5
+ |
+LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+ | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+ |
+ = help: the trait `Index<u32>` is not implemented for `[i32]`
+ = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+#![feature(rustc_attrs)]
+
+#[rustc_access_level] mod outer { //~ ERROR None
+ #[rustc_access_level] pub mod inner { //~ ERROR Some(Exported)
+ #[rustc_access_level]
+ extern "C" { //~ ERROR Some(Exported)
+ #[rustc_access_level] static a: u8; //~ ERROR None
+ #[rustc_access_level] pub fn b(); //~ ERROR Some(Exported)
+ }
+ #[rustc_access_level]
+ pub trait Trait { //~ ERROR Some(Exported)
+ #[rustc_access_level] const A: i32; //~ ERROR Some(Exported)
+ #[rustc_access_level] type B; //~ ERROR Some(Exported)
+ }
+
+ #[rustc_access_level]
+ pub struct Struct { //~ ERROR Some(Exported)
+ #[rustc_access_level] a: u8, //~ ERROR None
+ #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
+ }
+
+ #[rustc_access_level]
+ pub union Union { //~ ERROR Some(Exported)
+ #[rustc_access_level] a: u8, //~ ERROR None
+ #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
+ }
+
+ #[rustc_access_level]
+ pub enum Enum { //~ ERROR Some(Exported)
+ #[rustc_access_level] A( //~ ERROR Some(Exported)
+ #[rustc_access_level] Struct, //~ ERROR Some(Exported)
+ #[rustc_access_level] Union, //~ ERROR Some(Exported)
+ ),
+ }
+ }
+
+ #[rustc_access_level] macro_rules! none_macro { //~ ERROR None
+ () => {};
+ }
+
+ #[macro_export]
+ #[rustc_access_level] macro_rules! public_macro { //~ ERROR Some(Public)
+ () => {};
+ }
+}
+
+pub use outer::inner;
+
+fn main() {}
--- /dev/null
+error: None
+ --> $DIR/access_levels.rs:3:23
+ |
+LL | #[rustc_access_level] mod outer {
+ | ^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:4:27
+ |
+LL | #[rustc_access_level] pub mod inner {
+ | ^^^^^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:6:9
+ |
+LL | / extern "C" {
+LL | | #[rustc_access_level] static a: u8;
+LL | | #[rustc_access_level] pub fn b();
+LL | | }
+ | |_________^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:11:9
+ |
+LL | pub trait Trait {
+ | ^^^^^^^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:17:9
+ |
+LL | pub struct Struct {
+ | ^^^^^^^^^^^^^^^^^
+
+error: None
+ --> $DIR/access_levels.rs:18:35
+ |
+LL | #[rustc_access_level] a: u8,
+ | ^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:19:35
+ |
+LL | #[rustc_access_level] pub b: u8,
+ | ^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:23:9
+ |
+LL | pub union Union {
+ | ^^^^^^^^^^^^^^^
+
+error: None
+ --> $DIR/access_levels.rs:24:35
+ |
+LL | #[rustc_access_level] a: u8,
+ | ^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:25:35
+ |
+LL | #[rustc_access_level] pub b: u8,
+ | ^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:29:9
+ |
+LL | pub enum Enum {
+ | ^^^^^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:30:35
+ |
+LL | #[rustc_access_level] A(
+ | ^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:31:39
+ |
+LL | #[rustc_access_level] Struct,
+ | ^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:32:39
+ |
+LL | #[rustc_access_level] Union,
+ | ^^^^^
+
+error: None
+ --> $DIR/access_levels.rs:37:27
+ |
+LL | #[rustc_access_level] macro_rules! none_macro {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Some(Public)
+ --> $DIR/access_levels.rs:42:27
+ |
+LL | #[rustc_access_level] macro_rules! public_macro {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:12:35
+ |
+LL | #[rustc_access_level] const A: i32;
+ | ^^^^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:13:35
+ |
+LL | #[rustc_access_level] type B;
+ | ^^^^^^
+
+error: None
+ --> $DIR/access_levels.rs:7:35
+ |
+LL | #[rustc_access_level] static a: u8;
+ | ^^^^^^^^^^^^
+
+error: Some(Exported)
+ --> $DIR/access_levels.rs:8:35
+ |
+LL | #[rustc_access_level] pub fn b();
+ | ^^^^^^^^^^
+
+error: aborting due to 20 previous errors
+
| |_call the function in a closure: `|| unsafe { /* code */ }`
| required by a bound introduced by this call
|
- = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+ = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `ProcMacro::custom_derive`
--> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
help: remove the extra argument
|
LL | std::mem::size_of();
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~
error: aborting due to 3 previous errors
| |
| required by a bound introduced by this call
|
- = help: the trait `Fn<()>` is not implemented for `fn() {foo}`
+ = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call`
| |
| required by a bound introduced by this call
|
- = help: the trait `FnMut<()>` is not implemented for `fn() {foo}`
+ = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_mut`
| |
| required by a bound introduced by this call
|
- = help: the trait `FnOnce<()>` is not implemented for `fn() {foo}`
+ = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_once`
| |
| required by a bound introduced by this call
|
- = help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+ = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call`
| |
| required by a bound introduced by this call
|
- = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+ = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_mut`
| |
| required by a bound introduced by this call
|
- = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+ = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
= note: `#[target_feature]` functions do not implement the `Fn` traits
note: required by a bound in `call_once`
help: remove the extra argument
|
LL | foo(Some(42), 2);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/issue-34264.rs:8:13
help: remove the extra argument
|
LL | bar(1, 2);
- | ~~~~~~~~~
+ | ~~~~~~
error: aborting due to 6 previous errors
help: provide the argument
|
LL | let _: Result<(), String> = Ok(());
- | ~~~~~~
+ | ~~~~
error[E0061]: this function takes 2 arguments but 0 arguments were supplied
--> $DIR/missing-unit-argument.rs:12:5
help: provide the arguments
|
LL | foo((), ());
- | ~~~~~~~~~~~
+ | ~~~~~~~~
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/missing-unit-argument.rs:13:5
help: provide the argument
|
LL | foo((), ());
- | ~~~~~~~~~~~
+ | ~~~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/missing-unit-argument.rs:14:5
help: provide the argument
|
LL | bar(());
- | ~~~~~~~
+ | ~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/missing-unit-argument.rs:15:7
help: provide the argument
|
LL | S.baz(());
- | ~~~~~~~
+ | ~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/missing-unit-argument.rs:16:7
help: provide the argument
|
LL | S.generic::<()>(());
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~
error: aborting due to 6 previous errors
help: remove the extra argument
|
LL | let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/args-instead-of-tuple-errors.rs:8:5
help: remove the extra argument
|
LL | int_bool(/* (i32, bool) */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~
error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
--> $DIR/args-instead-of-tuple-errors.rs:11:28
help: provide the argument
|
LL | let _: Option<(i8,)> = Some(/* (i8,) */);
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple-errors.rs:14:34
help: provide the argument
|
LL | let _: Option<()> = Some(());
- | ~~~~~~~~
+ | ~~~~
error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple.rs:14:34
| |
| required by a bound introduced by this call
|
- = help: the trait `Future` is not implemented for `fn() -> impl Future<Output = ()> {foo}`
+ = help: the trait `Future` is not implemented for fn item `fn() -> impl Future<Output = ()> {foo}`
= note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `bar`
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
| |
| required by a bound introduced by this call
|
- = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
+ = help: the trait `Future` is not implemented for closure `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
= note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `bar`
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
--- /dev/null
+fn main() {
+ let vec = Vec::new();
+ Vec::contains(&vec, &0);
+ //~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+ //~| HELP the function `contains` is implemented on `[_]`
+}
--- /dev/null
+error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+ --> $DIR/deref-path-method.rs:3:10
+ |
+LL | Vec::contains(&vec, &0);
+ | ^^^^^^^^ function or associated item not found in `Vec<_, _>`
+ |
+help: the function `contains` is implemented on `[_]`
+ |
+LL | <[_]>::contains(&vec, &0);
+ | ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
| --- consider calling this function
...
LL | bar(foo);
- | --- ^^^ the trait `T` is not implemented for `fn() -> impl T<O = ()> {foo}`
+ | --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T<O = ()> {foo}`
| |
| required by a bound introduced by this call
|
LL | let closure = || S;
| -- consider calling this closure
LL | bar(closure);
- | --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
+ | --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
| |
| required by a bound introduced by this call
|
help: remove the extra argument
|
LL | groups.push(/* (Vec<String>, Vec<Process>) */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
help: remove the extra argument
|
LL | (|| {})();
- | ~~~~~~~~~
+ | ~~
error: aborting due to previous error
help: provide the argument
|
LL | <E>::V(/* u8 */);
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
help: remove the extra argument
|
LL | let x: Vec::with_capacity(10);
- | ~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~
error: aborting due to 2 previous errors
help: remove the extra argument
|
LL | l(vec![])
- |
+ | ~~~~~~~~
error: aborting due to previous error
help: remove the extra argument
|
LL | let _ = Some(3);
- | ~~~~~~~
+ | ~~~
error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:7:13
help: remove the extra arguments
|
LL | let _ = Ok(3);
- | ~~~~~
+ | ~~~
error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:8:13
help: provide the argument
|
LL | let _ = Ok(/* value */);
- | ~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~
error[E0061]: this struct takes 1 argument but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:9:13
help: provide the argument
|
LL | let _ = Wrapper(/* i32 */);
- | ~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~
error[E0061]: this struct takes 1 argument but 2 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:10:13
help: remove the extra argument
|
LL | let _ = Wrapper(5);
- | ~~~~~~~~~~
+ | ~~~
error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:11:13
help: provide the arguments
|
LL | let _ = DoubleWrapper(/* i32 */, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this struct takes 2 arguments but 1 argument was supplied
--> $DIR/struct-enum-wrong-args.rs:12:13
help: provide the argument
|
LL | let _ = DoubleWrapper(5, /* i32 */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~
error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:13:13
help: remove the extra argument
|
LL | let _ = DoubleWrapper(5, 2);
- | ~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~
error: aborting due to 8 previous errors
fn main() {
<i32 as Add<u32>>::add(1, 2);
//~^ ERROR cannot add `u32` to `i32`
+ //~| ERROR cannot add `u32` to `i32`
<i32 as Add<i32>>::add(1u32, 2);
//~^ ERROR mismatched types
<i32 as Add<i32>>::add(1, 2u32);
and 48 others
error[E0308]: mismatched types
- --> $DIR/ufcs-qpath-self-mismatch.rs:6:28
+ --> $DIR/ufcs-qpath-self-mismatch.rs:7:28
|
LL | <i32 as Add<i32>>::add(1u32, 2);
| ---------------------- ^^^^ expected `i32`, found `u32`
| ~~~
error[E0308]: mismatched types
- --> $DIR/ufcs-qpath-self-mismatch.rs:8:31
+ --> $DIR/ufcs-qpath-self-mismatch.rs:9:31
|
LL | <i32 as Add<i32>>::add(1, 2u32);
| ---------------------- ^^^^ expected `i32`, found `u32`
LL | <i32 as Add<i32>>::add(1, 2i32);
| ~~~
-error: aborting due to 3 previous errors
+error[E0277]: cannot add `u32` to `i32`
+ --> $DIR/ufcs-qpath-self-mismatch.rs:4:5
+ |
+LL | <i32 as Add<u32>>::add(1, 2);
+ | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
+ |
+ = help: the trait `Add<u32>` is not implemented for `i32`
+ = help: the following other types implement trait `Add<Rhs>`:
+ <&'a f32 as Add<f32>>
+ <&'a f64 as Add<f64>>
+ <&'a i128 as Add<i128>>
+ <&'a i16 as Add<i16>>
+ <&'a i32 as Add<i32>>
+ <&'a i64 as Add<i64>>
+ <&'a i8 as Add<i8>>
+ <&'a isize as Add<isize>>
+ and 48 others
+
+error: aborting due to 4 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-wrong-abi.rs:9:15
|
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-wrong-abi.rs:12:19
|
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-wrong-abi.rs:15:20
|
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20
| ^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
= help: unsized fn params are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
- |
-LL | &X(&*Y)
- | +
error: aborting due to previous error
edition = "2021"
[dependencies]
-rustdoc = { path = "../../librustdoc" }
+mdbook = { version = "0.4", default-features = false, features = ["search"] }
[[bin]]
name = "error_index_generator"
--- /dev/null
+[book]
+title = "Error codes index"
+description = "Book listing all Rust error codes"
+src = ""
+
+[output.html]
+git-repository-url = "https://github.com/rust-lang/rust/"
+additional-css = ["error-index.css"]
+additional-js = ["error-index.js"]
+
+[output.html.search]
+enable = true
+limit-results = 20
+use-boolean-and = true
+boost-title = 2
+boost-hierarchy = 2
+boost-paragraph = 1
+expand = true
+heading-split-level = 0
--- /dev/null
+code.compile_fail {
+ border-left: 2px solid red;
+}
+
+pre .tooltip {
+ position: absolute;
+ left: -25px;
+ top: 0;
+ z-index: 1;
+ color: red;
+ cursor: pointer;
+}
+pre .tooltip::after {
+ display: none;
+ content: "This example deliberately fails to compile";
+ background-color: #000;
+ color: #fff;
+ border-color: #000;
+ text-align: center;
+ padding: 5px 3px 3px 3px;
+ border-radius: 6px;
+ margin-left: 5px;
+}
+pre .tooltip::before {
+ display: none;
+ border-color: transparent black transparent transparent;
+ content: " ";
+ position: absolute;
+ top: 50%;
+ left: 16px;
+ margin-top: -5px;
+ border-width: 5px;
+ border-style: solid;
+}
+
+pre .tooltip:hover::before, pre .tooltip:hover::after {
+ display: inline;
+}
--- /dev/null
+for (const elem of document.querySelectorAll("pre.playground")) {
+ if (elem.querySelector(".compile_fail") === null) {
+ continue;
+ }
+ const child = document.createElement("div");
+ child.className = "tooltip";
+ child.textContent = "ⓘ";
+ elem.appendChild(child);
+}
#![feature(rustc_private)]
extern crate rustc_driver;
-extern crate rustc_span;
+// We use the function we generate from `register_diagnostics!`.
use crate::error_codes::error_codes;
use std::env;
use std::error::Error;
-use std::fs::{create_dir_all, File};
+use std::fs::{self, File};
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
-use rustc_span::edition::DEFAULT_EDITION;
+use std::str::FromStr;
-use rustdoc::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground};
+use mdbook::book::{parse_summary, BookItem, Chapter};
+use mdbook::{Config, MDBook};
macro_rules! register_diagnostics {
($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
mod error_codes;
enum OutputFormat {
- HTML(HTMLFormatter),
+ HTML,
Markdown,
Unknown(String),
}
impl OutputFormat {
- fn from(format: &str, resource_suffix: &str) -> OutputFormat {
+ fn from(format: &str) -> OutputFormat {
match &*format.to_lowercase() {
- "html" => OutputFormat::HTML(HTMLFormatter(resource_suffix.to_owned())),
+ "html" => OutputFormat::HTML,
"markdown" => OutputFormat::Markdown,
s => OutputFormat::Unknown(s.to_owned()),
}
}
}
-struct HTMLFormatter(String);
-
-impl HTMLFormatter {
- fn create_error_code_file(
- &self,
- err_code: &str,
- explanation: &str,
- parent_dir: &Path,
- ) -> Result<(), Box<dyn Error>> {
- let mut output_file = File::create(parent_dir.join(err_code).with_extension("html"))?;
-
- self.header(&mut output_file, "../", "")?;
- self.title(&mut output_file, &format!("Error code {}", err_code))?;
-
- let mut id_map = IdMap::new();
- let playground =
- Playground { crate_name: None, url: String::from("https://play.rust-lang.org/") };
- write!(
- output_file,
- "{}",
- Markdown {
- content: explanation,
- links: &[],
- ids: &mut id_map,
- error_codes: ErrorCodes::Yes,
- edition: DEFAULT_EDITION,
- playground: &Some(playground),
- heading_offset: HeadingOffset::H1,
- }
- .into_string()
- )?;
- write!(
- output_file,
- "<p>\
- <a style='text-align: center;display: block;width: 100%;' \
- href='../error-index.html'>Back to list of error codes</a>\
- </p>",
- )?;
-
- self.footer(&mut output_file)
- }
-
- fn header(
- &self,
- output: &mut dyn Write,
- extra_path: &str,
- extra: &str,
- ) -> Result<(), Box<dyn Error>> {
- write!(
- output,
- r##"<!DOCTYPE html>
-<html>
-<head>
-<title>Rust Compiler Error Index</title>
-<meta charset="utf-8">
-<!-- Include rust.css after light.css so its rules take priority. -->
-<link rel="stylesheet" type="text/css" href="{extra_path}rustdoc{suffix}.css"/>
-<link rel="stylesheet" type="text/css" href="{extra_path}light{suffix}.css"/>
-<link rel="stylesheet" type="text/css" href="{extra_path}rust.css"/>
-<style>
-.error-undescribed {{
- display: none;
-}}
-</style>{extra}
-</head>
-<body>
-"##,
- suffix = self.0,
- )?;
- Ok(())
- }
-
- fn title(&self, output: &mut dyn Write, title: &str) -> Result<(), Box<dyn Error>> {
- write!(output, "<h1>{}</h1>\n", title)?;
- Ok(())
- }
-
- fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
- write!(output, "</body></html>")?;
- Ok(())
- }
-}
-
/// Output an HTML page for the errors in `err_map` to `output_path`.
fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
let mut output_file = File::create(output_path)?;
Ok(())
}
-fn render_html(output_path: &Path, formatter: HTMLFormatter) -> Result<(), Box<dyn Error>> {
- let mut output_file = File::create(output_path)?;
+// By default, mdbook doesn't consider code blocks as Rust ones contrary to rustdoc so we have
+// to manually add `rust` attribute whenever needed.
+fn add_rust_attribute_on_codeblock(explanation: &str) -> String {
+ // Very hacky way to add the rust attribute on all code blocks.
+ let mut skip = true;
+ explanation.split("\n```").fold(String::new(), |mut acc, part| {
+ if !acc.is_empty() {
+ acc.push_str("\n```");
+ }
+ if !skip {
+ if let Some(attrs) = part.split('\n').next() {
+ if !attrs.contains("rust")
+ && (attrs.is_empty()
+ || attrs.contains("compile_fail")
+ || attrs.contains("ignore")
+ || attrs.contains("edition"))
+ {
+ if !attrs.is_empty() {
+ acc.push_str("rust,");
+ } else {
+ acc.push_str("rust");
+ }
+ }
+ }
+ }
+ skip = !skip;
+ acc.push_str(part);
+ acc
+ })
+}
- let error_codes_dir = "error_codes";
+fn render_html(output_path: &Path) -> Result<(), Box<dyn Error>> {
+ let mut introduction = format!(
+ "<script src='redirect.js'></script>
+# Rust error codes index
- let parent = output_path.parent().expect("There should have a parent").join(error_codes_dir);
+This page lists all the error codes emitted by the Rust compiler.
- if !parent.exists() {
- create_dir_all(&parent)?;
- }
+"
+ );
- formatter.header(
- &mut output_file,
- "",
- &format!(
- r#"<script>(function() {{
- if (window.location.hash) {{
- let code = window.location.hash.replace(/^#/, '');
- // We have to make sure this pattern matches to avoid inadvertently creating an
- // open redirect.
- if (/^E[0-9]+$/.test(code)) {{
- window.location = './{error_codes_dir}/' + code + '.html';
- }}
- }}
-}})()</script>"#
- ),
- )?;
- formatter.title(&mut output_file, "Rust Compiler Error Index")?;
+ let err_codes = error_codes();
+ let mut chapters = Vec::with_capacity(err_codes.len());
- write!(
- output_file,
- "<p>This page lists all the error codes emitted by the Rust compiler. If you want a full \
- explanation on an error code, click on it.</p>\
- <ul>",
- )?;
- for (err_code, explanation) in error_codes().iter() {
+ for (err_code, explanation) in err_codes.iter() {
if let Some(explanation) = explanation {
- write!(
- output_file,
- "<li><a href='./{0}/{1}.html'>{1}</a></li>",
- error_codes_dir, err_code
- )?;
- formatter.create_error_code_file(err_code, explanation, &parent)?;
+ introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
+
+ let content = add_rust_attribute_on_codeblock(explanation);
+ chapters.push(BookItem::Chapter(Chapter {
+ name: err_code.to_string(),
+ content: format!("# Error code {}\n\n{}\n", err_code, content),
+ number: None,
+ sub_items: Vec::new(),
+ // We generate it into the `error_codes` folder.
+ path: Some(PathBuf::from(&format!("{}.html", err_code))),
+ source_path: None,
+ parent_names: Vec::new(),
+ }));
} else {
- write!(output_file, "<li>{}</li>", err_code)?;
+ introduction.push_str(&format!(" * {}\n", err_code));
}
}
- write!(output_file, "</ul>")?;
- formatter.footer(&mut output_file)
+
+ let mut config = Config::from_str(include_str!("book_config.toml"))?;
+ config.build.build_dir = output_path.join("error_codes").to_path_buf();
+ let mut book = MDBook::load_with_config_and_summary(
+ env!("CARGO_MANIFEST_DIR"),
+ config,
+ parse_summary("")?,
+ )?;
+ let chapter = Chapter {
+ name: "Rust error codes index".to_owned(),
+ content: introduction,
+ number: None,
+ sub_items: chapters,
+ // Very important: this file is named as `error-index.html` and not `index.html`!
+ path: Some(PathBuf::from("error-index.html")),
+ source_path: None,
+ parent_names: Vec::new(),
+ };
+ book.book.sections.push(BookItem::Chapter(chapter));
+ book.build()?;
+
+ // We can't put this content into another file, otherwise `mbdbook` will also put it into the
+ // output directory, making a duplicate.
+ fs::write(
+ output_path.join("error-index.html"),
+ r#"<!DOCTYPE html>
+<html>
+ <head>
+ <title>Rust error codes index - Error codes index</title>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+ <meta name="description" content="Book listing all Rust error codes">
+ <script src="error_codes/redirect.js"></script>
+ </head>
+ <body>
+ <div>If you are not automatically redirected to the error code index, please <a id="index-link" href="./error_codes/error-index.html">here</a>.
+ <script>document.getElementById("index-link").click()</script>
+ </body>
+</html>"#,
+ )?;
+
+ // No need for a 404 file, it's already handled by the server.
+ fs::remove_file(output_path.join("error_codes/404.html"))?;
+
+ Ok(())
}
fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
match format {
OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
- OutputFormat::HTML(h) => render_html(dst, h),
+ OutputFormat::HTML => render_html(dst),
OutputFormat::Markdown => render_markdown(dst),
}
}
let mut args = env::args().skip(1);
let format = args.next();
let dst = args.next();
- let resource_suffix = args.next().unwrap_or_else(String::new);
- let format = format
- .map(|a| OutputFormat::from(&a, &resource_suffix))
- .unwrap_or(OutputFormat::from("html", &resource_suffix));
+ let format = format.map(|a| OutputFormat::from(&a)).unwrap_or(OutputFormat::from("html"));
let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format {
- OutputFormat::HTML(..) => PathBuf::from("doc/error-index.html"),
+ OutputFormat::HTML => PathBuf::from("doc"),
OutputFormat::Markdown => PathBuf::from("doc/error-index.md"),
OutputFormat::Unknown(..) => PathBuf::from("<nul>"),
});
fn main() {
rustc_driver::init_env_logger("RUST_LOG");
let (format, dst) = parse_args();
- let result =
- rustc_span::create_default_session_globals_then(move || main_with_result(format, &dst));
+ let result = main_with_result(format, &dst);
if let Err(e) = result {
- panic!("{}", e.to_string());
+ panic!("{:?}", e);
}
}
--- /dev/null
+(function() {
+ if (window.location.hash) {
+ let code = window.location.hash.replace(/^#/, '');
+ // We have to make sure this pattern matches to avoid inadvertently creating an
+ // open redirect.
+ if (!/^E[0-9]+$/.test(code)) {
+ return;
+ }
+ if (window.location.pathname.indexOf("/error_codes/") !== -1) {
+ // We're not at the top level, so we don't prepend with "./error_codes/".
+ window.location = './' + code + '.html';
+ } else {
+ window.location = './error_codes/' + code + '.html';
+ }
+ }
+})()
/// Descriptions of rustc lint groups.
static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
("unused", "Lints that detect things being declared but not used, or excess syntax"),
+ ("let-underscore", "Lints that detect wildcard let bindings that are likely to be invalid"),
("rustdoc", "Rustdoc-specific lints"),
("rust-2018-idioms", "Lints to nudge you toward idiomatic features of Rust 2018"),
("nonstandard-style", "Violation of standard naming conventions"),
//! make gcc/clang pass `-flavor <flavor>` as the first two arguments in the linker invocation
//! and since Windows does not support symbolic links for files this wrapper is used in place of a
//! symbolic link. It execs `../rust-lld -flavor <flavor>` by propagating the flavor argument
-//! passed to the wrapper as the first two arguments. On Windows it spawns a `..\rust-lld.exe`
-//! child process.
+//! obtained from the wrapper's name as the first two arguments.
+//! On Windows it spawns a `..\rust-lld.exe` child process.
use std::fmt::Display;
use std::path::{Path, PathBuf};
rust_lld_path
}
+/// Extract LLD flavor name from the lld-wrapper executable name.
+fn get_lld_flavor(current_exe_path: &Path) -> Result<&'static str, String> {
+ let stem = current_exe_path.file_stem();
+ Ok(match stem.and_then(|s| s.to_str()) {
+ Some("ld.lld") => "gnu",
+ Some("ld64.lld") => "darwin",
+ Some("lld-link") => "link",
+ Some("wasm-ld") => "wasm",
+ _ => return Err(format!("{:?}", stem)),
+ })
+}
+
/// Returns the command for invoking rust-lld with the correct flavor.
-/// LLD only accepts the flavor argument at the first two arguments, so move it there.
+/// LLD only accepts the flavor argument at the first two arguments, so pass it there.
///
/// Exits on error.
fn get_rust_lld_command(current_exe_path: &Path) -> process::Command {
let rust_lld_path = get_rust_lld_path(current_exe_path);
let mut command = process::Command::new(rust_lld_path);
- let mut flavor = None;
- let args = env::args_os()
- .skip(1)
- .filter(|arg| match arg.to_str().and_then(|s| s.strip_prefix("-rustc-lld-flavor=")) {
- Some(suffix) => {
- flavor = Some(suffix.to_string());
- false
- }
- None => true,
- })
- .collect::<Vec<_>>();
+ let flavor =
+ get_lld_flavor(current_exe_path).unwrap_or_exit_with("executable has unexpected name");
command.arg("-flavor");
- command.arg(flavor.unwrap_or_exit_with("-rustc-lld-flavor=<flavor> is not passed"));
- command.args(args);
+ command.arg(flavor);
+ command.args(env::args_os().skip(1));
command
}
-Subproject commit 8c8b479be723fb103b0b1203faf9246a3f587250
+Subproject commit dba35d2be72f4b78343d1a0f0b4737306f310672
walk::filter_dirs(path)
// We exempt these as they require the placeholder
// for their operation
- || path.ends_with("compiler/rustc_passes/src/lib_features.rs")
+ || path.ends_with("compiler/rustc_attr/src/builtin.rs")
|| path.ends_with("src/tools/tidy/src/features/version.rs")
|| path.ends_with("src/tools/replace-version-placeholder")
},
"compiler/rustc_macros/src/diagnostics"
]
+[autolabel."A-query-system"]
+trigger_files = [
+ "compiler/rustc_query_system",
+ "compiler/rustc_query_impl",
+ "compiler/rustc_macros/src/query.rs"
+]
+
[notify-zulip."I-prioritize"]
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
topic = "#{number} {title}"