diff --git a/Cargo.lock b/Cargo.lock index e0ffec3d7a2a3..8333560119640 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3337,6 +3337,7 @@ dependencies = [ "rustdoc-json-types", "serde_json", "similar", + "tempfile", "wasmparser 0.236.1", ] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f645c7fe7dea5..4c1bcffa1cf4c 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4615,6 +4615,11 @@ pub struct Upvar { pub struct TraitCandidate { pub def_id: DefId, pub import_ids: SmallVec<[LocalDefId; 1]>, + // Indicates whether this trait candidate is ambiguously glob imported + // in it's scope. Related to the AMBIGUOUS_GLOB_IMPORTED_TRAITS lint. + // If this is set to true and the trait is used as a result of method lookup, this + // lint is thrown. + pub lint_ambiguous: bool, } #[derive(Copy, Clone, Debug, HashStable_Generic)] diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 270f011b2b15f..608bc7dffd9c0 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use std::ops::Deref; use rustc_hir as hir; @@ -12,7 +13,9 @@ use rustc_hir_analysis::hir_ty_lowering::{ use rustc_infer::infer::{ BoundRegionConversionTime, DefineOpaqueTypes, InferOk, RegionVariableOrigin, }; -use rustc_lint::builtin::RESOLVING_TO_ITEMS_SHADOWING_SUPERTRAIT_ITEMS; +use rustc_lint::builtin::{ + AMBIGUOUS_GLOB_IMPORTED_TRAITS, RESOLVING_TO_ITEMS_SHADOWING_SUPERTRAIT_ITEMS, +}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, @@ -149,6 +152,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // Lint when an item is shadowing a supertrait item. self.lint_shadowed_supertrait_items(pick, segment); + // Lint when a trait is ambiguously imported + self.lint_ambiguously_glob_imported_traits(pick, segment); + // Add any trait/regions obligations specified on the method's type parameters. // We won't add these if we encountered an illegal sized bound, so that we can use // a custom error in that case. @@ -322,7 +328,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { }) } - probe::TraitPick => { + probe::TraitPick(_) => { let trait_def_id = pick.item.container_id(self.tcx); // Make a trait reference `$0 : Trait<$1...$n>` @@ -719,6 +725,25 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ); } + fn lint_ambiguously_glob_imported_traits( + &self, + pick: &probe::Pick<'_>, + segment: &hir::PathSegment<'tcx>, + ) { + if pick.kind != probe::PickKind::TraitPick(true) { + return; + } + let trait_name = self.tcx.item_name(pick.item.container_id(self.tcx)); + let import_span = self.tcx.hir_span_if_local(pick.import_ids[0].to_def_id()).unwrap(); + + self.tcx.node_lint(AMBIGUOUS_GLOB_IMPORTED_TRAITS, segment.hir_id, |diag| { + diag.primary_message(format!("Use of ambiguously glob imported trait `{trait_name}`")) + .span(segment.ident.span) + .span_label(import_span, format!("`{trait_name}` imported ambiguously here")) + .help(format!("Import `{trait_name}` explicitly")); + }); + } + fn upcast( &mut self, source_trait_ref: ty::PolyTraitRef<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index ed71ad2119c97..31ca0e46091cc 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -106,7 +106,7 @@ pub(crate) struct Candidate<'tcx> { pub(crate) enum CandidateKind<'tcx> { InherentImplCandidate { impl_def_id: DefId, receiver_steps: usize }, ObjectCandidate(ty::PolyTraitRef<'tcx>), - TraitCandidate(ty::PolyTraitRef<'tcx>), + TraitCandidate(ty::PolyTraitRef<'tcx>, bool /* lint_ambiguous */), WhereClauseCandidate(ty::PolyTraitRef<'tcx>), } @@ -235,7 +235,10 @@ pub(crate) struct Pick<'tcx> { pub(crate) enum PickKind<'tcx> { InherentImplPick, ObjectPick, - TraitPick, + TraitPick( + // Is Ambiguously Imported + bool, + ), WhereClausePick( // Trait ty::PolyTraitRef<'tcx>, @@ -560,7 +563,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { probe_cx.push_candidate( Candidate { item, - kind: CandidateKind::TraitCandidate(ty::Binder::dummy(trait_ref)), + kind: CandidateKind::TraitCandidate( + ty::Binder::dummy(trait_ref), + false, + ), import_ids: smallvec![], }, false, @@ -1018,6 +1024,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.assemble_extension_candidates_for_trait( &trait_candidate.import_ids, trait_did, + trait_candidate.lint_ambiguous, ); } } @@ -1029,7 +1036,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let mut duplicates = FxHashSet::default(); for trait_info in suggest::all_traits(self.tcx) { if duplicates.insert(trait_info.def_id) { - self.assemble_extension_candidates_for_trait(&smallvec![], trait_info.def_id); + self.assemble_extension_candidates_for_trait( + &smallvec![], + trait_info.def_id, + false, + ); } } } @@ -1055,6 +1066,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &mut self, import_ids: &SmallVec<[LocalDefId; 1]>, trait_def_id: DefId, + lint_ambiguous: bool, ) { let trait_args = self.fresh_args_for_item(self.span, trait_def_id); let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, trait_args); @@ -1076,7 +1088,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { Candidate { item, import_ids: import_ids.clone(), - kind: TraitCandidate(bound_trait_ref), + kind: TraitCandidate(bound_trait_ref, lint_ambiguous), }, false, ); @@ -1099,7 +1111,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { Candidate { item, import_ids: import_ids.clone(), - kind: TraitCandidate(ty::Binder::dummy(trait_ref)), + kind: TraitCandidate(ty::Binder::dummy(trait_ref), lint_ambiguous), }, false, ); @@ -1842,7 +1854,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ObjectCandidate(_) | WhereClauseCandidate(_) => { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } - TraitCandidate(trait_ref) => self.probe(|_| { + TraitCandidate(trait_ref, _) => self.probe(|_| { let trait_ref = self.instantiate_binder_with_fresh_vars( self.span, BoundRegionConversionTime::FnCall, @@ -1872,7 +1884,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn candidate_source_from_pick(&self, pick: &Pick<'tcx>) -> CandidateSource { match pick.kind { InherentImplPick => CandidateSource::Impl(pick.item.container_id(self.tcx)), - ObjectPick | WhereClausePick(_) | TraitPick => { + ObjectPick | WhereClausePick(_) | TraitPick(_) => { CandidateSource::Trait(pick.item.container_id(self.tcx)) } } @@ -1948,7 +1960,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { impl_bounds, )); } - TraitCandidate(poly_trait_ref) => { + TraitCandidate(poly_trait_ref, _) => { // Some trait methods are excluded for arrays before 2021. // (`array.into_iter()` wants a slice iterator for compatibility.) if let Some(method_name) = self.method_name { @@ -2274,11 +2286,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + let lint_ambiguous = match probes[0].0.kind { + TraitCandidate(_, lint) => lint, + _ => false, + }; + // FIXME: check the return type here somehow. // If so, just use this trait and call it a day. Some(Pick { item: probes[0].0.item, - kind: TraitPick, + kind: TraitPick(lint_ambiguous), import_ids: probes[0].0.import_ids.clone(), autoderefs: 0, autoref_or_ptr_adjustment: None, @@ -2348,9 +2365,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + let lint_ambiguous = match probes[0].0.kind { + TraitCandidate(_, lint) => lint, + _ => false, + }; + Some(Pick { item: child_candidate.item, - kind: TraitPick, + kind: TraitPick(lint_ambiguous), import_ids: child_candidate.import_ids.clone(), autoderefs: 0, autoref_or_ptr_adjustment: None, @@ -2613,7 +2635,7 @@ impl<'tcx> Candidate<'tcx> { kind: match self.kind { InherentImplCandidate { .. } => InherentImplPick, ObjectCandidate(_) => ObjectPick, - TraitCandidate(_) => TraitPick, + TraitCandidate(_, lint_ambiguous) => TraitPick(lint_ambiguous), WhereClauseCandidate(trait_ref) => { // Only trait derived from where-clauses should // appear here, so they should not contain any diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index c165b91cc9163..ff108031badc1 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -17,6 +17,7 @@ declare_lint_pass! { AARCH64_SOFTFLOAT_NEON, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_ASSOCIATED_ITEMS, + AMBIGUOUS_GLOB_IMPORTED_TRAITS, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_GLOB_REEXPORTS, AMBIGUOUS_PANIC_IMPORTS, @@ -4473,6 +4474,60 @@ declare_lint! { }; } +declare_lint! { + /// The `ambiguous_glob_imported_traits` lint reports uses of traits that are + /// imported ambiguously via glob imports. Previously, this was not enforced + /// due to a bug in rustc. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(ambiguous_glob_imported_traits)] + /// mod m1 { + /// pub trait Trait { + /// fn method1(&self) {} + /// } + /// impl Trait for u8 {} + /// } + /// mod m2 { + /// pub trait Trait { + /// fn method2(&self) {} + /// } + /// impl Trait for u8 {} + /// } + /// + /// fn main() { + /// use m1::*; + /// use m2::*; + /// 0u8.method1(); + /// 0u8.method2(); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// When multiple traits with the same name are brought into scope through glob imports, + /// one trait becomes the "primary" one while the others are shadowed. Methods from the + /// shadowed traits (e.g. `method2`) become inaccessible, while methods from the "primary" + /// trait (e.g. `method1`) still resolve. Ideally, none of the ambiguous traits would be in scope, + /// but we have to allow this for now because of backwards compatibility. + /// This lint reports uses of these "primary" traits that are ambiguous. + /// + /// This is a [future-incompatible] lint to transition this to a + /// hard error in the future. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub AMBIGUOUS_GLOB_IMPORTED_TRAITS, + Warn, + "detects uses of ambiguously glob imported traits", + @future_incompatible = FutureIncompatibleInfo { + reason: fcw!(FutureReleaseError #147992), + report_in_deps: false, + }; +} + declare_lint! { /// The `ambiguous_panic_imports` lint detects ambiguous core and std panic imports, but /// previously didn't do that due to `#[macro_use]` prelude macro import. diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 104e95277a1a2..1ad9bbc3b4b30 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -378,9 +378,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { return_result_from_ensure_ok, ); - if modifiers.cache.is_some() { - attributes.push(quote! { (cache) }); - } // Pass on the cache modifier if modifiers.cache.is_some() { attributes.push(quote! { (cache) }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ed4727b9d4217..52b016b6bdca2 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -622,7 +622,18 @@ struct ModuleData<'ra> { globs: CmRefCell>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. - traits: CmRefCell, Option>)]>>>, + traits: CmRefCell< + Option< + Box< + [( + Macros20NormalizedIdent, + Decl<'ra>, + Option>, + bool, /* lint ambiguous */ + )], + >, + >, + >, /// Span of the module itself. Used for error reporting. span: Span, @@ -719,7 +730,12 @@ impl<'ra> Module<'ra> { return; } if let Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) = binding.res() { - collected_traits.push((name, binding, r.as_ref().get_module(def_id))) + collected_traits.push(( + name, + binding, + r.as_ref().get_module(def_id), + binding.is_ambiguity_recursive(), + )); } }); *traits = Some(collected_traits.into_boxed_slice()); @@ -1877,7 +1893,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some(module) = current_trait { if self.trait_may_have_item(Some(module), assoc_item) { let def_id = module.def_id(); - found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] }); + found_traits.push(TraitCandidate { + def_id, + import_ids: smallvec![], + lint_ambiguous: false, + }); } } @@ -1915,11 +1935,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) { module.ensure_traits(self); let traits = module.traits.borrow(); - for &(trait_name, trait_binding, trait_module) in traits.as_ref().unwrap().iter() { + for &(trait_name, trait_binding, trait_module, lint_ambiguous) in + traits.as_ref().unwrap().iter() + { if self.trait_may_have_item(trait_module, assoc_item) { let def_id = trait_binding.res().def_id(); let import_ids = self.find_transitive_imports(&trait_binding.kind, trait_name.0); - found_traits.push(TraitCandidate { def_id, import_ids }); + found_traits.push(TraitCandidate { def_id, import_ids, lint_ambiguous }); } } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 4f4c710c12a26..7af99fbb311da 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -22,7 +22,9 @@ use rustc_hashes::Hash64; use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION}; use rustc_span::source_map::FilePathMapping; -use rustc_span::{FileName, RealFileName, SourceFileHashAlgorithm, Symbol, sym}; +use rustc_span::{ + FileName, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, Symbol, sym, +}; use rustc_target::spec::{ FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo, Target, TargetTuple, @@ -1317,6 +1319,29 @@ impl OutputFilenames { } } +pub(crate) fn parse_remap_path_scope( + early_dcx: &EarlyDiagCtxt, + matches: &getopts::Matches, +) -> RemapPathScopeComponents { + if let Some(v) = matches.opt_str("remap-path-scope") { + let mut slot = RemapPathScopeComponents::empty(); + for s in v.split(',') { + slot |= match s { + "macro" => RemapPathScopeComponents::MACRO, + "diagnostics" => RemapPathScopeComponents::DIAGNOSTICS, + "debuginfo" => RemapPathScopeComponents::DEBUGINFO, + "coverage" => RemapPathScopeComponents::COVERAGE, + "object" => RemapPathScopeComponents::OBJECT, + "all" => RemapPathScopeComponents::all(), + _ => early_dcx.early_fatal("argument for `--remap-path-scope` must be a comma separated list of scopes: `macro`, `diagnostics`, `debuginfo`, `coverage`, `object`, `all`"), + } + } + slot + } else { + RemapPathScopeComponents::all() + } +} + #[derive(Clone, Debug)] pub struct Sysroot { pub explicit: Option, @@ -1353,9 +1378,9 @@ pub fn host_tuple() -> &'static str { fn file_path_mapping( remap_path_prefix: Vec<(PathBuf, PathBuf)>, - unstable_opts: &UnstableOptions, + remap_path_scope: RemapPathScopeComponents, ) -> FilePathMapping { - FilePathMapping::new(remap_path_prefix.clone(), unstable_opts.remap_path_scope) + FilePathMapping::new(remap_path_prefix.clone(), remap_path_scope) } impl Default for Options { @@ -1367,7 +1392,7 @@ impl Default for Options { // to create a default working directory. let working_dir = { let working_dir = std::env::current_dir().unwrap(); - let file_mapping = file_path_mapping(Vec::new(), &unstable_opts); + let file_mapping = file_path_mapping(Vec::new(), RemapPathScopeComponents::empty()); file_mapping.to_real_filename(&RealFileName::empty(), &working_dir) }; @@ -1402,6 +1427,7 @@ impl Default for Options { cli_forced_codegen_units: None, cli_forced_local_thinlto_off: false, remap_path_prefix: Vec::new(), + remap_path_scope: RemapPathScopeComponents::all(), real_rust_source_base_dir: None, real_rustc_dev_source_base_dir: None, edition: DEFAULT_EDITION, @@ -1428,7 +1454,7 @@ impl Options { } pub fn file_path_mapping(&self) -> FilePathMapping { - file_path_mapping(self.remap_path_prefix.clone(), &self.unstable_opts) + file_path_mapping(self.remap_path_prefix.clone(), self.remap_path_scope) } /// Returns `true` if there will be an output file generated. @@ -1866,6 +1892,14 @@ pub fn rustc_optgroups() -> Vec { "Remap source names in all output (compiler messages and output files)", "=", ), + opt( + Stable, + Opt, + "", + "remap-path-scope", + "Defines which scopes of paths should be remapped by `--remap-path-prefix`", + "", + ), opt(Unstable, Multi, "", "env-set", "Inject an environment variable", "="), ]; options.extend(verbose_only.into_iter().map(|mut opt| { @@ -2669,6 +2703,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let externs = parse_externs(early_dcx, matches, &unstable_opts); let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts); + let remap_path_scope = parse_remap_path_scope(early_dcx, matches); let pretty = parse_pretty(early_dcx, &unstable_opts); @@ -2735,7 +2770,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M early_dcx.early_fatal(format!("Current directory is invalid: {e}")); }); - let file_mapping = file_path_mapping(remap_path_prefix.clone(), &unstable_opts); + let file_mapping = file_path_mapping(remap_path_prefix.clone(), remap_path_scope); file_mapping.to_real_filename(&RealFileName::empty(), &working_dir) }; @@ -2772,6 +2807,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M cli_forced_codegen_units: codegen_units, cli_forced_local_thinlto_off: disable_local_thinlto, remap_path_prefix, + remap_path_scope, real_rust_source_base_dir, real_rustc_dev_source_base_dir, edition, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index dfb388c9380d4..8d3deb0f25e1e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -454,6 +454,8 @@ top_level_options!( /// Remap source path prefixes in all output (messages, object files, debug, etc.). remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH], + /// Defines which scopes of paths should be remapped by `--remap-path-prefix`. + remap_path_scope: RemapPathScopeComponents [TRACKED_NO_CRATE_HASH], /// Base directory containing the `library/` directory for the Rust standard library. /// Right now it's always `$sysroot/lib/rustlib/src/rust` @@ -872,7 +874,6 @@ mod desc { pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `gcs`, `pac-ret`, (optionally with `pc`, `b-key`, `leaf` if `pac-ret` is set)"; pub(crate) const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; - pub(crate) const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `debuginfo`, `coverage`, `object`, `all`"; pub(crate) const parse_inlining_threshold: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number"; pub(crate) const parse_llvm_module_flag: &str = ":::. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)"; @@ -1737,29 +1738,6 @@ pub mod parse { true } - pub(crate) fn parse_remap_path_scope( - slot: &mut RemapPathScopeComponents, - v: Option<&str>, - ) -> bool { - if let Some(v) = v { - *slot = RemapPathScopeComponents::empty(); - for s in v.split(',') { - *slot |= match s { - "macro" => RemapPathScopeComponents::MACRO, - "diagnostics" => RemapPathScopeComponents::DIAGNOSTICS, - "debuginfo" => RemapPathScopeComponents::DEBUGINFO, - "coverage" => RemapPathScopeComponents::COVERAGE, - "object" => RemapPathScopeComponents::OBJECT, - "all" => RemapPathScopeComponents::all(), - _ => return false, - } - } - true - } else { - false - } - } - pub(crate) fn parse_relocation_model(slot: &mut Option, v: Option<&str>) -> bool { match v.and_then(|s| RelocModel::from_str(s).ok()) { Some(relocation_model) => *slot = Some(relocation_model), @@ -2614,8 +2592,6 @@ options! { "whether ELF relocations can be relaxed"), remap_cwd_prefix: Option = (None, parse_opt_pathbuf, [TRACKED], "remap paths under the current working directory to this path prefix"), - remap_path_scope: RemapPathScopeComponents = (RemapPathScopeComponents::all(), parse_remap_path_scope, [TRACKED], - "remap path scope (default: all)"), remark_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], "directory into which to write optimization remarks (if not specified, they will be \ written to standard error output)"), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8650ec00100bd..ef475630d4943 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1801,6 +1801,8 @@ supported_targets! { ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178), ("x86_64-pc-cygwin", x86_64_pc_cygwin), + + ("x86_64-unknown-linux-gnuasan", x86_64_unknown_linux_gnuasan), } /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]> diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs index 935666630daec..56e1c8a9705d0 100644 --- a/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { Target { llvm_target: "i586-unknown-redox".into(), - metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None }, + metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None }, pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128" diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnuasan.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnuasan.rs new file mode 100644 index 0000000000000..5d0ee0e1eb4c4 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnuasan.rs @@ -0,0 +1,16 @@ +use crate::spec::{SanitizerSet, Target, TargetMetadata}; + +pub(crate) fn target() -> Target { + let mut base = super::x86_64_unknown_linux_gnu::target(); + base.metadata = TargetMetadata { + description: Some( + "64-bit Linux (kernel 3.2+, glibc 2.17+) with ASAN enabled by default".into(), + ), + tier: Some(2), + host_tools: Some(false), + std: Some(true), + }; + base.supported_sanitizers = SanitizerSet::ADDRESS; + base.default_sanitizers = SanitizerSet::ADDRESS; + base +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs index ecf232f1ab2fa..768b1a1ba1128 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { llvm_target: "x86_64-unknown-linux-none".into(), metadata: TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs index 83835705f3daa..0fb4d186087bc 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(), arch: Arch::Xtensa, - metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None }, + metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None }, options: TargetOptions { endian: Endian::Little, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs index 42e4c7bf8bec2..81eab657db712 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(), arch: Arch::Xtensa, - metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None }, + metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None }, options: TargetOptions { endian: Endian::Little, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs index 498daf4e60639..fb1f4f4719794 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(), arch: Arch::Xtensa, - metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None }, + metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None }, options: TargetOptions { endian: Endian::Little, diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 6bef58a0ac20c..5f956f03ecb18 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -53,6 +53,11 @@ check-aux: src/tools/cargotest \ src/tools/test-float-parse \ $(BOOTSTRAP_ARGS) + # The build-std suite is off by default because it is uncommonly slow + # and memory-hungry. + $(Q)$(BOOTSTRAP) test --stage 2 \ + build-std \ + $(BOOTSTRAP_ARGS) # Run standard library tests in Miri. $(Q)MIRIFLAGS="-Zmiri-strict-provenance" \ $(BOOTSTRAP) miri --stage 2 \ diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index f6a763b940753..93b65dbec905e 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1515,6 +1515,7 @@ fn supported_sanitizers( "x86_64", &["asan", "dfsan", "lsan", "msan", "safestack", "tsan", "rtsan"], ), + "x86_64-unknown-linux-gnuasan" => common_libs("linux", "x86_64", &["asan"]), "x86_64-unknown-linux-musl" => { common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index f3a1c6b0e3dde..080931fc0a93d 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1625,6 +1625,12 @@ test!(RunMakeCargo { suite: "run-make-cargo", default: true }); +test!(BuildStd { + path: "tests/build-std", + mode: CompiletestMode::RunMake, + suite: "build-std", + default: false +}); test!(AssemblyLlvm { path: "tests/assembly-llvm", @@ -1948,7 +1954,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the let stage0_rustc_path = builder.compiler(0, test_compiler.host); cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path)); - if suite == "run-make-cargo" { + if matches!(suite, "run-make-cargo" | "build-std") { let cargo_path = if test_compiler.stage == 0 { // If we're using `--stage 0`, we should provide the bootstrap cargo. builder.initial_cargo.clone() diff --git a/src/bootstrap/src/core/builder/cli_paths.rs b/src/bootstrap/src/core/builder/cli_paths.rs index 5ff2b380e4b93..1b0caa980e1de 100644 --- a/src/bootstrap/src/core/builder/cli_paths.rs +++ b/src/bootstrap/src/core/builder/cli_paths.rs @@ -20,6 +20,7 @@ pub(crate) const PATH_REMAP: &[(&str, &[&str])] = &[ &[ // tidy-alphabetical-start "tests/assembly-llvm", + "tests/build-std", "tests/codegen-llvm", "tests/codegen-units", "tests/coverage", diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap index ad9660ef5c918..65349a59a1e80 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap @@ -5,6 +5,9 @@ expression: test tests [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/assembly-llvm) +[Test] test::BuildStd + targets: [aarch64-unknown-linux-gnu] + - Suite(test::tests/build-std) [Test] test::CodegenLlvm targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/codegen-llvm) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap index 4572f089b0ae3..694bb0672ee42 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap @@ -5,6 +5,9 @@ expression: test tests --skip=coverage [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/assembly-llvm) +[Test] test::BuildStd + targets: [aarch64-unknown-linux-gnu] + - Suite(test::tests/build-std) [Test] test::CodegenLlvm targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/codegen-llvm) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 14cae2d0efc4b..a995f5c8a219e 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -927,6 +927,7 @@ impl<'a> Builder<'a> { test::CollectLicenseMetadata, test::RunMake, test::RunMakeCargo, + test::BuildStd, ), Kind::Miri => describe!(test::Crate), Kind::Bench => describe!(test::Crate, test::CrateLibrustc, test::CrateRustdoc), diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 66614cc6cced8..af26c2f87d026 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -2077,7 +2077,7 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( prepare_test_config(&ctx) - .render_steps(), @r" + .render_steps(), @" [build] rustc 0 -> Tidy 1 [test] tidy <> [build] rustdoc 0 @@ -2255,7 +2255,7 @@ mod snapshot { insta::assert_snapshot!( prepare_test_config(&ctx) .stage(2) - .render_steps(), @r" + .render_steps(), @" [build] rustc 0 -> Tidy 1 [test] tidy <> [build] rustdoc 0 diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 67f4eb37b2c11..d756a38581b2b 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -38,6 +38,7 @@ pub struct Finder { const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined "riscv64im-unknown-none-elf", + "x86_64-unknown-linux-gnuasan", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index d69e0a5ce988a..7f22bc27600ce 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -78,6 +78,10 @@ The following test suites are available, with links for more information: [`run-make`](#run-make-tests) are general purpose tests using Rust programs. +### The build-std test suite + +[`build-std`](#build-std-tests) test that -Zbuild-std works. + ### Rustdoc test suites | Test suite | Purpose | @@ -429,6 +433,12 @@ use cases that require testing in-tree `cargo` in conjunction with in-tree `rust The `run-make` test suite does not have access to in-tree `cargo` (so it can be the faster-to-iterate test suite). +### `build-std` tests + +The tests in [`tests/build-std`] check that `-Zbuild-std` works. This is currently +just a run-make test suite with a single recipe. The recipe generates test cases +and runs them in parallel. + #### Using Rust recipes Each test should be in a separate directory with a `rmake.rs` Rust program, diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 3b8852f8ff9f7..8ceeff2c9685e 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -151,5 +151,6 @@ - [x86_64-pc-cygwin](platform-support/x86_64-pc-cygwin.md) - [x86_64-unknown-linux-none](platform-support/x86_64-unknown-linux-none.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) + - [x86_64-unknown-linux-gnuasan](platform-support/x86_64-unknown-linux-gnuasan.md) - [xtensa-\*-none-elf](platform-support/xtensa.md) - [\*-nuttx-\*](platform-support/nuttx.md) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 507af9e2ffef7..b6ee6c3f5fa79 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -428,6 +428,14 @@ specified multiple times. Refer to the [Remap source paths](remap-source-paths.md) section of this book for further details and explanation. + +## `--remap-path-scope`: remap source paths in output + +Defines which scopes of paths should be remapped by `--remap-path-prefix`. + +Refer to the [Remap source paths](remap-source-paths.md) section of this book for +further details and explanation. + ## `--json`: configure json messages printed by the compiler diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 754d0c975ec36..889f96f5fefab 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -206,6 +206,7 @@ target | std | notes [`x86_64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on x86_64 [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android +[`x86_64-unknown-linux-gnuasan`](platform-support/x86_64-unknown-linux-gnuasan.md) | ✓ | 64-bit Linux (kernel 3.2+, glibc 2.17+) with ASAN enabled by default [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15+, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnuasan.md b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnuasan.md new file mode 100644 index 0000000000000..61934934553bf --- /dev/null +++ b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnuasan.md @@ -0,0 +1,56 @@ +# `x86_64-unknown-linux-gnuasan` + +**Tier: 2** + +Target mirroring `x86_64-unknown-linux-gnu` with AddressSanitizer enabled by +default. +The goal of this target is to allow shipping ASAN-instrumented standard +libraries through rustup, enabling a fully instrumented binary without requiring +nightly features (build-std). +Once build-std stabilizes, this target is no longer needed and will be removed. + +## Target maintainers + +- [@jakos-sec](https://github.com/jakos-sec) +- [@1c3t3a](https://github.com/1c3t3a) +- [@rust-lang/project-exploit-mitigations][project-exploit-mitigations] + +## Requirements + +The target is for cross-compilation only. Host tools are not supported, since +there is no need to have the host tools instrumented with ASAN. std is fully +supported. + +In all other aspects the target is equivalent to `x86_64-unknown-linux-gnu`. + +## Building the target + +The target can be built by enabling it for a rustc build: + +```toml +[build] +target = ["x86_64-unknown-linux-gnuasan"] +``` + +## Building Rust programs + +Rust programs can be compiled by adding this target via rustup: + +```sh +$ rustup target add x86_64-unknown-linux-gnuasan +``` + +and then compiling with the target: + +```sh +$ rustc foo.rs --target x86_64-unknown-linux-gnuasan +``` + +## Testing + +Created binaries will run on Linux without any external requirements. + +## Cross-compilation toolchains and C code + +The target supports C code and should use the same toolchain target as +`x86_64-unknown-linux-gnu`. diff --git a/src/doc/rustc/src/remap-source-paths.md b/src/doc/rustc/src/remap-source-paths.md index dc00278fac676..9912f353774be 100644 --- a/src/doc/rustc/src/remap-source-paths.md +++ b/src/doc/rustc/src/remap-source-paths.md @@ -6,7 +6,7 @@ output, including compiler diagnostics, debugging information, macro expansions, This is useful for normalizing build products, for example, by removing the current directory out of the paths emitted into object files. -The remapping is done via the `--remap-path-prefix` option. +The remapping is done via the `--remap-path-prefix` flag and can be customized via the `--remap-path-scope` flag. ## `--remap-path-prefix` @@ -39,6 +39,31 @@ rustc --remap-path-prefix "/home/user/project=/redacted" This example replaces all occurrences of `/home/user/project` in emitted paths with `/redacted`. +## `--remap-path-scope` + +Defines which scopes of paths should be remapped by `--remap-path-prefix`. + +This flag accepts a comma-separated list of values and may be specified multiple times, in which case the scopes are aggregated together. + +The valid scopes are: + +- `macro` - apply remappings to the expansion of `std::file!()` macro. This is where paths in embedded panic messages come from +- `diagnostics` - apply remappings to printed compiler diagnostics +- `debuginfo` - apply remappings to debug information +- `coverage` - apply remappings to coverage information +- `object` - apply remappings to all paths in compiled executables or libraries, but not elsewhere. Currently an alias for `macro,coverage,debuginfo`. +- `all` (default) - an alias for all of the above, also equivalent to supplying only `--remap-path-prefix` without `--remap-path-scope`. + +The scopes accepted by `--remap-path-scope` are not exhaustive - new scopes may be added in future releases for eventual stabilisation. +This implies that the `all` scope can correspond to different scopes between releases. + +### Example + +```sh +# With `object` scope only the build outputs will be remapped, the diagnostics won't be remapped. +rustc --remap-path-prefix=$(PWD)=/remapped --remap-path-scope=object main.rs +``` + ## Caveats and Limitations ### Paths generated by linkers diff --git a/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md b/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md deleted file mode 100644 index fb1c7d7a68789..0000000000000 --- a/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md +++ /dev/null @@ -1,23 +0,0 @@ -# `remap-path-scope` - -The tracking issue for this feature is: [#111540](https://github.com/rust-lang/rust/issues/111540). - ------------------------- - -When the `--remap-path-prefix` option is passed to rustc, source path prefixes in all output will be affected by default. -The `--remap-path-scope` argument can be used in conjunction with `--remap-path-prefix` to determine paths in which output context should be affected. -This flag accepts a comma-separated list of values and may be specified multiple times, in which case the scopes are aggregated together. The valid scopes are: - -- `macro` - apply remappings to the expansion of `std::file!()` macro. This is where paths in embedded panic messages come from -- `diagnostics` - apply remappings to printed compiler diagnostics -- `debuginfo` - apply remappings to debug information -- `coverage` - apply remappings to coverage information -- `object` - apply remappings to all paths in compiled executables or libraries, but not elsewhere. Currently an alias for `macro,debuginfo`. -- `all` - an alias for all of the above, also equivalent to supplying only `--remap-path-prefix` without `--remap-path-scope`. - -## Example -```sh -# This would produce an absolute path to main.rs in build outputs of -# "./main.rs". -rustc --remap-path-prefix=$(PWD)=/remapped -Zremap-path-scope=object main.rs -``` diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 106e521d5805f..c71a350ffd305 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -77,6 +77,7 @@ string_enum! { RustdocUi => "rustdoc-ui", Ui => "ui", UiFullDeps => "ui-fulldeps", + BuildStd => "build-std", } } diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 4eb8f91fe8946..ac8846a263c0d 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -190,8 +190,8 @@ impl TestCx<'_> { // through a specific CI runner). .env("LLVM_COMPONENTS", &self.config.llvm_components); - // Only `run-make-cargo` test suite gets an in-tree `cargo`, not `run-make`. - if self.config.suite == TestSuite::RunMakeCargo { + // The `run-make-cargo` and `build-std` suites need an in-tree `cargo`, `run-make` does not. + if matches!(self.config.suite, TestSuite::RunMakeCargo | TestSuite::BuildStd) { cmd.env( "CARGO", self.config.cargo_path.as_ref().expect("cargo must be built and made available"), diff --git a/src/tools/llvm-bitcode-linker/src/linker.rs b/src/tools/llvm-bitcode-linker/src/linker.rs index dafd847e76808..e682aecbbeed1 100644 --- a/src/tools/llvm-bitcode-linker/src/linker.rs +++ b/src/tools/llvm-bitcode-linker/src/linker.rs @@ -68,7 +68,7 @@ impl Session { .arg("-o") .arg(&self.link_path) .output() - .context("An error occured when calling llvm-link. Make sure the llvm-tools component is installed.")?; + .context("An error occurred when calling llvm-link. Make sure the llvm-tools component is installed.")?; if !llvm_link_output.status.success() { tracing::error!( @@ -115,7 +115,7 @@ impl Session { } let opt_output = opt_cmd.output().context( - "An error occured when calling opt. Make sure the llvm-tools component is installed.", + "An error occurred when calling opt. Make sure the llvm-tools component is installed.", )?; if !opt_output.status.success() { @@ -149,7 +149,7 @@ impl Session { .arg(&self.opt_path) .arg("-o").arg(&self.out_path) .output() - .context("An error occured when calling llc. Make sure the llvm-tools component is installed.")?; + .context("An error occurred when calling llc. Make sure the llvm-tools component is installed.")?; if !lcc_output.status.success() { tracing::error!( diff --git a/src/tools/miri/genmc-sys/cpp/include/MiriInterface.hpp b/src/tools/miri/genmc-sys/cpp/include/MiriInterface.hpp index b6b7b06509a5e..8110c8d24c593 100644 --- a/src/tools/miri/genmc-sys/cpp/include/MiriInterface.hpp +++ b/src/tools/miri/genmc-sys/cpp/include/MiriInterface.hpp @@ -79,7 +79,7 @@ struct MiriGenmcShim : private GenMCDriver { void handle_execution_start(); // This function must be called at the end of any execution, even if an error was found // during the execution. - // Returns `null`, or a string containing an error message if an error occured. + // Returns `null`, or a string containing an error message if an error occurred. std::unique_ptr handle_execution_end(); /***** Functions for handling events encountered during program execution. *****/ diff --git a/src/tools/miri/genmc-sys/src/lib.rs b/src/tools/miri/genmc-sys/src/lib.rs index b3a9880211dec..26de80f295d31 100644 --- a/src/tools/miri/genmc-sys/src/lib.rs +++ b/src/tools/miri/genmc-sys/src/lib.rs @@ -379,7 +379,7 @@ mod ffi { /// This function must be called at the start of any execution, before any events are reported to GenMC. fn handle_execution_start(self: Pin<&mut MiriGenmcShim>); /// This function must be called at the end of any execution, even if an error was found during the execution. - /// Returns `null`, or a string containing an error message if an error occured. + /// Returns `null`, or a string containing an error message if an error occurred. fn handle_execution_end(self: Pin<&mut MiriGenmcShim>) -> UniquePtr; /***** Functions for handling events encountered during program execution. *****/ diff --git a/src/tools/miri/src/concurrency/genmc/mod.rs b/src/tools/miri/src/concurrency/genmc/mod.rs index 36b1d2afade4f..740553ab85d64 100644 --- a/src/tools/miri/src/concurrency/genmc/mod.rs +++ b/src/tools/miri/src/concurrency/genmc/mod.rs @@ -220,7 +220,7 @@ impl GenmcCtx { /// Don't call this function if an error was found. /// /// GenMC detects certain errors only when the execution ends. - /// If an error occured, a string containing a short error description is returned. + /// If an error occurred, a string containing a short error description is returned. /// /// GenMC currently doesn't return an error in all cases immediately when one happens. /// This function will also check for those, and return their error description. diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 9d9cd656f5700..918f5ef0d5069 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -17,6 +17,7 @@ object = "0.37" regex = "1.11" serde_json = "1.0" similar = "2.7" +tempfile = "3" wasmparser = { version = "0.236", default-features = false, features = ["std", "features", "validate"] } # tidy-alphabetical-end diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index 0aeb189bb6a5b..f4a09f9faae8f 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -46,6 +46,8 @@ pub struct Command { // Emulate linear type semantics. drop_bomb: DropBomb, already_executed: bool, + + context: String, } impl Command { @@ -60,6 +62,7 @@ impl Command { stdout: None, stderr: None, already_executed: false, + context: String::new(), } } @@ -69,6 +72,16 @@ impl Command { self.cmd } + pub(crate) fn get_context(&self) -> &str { + &self.context + } + + /// Appends context to the command, to provide a better error message if the command fails. + pub fn context(&mut self, ctx: &str) -> &mut Self { + self.context.push_str(&format!("{ctx}\n")); + self + } + /// Specify a stdin input buffer. This is a convenience helper, pub fn stdin_buf>(&mut self, input: I) -> &mut Self { self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice()); diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 5253dc04a93e2..b19d73b78a942 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -34,7 +34,9 @@ pub mod rfs { } // Re-exports of third-party library crates. -pub use {bstr, gimli, libc, object, regex, rustdoc_json_types, serde_json, similar, wasmparser}; +pub use { + bstr, gimli, libc, object, regex, rustdoc_json_types, serde_json, similar, tempfile, wasmparser, +}; // Helpers for building names of output artifacts that are potentially target-specific. pub use crate::artifact_names::{ diff --git a/src/tools/run-make-support/src/util.rs b/src/tools/run-make-support/src/util.rs index af01758447b93..7908dc1f7b3d9 100644 --- a/src/tools/run-make-support/src/util.rs +++ b/src/tools/run-make-support/src/util.rs @@ -21,6 +21,9 @@ pub(crate) fn handle_failed_output( eprintln!("output status: `{}`", output.status()); eprintln!("=== STDOUT ===\n{}\n\n", output.stdout_utf8()); eprintln!("=== STDERR ===\n{}\n\n", output.stderr_utf8()); + if !cmd.get_context().is_empty() { + eprintln!("Context:\n{}", cmd.get_context()); + } std::process::exit(1) } diff --git a/src/tools/tidy/src/diagnostics.rs b/src/tools/tidy/src/diagnostics.rs index 88816b5abefff..6f53f2fff1a48 100644 --- a/src/tools/tidy/src/diagnostics.rs +++ b/src/tools/tidy/src/diagnostics.rs @@ -213,7 +213,7 @@ impl RunningCheck { } } - /// Has an error already occured for this check? + /// Has an error already occurred for this check? pub fn is_bad(&self) -> bool { self.bad } diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index c8b81cc858d6a..0eced9df3c46d 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -673,6 +673,9 @@ //@ revisions: x86_64_unknown_linux_gnux32 //@ [x86_64_unknown_linux_gnux32] compile-flags: --target x86_64-unknown-linux-gnux32 //@ [x86_64_unknown_linux_gnux32] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_linux_gnuasan +//@ [x86_64_unknown_linux_gnuasan] compile-flags: --target x86_64-unknown-linux-gnuasan +//@ [x86_64_unknown_linux_gnuasan] needs-llvm-components: x86 //@ revisions: x86_64_unknown_linux_musl //@ [x86_64_unknown_linux_musl] compile-flags: --target x86_64-unknown-linux-musl //@ [x86_64_unknown_linux_musl] needs-llvm-components: x86 diff --git a/tests/build-std/configurations/rmake.rs b/tests/build-std/configurations/rmake.rs new file mode 100644 index 0000000000000..99cb9f9b0f4d4 --- /dev/null +++ b/tests/build-std/configurations/rmake.rs @@ -0,0 +1,131 @@ +// This test ensures we are able to compile -Zbuild-std=core under a variety of profiles. +// Currently, it tests that we can compile to all Tier 1 targets, and it does this by checking what +// the tier metadata in target-spec JSON. This means that all in-tree targets must have a tier set. + +#![deny(warnings)] + +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; +use std::thread; + +use run_make_support::serde_json::{self, Value}; +use run_make_support::tempfile::TempDir; +use run_make_support::{cargo, rfs, rustc}; + +#[derive(Clone)] +struct Task { + target: String, + opt_level: u8, + debug: u8, + panic: &'static str, +} + +fn manifest(task: &Task) -> String { + let Task { opt_level, debug, panic, target: _ } = task; + format!( + r#"[package] +name = "scratch" +version = "0.1.0" +edition = "2024" + +[lib] +path = "lib.rs" + +[profile.release] +opt-level = {opt_level} +debug = {debug} +panic = "{panic}" +"# + ) +} + +fn main() { + let mut targets = Vec::new(); + let all_targets = + rustc().args(&["--print=all-target-specs-json", "-Zunstable-options"]).run().stdout_utf8(); + let all_targets: HashMap = serde_json::from_str(&all_targets).unwrap(); + for (target, spec) in all_targets { + let metadata = spec.as_object().unwrap()["metadata"].as_object().unwrap(); + let tier = metadata["tier"] + .as_u64() + .expect(&format!("Target {} is missing tier metadata", target)); + if tier == 1 { + targets.push(target); + } + } + + let mut tasks = Vec::new(); + + // Testing every combination of compiler flags is infeasible. So we are making some attempt to + // choose combinations that will tend to run into problems. + // + // The particular combination of settings below is tuned to look for problems generating the + // code for compiler-builtins. + // We only exercise opt-level 0 and 3 to exercise mir-opt-level 1 and 2. + // We only exercise debug 0 and 2 because level 2 turns off some MIR optimizations. + // We only test abort and immediate-abort because abort vs unwind doesn't change MIR much at + // all. but immediate-abort does. + // + // Currently this only tests that we can compile the tier 1 targets. But since we are using + // -Zbuild-std=core, we could have any list of targets. + + for opt_level in [0, 3] { + for debug in [0, 2] { + for panic in ["abort", "immediate-abort"] { + for target in &targets { + tasks.push(Task { target: target.clone(), opt_level, debug, panic }); + } + } + } + } + + let tasks = Arc::new(Mutex::new(tasks)); + let mut threads = Vec::new(); + + // Try to obey the -j argument passed to bootstrap, otherwise fall back to using all the system + // resouces. This test can be rather memory-hungry (~1 GB/thread); if it causes trouble in + // practice do not hesitate to limit its parallelism. + for _ in 0..run_make_support::env::jobs() { + let tasks = Arc::clone(&tasks); + let handle = thread::spawn(move || { + loop { + let maybe_task = tasks.lock().unwrap().pop(); + if let Some(task) = maybe_task { + test(task); + } else { + break; + } + } + }); + threads.push(handle); + } + + for t in threads { + t.join().unwrap(); + } +} + +fn test(task: Task) { + let dir = TempDir::new().unwrap(); + + let manifest = manifest(&task); + rfs::write(dir.path().join("Cargo.toml"), &manifest); + rfs::write(dir.path().join("lib.rs"), "#![no_std]"); + + let mut args = vec!["build", "--release", "-Zbuild-std=core", "--target", &task.target, "-j1"]; + if task.panic == "immediate-abort" { + args.push("-Zpanic-immediate-abort"); + } + cargo() + .current_dir(dir.path()) + .args(&args) + .env("RUSTC_BOOTSTRAP", "1") + // Visual Studio 2022 requires that the LIB env var be set so it can + // find the Windows SDK. + .env("LIB", std::env::var("LIB").unwrap_or_default()) + .context(&format!( + "build-std for target `{}` failed with the following Cargo.toml:\n\n{manifest}", + task.target + )) + .run(); +} diff --git a/tests/coverage/remap-path-prefix.rs b/tests/coverage/remap-path-prefix.rs index 29c5826989c44..031b87b8f7716 100644 --- a/tests/coverage/remap-path-prefix.rs +++ b/tests/coverage/remap-path-prefix.rs @@ -10,8 +10,8 @@ //@ revisions: with_remap with_coverage_scope with_object_scope with_macro_scope //@ compile-flags: --remap-path-prefix={{src-base}}=remapped // -//@[with_coverage_scope] compile-flags: -Zremap-path-scope=coverage -//@[with_object_scope] compile-flags: -Zremap-path-scope=object -//@[with_macro_scope] compile-flags: -Zremap-path-scope=macro +//@[with_coverage_scope] compile-flags: --remap-path-scope=coverage +//@[with_object_scope] compile-flags: --remap-path-scope=object +//@[with_macro_scope] compile-flags: --remap-path-scope=macro fn main() {} diff --git a/tests/coverage/remap-path-prefix.with_macro_scope.coverage b/tests/coverage/remap-path-prefix.with_macro_scope.coverage index 63979d8fe15a5..9e8317672f90a 100644 --- a/tests/coverage/remap-path-prefix.with_macro_scope.coverage +++ b/tests/coverage/remap-path-prefix.with_macro_scope.coverage @@ -10,9 +10,9 @@ LL| |//@ revisions: with_remap with_coverage_scope with_object_scope with_macro_scope LL| |//@ compile-flags: --remap-path-prefix={{src-base}}=remapped LL| |// - LL| |//@[with_coverage_scope] compile-flags: -Zremap-path-scope=coverage - LL| |//@[with_object_scope] compile-flags: -Zremap-path-scope=object - LL| |//@[with_macro_scope] compile-flags: -Zremap-path-scope=macro + LL| |//@[with_coverage_scope] compile-flags: --remap-path-scope=coverage + LL| |//@[with_object_scope] compile-flags: --remap-path-scope=object + LL| |//@[with_macro_scope] compile-flags: --remap-path-scope=macro LL| | LL| 1|fn main() {} diff --git a/tests/run-make/remap-path-prefix-consts/rmake.rs b/tests/run-make/remap-path-prefix-consts/rmake.rs index d07a5e00768a7..07b5e2f974147 100644 --- a/tests/run-make/remap-path-prefix-consts/rmake.rs +++ b/tests/run-make/remap-path-prefix-consts/rmake.rs @@ -97,7 +97,7 @@ fn main() { location_caller .crate_type("lib") .remap_path_prefix(cwd(), "/remapped") - .arg("-Zremap-path-scope=object") + .arg("--remap-path-scope=object") .input(cwd().join("location-caller.rs")); location_caller.run(); @@ -105,7 +105,7 @@ fn main() { runner .crate_type("bin") .remap_path_prefix(cwd(), "/remapped") - .arg("-Zremap-path-scope=diagnostics") + .arg("--remap-path-scope=diagnostics") .input(cwd().join("runner.rs")) .output(&runner_bin); runner.run(); diff --git a/tests/run-make/remap-path-prefix-dwarf/rmake.rs b/tests/run-make/remap-path-prefix-dwarf/rmake.rs index 3b88fca0bb7f8..ab6c1fb70d682 100644 --- a/tests/run-make/remap-path-prefix-dwarf/rmake.rs +++ b/tests/run-make/remap-path-prefix-dwarf/rmake.rs @@ -105,7 +105,7 @@ fn check_dwarf_deps(scope: &str, dwarf_test: DwarfDump) { let mut rustc_sm = rustc(); rustc_sm.input(cwd().join("src/some_value.rs")); rustc_sm.arg("-Cdebuginfo=2"); - rustc_sm.arg(format!("-Zremap-path-scope={}", scope)); + rustc_sm.arg(format!("--remap-path-scope={}", scope)); rustc_sm.arg("--remap-path-prefix"); rustc_sm.arg(format!("{}=/REMAPPED", cwd().display())); rustc_sm.arg("-Csplit-debuginfo=off"); @@ -117,7 +117,7 @@ fn check_dwarf_deps(scope: &str, dwarf_test: DwarfDump) { rustc_pv.input(cwd().join("src/print_value.rs")); rustc_pv.output(&print_value_rlib); rustc_pv.arg("-Cdebuginfo=2"); - rustc_pv.arg(format!("-Zremap-path-scope={}", scope)); + rustc_pv.arg(format!("--remap-path-scope={}", scope)); rustc_pv.arg("--remap-path-prefix"); rustc_pv.arg(format!("{}=/REMAPPED", cwd().display())); rustc_pv.arg("-Csplit-debuginfo=off"); @@ -158,8 +158,8 @@ fn check_dwarf(test: DwarfTest) { rustc.arg("-Cdebuginfo=2"); if let Some(scope) = test.scope { match scope { - ScopeType::Object => rustc.arg("-Zremap-path-scope=object"), - ScopeType::Diagnostics => rustc.arg("-Zremap-path-scope=diagnostics"), + ScopeType::Object => rustc.arg("--remap-path-scope=object"), + ScopeType::Diagnostics => rustc.arg("--remap-path-scope=diagnostics"), }; if is_darwin() { rustc.arg("-Csplit-debuginfo=off"); diff --git a/tests/run-make/remap-path-prefix/rmake.rs b/tests/run-make/remap-path-prefix/rmake.rs index b75ca9e796ace..22ffd4f1f0d19 100644 --- a/tests/run-make/remap-path-prefix/rmake.rs +++ b/tests/run-make/remap-path-prefix/rmake.rs @@ -38,9 +38,9 @@ fn main() { rmeta_contains("/the/aux/lib.rs"); rmeta_not_contains("auxiliary"); - out_object.arg("-Zremap-path-scope=object"); - out_macro.arg("-Zremap-path-scope=macro"); - out_diagobj.arg("-Zremap-path-scope=diagnostics,object"); + out_object.arg("--remap-path-scope=object"); + out_macro.arg("--remap-path-scope=macro"); + out_diagobj.arg("--remap-path-scope=diagnostics,object"); if is_darwin() { out_object.arg("-Csplit-debuginfo=off"); out_macro.arg("-Csplit-debuginfo=off"); diff --git a/tests/run-make/rustc-help/help-v.diff b/tests/run-make/rustc-help/help-v.diff index 60a9dfbe201d9..94ed6a0ed027c 100644 --- a/tests/run-make/rustc-help/help-v.diff +++ b/tests/run-make/rustc-help/help-v.diff @@ -1,4 +1,4 @@ -@@ -65,10 +65,28 @@ +@@ -65,10 +65,31 @@ Set a codegen option -V, --version Print version info and exit -v, --verbose Use verbose output @@ -20,6 +20,9 @@ + --remap-path-prefix = + Remap source names in all output (compiler messages + and output files) ++ --remap-path-scope ++ Defines which scopes of paths should be remapped by ++ `--remap-path-prefix` + @path Read newline separated options from `path` Additional help: diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout index cf055e220c0de..0acbb766c1556 100644 --- a/tests/run-make/rustc-help/help-v.stdout +++ b/tests/run-make/rustc-help/help-v.stdout @@ -83,6 +83,9 @@ Options: --remap-path-prefix = Remap source names in all output (compiler messages and output files) + --remap-path-scope + Defines which scopes of paths should be remapped by + `--remap-path-prefix` @path Read newline separated options from `path` Additional help: diff --git a/tests/run-make/split-debuginfo/rmake.rs b/tests/run-make/split-debuginfo/rmake.rs index e53b710107812..0d311607a11a4 100644 --- a/tests/run-make/split-debuginfo/rmake.rs +++ b/tests/run-make/split-debuginfo/rmake.rs @@ -171,8 +171,7 @@ enum RemapPathPrefix { Unspecified, } -/// `-Zremap-path-scope`. See -/// . +/// `--remap-path-scope` #[derive(Debug, Clone)] enum RemapPathScope { /// Comma-separated list of remap scopes: `macro`, `diagnostics`, `debuginfo`, `object`, `all`. @@ -921,7 +920,7 @@ mod shared_linux_other_tests { .debuginfo(level.cli_value()) .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) .remap_path_prefix(cwd(), remapped_prefix) - .arg(format!("-Zremap-path-scope={scope}")) + .arg(format!("--remap-path-scope={scope}")) .run(); let found_files = cwd_filenames(); FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } @@ -950,7 +949,7 @@ mod shared_linux_other_tests { .debuginfo(level.cli_value()) .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) .remap_path_prefix(cwd(), remapped_prefix) - .arg(format!("-Zremap-path-scope={scope}")) + .arg(format!("--remap-path-scope={scope}")) .run(); let found_files = cwd_filenames(); FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } @@ -1202,7 +1201,7 @@ mod shared_linux_other_tests { .debuginfo(level.cli_value()) .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) .remap_path_prefix(cwd(), remapped_prefix) - .arg(format!("-Zremap-path-scope={scope}")) + .arg(format!("--remap-path-scope={scope}")) .run(); let found_files = cwd_filenames(); @@ -1242,7 +1241,7 @@ mod shared_linux_other_tests { .debuginfo(level.cli_value()) .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) .remap_path_prefix(cwd(), remapped_prefix) - .arg(format!("-Zremap-path-scope={scope}")) + .arg(format!("--remap-path-scope={scope}")) .run(); let found_files = cwd_filenames(); @@ -1356,7 +1355,7 @@ fn main() { // NOTE: these combinations are not exhaustive, because while porting to rmake.rs initially I // tried to preserve the existing test behavior closely. Notably, no attempt was made to // exhaustively cover all cases in the 6-fold Cartesian product of `{,-Csplit=debuginfo=...}` x - // `{,-Cdebuginfo=...}` x `{,--remap-path-prefix}` x `{,-Zremap-path-scope=...}` x + // `{,-Cdebuginfo=...}` x `{,--remap-path-prefix}` x `{,--remap-path-scope=...}` x // `{,-Zsplit-dwarf-kind=...}` x `{,-Clinker-plugin-lto}`. If you really want to, you can // identify which combination isn't exercised with a 6-layers nested for loop iterating through // each of the cli flag enum variants. diff --git a/tests/rustdoc-html/intra-doc/deps.rs b/tests/rustdoc-html/intra-doc/deps.rs index fd40b8326d0ff..1670a2d8fe7be 100644 --- a/tests/rustdoc-html/intra-doc/deps.rs +++ b/tests/rustdoc-html/intra-doc/deps.rs @@ -6,7 +6,7 @@ //@ compile-flags: --extern-html-root-url=empty=https://empty.example/ // This one is to ensure that we don't link to any item we see which has // an external html root URL unless it actually exists. -//@ compile-flags: --extern-html-root-url=non_existant=https://non-existant.example/ +//@ compile-flags: --extern-html-root-url=non_existent=https://non-existent.example/ //@ aux-build: empty.rs #![crate_name = "foo"] @@ -14,10 +14,10 @@ //@ has 'foo/index.html' //@ has - '//a[@href="https://empty.example/empty/index.html"]' 'empty' -// There should only be one intra doc links, we should not link `non_existant`. +// There should only be one intra doc links, we should not link `non_existent`. //@ count - '//*[@class="docblock"]//a' 1 //! [`empty`] //! -//! [`non_existant`] +//! [`non_existent`] extern crate empty; diff --git a/tests/ui/errors/auxiliary/file-debuginfo.rs b/tests/ui/errors/auxiliary/file-debuginfo.rs index 08113ec26bfd4..3c95512d8cc24 100644 --- a/tests/ui/errors/auxiliary/file-debuginfo.rs +++ b/tests/ui/errors/auxiliary/file-debuginfo.rs @@ -1,5 +1,5 @@ //@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ compile-flags: -Zremap-path-scope=debuginfo +//@ compile-flags: --remap-path-scope=debuginfo #[macro_export] macro_rules! my_file { diff --git a/tests/ui/errors/auxiliary/file-diag.rs b/tests/ui/errors/auxiliary/file-diag.rs index f29c349f703b2..61fc9d2b48291 100644 --- a/tests/ui/errors/auxiliary/file-diag.rs +++ b/tests/ui/errors/auxiliary/file-diag.rs @@ -1,5 +1,5 @@ //@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ compile-flags: -Zremap-path-scope=diagnostics +//@ compile-flags: --remap-path-scope=diagnostics #[macro_export] macro_rules! my_file { diff --git a/tests/ui/errors/auxiliary/file-macro.rs b/tests/ui/errors/auxiliary/file-macro.rs index 11abc0549a7b8..11e5de1e32746 100644 --- a/tests/ui/errors/auxiliary/file-macro.rs +++ b/tests/ui/errors/auxiliary/file-macro.rs @@ -1,5 +1,5 @@ //@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ compile-flags: -Zremap-path-scope=macro +//@ compile-flags: --remap-path-scope=macro #[macro_export] macro_rules! my_file { diff --git a/tests/ui/errors/auxiliary/trait-debuginfo.rs b/tests/ui/errors/auxiliary/trait-debuginfo.rs index d5a0825fe6d13..dbe3d09d317d0 100644 --- a/tests/ui/errors/auxiliary/trait-debuginfo.rs +++ b/tests/ui/errors/auxiliary/trait-debuginfo.rs @@ -1,4 +1,4 @@ //@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ compile-flags: -Zremap-path-scope=debuginfo +//@ compile-flags: --remap-path-scope=debuginfo pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/auxiliary/trait-diag.rs b/tests/ui/errors/auxiliary/trait-diag.rs index e07961a276a9d..3a30366683c4a 100644 --- a/tests/ui/errors/auxiliary/trait-diag.rs +++ b/tests/ui/errors/auxiliary/trait-diag.rs @@ -1,4 +1,4 @@ //@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ compile-flags: -Zremap-path-scope=diagnostics +//@ compile-flags: --remap-path-scope=diagnostics pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/auxiliary/trait-macro.rs b/tests/ui/errors/auxiliary/trait-macro.rs index 48673d04ee16f..334b1c9bba2f3 100644 --- a/tests/ui/errors/auxiliary/trait-macro.rs +++ b/tests/ui/errors/auxiliary/trait-macro.rs @@ -1,4 +1,4 @@ //@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ compile-flags: -Zremap-path-scope=macro +//@ compile-flags: --remap-path-scope=macro pub trait Trait: std::fmt::Display {} diff --git a/tests/ui/errors/remap-path-prefix-diagnostics.rs b/tests/ui/errors/remap-path-prefix-diagnostics.rs index fac7e937cb0b8..54dbcfd64711e 100644 --- a/tests/ui/errors/remap-path-prefix-diagnostics.rs +++ b/tests/ui/errors/remap-path-prefix-diagnostics.rs @@ -1,4 +1,4 @@ -// This test exercises `-Zremap-path-scope`, diagnostics printing paths and dependency. +// This test exercises `--remap-path-scope`, diagnostics printing paths and dependency. // // We test different combinations with/without remap in deps, with/without remap in this // crate but always in deps and always here but never in deps. @@ -12,10 +12,10 @@ //@[with-debuginfo-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped //@[not-diag-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped -//@[with-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics -//@[with-macro-in-deps] compile-flags: -Zremap-path-scope=macro -//@[with-debuginfo-in-deps] compile-flags: -Zremap-path-scope=debuginfo -//@[not-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics +//@[with-diag-in-deps] compile-flags: --remap-path-scope=diagnostics +//@[with-macro-in-deps] compile-flags: --remap-path-scope=macro +//@[with-debuginfo-in-deps] compile-flags: --remap-path-scope=debuginfo +//@[not-diag-in-deps] compile-flags: --remap-path-scope=diagnostics //@[with-diag-in-deps] aux-build:trait-diag.rs //@[with-macro-in-deps] aux-build:trait-macro.rs diff --git a/tests/ui/errors/remap-path-prefix-macro.rs b/tests/ui/errors/remap-path-prefix-macro.rs index 3e93843f91641..1f895aeeb6b4d 100644 --- a/tests/ui/errors/remap-path-prefix-macro.rs +++ b/tests/ui/errors/remap-path-prefix-macro.rs @@ -1,4 +1,4 @@ -// This test exercises `-Zremap-path-scope`, macros (like file!()) and dependency. +// This test exercises `--remap-path-scope`, macros (like file!()) and dependency. // // We test different combinations with/without remap in deps, with/without remap in // this crate but always in deps and always here but never in deps. @@ -15,10 +15,10 @@ //@[with-debuginfo-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped //@[not-macro-in-deps] compile-flags: --remap-path-prefix={{src-base}}=remapped -//@[with-diag-in-deps] compile-flags: -Zremap-path-scope=diagnostics -//@[with-macro-in-deps] compile-flags: -Zremap-path-scope=macro -//@[with-debuginfo-in-deps] compile-flags: -Zremap-path-scope=debuginfo -//@[not-macro-in-deps] compile-flags: -Zremap-path-scope=macro +//@[with-diag-in-deps] compile-flags: --remap-path-scope=diagnostics +//@[with-macro-in-deps] compile-flags: --remap-path-scope=macro +//@[with-debuginfo-in-deps] compile-flags: --remap-path-scope=debuginfo +//@[not-macro-in-deps] compile-flags: --remap-path-scope=macro //@[with-diag-in-deps] aux-build:file-diag.rs //@[with-macro-in-deps] aux-build:file-macro.rs diff --git a/tests/ui/errors/remap-path-prefix.rs b/tests/ui/errors/remap-path-prefix.rs index de18aa8cc204b..b495147113551 100644 --- a/tests/ui/errors/remap-path-prefix.rs +++ b/tests/ui/errors/remap-path-prefix.rs @@ -1,7 +1,7 @@ //@ revisions: normal with-diagnostic-scope without-diagnostic-scope //@ compile-flags: --remap-path-prefix={{src-base}}=remapped -//@ [with-diagnostic-scope]compile-flags: -Zremap-path-scope=diagnostics -//@ [without-diagnostic-scope]compile-flags: -Zremap-path-scope=object +//@ [with-diagnostic-scope]compile-flags: --remap-path-scope=diagnostics +//@ [without-diagnostic-scope]compile-flags: --remap-path-scope=object // Manually remap, so the remapped path remains in .stderr file. // The remapped paths are not normalized by compiletest. diff --git a/tests/ui/imports/ambiguous-trait-in-scope.rs b/tests/ui/imports/ambiguous-trait-in-scope.rs new file mode 100644 index 0000000000000..d122762973969 --- /dev/null +++ b/tests/ui/imports/ambiguous-trait-in-scope.rs @@ -0,0 +1,84 @@ +//@ edition:2018 +//@ aux-crate:external=ambiguous-trait-reexport.rs + +mod m1 { + pub trait Trait { + fn method1(&self) {} + } + impl Trait for u8 {} +} +mod m2 { + pub trait Trait { + fn method2(&self) {} + } + impl Trait for u8 {} +} +mod m1_reexport { + pub use crate::m1::Trait; +} +mod m2_reexport { + pub use crate::m2::Trait; +} + +mod ambig_reexport { + pub use crate::m1::*; + pub use crate::m2::*; +} + +fn test1() { + // Create an ambiguous import for `Trait` in one order + use m1::*; + use m2::*; + 0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits] + //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + 0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope +} + +fn test2() { + // Create an ambiguous import for `Trait` in another order + use m2::*; + use m1::*; + 0u8.method1(); //~ ERROR: no method named `method1` found for type `u8` in the current scope + 0u8.method2(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits] + //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +} + +fn test_indirect_reexport() { + use m1_reexport::*; + use m2_reexport::*; + 0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits] + //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + 0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope +} + +fn test_ambig_reexport() { + use ambig_reexport::*; + 0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits] + //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + 0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope +} + +fn test_external() { + use external::m1::*; + use external::m2::*; + 0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits] + //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + 0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope +} + +fn test_external_indirect_reexport() { + use external::m1_reexport::*; + use external::m2_reexport::*; + 0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits] + //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + 0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope +} + +fn test_external_ambig_reexport() { + use external::ambig_reexport::*; + 0u8.method1(); //~ WARNING Use of ambiguously glob imported trait `Trait` [ambiguous_glob_imported_traits] + //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + 0u8.method2(); //~ ERROR: no method named `method2` found for type `u8` in the current scope +} + +fn main() {} diff --git a/tests/ui/imports/ambiguous-trait-in-scope.stderr b/tests/ui/imports/ambiguous-trait-in-scope.stderr new file mode 100644 index 0000000000000..cac1f4bb73fb1 --- /dev/null +++ b/tests/ui/imports/ambiguous-trait-in-scope.stderr @@ -0,0 +1,191 @@ +warning: Use of ambiguously glob imported trait `Trait` + --> $DIR/ambiguous-trait-in-scope.rs:32:9 + | +LL | use m1::*; + | -- `Trait` imported ambiguously here +LL | use m2::*; +LL | 0u8.method1(); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #147992 + = help: Import `Trait` explicitly + = note: `#[warn(ambiguous_glob_imported_traits)]` (part of `#[warn(future_incompatible)]`) on by default + +error[E0599]: no method named `method2` found for type `u8` in the current scope + --> $DIR/ambiguous-trait-in-scope.rs:34:9 + | +LL | 0u8.method2(); + | ^^^^^^^ method not found in `u8` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them + | +LL + use ambiguous_trait_reexport::m2::Trait; + | +LL + use crate::m2::Trait; + | + +error[E0599]: no method named `method1` found for type `u8` in the current scope + --> $DIR/ambiguous-trait-in-scope.rs:41:9 + | +LL | 0u8.method1(); + | ^^^^^^^ method not found in `u8` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `method1` are implemented but not in scope; perhaps you want to import one of them + | +LL + use ambiguous_trait_reexport::m1::Trait; + | +LL + use crate::m1::Trait; + | + +warning: Use of ambiguously glob imported trait `Trait` + --> $DIR/ambiguous-trait-in-scope.rs:42:9 + | +LL | use m2::*; + | -- `Trait` imported ambiguously here +... +LL | 0u8.method2(); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #147992 + = help: Import `Trait` explicitly + +warning: Use of ambiguously glob imported trait `Trait` + --> $DIR/ambiguous-trait-in-scope.rs:49:9 + | +LL | use m1_reexport::*; + | ----------- `Trait` imported ambiguously here +LL | use m2_reexport::*; +LL | 0u8.method1(); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #147992 + = help: Import `Trait` explicitly + +error[E0599]: no method named `method2` found for type `u8` in the current scope + --> $DIR/ambiguous-trait-in-scope.rs:51:9 + | +LL | 0u8.method2(); + | ^^^^^^^ method not found in `u8` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them + | +LL + use ambiguous_trait_reexport::m2::Trait; + | +LL + use crate::m2::Trait; + | + +warning: Use of ambiguously glob imported trait `Trait` + --> $DIR/ambiguous-trait-in-scope.rs:56:9 + | +LL | use ambig_reexport::*; + | -------------- `Trait` imported ambiguously here +LL | 0u8.method1(); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #147992 + = help: Import `Trait` explicitly + +error[E0599]: no method named `method2` found for type `u8` in the current scope + --> $DIR/ambiguous-trait-in-scope.rs:58:9 + | +LL | 0u8.method2(); + | ^^^^^^^ method not found in `u8` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them + | +LL + use ambiguous_trait_reexport::m2::Trait; + | +LL + use crate::m2::Trait; + | + +warning: Use of ambiguously glob imported trait `Trait` + --> $DIR/ambiguous-trait-in-scope.rs:64:9 + | +LL | use external::m1::*; + | ------------ `Trait` imported ambiguously here +LL | use external::m2::*; +LL | 0u8.method1(); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #147992 + = help: Import `Trait` explicitly + +error[E0599]: no method named `method2` found for type `u8` in the current scope + --> $DIR/ambiguous-trait-in-scope.rs:66:9 + | +LL | 0u8.method2(); + | ^^^^^^^ method not found in `u8` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them + | +LL + use ambiguous_trait_reexport::m2::Trait; + | +LL + use crate::m2::Trait; + | + +warning: Use of ambiguously glob imported trait `Trait` + --> $DIR/ambiguous-trait-in-scope.rs:72:9 + | +LL | use external::m1_reexport::*; + | --------------------- `Trait` imported ambiguously here +LL | use external::m2_reexport::*; +LL | 0u8.method1(); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #147992 + = help: Import `Trait` explicitly + +error[E0599]: no method named `method2` found for type `u8` in the current scope + --> $DIR/ambiguous-trait-in-scope.rs:74:9 + | +LL | 0u8.method2(); + | ^^^^^^^ method not found in `u8` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them + | +LL + use ambiguous_trait_reexport::m2::Trait; + | +LL + use crate::m2::Trait; + | + +warning: Use of ambiguously glob imported trait `Trait` + --> $DIR/ambiguous-trait-in-scope.rs:79:9 + | +LL | use external::ambig_reexport::*; + | ------------------------ `Trait` imported ambiguously here +LL | 0u8.method1(); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #147992 + = help: Import `Trait` explicitly + +error[E0599]: no method named `method2` found for type `u8` in the current scope + --> $DIR/ambiguous-trait-in-scope.rs:81:9 + | +LL | 0u8.method2(); + | ^^^^^^^ method not found in `u8` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `method2` are implemented but not in scope; perhaps you want to import one of them + | +LL + use ambiguous_trait_reexport::m2::Trait; + | +LL + use crate::m2::Trait; + | + +error: aborting due to 7 previous errors; 7 warnings emitted + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/imports/auxiliary/ambiguous-trait-reexport.rs b/tests/ui/imports/auxiliary/ambiguous-trait-reexport.rs new file mode 100644 index 0000000000000..77fb0c7d39348 --- /dev/null +++ b/tests/ui/imports/auxiliary/ambiguous-trait-reexport.rs @@ -0,0 +1,23 @@ +pub mod m1 { + pub trait Trait { + fn method1(&self) {} + } + impl Trait for u8 {} +} +pub mod m2 { + pub trait Trait { + fn method2(&self) {} + } + impl Trait for u8 {} +} +pub mod m1_reexport { + pub use crate::m1::Trait; +} +pub mod m2_reexport { + pub use crate::m2::Trait; +} + +pub mod ambig_reexport { + pub use crate::m1::*; + pub use crate::m2::*; +} diff --git a/tests/ui/imports/no-ambiguous-trait-lint-on-redundant-import.rs b/tests/ui/imports/no-ambiguous-trait-lint-on-redundant-import.rs new file mode 100644 index 0000000000000..ee08fd8ea8005 --- /dev/null +++ b/tests/ui/imports/no-ambiguous-trait-lint-on-redundant-import.rs @@ -0,0 +1,27 @@ +//@ check-pass +// The AMBIGUOUS_GLOB_IMPORTED_TRAITS lint is reported on uses of traits that are +// ambiguously glob imported. This test checks that we don't report this lint +// when the same trait is glob imported multiple times. + +mod t { + pub trait Trait { + fn method(&self) {} + } + + impl Trait for i8 {} +} + +mod m1 { + pub use t::Trait; +} + +mod m2 { + pub use t::Trait; +} + +use m1::*; +use m2::*; + +fn main() { + 0i8.method(); +}