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:
commit
5c49c4f7c8
67 changed files with 880 additions and 140 deletions
|
|
@ -3337,6 +3337,7 @@ dependencies = [
|
|||
"rustdoc-json-types",
|
||||
"serde_json",
|
||||
"similar",
|
||||
"tempfile",
|
||||
"wasmparser 0.236.1",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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) });
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)"),
|
||||
|
|
|
|||
|
|
@ -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>]>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -77,6 +77,7 @@ string_enum! {
|
|||
RustdocUi => "rustdoc-ui",
|
||||
Ui => "ui",
|
||||
UiFullDeps => "ui-fulldeps",
|
||||
BuildStd => "build-std",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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!(
|
||||
|
|
|
|||
|
|
@ -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. *****/
|
||||
|
|
|
|||
|
|
@ -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. *****/
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
131
tests/build-std/configurations/rmake.rs
Normal file
131
tests/build-std/configurations/rmake.rs
Normal 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();
|
||||
}
|
||||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
84
tests/ui/imports/ambiguous-trait-in-scope.rs
Normal file
84
tests/ui/imports/ambiguous-trait-in-scope.rs
Normal 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() {}
|
||||
191
tests/ui/imports/ambiguous-trait-in-scope.stderr
Normal file
191
tests/ui/imports/ambiguous-trait-in-scope.stderr
Normal 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`.
|
||||
23
tests/ui/imports/auxiliary/ambiguous-trait-reexport.rs
Normal file
23
tests/ui/imports/auxiliary/ambiguous-trait-reexport.rs
Normal 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::*;
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue