diff --git a/Cargo.lock b/Cargo.lock index f83678f0ca671..307cdde7e1c89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3519,6 +3519,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "rustc_target", "serde", "serde_json", "termcolor", diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b662513e70fbe..b798862583952 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -181,16 +181,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { 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) } } diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl new file mode 100644 index 0000000000000..00067a1bf6ad7 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -0,0 +1,272 @@ +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` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 8f47be25db917..464821f55b5cc 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -46,6 +46,7 @@ fluent_messages! { 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", diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 36805aa874fe7..4d207fd17fb2d 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -15,13 +15,14 @@ rustc_macros = { path = "../rustc_macros" } 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" ] } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 95ae9765a4816..a052aaee04756 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -10,6 +10,7 @@ use rustc_lint_defs::{Applicability, LintExpectationId}; 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}; @@ -144,6 +145,12 @@ impl IntoDiagnosticArg for usize { } } +impl IntoDiagnosticArg for PanicStrategy { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string())) + } +} + impl<'source> Into> for DiagnosticArgValue<'source> { fn into(self) -> FluentValue<'source> { match self { diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 708d0b1fd8a30..edffec8ab55c4 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,5 +1,9 @@ //! 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}; @@ -746,15 +750,10 @@ impl<'a> CrateLoader<'a> { // 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); @@ -774,10 +773,7 @@ impl<'a> CrateLoader<'a> { 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; }; @@ -785,18 +781,14 @@ impl<'a> CrateLoader<'a> { // 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(), @@ -832,11 +824,10 @@ impl<'a> CrateLoader<'a> { 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()), } @@ -855,10 +846,7 @@ impl<'a> CrateLoader<'a> { 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); } @@ -882,14 +870,11 @@ impl<'a> CrateLoader<'a> { 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(), + }); } } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index b765c34f8e364..9ad0099ad251b 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -52,6 +52,10 @@ //! 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; @@ -136,11 +140,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { 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(); } @@ -224,12 +224,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { 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 }); } } } @@ -253,17 +248,7 @@ fn add_library( // 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 => { @@ -360,11 +345,7 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { 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, @@ -384,13 +365,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { // 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 @@ -407,28 +385,19 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { } 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, + }); } } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs new file mode 100644 index 0000000000000..18d0248333a51 --- /dev/null +++ b/compiler/rustc_metadata/src/errors.rs @@ -0,0 +1,672 @@ +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, +} + +#[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, +} + +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, +} + +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, +} diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index e6072901aaa43..f360a586476e7 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -1,3 +1,6 @@ +use crate::errors::{ + FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError, +}; use crate::{encode_metadata, EncodedMetadata}; use rustc_data_structures::temp_dir::MaybeTempDir; @@ -23,8 +26,8 @@ pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &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 @@ -65,7 +68,7 @@ pub fn encode_and_write_metadata( 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); @@ -73,12 +76,8 @@ pub fn encode_and_write_metadata( // 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 => { @@ -93,8 +92,8 @@ pub fn encode_and_write_metadata( // 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 @@ -109,8 +108,8 @@ pub fn encode_and_write_metadata( // 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; diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6440f3e390cf1..fae5b664f4e43 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -16,6 +16,8 @@ #![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; @@ -34,6 +36,7 @@ mod native_libs; mod rmeta; pub mod creader; +pub mod errors; pub mod fs; pub mod locator; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 2c1c84b0be26a..5edad819e7e3c 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -213,6 +213,13 @@ //! 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}; @@ -220,18 +227,19 @@ use rustc_data_structures::memmap::Mmap; 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}; @@ -288,6 +296,16 @@ impl fmt::Display for CrateFlavor { } } +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, @@ -938,41 +956,20 @@ impl fmt::Display for MetadataError<'_> { 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()`. @@ -1000,223 +997,142 @@ impl CrateError { s }) .collect::(); - 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(""); - 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("".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 }); + } + } } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 8bafe203748f3..87b5e750f1cb1 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,7 +1,6 @@ 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}; @@ -12,6 +11,18 @@ use rustc_session::Session; 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 { let mut collector = Collector { tcx, libs: Vec::new() }; for id in tcx.hir().items() { @@ -66,32 +77,26 @@ impl<'tcx> Collector<'tcx> { 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; }; @@ -101,25 +106,13 @@ impl<'tcx> Collector<'tcx> { "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, @@ -132,13 +125,7 @@ impl<'tcx> Collector<'tcx> { 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; } }; @@ -146,32 +133,26 @@ impl<'tcx> Collector<'tcx> { } 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 { @@ -187,33 +168,26 @@ impl<'tcx> Collector<'tcx> { } 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; } @@ -222,11 +196,10 @@ impl<'tcx> Collector<'tcx> { "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; } }; @@ -243,9 +216,7 @@ impl<'tcx> Collector<'tcx> { 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() }); } } } @@ -257,11 +228,7 @@ impl<'tcx> Collector<'tcx> { 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; } }; @@ -279,10 +246,7 @@ impl<'tcx> Collector<'tcx> { } let assign_modifier = |dst: &mut Option| { 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); } @@ -292,11 +256,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(bundle) } ("bundle", _) => { - sess.span_err( - span, - "linking modifier `bundle` is only compatible with \ - `static` linking kind", - ); + sess.emit_err(BundleNeedsStatic { span }); } ("verbatim", _) => { @@ -308,11 +268,7 @@ impl<'tcx> Collector<'tcx> { 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 })) @@ -321,21 +277,11 @@ impl<'tcx> Collector<'tcx> { 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 }); } } } @@ -343,36 +289,23 @@ impl<'tcx> Collector<'tcx> { 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() @@ -401,10 +334,7 @@ impl<'tcx> Collector<'tcx> { .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 }); } } @@ -430,7 +360,7 @@ impl<'tcx> Collector<'tcx> { 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 @@ -439,23 +369,11 @@ impl<'tcx> Collector<'tcx> { .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 }); } } } @@ -480,10 +398,13 @@ impl<'tcx> Collector<'tcx> { // 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 { @@ -562,20 +483,14 @@ impl<'tcx> Collector<'tcx> { 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 }); } } }; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3482d9f04514e..8f55fb59f0bf8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,3 +1,4 @@ +use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile}; use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::TableBuilder; use crate::rmeta::*; @@ -2269,7 +2270,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { 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. @@ -2314,10 +2315,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { // 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(); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 8f7877392483f..6217bffb8f76c 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -291,6 +291,9 @@ impl<'hir> Map<'hir> { 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 { if id.local_id == ItemLocalId::from_u32(0) { Some(self.tcx.hir_owner_parent(id.owner)) diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 85a0d4e449906..2710606f91436 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -409,8 +409,15 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { }) { 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) diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs index ded0888c33e15..e22675e9d5f4e 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs @@ -159,8 +159,8 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { 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); diff --git a/library/core/src/any.rs b/library/core/src/any.rs index e54f6c912d594..1a379ecc11c01 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -796,7 +796,7 @@ pub trait Provider { /// impl Provider for SomeConcreteType { /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { /// demand.provide_ref::(&self.field) - /// .provide_value::(|| self.num_field); + /// .provide_value::(self.num_field); /// } /// } /// ``` @@ -881,28 +881,55 @@ impl<'a> Demand<'a> { /// /// # 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::(self.field); + /// } + /// } + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn provide_value(&mut self, value: T) -> &mut Self + where + T: 'static, + { + self.provide::>(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::(|| self.field.clone()); + /// demand.provide_value_with::(|| self.field.clone()); /// } /// } /// ``` #[unstable(feature = "provide_any", issue = "96024")] - pub fn provide_value(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self + pub fn provide_value_with(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self where T: 'static, { self.provide_with::>(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 @@ -910,7 +937,8 @@ impl<'a> Demand<'a> { /// 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 } /// @@ -925,6 +953,40 @@ impl<'a> Demand<'a> { self.provide::>>(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::(|| { + /// if today_is_a_weekday() { + /// &self.business + /// } else { + /// &self.party + /// } + /// }); + /// } + /// } + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn provide_ref_with( + &mut self, + fulfil: impl FnOnce() -> &'a T, + ) -> &mut Self { + self.provide_with::>>(fulfil) + } + /// Provide a value with the given `Type` tag. fn provide(&mut self, value: I::Reified) -> &mut Self where @@ -946,6 +1008,156 @@ impl<'a> Demand<'a> { } 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); + /// + /// impl Provider for Parent { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// if let Some(v) = self.0 { + /// demand.provide_value::(v); + /// } + /// } + /// } + /// + /// struct Child { + /// parent: Parent, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option { + /// 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::() { + /// if let Some(v) = self.an_expensive_computation() { + /// demand.provide_value::(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::()); + /// } + /// } + /// + /// let parent = Parent(Some(42)); + /// let child = Child { parent }; + /// assert_eq!(Some(42), std::any::request_value::(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent }; + /// assert_eq!(Some(99), std::any::request_value::(&child)); + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn would_be_satisfied_by_value_of(&self) -> bool + where + T: 'static, + { + self.would_be_satisfied_by::>() + } + + /// 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); + /// + /// impl Provider for Parent { + /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + /// if let Some(v) = &self.0 { + /// demand.provide_ref::(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::() { + /// if let Some(v) = self.an_expensive_computation() { + /// demand.provide_ref::(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::()); + /// } + /// } + /// + /// let parent = Parent(Some("parent".into())); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("parent"), std::any::request_ref::(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("child"), std::any::request_ref::(&child)); + /// ``` + #[unstable(feature = "provide_any", issue = "96024")] + pub fn would_be_satisfied_by_ref_of(&self) -> bool + where + T: ?Sized + 'static, + { + self.would_be_satisfied_by::>>() + } + + fn would_be_satisfied_by(&self) -> bool + where + I: tags::Type<'a>, + { + matches!(self.0.downcast::(), Some(TaggedOption(None))) + } } #[unstable(feature = "provide_any", issue = "96024")] @@ -1050,6 +1262,21 @@ impl<'a> dyn Erased<'a> + 'a { /// Returns some reference to the dynamic value if it is tagged with `I`, /// or `None` otherwise. #[inline] + fn downcast(&self) -> Option<&TaggedOption<'a, I>> + where + I: tags::Type<'a>, + { + if self.tag_id() == TypeId::of::() { + // SAFETY: Just checked whether we're pointing to an I. + Some(unsafe { &*(self as *const Self).cast::>() }) + } else { + None + } + } + + /// Returns some mutable reference to the dynamic value if it is tagged with `I`, + /// or `None` otherwise. + #[inline] fn downcast_mut(&mut self) -> Option<&mut TaggedOption<'a, I>> where I: tags::Type<'a>, diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index 8ed0c88808fe2..9538b81394957 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -142,7 +142,7 @@ impl Provider for SomeConcreteType { demand .provide_ref::(&self.some_string) .provide_ref::(&self.some_string) - .provide_value::(|| "bye".to_owned()); + .provide_value_with::(|| "bye".to_owned()); } } diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index a456947534a45..c6aa7c77dbc41 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -1,16 +1,25 @@ //! Owned and borrowed Unix-like file descriptors. +//! +//! This module is supported on Unix platforms and WASI, which both use a +//! similar file descriptor system for referencing OS resources. #![stable(feature = "io_safety", since = "1.63.0")] #![deny(unsafe_op_in_unsafe_fn)] // `RawFd`, `AsRawFd`, etc. -pub mod raw; +mod raw; // `OwnedFd`, `AsFd`, etc. -pub mod owned; +mod owned; // Implementations for `AsRawFd` etc. for network types. mod net; #[cfg(test)] mod tests; + +// Export the types and traits for the public API. +#[unstable(feature = "os_fd", issue = "98699")] +pub use owned::*; +#[unstable(feature = "os_fd", issue = "98699")] +pub use raw::*; diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index a463bc41db7aa..3a1b04a83fa79 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -205,10 +205,7 @@ pub trait AsFd { /// ```rust,no_run /// use std::fs::File; /// # use std::io; - /// # #[cfg(target_os = "wasi")] - /// # use std::os::wasi::io::{AsFd, BorrowedFd}; - /// # #[cfg(unix)] - /// # use std::os::unix::io::{AsFd, BorrowedFd}; + /// # use std::os::fd::{AsFd, BorrowedFd}; /// /// let mut f = File::open("foo.txt")?; /// # #[cfg(any(unix, target_os = "wasi"))] diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 1b3d110426feb..42a9effcf92ab 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -42,10 +42,7 @@ pub trait AsRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{AsRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{AsRawFd, RawFd}; + /// use std::os::fd::{AsRawFd, RawFd}; /// /// let mut f = File::open("foo.txt")?; /// // Note that `raw_fd` is only valid as long as `f` exists. @@ -83,10 +80,7 @@ pub trait FromRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd}; + /// use std::os::fd::{FromRawFd, IntoRawFd, RawFd}; /// /// let f = File::open("foo.txt")?; /// # #[cfg(any(unix, target_os = "wasi"))] @@ -121,10 +115,7 @@ pub trait IntoRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{IntoRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{IntoRawFd, RawFd}; + /// use std::os::fd::{IntoRawFd, RawFd}; /// /// let f = File::open("foo.txt")?; /// #[cfg(any(unix, target_os = "wasi"))] diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 18c64b5100764..f62f5af774f0e 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -147,7 +147,7 @@ pub mod solid; pub mod vxworks; #[cfg(any(unix, target_os = "wasi", doc))] -mod fd; +pub mod fd; #[cfg(any(target_os = "linux", target_os = "android", doc))] mod net; diff --git a/library/std/src/os/unix/io/fd.rs b/library/std/src/os/unix/io/fd.rs deleted file mode 100644 index d4cb696459b7e..0000000000000 --- a/library/std/src/os/unix/io/fd.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Owned and borrowed file descriptors. - -// Tests for this module -#[cfg(test)] -mod tests; - -#[stable(feature = "io_safety", since = "1.63.0")] -pub use crate::os::fd::owned::*; diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 3ab5606f8897d..25b5dbff14f30 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -77,10 +77,9 @@ #![stable(feature = "rust1", since = "1.0.0")] -mod fd; -mod raw; - -#[stable(feature = "io_safety", since = "1.63.0")] -pub use fd::*; #[stable(feature = "rust1", since = "1.0.0")] -pub use raw::*; +pub use crate::os::fd::*; + +// Tests for this module +#[cfg(test)] +mod tests; diff --git a/library/std/src/os/unix/io/raw.rs b/library/std/src/os/unix/io/raw.rs deleted file mode 100644 index a4d2ba797d9c4..0000000000000 --- a/library/std/src/os/unix/io/raw.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Unix-specific extensions to general I/O primitives. - -#![stable(feature = "rust1", since = "1.0.0")] - -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::os::fd::raw::*; diff --git a/library/std/src/os/unix/io/fd/tests.rs b/library/std/src/os/unix/io/tests.rs similarity index 100% rename from library/std/src/os/unix/io/fd/tests.rs rename to library/std/src/os/unix/io/tests.rs diff --git a/library/std/src/os/wasi/io/mod.rs b/library/std/src/os/wasi/io/mod.rs index 6c884e2eaf471..d528590d75b9a 100644 --- a/library/std/src/os/wasi/io/mod.rs +++ b/library/std/src/os/wasi/io/mod.rs @@ -1,12 +1,6 @@ //! WASI-specific extensions to general I/O primitives. -#![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "wasi_ext", issue = "71213")] -mod fd; -mod raw; - -#[unstable(feature = "wasi_ext", issue = "71213")] -pub use fd::*; #[unstable(feature = "wasi_ext", issue = "71213")] -pub use raw::*; +pub use crate::os::fd::*; diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index c2a1613f288c5..53a510f080ece 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -79,7 +79,7 @@ the following commands: ```sh rustup target add x86_64-fuchsia -rustup target add aarch_64-fuchsia +rustup target add aarch64-fuchsia ``` After installing our Fuchsia targets, we can now compile a Rust binary that targets @@ -125,13 +125,20 @@ during compilation: [target.x86_64-fuchsia] rustflags = [ - "-Lnative", "/arch/x64/sysroot/lib", - "-Lnative", "/arch/x64/lib" + "-Lnative=/arch/x64/lib", + "-Lnative=/arch/x64/sysroot/lib" ] ``` *Note: Make sure to fill out `` with the path to the downloaded [Fuchsia SDK].* +These options configure the following: + +* `-Lnative=${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from + the SDK +* `-Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel + libraries from the SDK + In total, our new project will look like: **Current directory structure** @@ -368,6 +375,7 @@ language called CML. The Fuchsia devsite contains an [overview of CML] and a } ``` +**Current directory structure** ```txt hello_fuchsia/ ┗━ pkg/ @@ -386,6 +394,9 @@ ${SDK_PATH}/tools/${ARCH}/cmc compile \ -o pkg/meta/hello_fuchsia.cm ``` +*Note: `--includepath` tells the compiler where to look for `include`s from our CML. +In our case, we're only using `syslog/client.shard.cml`.* + **Current directory structure** ```txt hello_fuchsia/ @@ -397,19 +408,16 @@ hello_fuchsia/ ┗━ hello_fuchsia.cml ``` -*Note: `--includepath` tells the compiler where to look for `include`s from our CML. -In our case, we're only using `syslog/client.shard.cml`.* - ### Building a Fuchsia package Next, we'll build a package manifest as defined by our manifest: ```sh ${SDK_PATH}/tools/${ARCH}/pm \ - -o hello_fuchsia_manifest \ + -o pkg/hello_fuchsia_manifest \ -m pkg/hello_fuchsia.manifest \ build \ - -output-package-manifest hello_fuchsia_package_manifest + -output-package-manifest pkg/hello_fuchsia_package_manifest ``` This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can @@ -469,15 +477,15 @@ We can publish our new package to that repository with: ```sh ${SDK_PATH}/tools/${ARCH}/pm publish \ - -repo repo \ - -lp -f <(echo "hello_fuchsia_package_manifest") + -repo pkg/repo \ + -lp -f <(echo "pkg/hello_fuchsia_package_manifest") ``` Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using: ```sh ${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \ - repo \ + pkg/repo \ -r hello-fuchsia ``` diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6f49f00f93e5e..be10a5c101f7f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -349,8 +349,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( let where_preds = comma_sep(where_predicates, false); let clause = if f.alternate() { if ending == Ending::Newline { - // add a space so stripping
tags and breaking spaces still renders properly - format!(" where{where_preds}, ") + format!(" where{where_preds},") } else { format!(" where{where_preds}") } @@ -364,20 +363,16 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( if ending == Ending::Newline { let mut clause = " ".repeat(indent.saturating_sub(1)); - // add a space so stripping
tags and breaking spaces still renders properly - write!( - clause, - " where{where_preds}, " - )?; + write!(clause, "where{where_preds},")?; clause } else { // insert a
tag after a single space but before multiple spaces at the start if indent == 0 { - format!("
where{where_preds}") + format!("
where{where_preds}") } else { let mut clause = br_with_padding; clause.truncate(clause.len() - 5 * " ".len()); - write!(clause, " where{where_preds}")?; + write!(clause, "where{where_preds}")?; clause } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index eff34047e3c8f..7577c71962388 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1737,8 +1737,8 @@ pub(crate) fn render_impl_summary( // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], ) { - let id = - cx.derive_id(get_id_for_impl(&i.inner_impl().for_, i.inner_impl().trait_.as_ref(), cx)); + let inner_impl = i.inner_impl(); + let id = cx.derive_id(get_id_for_impl(&inner_impl.for_, inner_impl.trait_.as_ref(), cx)); let aliases = if aliases.is_empty() { String::new() } else { @@ -1750,9 +1750,9 @@ pub(crate) fn render_impl_summary( write!(w, "

"); if let Some(use_absolute) = use_absolute { - write!(w, "{}", i.inner_impl().print(use_absolute, cx)); + write!(w, "{}", inner_impl.print(use_absolute, cx)); if show_def_docs { - for it in &i.inner_impl().items { + for it in &inner_impl.items { if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { w.write_str(" "); assoc_type( @@ -1770,11 +1770,11 @@ pub(crate) fn render_impl_summary( } } } else { - write!(w, "{}", i.inner_impl().print(false, cx)); + write!(w, "{}", inner_impl.print(false, cx)); } write!(w, "

"); - let is_trait = i.inner_impl().trait_.is_some(); + let is_trait = inner_impl.trait_.is_some(); if is_trait { if let Some(portability) = portability(&i.impl_item, Some(parent)) { write!(w, "{}", portability); diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 87f91be3ac82c..7f3172878bfb5 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -143,3 +143,30 @@ pub struct LongItemInfo2; /// Some docs. #[doc(cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))] impl SimpleTrait for LongItemInfo2 {} + +pub struct WhereWhitespace; + +impl WhereWhitespace { + pub fn new(f: F) -> Self + where + F: FnMut() -> i32, + {} +} + +impl Whitespace<&K> for WhereWhitespace +where + K: std::fmt::Debug, +{ + type Output = WhereWhitespace; + fn index(&self, _key: &K) -> &Self::Output { + self + } +} + +pub trait Whitespace +where + Idx: ?Sized, +{ + type Output; + fn index(&self, index: Idx) -> &Self::Output; +} diff --git a/src/test/rustdoc-gui/where-whitespace.goml b/src/test/rustdoc-gui/where-whitespace.goml new file mode 100644 index 0000000000000..1a3ff1f491cbb --- /dev/null +++ b/src/test/rustdoc-gui/where-whitespace.goml @@ -0,0 +1,27 @@ +// This test ensures that the where conditions are correctly displayed. +goto: file://|DOC_PATH|/lib2/trait.Whitespace.html +show-text: true +// First, we check in the trait definition if the where clause is "on its own" (not on the same +// line than "pub trait Whitespace"). +compare-elements-position-false: (".item-decl code", ".where.fmt-newline", ("y")) +// And that the code following it isn't on the same line either. +compare-elements-position-false: (".item-decl .fnname", ".where.fmt-newline", ("y")) + +goto: file://|DOC_PATH|/lib2/struct.WhereWhitespace.html +// We make the screen a bit wider to ensure that the trait impl is on one line. +size: (915, 915) + +compare-elements-position-false: ("#method\.new .fnname", "#method\.new .where.fmt-newline", ("y")) +// We ensure that both the trait name and the struct name are on the same line in +// "impl Whitespace<&K> for WhereWhitespace". +compare-elements-position: ( + "#trait-implementations-list .impl h3 .trait", + "#trait-implementations-list .impl h3 .struct", + ("y"), +) +// And we now check that the where condition isn't on the same line. +compare-elements-position-false: ( + "#trait-implementations-list .impl h3 .trait", + "#trait-implementations-list .impl h3 .where.fmt-newline", + ("y"), +) diff --git a/src/test/rustdoc-js-std/asrawfd.js b/src/test/rustdoc-js-std/asrawfd.js index fd228a59099e9..369a34f9c6eb7 100644 --- a/src/test/rustdoc-js-std/asrawfd.js +++ b/src/test/rustdoc-js-std/asrawfd.js @@ -6,9 +6,9 @@ const EXPECTED = { 'others': [ // Reproduction test for https://github.com/rust-lang/rust/issues/78724 // Validate that type alias methods get the correct path. - { 'path': 'std::os::unix::io::AsRawFd', 'name': 'as_raw_fd' }, - { 'path': 'std::os::wasi::io::AsRawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, { 'path': 'std::os::linux::process::PidFd', 'name': 'as_raw_fd' }, - { 'path': 'std::os::unix::io::RawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::RawFd', 'name': 'as_raw_fd' }, ], }; diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs index 352a8e646bb49..87d2f29e26055 100644 --- a/src/test/rustdoc/const-generics/const-generics-docs.rs +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -31,12 +31,12 @@ impl Trait<{1 + 2}> for u8 {} impl Trait for [u8; N] {} // @has foo/struct.Foo.html '//pre[@class="rust struct"]' \ -// 'pub struct Foo where u8: Trait' +// 'pub struct Foowhere u8: Trait' pub struct Foo where u8: Trait; // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar(_)' pub struct Bar([T; N]); -// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl Foo where u8: Trait' +// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl Foowhere u8: Trait' impl Foo where u8: Trait { // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize' pub const FOO_ASSOC: usize = M + 13; @@ -50,14 +50,14 @@ impl Foo where u8: Trait { // @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl Bar' impl Bar { // @has - '//*[@id="method.hey"]' \ - // 'pub fn hey(&self) -> Foo where u8: Trait' + // 'pub fn hey(&self) -> Foowhere u8: Trait' pub fn hey(&self) -> Foo where u8: Trait { Foo } } // @has foo/fn.test.html '//pre[@class="rust fn"]' \ -// 'pub fn test() -> impl Trait where u8: Trait' +// 'pub fn test() -> impl Traitwhere u8: Trait' pub fn test() -> impl Trait where u8: Trait { 2u8 } diff --git a/src/test/rustdoc/generic-associated-types/gats.rs b/src/test/rustdoc/generic-associated-types/gats.rs index ae981b9499a67..2b9d4952d04ee 100644 --- a/src/test/rustdoc/generic-associated-types/gats.rs +++ b/src/test/rustdoc/generic-associated-types/gats.rs @@ -3,7 +3,7 @@ // @has foo/trait.LendingIterator.html pub trait LendingIterator { - // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a" + // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a" type Item<'a> where Self: 'a; // @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]' \ @@ -24,7 +24,7 @@ impl LendingIterator for () { pub struct Infinite(T); // @has foo/trait.LendingIterator.html -// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T" +// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a = &'a T" impl LendingIterator for Infinite { type Item<'a> where Self: 'a = &'a T; diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs index b75b8de52f9cb..59b5b6e5797cc 100644 --- a/src/test/rustdoc/higher-ranked-trait-bounds.rs +++ b/src/test/rustdoc/higher-ranked-trait-bounds.rs @@ -4,7 +4,7 @@ pub trait Trait<'x> {} // @has foo/fn.test1.html -// @has - '//pre' "pub fn test1() where for<'a> &'a T: Iterator," +// @has - '//pre' "pub fn test1()where for<'a> &'a T: Iterator," pub fn test1() where for<'a> &'a T: Iterator, @@ -12,7 +12,7 @@ where } // @has foo/fn.test2.html -// @has - '//pre' "pub fn test2() where for<'a, 'b> &'a T: Trait<'b>," +// @has - '//pre' "pub fn test2()where for<'a, 'b> &'a T: Trait<'b>," pub fn test2() where for<'a, 'b> &'a T: Trait<'b>, @@ -20,7 +20,7 @@ where } // @has foo/fn.test3.html -// @has - '//pre' "pub fn test3() where F: for<'a, 'b> Fn(&'a u8, &'b u8)," +// @has - '//pre' "pub fn test3()where F: for<'a, 'b> Fn(&'a u8, &'b u8)," pub fn test3() where F: for<'a, 'b> Fn(&'a u8, &'b u8), @@ -38,7 +38,7 @@ pub struct Foo<'a> { // @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>" impl<'a> Foo<'a> { - // @has - '//h4[@class="code-header"]' "pub fn bar() where T: Trait<'a>," + // @has - '//h4[@class="code-header"]' "pub fn bar()where T: Trait<'a>," pub fn bar() where T: Trait<'a>, diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs index 249158c1a1f89..b1481e1f27978 100644 --- a/src/test/rustdoc/impl-parts.rs +++ b/src/test/rustdoc/impl-parts.rs @@ -6,7 +6,7 @@ pub auto trait AnAutoTrait {} pub struct Foo { field: T } // @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl !AnAutoTrait for Foo where T: Sync," +// "impl !AnAutoTrait for Foowhere T: Sync," // @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ -// "impl !AnAutoTrait for Foo where T: Sync," +// "impl !AnAutoTrait for Foowhere T: Sync," impl !AnAutoTrait for Foo where T: Sync {} diff --git a/src/test/rustdoc/issue-20727-4.rs b/src/test/rustdoc/issue-20727-4.rs index 84fc6f94a265a..643f938759093 100644 --- a/src/test/rustdoc/issue-20727-4.rs +++ b/src/test/rustdoc/issue-20727-4.rs @@ -25,7 +25,7 @@ pub trait IndexMut: Index { pub mod reexport { // @has issue_20727_4/reexport/trait.Index.html - // @has - '//*[@class="rust trait"]' 'trait Index where Idx: ?Sized, {' + // @has - '//*[@class="rust trait"]' 'trait Indexwhere Idx: ?Sized,{' // @has - '//*[@class="rust trait"]' 'type Output: ?Sized' // @has - '//*[@class="rust trait"]' \ // 'fn index(&self, index: Idx) -> &Self::Output' @@ -33,7 +33,7 @@ pub mod reexport { // @has issue_20727_4/reexport/trait.IndexMut.html // @has - '//*[@class="rust trait"]' \ - // 'trait IndexMut: Index where Idx: ?Sized, {' + // 'trait IndexMut: Indexwhere Idx: ?Sized,{' // @has - '//*[@class="rust trait"]' \ // 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;' pub use issue_20727::IndexMut; diff --git a/src/test/rustdoc/issue-21801.rs b/src/test/rustdoc/issue-21801.rs index 2a586b6ff6cdc..29d2ec64c206d 100644 --- a/src/test/rustdoc/issue-21801.rs +++ b/src/test/rustdoc/issue-21801.rs @@ -5,5 +5,5 @@ extern crate issue_21801; // @has issue_21801/struct.Foo.html // @has - '//*[@id="method.new"]' \ -// 'fn new(f: F) -> Foo where F: FnMut() -> i32' +// 'fn new(f: F) -> Foowhere F: FnMut() -> i32' pub use issue_21801::Foo; diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs index 635c3175f8138..134821e1ef3ea 100644 --- a/src/test/rustdoc/issue-29503.rs +++ b/src/test/rustdoc/issue-29503.rs @@ -5,7 +5,7 @@ pub trait MyTrait { fn my_string(&self) -> String; } -// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl MyTrait for T where T: Debug" +// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl MyTrait for Twhere T: Debug" impl MyTrait for T where T: fmt::Debug, diff --git a/src/test/rustdoc/issue-34928.rs b/src/test/rustdoc/issue-34928.rs index 4184086f622ab..91b67757453d2 100644 --- a/src/test/rustdoc/issue-34928.rs +++ b/src/test/rustdoc/issue-34928.rs @@ -2,5 +2,5 @@ pub trait Bar {} -// @has foo/struct.Foo.html '//pre' 'pub struct Foo(pub T) where T: Bar;' +// @has foo/struct.Foo.html '//pre' 'pub struct Foo(pub T)where T: Bar;' pub struct Foo(pub T) where T: Bar; diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs index d88c29217023a..43fb705f58994 100644 --- a/src/test/rustdoc/issue-50159.rs +++ b/src/test/rustdoc/issue-50159.rs @@ -11,8 +11,8 @@ impl Signal2 for B where B: Signal { } // @has issue_50159/struct.Switch.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Switch where ::Item: Send' -// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Switch where ::Item: Sync' +// @has - '//h3[@class="code-header in-band"]' 'impl Send for Switchwhere ::Item: Send' +// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Switchwhere ::Item: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Switch { diff --git a/src/test/rustdoc/issue-51236.rs b/src/test/rustdoc/issue-51236.rs index ee11ccc681163..aa5890a84514f 100644 --- a/src/test/rustdoc/issue-51236.rs +++ b/src/test/rustdoc/issue-51236.rs @@ -8,7 +8,7 @@ pub mod traits { // @has issue_51236/struct.Owned.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for Owned where >::Reader: Send" +// "impl Send for Ownedwhere >::Reader: Send" pub struct Owned where T: for<'a> ::traits::Owned<'a> { marker: PhantomData<>::Reader>, } diff --git a/src/test/rustdoc/issue-54705.rs b/src/test/rustdoc/issue-54705.rs index bedaf5c4ddc36..ce0f85d25da56 100644 --- a/src/test/rustdoc/issue-54705.rs +++ b/src/test/rustdoc/issue-54705.rs @@ -1,13 +1,11 @@ pub trait ScopeHandle<'scope> {} - - // @has issue_54705/struct.ScopeFutureContents.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'scope, S> Send for ScopeFutureContents<'scope, S> where S: Sync" +// "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync" // // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S> where S: Sync" +// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync" pub struct ScopeFutureContents<'scope, S> where S: ScopeHandle<'scope>, { diff --git a/src/test/rustdoc/issue-98697.rs b/src/test/rustdoc/issue-98697.rs index 83e08094c0953..a8841f137fecf 100644 --- a/src/test/rustdoc/issue-98697.rs +++ b/src/test/rustdoc/issue-98697.rs @@ -8,7 +8,7 @@ extern crate issue_98697_reexport_with_anonymous_lifetime; -// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro() where F: Fn(&str)' +// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro()where F: Fn(&str)' // @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<' pub use issue_98697_reexport_with_anonymous_lifetime::repro; diff --git a/src/test/rustdoc/primitive-slice-auto-trait.rs b/src/test/rustdoc/primitive-slice-auto-trait.rs index b3f511bc1f153..7f8f74ff457a5 100644 --- a/src/test/rustdoc/primitive-slice-auto-trait.rs +++ b/src/test/rustdoc/primitive-slice-auto-trait.rs @@ -7,8 +7,8 @@ // @has - '//span[@class="in-band"]' 'Primitive Type slice' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' -// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for [T] where T: Send' -// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Sync for [T] where T: Sync' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for [T]where T: Send' +// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Sync for [T]where T: Sync' #[doc(primitive = "slice")] /// this is a test! mod slice_prim {} diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs index 54c54fdbf68a8..19138fd1aceb2 100644 --- a/src/test/rustdoc/synthetic_auto/basic.rs +++ b/src/test/rustdoc/synthetic_auto/basic.rs @@ -1,6 +1,6 @@ // @has basic/struct.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foo where T: Send' -// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Foo where T: Sync' +// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foowhere T: Send' +// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Foowhere T: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Foo { diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index f9017b90caee7..39f78983da2b0 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -21,7 +21,7 @@ mod foo { // @has complex/struct.NotOuter.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ +// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, >::MyItem: Copy, 'a: 'static" pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter}; diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs index ee1393f9729c1..0c94850e78608 100644 --- a/src/test/rustdoc/synthetic_auto/lifetimes.rs +++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs @@ -10,10 +10,10 @@ where // @has lifetimes/struct.Foo.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'c, K> Send for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" +// "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'c, K> Sync for Foo<'c, K> where K: Sync" +// "impl<'c, K> Sync for Foo<'c, K>where K: Sync" pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, } diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index 49bad162211b7..35047e3e8c071 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -1,6 +1,6 @@ // @has manual/struct.Foo.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// 'impl Sync for Foo where T: Sync' +// 'impl Sync for Foowhere T: Sync' // // @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // 'impl Send for Foo' diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs index 69edbee619e31..09587bcc30f13 100644 --- a/src/test/rustdoc/synthetic_auto/nested.rs +++ b/src/test/rustdoc/synthetic_auto/nested.rs @@ -10,10 +10,10 @@ where // @has nested/struct.Foo.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// 'impl Send for Foo where T: Copy' +// 'impl Send for Foowhere T: Copy' // // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// 'impl Sync for Foo where T: Sync' +// 'impl Sync for Foowhere T: Sync' pub struct Foo { inner_field: Inner, } diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index 16ab876e829ef..41375decc8a4a 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -10,7 +10,7 @@ where // @has no_redundancy/struct.Outer.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for Outer where T: Send + Copy" +// "impl Send for Outerwhere T: Send + Copy" pub struct Outer { inner_field: Inner, } diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs index 8b020582563f3..e80b1b1dc9bcf 100644 --- a/src/test/rustdoc/synthetic_auto/project.rs +++ b/src/test/rustdoc/synthetic_auto/project.rs @@ -24,10 +24,10 @@ where // @has project/struct.Foo.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'c, K> Send for Foo<'c, K> where K: MyTrait, 'c: 'static" +// "impl<'c, K> Send for Foo<'c, K>where K: MyTrait, 'c: 'static" // // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl<'c, K> Sync for Foo<'c, K> where K: MyTrait, ::MyItem: OtherTrait, \ +// "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, ::MyItem: OtherTrait, \ // 'c: 'static," pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs index ccef901b18da3..d15a8de7d2fe1 100644 --- a/src/test/rustdoc/synthetic_auto/self-referential.rs +++ b/src/test/rustdoc/synthetic_auto/self-referential.rs @@ -24,6 +24,6 @@ impl Pattern for Wrapper { // @has self_referential/struct.WriteAndThen.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for WriteAndThen where ::Value: Send" +// "impl Send for WriteAndThenwhere ::Value: Send" pub struct WriteAndThen(pub P1::Value,pub > as Pattern>::Value) where P1: Pattern; diff --git a/src/test/rustdoc/synthetic_auto/static-region.rs b/src/test/rustdoc/synthetic_auto/static-region.rs index 36e985144b0e0..08e9567313e22 100644 --- a/src/test/rustdoc/synthetic_auto/static-region.rs +++ b/src/test/rustdoc/synthetic_auto/static-region.rs @@ -4,7 +4,7 @@ pub trait OwnedTrait<'a> { // @has static_region/struct.Owned.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for Owned where >::Reader: Send" +// "impl Send for Ownedwhere >::Reader: Send" pub struct Owned where T: OwnedTrait<'static> { marker: >::Reader, } diff --git a/src/test/rustdoc/where-clause-order.rs b/src/test/rustdoc/where-clause-order.rs index 3150a8ea05f41..b8502e10a48c4 100644 --- a/src/test/rustdoc/where-clause-order.rs +++ b/src/test/rustdoc/where-clause-order.rs @@ -7,7 +7,7 @@ where } // @has 'foo/trait.SomeTrait.html' -// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E) where A: PartialOrd + PartialEq, B: PartialOrd + PartialEq, C: PartialOrd + PartialEq, D: PartialOrd + PartialEq, E: PartialOrd + PartialEq + ?Sized, " +// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd + PartialEq, B: PartialOrd + PartialEq, C: PartialOrd + PartialEq, D: PartialOrd + PartialEq, E: PartialOrd + PartialEq + ?Sized, " impl SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E) where A: PartialOrd + PartialEq, diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs index 50a5722fbaff6..c1a630e25ba0e 100644 --- a/src/test/rustdoc/where.rs +++ b/src/test/rustdoc/where.rs @@ -3,17 +3,17 @@ pub trait MyTrait { fn dummy(&self) { } } -// @has foo/struct.Alpha.html '//pre' "pub struct Alpha(_) where A: MyTrait" +// @has foo/struct.Alpha.html '//pre' "pub struct Alpha(_)where A: MyTrait" pub struct Alpha(A) where A: MyTrait; -// @has foo/trait.Bravo.html '//pre' "pub trait Bravo where B: MyTrait" +// @has foo/trait.Bravo.html '//pre' "pub trait Bravowhere B: MyTrait" pub trait Bravo where B: MyTrait { fn get(&self, B: B); } -// @has foo/fn.charlie.html '//pre' "pub fn charlie() where C: MyTrait" +// @has foo/fn.charlie.html '//pre' "pub fn charlie()where C: MyTrait" pub fn charlie() where C: MyTrait {} pub struct Delta(D); // @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Delta where D: MyTrait" +// "impl Deltawhere D: MyTrait" impl Delta where D: MyTrait { pub fn delta() {} } @@ -33,19 +33,19 @@ pub trait TraitWhere { } // @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl MyTrait for Echo where E: MyTrait" +// "impl MyTrait for Echowhere E: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ -// "impl MyTrait for Echo where E: MyTrait" -impl MyTrait for Echo where E: MyTrait {} +// "impl MyTrait for Echowhere E: MyTrait" +impl MyTrait for Echowhere E: MyTrait {} pub enum Foxtrot { Foxtrot1(F) } // @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl MyTrait for Foxtrot where F: MyTrait" +// "impl MyTrait for Foxtrotwhere F: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ -// "impl MyTrait for Foxtrot where F: MyTrait" -impl MyTrait for Foxtrot where F: MyTrait {} +// "impl MyTrait for Foxtrotwhere F: MyTrait" +impl MyTrait for Foxtrotwhere F: MyTrait {} // @has foo/type.Golf.html '//pre[@class="rust typedef"]' \ -// "type Golf where T: Clone, = (T, T)" +// "type Golfwhere T: Clone, = (T, T)" pub type Golf where T: Clone = (T, T); diff --git a/src/test/ui/async-await/issue-73137.rs b/src/test/ui/async-await/issue-73137.rs index c43ce2cadba04..dcbe7765a9e1c 100644 --- a/src/test/ui/async-await/issue-73137.rs +++ b/src/test/ui/async-await/issue-73137.rs @@ -2,6 +2,9 @@ // 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; diff --git a/src/test/ui/mir/issue-99866.rs b/src/test/ui/mir/issue-99866.rs new file mode 100644 index 0000000000000..d39ae6ebf1da2 --- /dev/null +++ b/src/test/ui/mir/issue-99866.rs @@ -0,0 +1,25 @@ +// check-pass +pub trait Backend { + type DescriptorSetLayout; +} + +pub struct Back; + +impl Backend for Back { + type DescriptorSetLayout = u32; +} + +pub struct HalSetLayouts { + vertex_layout: ::DescriptorSetLayout, +} + +impl HalSetLayouts { + pub fn iter(self) -> DSL + where + Back: Backend, + { + self.vertex_layout + } +} + +fn main() {}