Auto merge of #151409 - GuillaumeGomez:rollup-bDqwVwM, r=GuillaumeGomez

Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#147611 (Stabilize `-Zremap-path-scope`)
 - rust-lang/rust#149058 (FCW Lint when using an ambiguously glob imported trait)
 - rust-lang/rust#149644 (Create x86_64-unknown-linux-gnuasan target which enables ASAN by default)
 - rust-lang/rust#150524 (Test that -Zbuild-std=core works on a variety of profiles)
 - rust-lang/rust#151394 (Fix typos: 'occured' -> 'occurred' and 'non_existant' -> 'non_existent')
 - rust-lang/rust#151396 (`rustc_queries!`: Don't push the `(cache)` modifier twice)

r? @ghost
This commit is contained in:
bors 2026-01-20 14:42:53 +00:00
commit 5c49c4f7c8
67 changed files with 880 additions and 140 deletions

View file

@ -3337,6 +3337,7 @@ dependencies = [
"rustdoc-json-types",
"serde_json",
"similar",
"tempfile",
"wasmparser 0.236.1",
]

View file

@ -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)]

View file

@ -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>,

View file

@ -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

View file

@ -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.

View file

@ -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) });

View file

@ -622,7 +622,18 @@ struct ModuleData<'ra> {
globs: CmRefCell<Vec<Import<'ra>>>,
/// Used to memoize the traits in this module for faster searches through all traits in scope.
traits: CmRefCell<Option<Box<[(Macros20NormalizedIdent, Decl<'ra>, Option<Module<'ra>>)]>>>,
traits: CmRefCell<
Option<
Box<
[(
Macros20NormalizedIdent,
Decl<'ra>,
Option<Module<'ra>>,
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 });
}
}
}

View file

@ -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<PathBuf>,
@ -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<RustcOptGroup> {
"Remap source names in all output (compiler messages and output files)",
"<FROM>=<TO>",
),
opt(
Stable,
Opt,
"",
"remap-path-scope",
"Defines which scopes of paths should be remapped by `--remap-path-prefix`",
"<macro,diagnostics,debuginfo,coverage,object,all>",
),
opt(Unstable, Multi, "", "env-set", "Inject an environment variable", "<VAR>=<VALUE>"),
];
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,

View file

@ -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 = "<key>:<type>:<value>:<behavior>. 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<RelocModel>, 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<PathBuf> = (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<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"directory into which to write optimization remarks (if not specified, they will be \
written to standard error output)"),

View file

@ -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>]>

View file

@ -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"

View file

@ -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
}

View file

@ -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),
},

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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 \

View file

@ -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"])
}

View file

@ -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()

View file

@ -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",

View file

@ -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)

View file

@ -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)

View file

@ -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),

View file

@ -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 <host> -> Tidy 1 <host>
[test] tidy <>
[build] rustdoc 0 <host>
@ -2255,7 +2255,7 @@ mod snapshot {
insta::assert_snapshot!(
prepare_test_config(&ctx)
.stage(2)
.render_steps(), @r"
.render_steps(), @"
[build] rustc 0 <host> -> Tidy 1 <host>
[test] tidy <>
[build] rustdoc 0 <host>

View file

@ -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

View file

@ -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,

View file

@ -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)

View file

@ -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.
<a id="option-remap-path-scope"></a>
## `--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.
<a id="option-json"></a>
## `--json`: configure json messages printed by the compiler

View file

@ -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

View file

@ -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`.

View file

@ -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

View file

@ -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
```

View file

@ -77,6 +77,7 @@ string_enum! {
RustdocUi => "rustdoc-ui",
Ui => "ui",
UiFullDeps => "ui-fulldeps",
BuildStd => "build-std",
}
}

View file

@ -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"),

View file

@ -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!(

View file

@ -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<std::string> handle_execution_end();
/***** Functions for handling events encountered during program execution. *****/

View file

@ -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<CxxString>;
/***** Functions for handling events encountered during program execution. *****/

View file

@ -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.

View file

@ -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

View file

@ -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<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice());

View file

@ -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::{

View file

@ -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)
}

View file

@ -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
}

View file

@ -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

View file

@ -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<String, Value> = 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();
}

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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();

View file

@ -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");

View file

@ -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");

View file

@ -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 <FROM>=<TO>
+ Remap source names in all output (compiler messages
+ and output files)
+ --remap-path-scope <macro,diagnostics,debuginfo,coverage,object,all>
+ Defines which scopes of paths should be remapped by
+ `--remap-path-prefix`
+ @path Read newline separated options from `path`
Additional help:

View file

@ -83,6 +83,9 @@ Options:
--remap-path-prefix <FROM>=<TO>
Remap source names in all output (compiler messages
and output files)
--remap-path-scope <macro,diagnostics,debuginfo,coverage,object,all>
Defines which scopes of paths should be remapped by
`--remap-path-prefix`
@path Read newline separated options from `path`
Additional help:

View file

@ -171,8 +171,7 @@ enum RemapPathPrefix {
Unspecified,
}
/// `-Zremap-path-scope`. See
/// <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/remap-path-scope.html#remap-path-scope>.
/// `--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.

View file

@ -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;

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {}

View file

@ -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 {}

View file

@ -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 {}

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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() {}

View file

@ -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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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`.

View file

@ -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::*;
}

View file

@ -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();
}