Auto merge of #145407 - Kobzol:rollup-g6yhx82, r=Kobzol
Rollup of 11 pull requests Successful merges: - rust-lang/rust#137872 (Include whitespace in "remove |" suggestion and make it hidden) - rust-lang/rust#144631 (Fix test intrinsic-raw_eq-const-bad for big-endian) - rust-lang/rust#145233 (cfg_select: Support unbraced expressions) - rust-lang/rust#145261 (Improve tracing in bootstrap) - rust-lang/rust#145324 (Rename and document `ONLY_HOSTS` in bootstrap) - rust-lang/rust#145353 (bootstrap: Fix jemalloc 64K page support for aarch64 tools) - rust-lang/rust#145379 (bootstrap: Support passing `--timings` to cargo) - rust-lang/rust#145397 (Rust documentation, use `rustc-dev-guide` :3) - rust-lang/rust#145398 (Use `default_field_values` in `Resolver`) - rust-lang/rust#145401 (cleanup: Remove useless `[T].iter().last()`) - rust-lang/rust#145403 (Adjust error message grammar to be less awkward) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
3507a749b3
70 changed files with 976 additions and 813 deletions
|
|
@ -1741,7 +1741,7 @@ fn deny_equality_constraints(
|
|||
.map(|segment| segment.ident.name)
|
||||
.zip(poly.trait_ref.path.segments.iter().map(|segment| segment.ident.name))
|
||||
.all(|(a, b)| a == b)
|
||||
&& let Some(potential_assoc) = full_path.segments.iter().last()
|
||||
&& let Some(potential_assoc) = full_path.segments.last()
|
||||
{
|
||||
suggest(poly, potential_assoc, predicate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
.with_span_help(
|
||||
self.get_closure_bound_clause_span(*def_id),
|
||||
"`Fn` and `FnMut` closures require captured values to be able to be \
|
||||
consumed multiple times, but an `FnOnce` consume them only once",
|
||||
consumed multiple times, but `FnOnce` closures may consume them only once",
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -1113,7 +1113,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
.map(|snippet| {
|
||||
debug_assert!(
|
||||
!(sp.is_empty() && snippet.is_empty()),
|
||||
"Span must not be empty and have no suggestion"
|
||||
"Span `{sp:?}` must not be empty and have no suggestion"
|
||||
);
|
||||
Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] }
|
||||
})
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ impl<'ty> FieldInnerTy<'ty> {
|
|||
};
|
||||
|
||||
let path = &ty_path.path;
|
||||
let ty = path.segments.iter().last().unwrap();
|
||||
let ty = path.segments.last().unwrap();
|
||||
let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments else {
|
||||
panic!("expected bracketed generic arguments");
|
||||
};
|
||||
|
|
|
|||
|
|
@ -862,8 +862,8 @@ parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up
|
|||
|
||||
parse_too_short_hex_escape = numeric character escape is too short
|
||||
|
||||
parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
|
||||
.suggestion = remove the `{$token}`
|
||||
parse_trailing_vert_not_allowed = a trailing `{$token}` is not allowed in an or-pattern
|
||||
parse_trailing_vert_not_allowed_suggestion = remove the `{$token}`
|
||||
|
||||
parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
|
||||
parse_trait_alias_cannot_be_const = trait aliases cannot be `const`
|
||||
|
|
|
|||
|
|
@ -2661,7 +2661,7 @@ pub(crate) enum TopLevelOrPatternNotAllowedSugg {
|
|||
parse_sugg_remove_leading_vert_in_pattern,
|
||||
code = "",
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
style = "tool-only"
|
||||
)]
|
||||
RemoveLeadingVert {
|
||||
#[primary_span]
|
||||
|
|
@ -2694,12 +2694,25 @@ pub(crate) struct UnexpectedVertVertInPattern {
|
|||
pub start: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
parse_trailing_vert_not_allowed,
|
||||
code = "",
|
||||
applicability = "machine-applicable",
|
||||
style = "tool-only"
|
||||
)]
|
||||
pub(crate) struct TrailingVertSuggestion {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_trailing_vert_not_allowed)]
|
||||
pub(crate) struct TrailingVertNotAllowed {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "", applicability = "machine-applicable", style = "verbose")]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: TrailingVertSuggestion,
|
||||
#[label(parse_label_while_parsing_or_pattern_here)]
|
||||
pub start: Option<Span>,
|
||||
pub token: Token,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use rustc_ast::token::Token;
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::{MetaItemInner, token};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::exp;
|
||||
use crate::parser::Parser;
|
||||
use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos};
|
||||
|
||||
pub enum CfgSelectPredicate {
|
||||
Cfg(MetaItemInner),
|
||||
|
|
@ -23,19 +24,26 @@ pub struct CfgSelectBranches {
|
|||
pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>,
|
||||
}
|
||||
|
||||
/// Parses a `TokenTree` that must be of the form `{ /* ... */ }`, and returns a `TokenStream` where
|
||||
/// the surrounding braces are stripped.
|
||||
/// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an
|
||||
/// expression followed by a comma (and strip the comma).
|
||||
fn parse_token_tree<'a>(p: &mut Parser<'a>) -> PResult<'a, TokenStream> {
|
||||
// Generate an error if the `=>` is not followed by `{`.
|
||||
if p.token != token::OpenBrace {
|
||||
p.expect(exp!(OpenBrace))?;
|
||||
if p.token == token::OpenBrace {
|
||||
// Strip the outer '{' and '}'.
|
||||
match p.parse_token_tree() {
|
||||
TokenTree::Token(..) => unreachable!("because of the expect above"),
|
||||
TokenTree::Delimited(.., tts) => return Ok(tts),
|
||||
}
|
||||
}
|
||||
|
||||
// Strip the outer '{' and '}'.
|
||||
match p.parse_token_tree() {
|
||||
TokenTree::Token(..) => unreachable!("because of the expect above"),
|
||||
TokenTree::Delimited(.., tts) => Ok(tts),
|
||||
let expr = p.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| {
|
||||
p.parse_expr_res(Restrictions::STMT_EXPR, AttrWrapper::empty())
|
||||
.map(|(expr, _)| (expr, Trailing::No, UsePreAttrPos::No))
|
||||
})?;
|
||||
if !classify::expr_is_complete(&expr) && p.token != token::CloseBrace && p.token != token::Eof {
|
||||
p.expect(exp!(Comma))?;
|
||||
} else {
|
||||
let _ = p.eat(exp!(Comma));
|
||||
}
|
||||
Ok(TokenStream::from_ast(&expr))
|
||||
}
|
||||
|
||||
pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> {
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ use crate::errors::{
|
|||
GenericArgsInPatRequireTurbofishSyntax, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow,
|
||||
InclusiveRangeNoEnd, InvalidMutInPattern, ParenRangeSuggestion, PatternOnWrongSideOfAt,
|
||||
RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder, TopLevelOrPatternNotAllowed,
|
||||
TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, UnexpectedExpressionInPattern,
|
||||
UnexpectedExpressionInPatternSugg, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat,
|
||||
UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam,
|
||||
UnexpectedVertVertInPattern, WrapInParens,
|
||||
TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, TrailingVertSuggestion,
|
||||
UnexpectedExpressionInPattern, UnexpectedExpressionInPatternSugg, UnexpectedLifetimeInPattern,
|
||||
UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
|
||||
UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens,
|
||||
};
|
||||
use crate::parser::expr::{DestructuredFloat, could_be_unclosed_char_literal};
|
||||
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
|
||||
|
|
@ -267,10 +267,9 @@ impl<'a> Parser<'a> {
|
|||
|
||||
if let PatKind::Or(pats) = &pat.kind {
|
||||
let span = pat.span;
|
||||
let sub = if pats.len() == 1 {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert {
|
||||
span: span.with_hi(span.lo() + BytePos(1)),
|
||||
})
|
||||
let sub = if let [_] = &pats[..] {
|
||||
let span = span.with_hi(span.lo() + BytePos(1));
|
||||
Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span })
|
||||
} else {
|
||||
Some(TopLevelOrPatternNotAllowedSugg::WrapInParens {
|
||||
span,
|
||||
|
|
@ -362,6 +361,9 @@ impl<'a> Parser<'a> {
|
|||
self.dcx().emit_err(TrailingVertNotAllowed {
|
||||
span: self.token.span,
|
||||
start: lo,
|
||||
suggestion: TrailingVertSuggestion {
|
||||
span: self.prev_token.span.shrink_to_hi().with_hi(self.token.span.hi()),
|
||||
},
|
||||
token: self.token,
|
||||
note_double_vert: self.token.kind == token::OrOr,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(default_field_values)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
|
@ -1075,7 +1076,7 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
/// Assert that we are in speculative resolution mode.
|
||||
assert_speculative: bool,
|
||||
|
||||
prelude: Option<Module<'ra>>,
|
||||
prelude: Option<Module<'ra>> = None,
|
||||
extern_prelude: FxIndexMap<Macros20NormalizedIdent, ExternPreludeEntry<'ra>>,
|
||||
|
||||
/// N.B., this is used only for better diagnostics, not name resolution itself.
|
||||
|
|
@ -1087,10 +1088,10 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
field_visibility_spans: FxHashMap<DefId, Vec<Span>>,
|
||||
|
||||
/// All imports known to succeed or fail.
|
||||
determined_imports: Vec<Import<'ra>>,
|
||||
determined_imports: Vec<Import<'ra>> = Vec::new(),
|
||||
|
||||
/// All non-determined imports.
|
||||
indeterminate_imports: Vec<Import<'ra>>,
|
||||
indeterminate_imports: Vec<Import<'ra>> = Vec::new(),
|
||||
|
||||
// Spans for local variables found during pattern resolution.
|
||||
// Used for suggestions during error reporting.
|
||||
|
|
@ -1141,19 +1142,19 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
|
||||
/// Maps glob imports to the names of items actually imported.
|
||||
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
|
||||
glob_error: Option<ErrorGuaranteed>,
|
||||
visibilities_for_hashing: Vec<(LocalDefId, Visibility)>,
|
||||
glob_error: Option<ErrorGuaranteed> = None,
|
||||
visibilities_for_hashing: Vec<(LocalDefId, Visibility)> = Vec::new(),
|
||||
used_imports: FxHashSet<NodeId>,
|
||||
maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
|
||||
|
||||
/// Privacy errors are delayed until the end in order to deduplicate them.
|
||||
privacy_errors: Vec<PrivacyError<'ra>>,
|
||||
privacy_errors: Vec<PrivacyError<'ra>> = Vec::new(),
|
||||
/// Ambiguity errors are delayed for deduplication.
|
||||
ambiguity_errors: Vec<AmbiguityError<'ra>>,
|
||||
ambiguity_errors: Vec<AmbiguityError<'ra>> = Vec::new(),
|
||||
/// `use` injections are delayed for better placement and deduplication.
|
||||
use_injections: Vec<UseError<'tcx>>,
|
||||
use_injections: Vec<UseError<'tcx>> = Vec::new(),
|
||||
/// Crate-local macro expanded `macro_export` referred to by a module-relative path.
|
||||
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
|
||||
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)> = BTreeSet::new(),
|
||||
|
||||
arenas: &'ra ResolverArenas<'ra>,
|
||||
dummy_binding: NameBinding<'ra>,
|
||||
|
|
@ -1205,9 +1206,9 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
/// Avoid duplicated errors for "name already defined".
|
||||
name_already_seen: FxHashMap<Symbol, Span>,
|
||||
|
||||
potentially_unused_imports: Vec<Import<'ra>>,
|
||||
potentially_unused_imports: Vec<Import<'ra>> = Vec::new(),
|
||||
|
||||
potentially_unnecessary_qualifications: Vec<UnnecessaryQualification<'ra>>,
|
||||
potentially_unnecessary_qualifications: Vec<UnnecessaryQualification<'ra>> = Vec::new(),
|
||||
|
||||
/// Table for mapping struct IDs into struct constructor IDs,
|
||||
/// it's not used during normal resolution, only for better error reporting.
|
||||
|
|
@ -1216,7 +1217,7 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
|
||||
lint_buffer: LintBuffer,
|
||||
|
||||
next_node_id: NodeId,
|
||||
next_node_id: NodeId = CRATE_NODE_ID,
|
||||
|
||||
node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>,
|
||||
|
||||
|
|
@ -1234,17 +1235,17 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
|
||||
delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
|
||||
|
||||
main_def: Option<MainDefinition>,
|
||||
main_def: Option<MainDefinition> = None,
|
||||
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
|
||||
/// A list of proc macro LocalDefIds, written out in the order in which
|
||||
/// they are declared in the static array generated by proc_macro_harness.
|
||||
proc_macros: Vec<LocalDefId>,
|
||||
proc_macros: Vec<LocalDefId> = Vec::new(),
|
||||
confused_type_with_std_module: FxIndexMap<Span, Span>,
|
||||
/// Whether lifetime elision was successful.
|
||||
lifetime_elision_allowed: FxHashSet<NodeId>,
|
||||
|
||||
/// Names of items that were stripped out via cfg with their corresponding cfg meta item.
|
||||
stripped_cfg_items: Vec<StrippedCfgItem<NodeId>>,
|
||||
stripped_cfg_items: Vec<StrippedCfgItem<NodeId>> = Vec::new(),
|
||||
|
||||
effective_visibilities: EffectiveVisibilities,
|
||||
doc_link_resolutions: FxIndexMap<LocalDefId, DocLinkResMap>,
|
||||
|
|
@ -1558,9 +1559,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
field_defaults: Default::default(),
|
||||
field_visibility_spans: FxHashMap::default(),
|
||||
|
||||
determined_imports: Vec::new(),
|
||||
indeterminate_imports: Vec::new(),
|
||||
|
||||
pat_span_map: Default::default(),
|
||||
partial_res_map: Default::default(),
|
||||
import_res_map: Default::default(),
|
||||
|
|
@ -1579,16 +1577,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ast_transform_scopes: FxHashMap::default(),
|
||||
|
||||
glob_map: Default::default(),
|
||||
glob_error: None,
|
||||
visibilities_for_hashing: Default::default(),
|
||||
used_imports: FxHashSet::default(),
|
||||
maybe_unused_trait_imports: Default::default(),
|
||||
|
||||
privacy_errors: Vec::new(),
|
||||
ambiguity_errors: Vec::new(),
|
||||
use_injections: Vec::new(),
|
||||
macro_expanded_macro_export_errors: BTreeSet::new(),
|
||||
|
||||
arenas,
|
||||
dummy_binding: arenas.new_pub_res_binding(Res::Err, DUMMY_SP, LocalExpnId::ROOT),
|
||||
builtin_types_bindings: PrimTy::ALL
|
||||
|
|
@ -1632,8 +1623,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
derive_data: Default::default(),
|
||||
local_macro_def_scopes: FxHashMap::default(),
|
||||
name_already_seen: FxHashMap::default(),
|
||||
potentially_unused_imports: Vec::new(),
|
||||
potentially_unnecessary_qualifications: Default::default(),
|
||||
struct_constructors: Default::default(),
|
||||
unused_macros: Default::default(),
|
||||
unused_macro_rules: Default::default(),
|
||||
|
|
@ -1643,16 +1632,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
builtin_attrs: Default::default(),
|
||||
containers_deriving_copy: Default::default(),
|
||||
lint_buffer: LintBuffer::default(),
|
||||
next_node_id: CRATE_NODE_ID,
|
||||
node_id_to_def_id,
|
||||
disambiguator: DisambiguatorState::new(),
|
||||
placeholder_field_indices: Default::default(),
|
||||
invocation_parents,
|
||||
legacy_const_generic_args: Default::default(),
|
||||
item_generics_num_lifetimes: Default::default(),
|
||||
main_def: Default::default(),
|
||||
trait_impls: Default::default(),
|
||||
proc_macros: Default::default(),
|
||||
confused_type_with_std_module: Default::default(),
|
||||
lifetime_elision_allowed: Default::default(),
|
||||
stripped_cfg_items: Default::default(),
|
||||
|
|
@ -1667,6 +1653,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
current_crate_outer_attr_insert_span,
|
||||
mods_with_parse_errors: Default::default(),
|
||||
impl_trait_names: Default::default(),
|
||||
..
|
||||
};
|
||||
|
||||
let root_parent_scope = ParentScope::module(graph_root, resolver.arenas);
|
||||
|
|
|
|||
|
|
@ -223,13 +223,14 @@ pub macro assert_matches {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The `cfg_select!` macro can also be used in expression position:
|
||||
/// The `cfg_select!` macro can also be used in expression position, with or without braces on the
|
||||
/// right-hand side:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cfg_select)]
|
||||
///
|
||||
/// let _some_string = cfg_select! {
|
||||
/// unix => { "With great power comes great electricity bills" }
|
||||
/// unix => "With great power comes great electricity bills",
|
||||
/// _ => { "Behind every successful diet is an unwatched pizza" }
|
||||
/// };
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -11,21 +11,18 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
|
|
@ -47,6 +44,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"build_helper",
|
||||
"cc",
|
||||
"chrono",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"cmake",
|
||||
|
|
@ -71,7 +69,6 @@ dependencies = [
|
|||
"toml",
|
||||
"tracing",
|
||||
"tracing-chrome",
|
||||
"tracing-forest",
|
||||
"tracing-subscriber",
|
||||
"walkdir",
|
||||
"windows",
|
||||
|
|
@ -112,6 +109,15 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
|
|
@ -458,6 +464,15 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.1"
|
||||
|
|
@ -775,26 +790,6 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
|
|
@ -857,19 +852,6 @@ dependencies = [
|
|||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-forest"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ default-run = "bootstrap"
|
|||
|
||||
[features]
|
||||
build-metrics = ["sysinfo"]
|
||||
tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:tracing-forest"]
|
||||
tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:chrono", "dep:tempfile"]
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
|
@ -61,10 +61,11 @@ xz2 = "0.1"
|
|||
sysinfo = { version = "0.37.0", default-features = false, optional = true, features = ["system"] }
|
||||
|
||||
# Dependencies needed by the `tracing` feature
|
||||
chrono = { version = "0.4", default-features = false, optional = true, features = ["now", "std"] }
|
||||
tracing = { version = "0.1", optional = true, features = ["attributes"] }
|
||||
tracing-chrome = { version = "0.7", optional = true }
|
||||
tracing-subscriber = { version = "0.3", optional = true, features = ["env-filter", "fmt", "registry", "std"] }
|
||||
tracing-forest = { version = "0.1.6", optional = true, default-features = false, features = ["smallvec", "ansi", "env-filter"] }
|
||||
tempfile = { version = "3.15.0", optional = true }
|
||||
|
||||
[target.'cfg(windows)'.dependencies.junction]
|
||||
version = "1.0.0"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io::{self, BufRead, BufReader, IsTerminal, Write};
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::time::Instant;
|
||||
use std::{env, process};
|
||||
|
|
@ -15,19 +16,16 @@ use bootstrap::{
|
|||
Build, CONFIG_CHANGE_HISTORY, ChangeId, Config, Flags, Subcommand, debug,
|
||||
find_recent_config_change_ids, human_readable_changes, t,
|
||||
};
|
||||
#[cfg(feature = "tracing")]
|
||||
use tracing::instrument;
|
||||
|
||||
fn is_bootstrap_profiling_enabled() -> bool {
|
||||
env::var("BOOTSTRAP_PROFILE").is_ok_and(|v| v == "1")
|
||||
fn is_tracing_enabled() -> bool {
|
||||
cfg!(feature = "tracing")
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", instrument(level = "trace", name = "main"))]
|
||||
fn main() {
|
||||
#[cfg(feature = "tracing")]
|
||||
let _guard = setup_tracing();
|
||||
let guard = bootstrap::setup_tracing("BOOTSTRAP_TRACING");
|
||||
|
||||
let start_time = Instant::now();
|
||||
let _start_time = Instant::now();
|
||||
|
||||
let args = env::args().skip(1).collect::<Vec<_>>();
|
||||
|
||||
|
|
@ -102,6 +100,35 @@ fn main() {
|
|||
let dump_bootstrap_shims = config.dump_bootstrap_shims;
|
||||
let out_dir = config.out.clone();
|
||||
|
||||
let tracing_enabled = is_tracing_enabled();
|
||||
|
||||
// Prepare a directory for tracing output
|
||||
// Also store a symlink named "latest" to point to the latest tracing directory.
|
||||
let tracing_dir = out_dir.join("bootstrap-trace").join(std::process::id().to_string());
|
||||
let latest_trace_dir = tracing_dir.parent().unwrap().join("latest");
|
||||
if tracing_enabled {
|
||||
let _ = std::fs::remove_dir_all(&tracing_dir);
|
||||
std::fs::create_dir_all(&tracing_dir).unwrap();
|
||||
|
||||
#[cfg(windows)]
|
||||
let _ = std::fs::remove_dir(&latest_trace_dir);
|
||||
#[cfg(not(windows))]
|
||||
let _ = std::fs::remove_file(&latest_trace_dir);
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn symlink_dir_inner(original: &Path, link: &Path) -> io::Result<()> {
|
||||
use std::os::unix::fs;
|
||||
fs::symlink(original, link)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
|
||||
junction::create(target, junction)
|
||||
}
|
||||
|
||||
t!(symlink_dir_inner(&tracing_dir, &latest_trace_dir));
|
||||
}
|
||||
|
||||
debug!("creating new build based on config");
|
||||
let mut build = Build::new(config);
|
||||
build.build();
|
||||
|
|
@ -156,12 +183,13 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
if is_bootstrap_profiling_enabled() {
|
||||
build.report_summary(start_time);
|
||||
}
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
build.report_step_graph();
|
||||
{
|
||||
build.report_summary(&tracing_dir.join("command-stats.txt"), _start_time);
|
||||
build.report_step_graph(&tracing_dir);
|
||||
guard.copy_to_dir(&tracing_dir);
|
||||
eprintln!("Tracing/profiling output has been written to {}", latest_trace_dir.display());
|
||||
}
|
||||
}
|
||||
|
||||
fn check_version(config: &Config) -> Option<String> {
|
||||
|
|
@ -219,37 +247,3 @@ fn check_version(config: &Config) -> Option<String> {
|
|||
|
||||
Some(msg)
|
||||
}
|
||||
|
||||
// # Note on `tracing` usage in bootstrap
|
||||
//
|
||||
// Due to the conditional compilation via the `tracing` cargo feature, this means that `tracing`
|
||||
// usages in bootstrap need to be also gated behind the `tracing` feature:
|
||||
//
|
||||
// - `tracing` macros with log levels (`trace!`, `debug!`, `warn!`, `info`, `error`) should not be
|
||||
// used *directly*. You should use the wrapped `tracing` macros which gate the actual invocations
|
||||
// behind `feature = "tracing"`.
|
||||
// - `tracing`'s `#[instrument(..)]` macro will need to be gated like `#![cfg_attr(feature =
|
||||
// "tracing", instrument(..))]`.
|
||||
#[cfg(feature = "tracing")]
|
||||
fn setup_tracing() -> impl Drop {
|
||||
use tracing_forest::ForestLayer;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
|
||||
let filter = EnvFilter::from_env("BOOTSTRAP_TRACING");
|
||||
|
||||
let mut chrome_layer = tracing_chrome::ChromeLayerBuilder::new().include_args(true);
|
||||
|
||||
// Writes the Chrome profile to trace-<unix-timestamp>.json if enabled
|
||||
if !is_bootstrap_profiling_enabled() {
|
||||
chrome_layer = chrome_layer.writer(io::sink());
|
||||
}
|
||||
|
||||
let (chrome_layer, _guard) = chrome_layer.build();
|
||||
|
||||
let registry =
|
||||
tracing_subscriber::registry().with(filter).with(ForestLayer::default()).with(chrome_layer);
|
||||
|
||||
tracing::subscriber::set_global_default(registry).unwrap();
|
||||
_guard
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ impl Rustc {
|
|||
|
||||
impl Step for Rustc {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -324,7 +324,7 @@ pub struct CodegenBackend {
|
|||
|
||||
impl Step for CodegenBackend {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -410,7 +410,7 @@ macro_rules! tool_check_step {
|
|||
|
||||
impl Step for $name {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
/// Most of the tool-checks using this macro are run by default.
|
||||
const DEFAULT: bool = true $( && $default )?;
|
||||
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ impl Rustc {
|
|||
|
||||
impl Step for Rustc {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use std::{env, fs, str};
|
|||
|
||||
use serde_derive::Deserialize;
|
||||
#[cfg(feature = "tracing")]
|
||||
use tracing::{instrument, span};
|
||||
use tracing::span;
|
||||
|
||||
use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags};
|
||||
use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
|
||||
|
|
@ -104,7 +104,6 @@ impl Step for Std {
|
|||
run.crate_or_deps("sysroot").path("library")
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))]
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let crates = std_crates_for_run_make(&run);
|
||||
let builder = run.builder;
|
||||
|
|
@ -135,19 +134,6 @@ impl Step for Std {
|
|||
/// This will build the standard library for a particular stage of the build
|
||||
/// using the `compiler` targeting the `target` architecture. The artifacts
|
||||
/// created will also be linked into the sysroot directory.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "Std::run",
|
||||
skip_all,
|
||||
fields(
|
||||
target = ?self.target,
|
||||
compiler = ?self.compiler,
|
||||
force_recompile = self.force_recompile
|
||||
),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let target = self.target;
|
||||
|
||||
|
|
@ -717,19 +703,6 @@ impl Step for StdLink {
|
|||
/// Note that this assumes that `compiler` has already generated the libstd
|
||||
/// libraries for `target`, and this method will find them in the relevant
|
||||
/// output directory.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "trace",
|
||||
name = "StdLink::run",
|
||||
skip_all,
|
||||
fields(
|
||||
compiler = ?self.compiler,
|
||||
target_compiler = ?self.target_compiler,
|
||||
target = ?self.target
|
||||
),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let compiler = self.compiler;
|
||||
let target_compiler = self.target_compiler;
|
||||
|
|
@ -895,15 +868,6 @@ impl Step for StartupObjects {
|
|||
/// They don't require any library support as they're just plain old object
|
||||
/// files, so we just use the nightly snapshot compiler to always build them (as
|
||||
/// no other compilers are guaranteed to be available).
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "trace",
|
||||
name = "StartupObjects::run",
|
||||
skip_all,
|
||||
fields(compiler = ?self.compiler, target = ?self.target),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
|
||||
let for_compiler = self.compiler;
|
||||
let target = self.target;
|
||||
|
|
@ -995,7 +959,7 @@ impl Step for Rustc {
|
|||
/// uplifting it from stage Y, causing the other stage to fail when attempting to link with
|
||||
/// stage X which was never actually built.
|
||||
type Output = u32;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -1033,15 +997,6 @@ impl Step for Rustc {
|
|||
/// This will build the compiler for a particular stage of the build using
|
||||
/// the `build_compiler` targeting the `target` architecture. The artifacts
|
||||
/// created will also be linked into the sysroot directory.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "Rustc::run",
|
||||
skip_all,
|
||||
fields(previous_compiler = ?self.build_compiler, target = ?self.target),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> u32 {
|
||||
let build_compiler = self.build_compiler;
|
||||
let target = self.target;
|
||||
|
|
@ -1397,6 +1352,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
|
|||
|
||||
// Build jemalloc on AArch64 with support for page sizes up to 64K
|
||||
// See: https://github.com/rust-lang/rust/pull/135081
|
||||
// See also the "JEMALLOC_SYS_WITH_LG_PAGE" setting in the tool build step.
|
||||
if builder.config.jemalloc(target)
|
||||
&& target.starts_with("aarch64")
|
||||
&& env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
|
||||
|
|
@ -1517,19 +1473,6 @@ impl Step for RustcLink {
|
|||
}
|
||||
|
||||
/// Same as `std_link`, only for librustc
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "trace",
|
||||
name = "RustcLink::run",
|
||||
skip_all,
|
||||
fields(
|
||||
compiler = ?self.compiler,
|
||||
previous_stage_compiler = ?self.previous_stage_compiler,
|
||||
target = ?self.target,
|
||||
),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let compiler = self.compiler;
|
||||
let previous_stage_compiler = self.previous_stage_compiler;
|
||||
|
|
@ -1559,7 +1502,7 @@ pub struct GccCodegenBackend {
|
|||
impl Step for GccCodegenBackend {
|
||||
type Output = GccCodegenBackendOutput;
|
||||
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("rustc_codegen_gcc").alias("cg_gcc")
|
||||
|
|
@ -1571,17 +1514,6 @@ impl Step for GccCodegenBackend {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "GccCodegenBackend::run",
|
||||
skip_all,
|
||||
fields(
|
||||
compilers = ?self.compilers,
|
||||
),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> Self::Output {
|
||||
let target = self.compilers.target();
|
||||
let build_compiler = self.compilers.build_compiler();
|
||||
|
|
@ -1644,7 +1576,7 @@ pub struct CraneliftCodegenBackend {
|
|||
|
||||
impl Step for CraneliftCodegenBackend {
|
||||
type Output = BuildStamp;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("rustc_codegen_cranelift").alias("cg_clif")
|
||||
|
|
@ -1656,17 +1588,6 @@ impl Step for CraneliftCodegenBackend {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "CraneliftCodegenBackend::run",
|
||||
skip_all,
|
||||
fields(
|
||||
compilers = ?self.compilers,
|
||||
),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> Self::Output {
|
||||
let target = self.compilers.target();
|
||||
let build_compiler = self.compilers.build_compiler();
|
||||
|
|
@ -1841,15 +1762,6 @@ impl Step for Sysroot {
|
|||
/// Returns the sysroot that `compiler` is supposed to use.
|
||||
/// For the stage0 compiler, this is stage0-sysroot (because of the initial std build).
|
||||
/// For all other stages, it's the same stage directory that the compiler lives in.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "Sysroot::run",
|
||||
skip_all,
|
||||
fields(compiler = ?self.compiler),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
let compiler = self.compiler;
|
||||
let host_dir = builder.out.join(compiler.host);
|
||||
|
|
@ -2008,7 +1920,7 @@ pub struct Assemble {
|
|||
|
||||
impl Step for Assemble {
|
||||
type Output = Compiler;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("compiler/rustc").path("compiler")
|
||||
|
|
@ -2025,15 +1937,6 @@ impl Step for Assemble {
|
|||
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler
|
||||
/// must have been previously produced by the `stage - 1` builder.build
|
||||
/// compiler.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "Assemble::run",
|
||||
skip_all,
|
||||
fields(target_compiler = ?self.target_compiler),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> Compiler {
|
||||
let target_compiler = self.target_compiler;
|
||||
|
||||
|
|
@ -2592,7 +2495,7 @@ pub fn stream_cargo(
|
|||
let mut cmd = cargo.into_cmd();
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let _run_span = crate::trace_cmd!(cmd);
|
||||
let _run_span = crate::utils::tracing::trace_cmd(&cmd);
|
||||
|
||||
// Instruct Cargo to give us json messages on stdout, critically leaving
|
||||
// stderr as piped so we can get those pretty colors.
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ pub struct RustcDocs {
|
|||
impl Step for RustcDocs {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -402,7 +402,7 @@ pub struct Rustc {
|
|||
impl Step for Rustc {
|
||||
type Output = GeneratedTarball;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("rustc")
|
||||
|
|
@ -794,7 +794,7 @@ pub struct RustcDev {
|
|||
impl Step for RustcDev {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("rustc-dev")
|
||||
|
|
@ -1024,7 +1024,7 @@ impl Step for Src {
|
|||
/// The output path of the src installer tarball
|
||||
type Output = GeneratedTarball;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("rust-src")
|
||||
|
|
@ -1085,7 +1085,7 @@ impl Step for PlainSourceTarball {
|
|||
/// Produces the location of the tarball generated
|
||||
type Output = GeneratedTarball;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -1233,7 +1233,7 @@ pub struct Cargo {
|
|||
impl Step for Cargo {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let default = should_build_extended_tool(run.builder, "cargo");
|
||||
|
|
@ -1287,7 +1287,7 @@ pub struct RustAnalyzer {
|
|||
impl Step for RustAnalyzer {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let default = should_build_extended_tool(run.builder, "rust-analyzer");
|
||||
|
|
@ -1330,7 +1330,7 @@ pub struct Clippy {
|
|||
impl Step for Clippy {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let default = should_build_extended_tool(run.builder, "clippy");
|
||||
|
|
@ -1378,7 +1378,7 @@ pub struct Miri {
|
|||
impl Step for Miri {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let default = should_build_extended_tool(run.builder, "miri");
|
||||
|
|
@ -1428,7 +1428,7 @@ pub struct CraneliftCodegenBackend {
|
|||
impl Step for CraneliftCodegenBackend {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
// We only want to build the cranelift backend in `x dist` if the backend was enabled
|
||||
|
|
@ -1519,7 +1519,7 @@ pub struct Rustfmt {
|
|||
impl Step for Rustfmt {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let default = should_build_extended_tool(run.builder, "rustfmt");
|
||||
|
|
@ -1564,7 +1564,7 @@ pub struct Extended {
|
|||
impl Step for Extended {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -2301,7 +2301,7 @@ pub struct LlvmTools {
|
|||
|
||||
impl Step for LlvmTools {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -2406,7 +2406,7 @@ pub struct LlvmBitcodeLinker {
|
|||
impl Step for LlvmBitcodeLinker {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
|
||||
|
|
@ -2458,7 +2458,7 @@ pub struct RustDev {
|
|||
impl Step for RustDev {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("rust-dev")
|
||||
|
|
@ -2561,7 +2561,7 @@ pub struct Bootstrap {
|
|||
impl Step for Bootstrap {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = false;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("bootstrap")
|
||||
|
|
@ -2601,7 +2601,7 @@ pub struct BuildManifest {
|
|||
impl Step for BuildManifest {
|
||||
type Output = GeneratedTarball;
|
||||
const DEFAULT: bool = false;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("build-manifest")
|
||||
|
|
@ -2633,7 +2633,7 @@ pub struct ReproducibleArtifacts {
|
|||
impl Step for ReproducibleArtifacts {
|
||||
type Output = Option<GeneratedTarball>;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("reproducible-artifacts")
|
||||
|
|
|
|||
|
|
@ -830,7 +830,7 @@ impl Rustc {
|
|||
impl Step for Rustc {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -975,7 +975,7 @@ macro_rules! tool_doc {
|
|||
impl Step for $tool {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -1139,7 +1139,7 @@ pub struct ErrorIndex {
|
|||
impl Step for ErrorIndex {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -1181,7 +1181,7 @@ pub struct UnstableBookGen {
|
|||
impl Step for UnstableBookGen {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -1248,7 +1248,7 @@ impl RustcBook {
|
|||
impl Step for RustcBook {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ impl GccOutput {
|
|||
impl Step for Gcc {
|
||||
type Output = GccOutput;
|
||||
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/gcc").alias("gcc")
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ macro_rules! install {
|
|||
$($name:ident,
|
||||
$condition_name: ident = $path_or_alias: literal,
|
||||
$default_cond:expr,
|
||||
only_hosts: $only_hosts:expr,
|
||||
IS_HOST: $IS_HOST:expr,
|
||||
$run_item:block $(, $c:ident)*;)+) => {
|
||||
$(
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
|
|
@ -183,7 +183,7 @@ macro_rules! install {
|
|||
impl Step for $name {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = $only_hosts;
|
||||
const IS_HOST: bool = $IS_HOST;
|
||||
$(const $c: bool = true;)*
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -206,11 +206,11 @@ macro_rules! install {
|
|||
}
|
||||
|
||||
install!((self, builder, _config),
|
||||
Docs, path = "src/doc", _config.docs, only_hosts: false, {
|
||||
Docs, path = "src/doc", _config.docs, IS_HOST: false, {
|
||||
let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
|
||||
install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
|
||||
};
|
||||
Std, path = "library/std", true, only_hosts: false, {
|
||||
Std, path = "library/std", true, IS_HOST: false, {
|
||||
// `expect` should be safe, only None when host != build, but this
|
||||
// only runs when host == build
|
||||
let tarball = builder.ensure(dist::Std {
|
||||
|
|
@ -219,13 +219,13 @@ install!((self, builder, _config),
|
|||
}).expect("missing std");
|
||||
install_sh(builder, "std", self.compiler.stage, Some(self.target), &tarball);
|
||||
};
|
||||
Cargo, alias = "cargo", Self::should_build(_config), only_hosts: true, {
|
||||
Cargo, alias = "cargo", Self::should_build(_config), IS_HOST: true, {
|
||||
let tarball = builder
|
||||
.ensure(dist::Cargo { build_compiler: self.compiler, target: self.target })
|
||||
.expect("missing cargo");
|
||||
install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
|
||||
};
|
||||
RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), only_hosts: true, {
|
||||
RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), IS_HOST: true, {
|
||||
if let Some(tarball) =
|
||||
builder.ensure(dist::RustAnalyzer { build_compiler: self.compiler, target: self.target })
|
||||
{
|
||||
|
|
@ -236,13 +236,13 @@ install!((self, builder, _config),
|
|||
);
|
||||
}
|
||||
};
|
||||
Clippy, alias = "clippy", Self::should_build(_config), only_hosts: true, {
|
||||
Clippy, alias = "clippy", Self::should_build(_config), IS_HOST: true, {
|
||||
let tarball = builder
|
||||
.ensure(dist::Clippy { build_compiler: self.compiler, target: self.target })
|
||||
.expect("missing clippy");
|
||||
install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
|
||||
};
|
||||
Miri, alias = "miri", Self::should_build(_config), only_hosts: true, {
|
||||
Miri, alias = "miri", Self::should_build(_config), IS_HOST: true, {
|
||||
if let Some(tarball) = builder.ensure(dist::Miri { build_compiler: self.compiler, target: self.target }) {
|
||||
install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
|
||||
} else {
|
||||
|
|
@ -252,7 +252,7 @@ install!((self, builder, _config),
|
|||
);
|
||||
}
|
||||
};
|
||||
LlvmTools, alias = "llvm-tools", _config.llvm_tools_enabled && _config.llvm_enabled(_config.host_target), only_hosts: true, {
|
||||
LlvmTools, alias = "llvm-tools", _config.llvm_tools_enabled && _config.llvm_enabled(_config.host_target), IS_HOST: true, {
|
||||
if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) {
|
||||
install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
|
||||
} else {
|
||||
|
|
@ -261,7 +261,7 @@ install!((self, builder, _config),
|
|||
);
|
||||
}
|
||||
};
|
||||
Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
|
||||
Rustfmt, alias = "rustfmt", Self::should_build(_config), IS_HOST: true, {
|
||||
if let Some(tarball) = builder.ensure(dist::Rustfmt {
|
||||
build_compiler: self.compiler,
|
||||
target: self.target
|
||||
|
|
@ -273,13 +273,13 @@ install!((self, builder, _config),
|
|||
);
|
||||
}
|
||||
};
|
||||
Rustc, path = "compiler/rustc", true, only_hosts: true, {
|
||||
Rustc, path = "compiler/rustc", true, IS_HOST: true, {
|
||||
let tarball = builder.ensure(dist::Rustc {
|
||||
compiler: builder.compiler(builder.top_stage, self.target),
|
||||
});
|
||||
install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
|
||||
};
|
||||
RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), only_hosts: true, {
|
||||
RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), IS_HOST: true, {
|
||||
if let Some(tarball) = builder.ensure(dist::CraneliftCodegenBackend {
|
||||
build_compiler: self.compiler,
|
||||
target: self.target
|
||||
|
|
@ -292,7 +292,7 @@ install!((self, builder, _config),
|
|||
);
|
||||
}
|
||||
};
|
||||
LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), only_hosts: true, {
|
||||
LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), IS_HOST: true, {
|
||||
if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.compiler, target: self.target }) {
|
||||
install_sh(builder, "llvm-bitcode-linker", self.compiler.stage, Some(self.target), &tarball);
|
||||
} else {
|
||||
|
|
@ -311,7 +311,7 @@ pub struct Src {
|
|||
impl Step for Src {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let config = &run.builder.config;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ use std::sync::OnceLock;
|
|||
use std::{env, fs};
|
||||
|
||||
use build_helper::git::PathFreshness;
|
||||
#[cfg(feature = "tracing")]
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step, StepMetadata};
|
||||
use crate::core::config::{Config, TargetSelection};
|
||||
|
|
@ -255,7 +253,7 @@ pub struct Llvm {
|
|||
impl Step for Llvm {
|
||||
type Output = LlvmResult;
|
||||
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/llvm-project").path("src/llvm-project/llvm")
|
||||
|
|
@ -266,15 +264,6 @@ impl Step for Llvm {
|
|||
}
|
||||
|
||||
/// Compile LLVM for `target`.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "Llvm::run",
|
||||
skip_all,
|
||||
fields(target = ?self.target),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> LlvmResult {
|
||||
let target = self.target;
|
||||
let target_native = if self.target.starts_with("riscv") {
|
||||
|
|
@ -908,7 +897,7 @@ pub struct Enzyme {
|
|||
|
||||
impl Step for Enzyme {
|
||||
type Output = PathBuf;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/enzyme/enzyme")
|
||||
|
|
@ -919,15 +908,6 @@ impl Step for Enzyme {
|
|||
}
|
||||
|
||||
/// Compile Enzyme for `target`.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "Enzyme::run",
|
||||
skip_all,
|
||||
fields(target = ?self.target),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
builder.require_submodule(
|
||||
"src/tools/enzyme",
|
||||
|
|
@ -1013,7 +993,7 @@ pub struct Lld {
|
|||
|
||||
impl Step for Lld {
|
||||
type Output = PathBuf;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/llvm-project/lld")
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub struct BuildManifest;
|
|||
|
||||
impl Step for BuildManifest {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/build-manifest")
|
||||
|
|
@ -61,7 +61,7 @@ pub struct BumpStage0;
|
|||
|
||||
impl Step for BumpStage0 {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/bump-stage0")
|
||||
|
|
@ -83,7 +83,7 @@ pub struct ReplaceVersionPlaceholder;
|
|||
|
||||
impl Step for ReplaceVersionPlaceholder {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/replace-version-placeholder")
|
||||
|
|
@ -107,7 +107,6 @@ pub struct Miri {
|
|||
|
||||
impl Step for Miri {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/miri")
|
||||
|
|
@ -175,7 +174,7 @@ pub struct CollectLicenseMetadata;
|
|||
|
||||
impl Step for CollectLicenseMetadata {
|
||||
type Output = PathBuf;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/collect-license-metadata")
|
||||
|
|
@ -206,7 +205,7 @@ pub struct GenerateCopyright;
|
|||
|
||||
impl Step for GenerateCopyright {
|
||||
type Output = Vec<PathBuf>;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/generate-copyright")
|
||||
|
|
@ -270,7 +269,7 @@ pub struct GenerateWindowsSys;
|
|||
|
||||
impl Step for GenerateWindowsSys {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/generate-windows-sys")
|
||||
|
|
@ -332,7 +331,7 @@ pub struct UnicodeTableGenerator;
|
|||
|
||||
impl Step for UnicodeTableGenerator {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/unicode-table-generator")
|
||||
|
|
@ -354,7 +353,7 @@ pub struct FeaturesStatusDump;
|
|||
|
||||
impl Step for FeaturesStatusDump {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/features-status-dump")
|
||||
|
|
@ -416,7 +415,7 @@ impl Step for CoverageDump {
|
|||
type Output = ();
|
||||
|
||||
const DEFAULT: bool = false;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/coverage-dump")
|
||||
|
|
@ -438,7 +437,7 @@ pub struct Rustfmt;
|
|||
|
||||
impl Step for Rustfmt {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/rustfmt")
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ pub(crate) struct MirOptPanicAbortSyntheticTarget {
|
|||
impl Step for MirOptPanicAbortSyntheticTarget {
|
||||
type Output = TargetSelection;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.never()
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ use std::path::{Path, PathBuf};
|
|||
use std::{env, fs, iter};
|
||||
|
||||
use build_helper::exit;
|
||||
#[cfg(feature = "tracing")]
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::core::build_steps::compile::{Std, run_cargo};
|
||||
use crate::core::build_steps::doc::DocumentationFormat;
|
||||
|
|
@ -51,7 +49,7 @@ pub struct CrateBootstrap {
|
|||
|
||||
impl Step for CrateBootstrap {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -109,7 +107,7 @@ pub struct Linkcheck {
|
|||
|
||||
impl Step for Linkcheck {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
|
||||
|
|
@ -189,7 +187,7 @@ pub struct HtmlCheck {
|
|||
impl Step for HtmlCheck {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -236,7 +234,7 @@ pub struct Cargotest {
|
|||
|
||||
impl Step for Cargotest {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/cargotest")
|
||||
|
|
@ -313,7 +311,7 @@ impl Cargo {
|
|||
|
||||
impl Step for Cargo {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path(Self::CRATE_PATH)
|
||||
|
|
@ -410,7 +408,7 @@ pub struct RustAnalyzer {
|
|||
|
||||
impl Step for RustAnalyzer {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -469,7 +467,7 @@ pub struct Rustfmt {
|
|||
|
||||
impl Step for Rustfmt {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/rustfmt")
|
||||
|
|
@ -561,7 +559,6 @@ impl Miri {
|
|||
|
||||
impl Step for Miri {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/miri")
|
||||
|
|
@ -681,7 +678,6 @@ pub struct CargoMiri {
|
|||
|
||||
impl Step for CargoMiri {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/miri/cargo-miri")
|
||||
|
|
@ -760,10 +756,6 @@ impl Step for CompiletestTest {
|
|||
}
|
||||
|
||||
/// Runs `cargo test` for compiletest.
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(level = "debug", name = "CompiletestTest::run", skip_all)
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let host = self.host;
|
||||
|
||||
|
|
@ -811,7 +803,7 @@ pub struct Clippy {
|
|||
|
||||
impl Step for Clippy {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -911,7 +903,7 @@ pub struct RustdocTheme {
|
|||
impl Step for RustdocTheme {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/rustdoc-themes")
|
||||
|
|
@ -948,7 +940,7 @@ pub struct RustdocJSStd {
|
|||
impl Step for RustdocJSStd {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let default = run.builder.config.nodejs.is_some();
|
||||
|
|
@ -1008,7 +1000,7 @@ pub struct RustdocJSNotStd {
|
|||
impl Step for RustdocJSNotStd {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let default = run.builder.config.nodejs.is_some();
|
||||
|
|
@ -1063,7 +1055,7 @@ pub struct RustdocGUI {
|
|||
impl Step for RustdocGUI {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -1156,7 +1148,7 @@ pub struct Tidy;
|
|||
impl Step for Tidy {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
/// Runs the `tidy` tool.
|
||||
///
|
||||
|
|
@ -1274,7 +1266,7 @@ macro_rules! test {
|
|||
mode: $mode:expr,
|
||||
suite: $suite:expr,
|
||||
default: $default:expr
|
||||
$( , only_hosts: $only_hosts:expr )? // default: false
|
||||
$( , IS_HOST: $IS_HOST:expr )? // default: false
|
||||
$( , compare_mode: $compare_mode:expr )? // default: None
|
||||
$( , )? // optional trailing comma
|
||||
}
|
||||
|
|
@ -1289,10 +1281,10 @@ macro_rules! test {
|
|||
impl Step for $name {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = $default;
|
||||
const ONLY_HOSTS: bool = (const {
|
||||
const IS_HOST: bool = (const {
|
||||
#[allow(unused_assignments, unused_mut)]
|
||||
let mut value = false;
|
||||
$( value = $only_hosts; )?
|
||||
$( value = $IS_HOST; )?
|
||||
value
|
||||
});
|
||||
|
||||
|
|
@ -1340,7 +1332,7 @@ pub struct CrateRunMakeSupport {
|
|||
|
||||
impl Step for CrateRunMakeSupport {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/run-make-support")
|
||||
|
|
@ -1377,7 +1369,7 @@ pub struct CrateBuildHelper {
|
|||
|
||||
impl Step for CrateBuildHelper {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/build_helper")
|
||||
|
|
@ -1445,7 +1437,7 @@ test!(UiFullDeps {
|
|||
mode: "ui",
|
||||
suite: "ui-fulldeps",
|
||||
default: true,
|
||||
only_hosts: true,
|
||||
IS_HOST: true,
|
||||
});
|
||||
|
||||
test!(Rustdoc {
|
||||
|
|
@ -1453,14 +1445,14 @@ test!(Rustdoc {
|
|||
mode: "rustdoc",
|
||||
suite: "rustdoc",
|
||||
default: true,
|
||||
only_hosts: true,
|
||||
IS_HOST: true,
|
||||
});
|
||||
test!(RustdocUi {
|
||||
path: "tests/rustdoc-ui",
|
||||
mode: "ui",
|
||||
suite: "rustdoc-ui",
|
||||
default: true,
|
||||
only_hosts: true,
|
||||
IS_HOST: true,
|
||||
});
|
||||
|
||||
test!(RustdocJson {
|
||||
|
|
@ -1468,7 +1460,7 @@ test!(RustdocJson {
|
|||
mode: "rustdoc-json",
|
||||
suite: "rustdoc-json",
|
||||
default: true,
|
||||
only_hosts: true,
|
||||
IS_HOST: true,
|
||||
});
|
||||
|
||||
test!(Pretty {
|
||||
|
|
@ -1476,7 +1468,7 @@ test!(Pretty {
|
|||
mode: "pretty",
|
||||
suite: "pretty",
|
||||
default: true,
|
||||
only_hosts: true,
|
||||
IS_HOST: true,
|
||||
});
|
||||
|
||||
test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
|
||||
|
|
@ -1507,7 +1499,7 @@ impl Step for Coverage {
|
|||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
/// Compiletest will automatically skip the "coverage-run" tests if necessary.
|
||||
const ONLY_HOSTS: bool = false;
|
||||
const IS_HOST: bool = false;
|
||||
|
||||
fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
// Support various invocation styles, including:
|
||||
|
|
@ -1586,7 +1578,7 @@ test!(CoverageRunRustdoc {
|
|||
mode: "coverage-run",
|
||||
suite: "coverage-run-rustdoc",
|
||||
default: true,
|
||||
only_hosts: true,
|
||||
IS_HOST: true,
|
||||
});
|
||||
|
||||
// For the mir-opt suite we do not use macros, as we need custom behavior when blessing.
|
||||
|
|
@ -1599,7 +1591,6 @@ pub struct MirOpt {
|
|||
impl Step for MirOpt {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.suite_path("tests/mir-opt")
|
||||
|
|
@ -2276,7 +2267,7 @@ struct BookTest {
|
|||
|
||||
impl Step for BookTest {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.never()
|
||||
|
|
@ -2442,7 +2433,7 @@ macro_rules! test_book {
|
|||
impl Step for $name {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = $default;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path($path)
|
||||
|
|
@ -2502,7 +2493,7 @@ pub struct ErrorIndex {
|
|||
impl Step for ErrorIndex {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
// Also add `error-index` here since that is what appears in the error message
|
||||
|
|
@ -2598,7 +2589,7 @@ pub struct CrateLibrustc {
|
|||
impl Step for CrateLibrustc {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.crate_or_deps("rustc-main").path("compiler")
|
||||
|
|
@ -2883,7 +2874,7 @@ pub struct CrateRustdoc {
|
|||
impl Step for CrateRustdoc {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.paths(&["src/librustdoc", "src/tools/rustdoc"])
|
||||
|
|
@ -2975,7 +2966,7 @@ pub struct CrateRustdocJsonTypes {
|
|||
impl Step for CrateRustdocJsonTypes {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/rustdoc-json-types")
|
||||
|
|
@ -3164,7 +3155,7 @@ pub struct Bootstrap;
|
|||
impl Step for Bootstrap {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
/// Tests the build system itself.
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
|
|
@ -3234,7 +3225,7 @@ pub struct TierCheck {
|
|||
impl Step for TierCheck {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/tier-check")
|
||||
|
|
@ -3288,7 +3279,7 @@ pub struct LintDocs {
|
|||
impl Step for LintDocs {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/lint-docs")
|
||||
|
|
@ -3314,7 +3305,7 @@ pub struct RustInstaller;
|
|||
|
||||
impl Step for RustInstaller {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
/// Ensure the version placeholder replacement tool builds
|
||||
|
|
@ -3434,7 +3425,7 @@ pub struct CodegenCranelift {
|
|||
impl Step for CodegenCranelift {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.paths(&["compiler/rustc_codegen_cranelift"])
|
||||
|
|
@ -3562,7 +3553,7 @@ pub struct CodegenGCC {
|
|||
impl Step for CodegenGCC {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.paths(&["compiler/rustc_codegen_gcc"])
|
||||
|
|
@ -3695,7 +3686,7 @@ pub struct TestFloatParse {
|
|||
|
||||
impl Step for TestFloatParse {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -3761,7 +3752,7 @@ pub struct CollectLicenseMetadata;
|
|||
|
||||
impl Step for CollectLicenseMetadata {
|
||||
type Output = PathBuf;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/collect-license-metadata")
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ use std::ffi::OsStr;
|
|||
use std::path::PathBuf;
|
||||
use std::{env, fs};
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::core::build_steps::compile::is_lto_stage;
|
||||
use crate::core::build_steps::toolstate::ToolState;
|
||||
use crate::core::build_steps::{compile, llvm};
|
||||
|
|
@ -229,6 +226,14 @@ pub fn prepare_tool_cargo(
|
|||
// own copy
|
||||
cargo.env("LZMA_API_STATIC", "1");
|
||||
|
||||
// Build jemalloc on AArch64 with support for page sizes up to 64K
|
||||
// See: https://github.com/rust-lang/rust/pull/135081
|
||||
// Note that `miri` always uses jemalloc. As such, there is no checking of the jemalloc build flag.
|
||||
// See also the "JEMALLOC_SYS_WITH_LG_PAGE" setting in the compile build step.
|
||||
if target.starts_with("aarch64") && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() {
|
||||
cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
|
||||
}
|
||||
|
||||
// CFG_RELEASE is needed by rustfmt (and possibly other tools) which
|
||||
// import rustc-ap-rustc_attr which requires this to be set for the
|
||||
// `#[cfg(version(...))]` attribute.
|
||||
|
|
@ -415,14 +420,6 @@ macro_rules! bootstrap_tool {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = $tool_name,
|
||||
skip_all,
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
|
||||
$(
|
||||
for submodule in $submodules {
|
||||
|
|
@ -687,7 +684,7 @@ impl Step for Rustdoc {
|
|||
type Output = PathBuf;
|
||||
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/rustdoc").path("src/librustdoc")
|
||||
|
|
@ -809,7 +806,7 @@ impl Cargo {
|
|||
impl Step for Cargo {
|
||||
type Output = ToolBuildResult;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -885,7 +882,7 @@ impl LldWrapper {
|
|||
impl Step for LldWrapper {
|
||||
type Output = BuiltLldWrapper;
|
||||
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/lld-wrapper")
|
||||
|
|
@ -901,15 +898,6 @@ impl Step for LldWrapper {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "LldWrapper::run",
|
||||
skip_all,
|
||||
fields(build_compiler = ?self.build_compiler),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> Self::Output {
|
||||
let lld_dir = builder.ensure(llvm::Lld { target: self.target });
|
||||
let tool = builder.ensure(ToolBuild {
|
||||
|
|
@ -986,7 +974,7 @@ impl WasmComponentLd {
|
|||
impl Step for WasmComponentLd {
|
||||
type Output = ToolBuildResult;
|
||||
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/wasm-component-ld")
|
||||
|
|
@ -1002,15 +990,6 @@ impl Step for WasmComponentLd {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "debug",
|
||||
name = "WasmComponentLd::run",
|
||||
skip_all,
|
||||
fields(build_compiler = ?self.build_compiler),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
|
||||
builder.ensure(ToolBuild {
|
||||
build_compiler: self.build_compiler,
|
||||
|
|
@ -1049,7 +1028,7 @@ impl RustAnalyzer {
|
|||
impl Step for RustAnalyzer {
|
||||
type Output = ToolBuildResult;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -1102,7 +1081,7 @@ impl Step for RustAnalyzerProcMacroSrv {
|
|||
type Output = ToolBuildResult;
|
||||
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -1192,7 +1171,7 @@ impl LlvmBitcodeLinker {
|
|||
impl Step for LlvmBitcodeLinker {
|
||||
type Output = ToolBuildResult;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
let builder = run.builder;
|
||||
|
|
@ -1207,10 +1186,6 @@ impl Step for LlvmBitcodeLinker {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(level = "debug", name = "LlvmBitcodeLinker::run", skip_all)
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
|
||||
builder.ensure(ToolBuild {
|
||||
build_compiler: self.build_compiler,
|
||||
|
|
@ -1246,7 +1221,7 @@ pub enum LibcxxVersion {
|
|||
impl Step for LibcxxVersionTool {
|
||||
type Output = LibcxxVersion;
|
||||
const DEFAULT: bool = false;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.never()
|
||||
|
|
@ -1407,7 +1382,7 @@ macro_rules! tool_rustc_extended {
|
|||
impl Step for $name {
|
||||
type Output = ToolBuildResult;
|
||||
const DEFAULT: bool = true; // Overridden by `should_run_tool_build_step`
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
should_run_extended_rustc_tool(
|
||||
|
|
@ -1575,7 +1550,7 @@ impl TestFloatParse {
|
|||
|
||||
impl Step for TestFloatParse {
|
||||
type Output = ToolBuildResult;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
const DEFAULT: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pub(crate) struct Vendor {
|
|||
impl Step for Vendor {
|
||||
type Output = VendorOutput;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.alias("placeholder").default_condition(true)
|
||||
|
|
|
|||
|
|
@ -499,6 +499,10 @@ impl Builder<'_> {
|
|||
build_stamp::clear_if_dirty(self, &out_dir, &backend);
|
||||
}
|
||||
|
||||
if self.config.cmd.timings() {
|
||||
cargo.arg("--timings");
|
||||
}
|
||||
|
||||
if cmd_kind == Kind::Doc {
|
||||
let my_out = match mode {
|
||||
// This is the intended out directory for compiler documentation.
|
||||
|
|
|
|||
|
|
@ -100,8 +100,13 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
|
|||
/// by `Step::should_run`.
|
||||
const DEFAULT: bool = false;
|
||||
|
||||
/// If true, then this rule should be skipped if --target was specified, but --host was not
|
||||
const ONLY_HOSTS: bool = false;
|
||||
/// If this value is true, then the values of `run.target` passed to the `make_run` function of
|
||||
/// this Step will be determined based on the `--host` flag.
|
||||
/// If this value is false, then they will be determined based on the `--target` flag.
|
||||
///
|
||||
/// A corollary of the above is that if this is set to true, then the step will be skipped if
|
||||
/// `--target` was specified, but `--host` was explicitly set to '' (empty string).
|
||||
const IS_HOST: bool = false;
|
||||
|
||||
/// Primary function to implement `Step` logic.
|
||||
///
|
||||
|
|
@ -298,7 +303,7 @@ pub fn crate_description(crates: &[impl AsRef<str>]) -> String {
|
|||
|
||||
struct StepDescription {
|
||||
default: bool,
|
||||
only_hosts: bool,
|
||||
is_host: bool,
|
||||
should_run: fn(ShouldRun<'_>) -> ShouldRun<'_>,
|
||||
make_run: fn(RunConfig<'_>),
|
||||
name: &'static str,
|
||||
|
|
@ -500,7 +505,7 @@ impl StepDescription {
|
|||
fn from<S: Step>(kind: Kind) -> StepDescription {
|
||||
StepDescription {
|
||||
default: S::DEFAULT,
|
||||
only_hosts: S::ONLY_HOSTS,
|
||||
is_host: S::IS_HOST,
|
||||
should_run: S::should_run,
|
||||
make_run: S::make_run,
|
||||
name: std::any::type_name::<S>(),
|
||||
|
|
@ -516,7 +521,7 @@ impl StepDescription {
|
|||
}
|
||||
|
||||
// Determine the targets participating in this rule.
|
||||
let targets = if self.only_hosts { &builder.hosts } else { &builder.targets };
|
||||
let targets = if self.is_host { &builder.hosts } else { &builder.targets };
|
||||
|
||||
for target in targets {
|
||||
let run = RunConfig { builder, paths: pathsets.clone(), target: *target };
|
||||
|
|
@ -951,6 +956,9 @@ impl Step for Libdir {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
pub const STEP_SPAN_TARGET: &str = "STEP";
|
||||
|
||||
impl<'a> Builder<'a> {
|
||||
fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
|
||||
macro_rules! describe {
|
||||
|
|
@ -1271,7 +1279,7 @@ impl<'a> Builder<'a> {
|
|||
pub fn new(build: &Build) -> Builder<'_> {
|
||||
let paths = &build.config.paths;
|
||||
let (kind, paths) = match build.config.cmd {
|
||||
Subcommand::Build => (Kind::Build, &paths[..]),
|
||||
Subcommand::Build { .. } => (Kind::Build, &paths[..]),
|
||||
Subcommand::Check { .. } => (Kind::Check, &paths[..]),
|
||||
Subcommand::Clippy { .. } => (Kind::Clippy, &paths[..]),
|
||||
Subcommand::Fix => (Kind::Fix, &paths[..]),
|
||||
|
|
@ -1680,8 +1688,6 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
|
|||
panic!("{}", out);
|
||||
}
|
||||
if let Some(out) = self.cache.get(&step) {
|
||||
self.verbose_than(1, || println!("{}c {:?}", " ".repeat(stack.len()), step));
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
{
|
||||
if let Some(parent) = stack.last() {
|
||||
|
|
@ -1691,7 +1697,6 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
|
|||
}
|
||||
return out;
|
||||
}
|
||||
self.verbose_than(1, || println!("{}> {:?}", " ".repeat(stack.len()), step));
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
{
|
||||
|
|
@ -1706,10 +1711,29 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
|
|||
#[cfg(feature = "build-metrics")]
|
||||
self.metrics.enter_step(&step, self);
|
||||
|
||||
if self.config.print_step_timings && !self.config.dry_run() {
|
||||
println!("[TIMING:start] {}", pretty_print_step(&step));
|
||||
}
|
||||
|
||||
let (out, dur) = {
|
||||
let start = Instant::now();
|
||||
let zero = Duration::new(0, 0);
|
||||
let parent = self.time_spent_on_dependencies.replace(zero);
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let _span = {
|
||||
// Keep the target and field names synchronized with `setup_tracing`.
|
||||
let span = tracing::info_span!(
|
||||
target: STEP_SPAN_TARGET,
|
||||
// We cannot use a dynamic name here, so instead we record the actual step name
|
||||
// in the step_name field.
|
||||
"step",
|
||||
step_name = pretty_step_name::<S>(),
|
||||
args = step_debug_args(&step)
|
||||
);
|
||||
span.entered()
|
||||
};
|
||||
|
||||
let out = step.clone().run(self);
|
||||
let dur = start.elapsed();
|
||||
let deps = self.time_spent_on_dependencies.replace(parent + dur);
|
||||
|
|
@ -1717,13 +1741,9 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
|
|||
};
|
||||
|
||||
if self.config.print_step_timings && !self.config.dry_run() {
|
||||
let step_string = format!("{step:?}");
|
||||
let brace_index = step_string.find('{').unwrap_or(0);
|
||||
let type_string = type_name::<S>();
|
||||
println!(
|
||||
"[TIMING] {} {} -- {}.{:03}",
|
||||
&type_string.strip_prefix("bootstrap::").unwrap_or(type_string),
|
||||
&step_string[brace_index..],
|
||||
"[TIMING:end] {} -- {}.{:03}",
|
||||
pretty_print_step(&step),
|
||||
dur.as_secs(),
|
||||
dur.subsec_millis()
|
||||
);
|
||||
|
|
@ -1737,7 +1757,6 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
|
|||
let cur_step = stack.pop().expect("step stack empty");
|
||||
assert_eq!(cur_step.downcast_ref(), Some(&step));
|
||||
}
|
||||
self.verbose_than(1, || println!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
|
||||
self.cache.put(step, out.clone());
|
||||
out
|
||||
}
|
||||
|
|
@ -1810,6 +1829,25 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
|
|||
}
|
||||
}
|
||||
|
||||
/// Return qualified step name, e.g. `compile::Rustc`.
|
||||
pub fn pretty_step_name<S: Step>() -> String {
|
||||
// Normalize step type path to only keep the module and the type name
|
||||
let path = type_name::<S>().rsplit("::").take(2).collect::<Vec<_>>();
|
||||
path.into_iter().rev().collect::<Vec<_>>().join("::")
|
||||
}
|
||||
|
||||
/// Renders `step` using its `Debug` implementation and extract the field arguments out of it.
|
||||
fn step_debug_args<S: Step>(step: &S) -> String {
|
||||
let step_dbg_repr = format!("{step:?}");
|
||||
let brace_start = step_dbg_repr.find('{').unwrap_or(0);
|
||||
let brace_end = step_dbg_repr.rfind('}').unwrap_or(step_dbg_repr.len());
|
||||
step_dbg_repr[brace_start + 1..brace_end - 1].trim().to_string()
|
||||
}
|
||||
|
||||
fn pretty_print_step<S: Step>(step: &S) -> String {
|
||||
format!("{} {{ {} }}", pretty_step_name::<S>(), step_debug_args(step))
|
||||
}
|
||||
|
||||
impl<'a> AsRef<ExecutionContext> for Builder<'a> {
|
||||
fn as_ref(&self) -> &ExecutionContext {
|
||||
self.exec_ctx()
|
||||
|
|
|
|||
|
|
@ -1342,7 +1342,7 @@ impl Config {
|
|||
Subcommand::Doc { .. } => {
|
||||
flags_stage.or(build_doc_stage).unwrap_or(if download_rustc { 2 } else { 1 })
|
||||
}
|
||||
Subcommand::Build => {
|
||||
Subcommand::Build { .. } => {
|
||||
flags_stage.or(build_build_stage).unwrap_or(if download_rustc { 2 } else { 1 })
|
||||
}
|
||||
Subcommand::Test { .. } | Subcommand::Miri { .. } => {
|
||||
|
|
@ -1363,7 +1363,7 @@ impl Config {
|
|||
|
||||
// Now check that the selected stage makes sense, and if not, print a warning and end
|
||||
match (config.stage, &config.cmd) {
|
||||
(0, Subcommand::Build) => {
|
||||
(0, Subcommand::Build { .. }) => {
|
||||
eprintln!("ERROR: cannot build anything on stage 0. Use at least stage 1.");
|
||||
exit!(1);
|
||||
}
|
||||
|
|
@ -1396,7 +1396,7 @@ impl Config {
|
|||
Subcommand::Test { .. }
|
||||
| Subcommand::Miri { .. }
|
||||
| Subcommand::Doc { .. }
|
||||
| Subcommand::Build
|
||||
| Subcommand::Build { .. }
|
||||
| Subcommand::Bench { .. }
|
||||
| Subcommand::Dist
|
||||
| Subcommand::Install => {
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ fn normalize_args(args: &[String]) -> Vec<String> {
|
|||
it.collect()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, clap::Subcommand)]
|
||||
#[derive(Debug, Clone, clap::Subcommand)]
|
||||
pub enum Subcommand {
|
||||
#[command(aliases = ["b"], long_about = "\n
|
||||
Arguments:
|
||||
|
|
@ -256,8 +256,11 @@ pub enum Subcommand {
|
|||
./x.py build --stage 0
|
||||
./x.py build ")]
|
||||
/// Compile either the compiler or libraries
|
||||
#[default]
|
||||
Build,
|
||||
Build {
|
||||
#[arg(long)]
|
||||
/// Pass `--timings` to Cargo to get crate build timings
|
||||
timings: bool,
|
||||
},
|
||||
#[command(aliases = ["c"], long_about = "\n
|
||||
Arguments:
|
||||
This subcommand accepts a number of paths to directories to the crates
|
||||
|
|
@ -269,6 +272,9 @@ pub enum Subcommand {
|
|||
#[arg(long)]
|
||||
/// Check all targets
|
||||
all_targets: bool,
|
||||
#[arg(long)]
|
||||
/// Pass `--timings` to Cargo to get crate build timings
|
||||
timings: bool,
|
||||
},
|
||||
/// Run Clippy (uses rustup/cargo-installed clippy binary)
|
||||
#[command(long_about = "\n
|
||||
|
|
@ -494,11 +500,17 @@ Arguments:
|
|||
Perf(PerfArgs),
|
||||
}
|
||||
|
||||
impl Default for Subcommand {
|
||||
fn default() -> Self {
|
||||
Subcommand::Build { timings: false }
|
||||
}
|
||||
}
|
||||
|
||||
impl Subcommand {
|
||||
pub fn kind(&self) -> Kind {
|
||||
match self {
|
||||
Subcommand::Bench { .. } => Kind::Bench,
|
||||
Subcommand::Build => Kind::Build,
|
||||
Subcommand::Build { .. } => Kind::Build,
|
||||
Subcommand::Check { .. } => Kind::Check,
|
||||
Subcommand::Clippy { .. } => Kind::Clippy,
|
||||
Subcommand::Doc { .. } => Kind::Doc,
|
||||
|
|
@ -626,6 +638,13 @@ impl Subcommand {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn timings(&self) -> bool {
|
||||
match *self {
|
||||
Subcommand::Build { timings, .. } | Subcommand::Check { timings, .. } => timings,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vendor_versioned_dirs(&self) -> bool {
|
||||
match *self {
|
||||
Subcommand::Vendor { versioned_dirs, .. } => versioned_dirs,
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@ use crate::core::builder;
|
|||
use crate::core::builder::Kind;
|
||||
use crate::core::config::{DryRun, LldMode, LlvmLibunwind, TargetSelection, flags};
|
||||
use crate::utils::exec::{BootstrapCommand, command};
|
||||
use crate::utils::helpers::{
|
||||
self, dir_is_empty, exe, libdir, set_file_times, split_debuginfo, symlink_dir,
|
||||
};
|
||||
use crate::utils::helpers::{self, dir_is_empty, exe, libdir, set_file_times, split_debuginfo};
|
||||
|
||||
mod core;
|
||||
mod utils;
|
||||
|
||||
pub use core::builder::PathSet;
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use core::builder::STEP_SPAN_TARGET;
|
||||
pub use core::config::flags::{Flags, Subcommand};
|
||||
pub use core::config::{ChangeId, Config};
|
||||
|
||||
|
|
@ -53,7 +53,9 @@ use tracing::{instrument, span};
|
|||
pub use utils::change_tracker::{
|
||||
CONFIG_CHANGE_HISTORY, find_recent_config_change_ids, human_readable_changes,
|
||||
};
|
||||
pub use utils::helpers::PanicTracker;
|
||||
pub use utils::helpers::{PanicTracker, symlink_dir};
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use utils::tracing::setup_tracing;
|
||||
|
||||
use crate::core::build_steps::vendor::VENDOR_DIR;
|
||||
|
||||
|
|
@ -2005,13 +2007,13 @@ to download LLVM rather than building it.
|
|||
&self.config.exec_ctx
|
||||
}
|
||||
|
||||
pub fn report_summary(&self, start_time: Instant) {
|
||||
self.config.exec_ctx.profiler().report_summary(start_time);
|
||||
pub fn report_summary(&self, path: &Path, start_time: Instant) {
|
||||
self.config.exec_ctx.profiler().report_summary(path, start_time);
|
||||
}
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
pub fn report_step_graph(self) {
|
||||
self.step_graph.into_inner().store_to_dot_files();
|
||||
pub fn report_step_graph(self, directory: &Path) {
|
||||
self.step_graph.into_inner().store_to_dot_files(directory);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use std::hash::Hash;
|
|||
use std::io::{BufWriter, Write};
|
||||
use std::panic::Location;
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
use std::process::{
|
||||
Child, ChildStderr, ChildStdout, Command, CommandArgs, CommandEnvs, ExitStatus, Output, Stdio,
|
||||
};
|
||||
|
|
@ -26,10 +25,8 @@ use build_helper::ci::CiEnv;
|
|||
use build_helper::drop_bomb::DropBomb;
|
||||
use build_helper::exit;
|
||||
|
||||
use crate::PathBuf;
|
||||
use crate::core::config::DryRun;
|
||||
#[cfg(feature = "tracing")]
|
||||
use crate::trace_cmd;
|
||||
use crate::{PathBuf, t};
|
||||
|
||||
/// What should be done when the command fails.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
|
@ -77,9 +74,17 @@ pub struct CommandFingerprint {
|
|||
}
|
||||
|
||||
impl CommandFingerprint {
|
||||
#[cfg(feature = "tracing")]
|
||||
pub(crate) fn program_name(&self) -> String {
|
||||
Path::new(&self.program)
|
||||
.file_name()
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| "<unknown command>".to_string())
|
||||
}
|
||||
|
||||
/// Helper method to format both Command and BootstrapCommand as a short execution line,
|
||||
/// without all the other details (e.g. environment variables).
|
||||
pub fn format_short_cmd(&self) -> String {
|
||||
pub(crate) fn format_short_cmd(&self) -> String {
|
||||
use std::fmt::Write;
|
||||
|
||||
let mut cmd = self.program.to_string_lossy().to_string();
|
||||
|
|
@ -121,17 +126,9 @@ impl CommandProfiler {
|
|||
entry.traces.push(ExecutionTrace::CacheHit);
|
||||
}
|
||||
|
||||
pub fn report_summary(&self, start_time: Instant) {
|
||||
let pid = process::id();
|
||||
let filename = format!("bootstrap-profile-{pid}.txt");
|
||||
|
||||
let file = match File::create(&filename) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to create profiler output file: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
/// Report summary of executed commands file at the specified `path`.
|
||||
pub fn report_summary(&self, path: &Path, start_time: Instant) {
|
||||
let file = t!(File::create(path));
|
||||
|
||||
let mut writer = BufWriter::new(file);
|
||||
let stats = self.stats.lock().unwrap();
|
||||
|
|
@ -221,8 +218,6 @@ impl CommandProfiler {
|
|||
writeln!(writer, "Total cache hits: {total_cache_hits}").unwrap();
|
||||
writeln!(writer, "Estimated time saved due to cache hits: {total_saved_duration:.2?}")
|
||||
.unwrap();
|
||||
|
||||
println!("Command profiler report saved to {filename}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -686,9 +681,6 @@ impl ExecutionContext {
|
|||
) -> DeferredCommand<'a> {
|
||||
let fingerprint = command.fingerprint();
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let span_guard = trace_cmd!(command);
|
||||
|
||||
if let Some(cached_output) = self.command_cache.get(&fingerprint) {
|
||||
command.mark_as_executed();
|
||||
self.verbose(|| println!("Cache hit: {command:?}"));
|
||||
|
|
@ -696,6 +688,9 @@ impl ExecutionContext {
|
|||
return DeferredCommand { state: CommandState::Cached(cached_output) };
|
||||
}
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let span_guard = crate::utils::tracing::trace_cmd(command);
|
||||
|
||||
let created_at = command.get_created_location();
|
||||
let executed_at = std::panic::Location::caller();
|
||||
|
||||
|
|
@ -779,7 +774,7 @@ impl ExecutionContext {
|
|||
}
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let span_guard = trace_cmd!(command);
|
||||
let span_guard = crate::utils::tracing::trace_cmd(command);
|
||||
|
||||
let start_time = Instant::now();
|
||||
let fingerprint = command.fingerprint();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Debug;
|
||||
use std::io::BufWriter;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::core::builder::{AnyDebug, Step};
|
||||
use crate::core::builder::{AnyDebug, Step, pretty_step_name};
|
||||
use crate::t;
|
||||
|
||||
/// Records the executed steps and their dependencies in a directed graph,
|
||||
/// which can then be rendered into a DOT file for visualization.
|
||||
|
|
@ -41,13 +43,7 @@ impl StepGraph {
|
|||
metadata.get_target()
|
||||
)
|
||||
} else {
|
||||
let type_name = std::any::type_name::<S>();
|
||||
type_name
|
||||
.strip_prefix("bootstrap::core::")
|
||||
.unwrap_or(type_name)
|
||||
.strip_prefix("build_steps::")
|
||||
.unwrap_or(type_name)
|
||||
.to_string()
|
||||
pretty_step_name::<S>()
|
||||
};
|
||||
|
||||
let node = Node { label, tooltip: node_key.clone() };
|
||||
|
|
@ -80,10 +76,10 @@ impl StepGraph {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn store_to_dot_files(self) {
|
||||
pub fn store_to_dot_files(self, directory: &Path) {
|
||||
for (key, graph) in self.graphs.into_iter() {
|
||||
let filename = format!("bootstrap-steps{key}.dot");
|
||||
graph.render(&filename).unwrap();
|
||||
let filename = directory.join(format!("step-graph{key}.dot"));
|
||||
t!(graph.render(&filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -147,7 +143,7 @@ impl DotGraph {
|
|||
self.key_to_index.get(key).copied()
|
||||
}
|
||||
|
||||
fn render(&self, path: &str) -> std::io::Result<()> {
|
||||
fn render(&self, path: &Path) -> std::io::Result<()> {
|
||||
use std::io::Write;
|
||||
|
||||
let mut file = BufWriter::new(std::fs::File::create(path)?);
|
||||
|
|
|
|||
|
|
@ -48,17 +48,369 @@ macro_rules! error {
|
|||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! trace_cmd {
|
||||
($cmd:expr) => {
|
||||
{
|
||||
::tracing::span!(
|
||||
target: "COMMAND",
|
||||
::tracing::Level::TRACE,
|
||||
"executing command",
|
||||
cmd = $cmd.fingerprint().format_short_cmd(),
|
||||
full_cmd = ?$cmd
|
||||
).entered()
|
||||
}
|
||||
};
|
||||
#[cfg(feature = "tracing")]
|
||||
const COMMAND_SPAN_TARGET: &str = "COMMAND";
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
pub fn trace_cmd(command: &crate::BootstrapCommand) -> tracing::span::EnteredSpan {
|
||||
let fingerprint = command.fingerprint();
|
||||
let location = command.get_created_location();
|
||||
let location = format!("{}:{}", location.file(), location.line());
|
||||
|
||||
tracing::span!(
|
||||
target: COMMAND_SPAN_TARGET,
|
||||
tracing::Level::TRACE,
|
||||
"cmd",
|
||||
cmd_name = fingerprint.program_name().to_string(),
|
||||
cmd = fingerprint.format_short_cmd(),
|
||||
full_cmd = ?command,
|
||||
location
|
||||
)
|
||||
.entered()
|
||||
}
|
||||
|
||||
// # Note on `tracing` usage in bootstrap
|
||||
//
|
||||
// Due to the conditional compilation via the `tracing` cargo feature, this means that `tracing`
|
||||
// usages in bootstrap need to be also gated behind the `tracing` feature:
|
||||
//
|
||||
// - `tracing` macros with log levels (`trace!`, `debug!`, `warn!`, `info`, `error`) should not be
|
||||
// used *directly*. You should use the wrapped `tracing` macros which gate the actual invocations
|
||||
// behind `feature = "tracing"`.
|
||||
// - `tracing`'s `#[instrument(..)]` macro will need to be gated like `#![cfg_attr(feature =
|
||||
// "tracing", instrument(..))]`.
|
||||
#[cfg(feature = "tracing")]
|
||||
mod inner {
|
||||
use std::fmt::Debug;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use tracing::field::{Field, Visit};
|
||||
use tracing::{Event, Id, Level, Subscriber};
|
||||
use tracing_subscriber::layer::{Context, SubscriberExt};
|
||||
use tracing_subscriber::registry::{LookupSpan, SpanRef};
|
||||
use tracing_subscriber::{EnvFilter, Layer};
|
||||
|
||||
use crate::STEP_SPAN_TARGET;
|
||||
use crate::utils::tracing::COMMAND_SPAN_TARGET;
|
||||
|
||||
pub fn setup_tracing(env_name: &str) -> TracingGuard {
|
||||
let filter = EnvFilter::from_env(env_name);
|
||||
|
||||
let registry = tracing_subscriber::registry().with(filter).with(TracingPrinter::default());
|
||||
|
||||
// When we're creating this layer, we do not yet know the location of the tracing output
|
||||
// directory, because it is stored in the output directory determined after Config is parsed,
|
||||
// but we already want to make tracing calls during (and before) config parsing.
|
||||
// So we store the output into a temporary file, and then move it to the tracing directory
|
||||
// before bootstrap ends.
|
||||
let tempdir = tempfile::TempDir::new().expect("Cannot create temporary directory");
|
||||
let chrome_tracing_path = tempdir.path().join("bootstrap-trace.json");
|
||||
let file = std::io::BufWriter::new(File::create(&chrome_tracing_path).unwrap());
|
||||
|
||||
let chrome_layer = tracing_chrome::ChromeLayerBuilder::new()
|
||||
.writer(file)
|
||||
.include_args(true)
|
||||
.name_fn(Box::new(|event_or_span| match event_or_span {
|
||||
tracing_chrome::EventOrSpan::Event(e) => e.metadata().name().to_string(),
|
||||
tracing_chrome::EventOrSpan::Span(s) => {
|
||||
if s.metadata().target() == STEP_SPAN_TARGET
|
||||
&& let Some(extension) = s.extensions().get::<StepNameExtension>()
|
||||
{
|
||||
extension.0.clone()
|
||||
} else if s.metadata().target() == COMMAND_SPAN_TARGET
|
||||
&& let Some(extension) = s.extensions().get::<CommandNameExtension>()
|
||||
{
|
||||
extension.0.clone()
|
||||
} else {
|
||||
s.metadata().name().to_string()
|
||||
}
|
||||
}
|
||||
}));
|
||||
let (chrome_layer, guard) = chrome_layer.build();
|
||||
|
||||
tracing::subscriber::set_global_default(registry.with(chrome_layer)).unwrap();
|
||||
TracingGuard { guard, _tempdir: tempdir, chrome_tracing_path }
|
||||
}
|
||||
|
||||
pub struct TracingGuard {
|
||||
guard: tracing_chrome::FlushGuard,
|
||||
_tempdir: tempfile::TempDir,
|
||||
chrome_tracing_path: std::path::PathBuf,
|
||||
}
|
||||
|
||||
impl TracingGuard {
|
||||
pub fn copy_to_dir(self, dir: &std::path::Path) {
|
||||
drop(self.guard);
|
||||
std::fs::rename(&self.chrome_tracing_path, dir.join("chrome-trace.json")).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Visitor that extracts both known and unknown field values from events and spans.
|
||||
#[derive(Default)]
|
||||
struct FieldValues {
|
||||
/// Main event message
|
||||
message: Option<String>,
|
||||
/// Name of a recorded psna
|
||||
step_name: Option<String>,
|
||||
/// Short name of an executed command
|
||||
cmd_name: Option<String>,
|
||||
/// The rest of arbitrary event/span fields
|
||||
fields: Vec<(&'static str, String)>,
|
||||
}
|
||||
|
||||
impl Visit for FieldValues {
|
||||
/// Record fields if possible using `record_str`, to avoid rendering simple strings with
|
||||
/// their `Debug` representation, which adds extra quotes.
|
||||
fn record_str(&mut self, field: &Field, value: &str) {
|
||||
match field.name() {
|
||||
"step_name" => {
|
||||
self.step_name = Some(value.to_string());
|
||||
}
|
||||
"cmd_name" => {
|
||||
self.cmd_name = Some(value.to_string());
|
||||
}
|
||||
name => {
|
||||
self.fields.push((name, value.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn record_debug(&mut self, field: &Field, value: &dyn Debug) {
|
||||
let formatted = format!("{value:?}");
|
||||
match field.name() {
|
||||
"message" => {
|
||||
self.message = Some(formatted);
|
||||
}
|
||||
name => {
|
||||
self.fields.push((name, formatted));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum SpanAction {
|
||||
Enter,
|
||||
}
|
||||
|
||||
/// Holds the name of a step span, stored in `tracing_subscriber`'s extensions.
|
||||
struct StepNameExtension(String);
|
||||
|
||||
/// Holds the name of a command span, stored in `tracing_subscriber`'s extensions.
|
||||
struct CommandNameExtension(String);
|
||||
|
||||
#[derive(Default)]
|
||||
struct TracingPrinter {
|
||||
indent: std::sync::atomic::AtomicU32,
|
||||
span_values: std::sync::Mutex<std::collections::HashMap<tracing::Id, FieldValues>>,
|
||||
}
|
||||
|
||||
impl TracingPrinter {
|
||||
fn format_header<W: Write>(
|
||||
&self,
|
||||
writer: &mut W,
|
||||
time: DateTime<Utc>,
|
||||
level: &Level,
|
||||
) -> std::io::Result<()> {
|
||||
// Use a fixed-width timestamp without date, that shouldn't be very important
|
||||
let timestamp = time.format("%H:%M:%S.%3f");
|
||||
write!(writer, "{timestamp} ")?;
|
||||
// Make sure that levels are aligned to the same number of characters, in order not to
|
||||
// break the layout
|
||||
write!(writer, "{level:>5} ")?;
|
||||
write!(writer, "{}", " ".repeat(self.indent.load(Ordering::Relaxed) as usize))
|
||||
}
|
||||
|
||||
fn write_event<W: Write>(&self, writer: &mut W, event: &Event<'_>) -> std::io::Result<()> {
|
||||
let now = Utc::now();
|
||||
|
||||
self.format_header(writer, now, event.metadata().level())?;
|
||||
|
||||
let mut field_values = FieldValues::default();
|
||||
event.record(&mut field_values);
|
||||
|
||||
if let Some(msg) = &field_values.message {
|
||||
write!(writer, "{msg}")?;
|
||||
}
|
||||
|
||||
if !field_values.fields.is_empty() {
|
||||
if field_values.message.is_some() {
|
||||
write!(writer, " ")?;
|
||||
}
|
||||
write!(writer, "[")?;
|
||||
for (index, (name, value)) in field_values.fields.iter().enumerate() {
|
||||
write!(writer, "{name} = {value}")?;
|
||||
if index < field_values.fields.len() - 1 {
|
||||
write!(writer, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(writer, "]")?;
|
||||
}
|
||||
write_location(writer, event.metadata())?;
|
||||
writeln!(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_span<W: Write, S>(
|
||||
&self,
|
||||
writer: &mut W,
|
||||
span: SpanRef<'_, S>,
|
||||
field_values: Option<&FieldValues>,
|
||||
action: SpanAction,
|
||||
) -> std::io::Result<()>
|
||||
where
|
||||
S: for<'lookup> LookupSpan<'lookup>,
|
||||
{
|
||||
let now = Utc::now();
|
||||
|
||||
self.format_header(writer, now, span.metadata().level())?;
|
||||
match action {
|
||||
SpanAction::Enter => {
|
||||
write!(writer, "> ")?;
|
||||
}
|
||||
}
|
||||
|
||||
fn write_fields<'a, I: IntoIterator<Item = &'a (&'a str, String)>, W: Write>(
|
||||
writer: &mut W,
|
||||
iter: I,
|
||||
) -> std::io::Result<()> {
|
||||
let items = iter.into_iter().collect::<Vec<_>>();
|
||||
if !items.is_empty() {
|
||||
write!(writer, " [")?;
|
||||
for (index, (name, value)) in items.iter().enumerate() {
|
||||
write!(writer, "{name} = {value}")?;
|
||||
if index < items.len() - 1 {
|
||||
write!(writer, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(writer, "]")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// We handle steps specially. We instrument them dynamically in `Builder::ensure`,
|
||||
// and we want to have custom name for each step span. But tracing doesn't allow setting
|
||||
// dynamic span names. So we detect step spans here and override their name.
|
||||
match span.metadata().target() {
|
||||
// Executed step
|
||||
STEP_SPAN_TARGET => {
|
||||
let name =
|
||||
field_values.and_then(|v| v.step_name.as_deref()).unwrap_or(span.name());
|
||||
write!(writer, "{name}")?;
|
||||
|
||||
// There should be only one more field called `args`
|
||||
if let Some(values) = field_values {
|
||||
let field = &values.fields[0];
|
||||
write!(writer, " {{{}}}", field.1)?;
|
||||
}
|
||||
write_location(writer, span.metadata())?;
|
||||
}
|
||||
// Executed command
|
||||
COMMAND_SPAN_TARGET => {
|
||||
write!(writer, "{}", span.name())?;
|
||||
if let Some(values) = field_values {
|
||||
write_fields(
|
||||
writer,
|
||||
values.fields.iter().filter(|(name, _)| *name != "location"),
|
||||
)?;
|
||||
write!(
|
||||
writer,
|
||||
" ({})",
|
||||
values.fields.iter().find(|(name, _)| *name == "location").unwrap().1
|
||||
)?;
|
||||
}
|
||||
}
|
||||
// Other span
|
||||
_ => {
|
||||
write!(writer, "{}", span.name())?;
|
||||
if let Some(values) = field_values {
|
||||
write_fields(writer, values.fields.iter())?;
|
||||
}
|
||||
write_location(writer, span.metadata())?;
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_location<W: Write>(
|
||||
writer: &mut W,
|
||||
metadata: &'static tracing::Metadata<'static>,
|
||||
) -> std::io::Result<()> {
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
if let Some(filename) = metadata.file() {
|
||||
// Keep only the module name and file name to make it shorter
|
||||
let filename: PathBuf = Path::new(filename)
|
||||
.components()
|
||||
// Take last two path components
|
||||
.rev()
|
||||
.take(2)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect();
|
||||
|
||||
write!(writer, " ({}", filename.display())?;
|
||||
if let Some(line) = metadata.line() {
|
||||
write!(writer, ":{line}")?;
|
||||
}
|
||||
write!(writer, ")")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl<S> Layer<S> for TracingPrinter
|
||||
where
|
||||
S: Subscriber,
|
||||
S: for<'lookup> LookupSpan<'lookup>,
|
||||
{
|
||||
fn on_new_span(&self, attrs: &tracing::span::Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
|
||||
// Record value of span fields
|
||||
// Note that we do not implement changing values of span fields after they are created.
|
||||
// For that we would also need to implement the `on_record` method
|
||||
let mut field_values = FieldValues::default();
|
||||
attrs.record(&mut field_values);
|
||||
|
||||
// We need to propagate the actual name of the span to the Chrome layer below, because
|
||||
// it cannot access field values. We do that through extensions.
|
||||
if attrs.metadata().target() == STEP_SPAN_TARGET
|
||||
&& let Some(step_name) = field_values.step_name.clone()
|
||||
{
|
||||
ctx.span(id).unwrap().extensions_mut().insert(StepNameExtension(step_name));
|
||||
} else if attrs.metadata().target() == COMMAND_SPAN_TARGET
|
||||
&& let Some(cmd_name) = field_values.cmd_name.clone()
|
||||
{
|
||||
ctx.span(id).unwrap().extensions_mut().insert(CommandNameExtension(cmd_name));
|
||||
}
|
||||
self.span_values.lock().unwrap().insert(id.clone(), field_values);
|
||||
}
|
||||
|
||||
fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) {
|
||||
let mut writer = std::io::stderr().lock();
|
||||
self.write_event(&mut writer, event).unwrap();
|
||||
}
|
||||
|
||||
fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
|
||||
if let Some(span) = ctx.span(id) {
|
||||
let mut writer = std::io::stderr().lock();
|
||||
let values = self.span_values.lock().unwrap();
|
||||
let values = values.get(id);
|
||||
self.write_span(&mut writer, span, values, SpanAction::Enter).unwrap();
|
||||
}
|
||||
self.indent.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn on_exit(&self, _id: &Id, _ctx: Context<'_, S>) {
|
||||
self.indent.fetch_sub(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use inner::setup_tracing;
|
||||
|
|
|
|||
|
|
@ -172,9 +172,9 @@ unsafe Rust. It's also sometimes called "the 'nomicon."
|
|||
[The Unstable Book](unstable-book/index.html) has documentation for unstable
|
||||
features.
|
||||
|
||||
### The `rustc` Contribution Guide
|
||||
### The `rustc` Development Guide
|
||||
|
||||
[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/)
|
||||
[The `rustc-dev-guide`](https://rustc-dev-guide.rust-lang.org/)
|
||||
documents how the compiler works and how to contribute to it. This is useful if
|
||||
you want to build or modify the Rust compiler from source (e.g. to target
|
||||
something non-standard).
|
||||
|
|
|
|||
|
|
@ -1,120 +1,100 @@
|
|||
# Debugging bootstrap
|
||||
|
||||
There are two main ways to debug bootstrap itself. The first is through println logging, and the second is through the `tracing` feature.
|
||||
|
||||
> FIXME: this section should be expanded
|
||||
There are two main ways of debugging (and profiling bootstrap). The first is through println logging, and the second is through the `tracing` feature.
|
||||
|
||||
## `println` logging
|
||||
|
||||
Bootstrap has extensive unstructured logging. Most of it is gated behind the `--verbose` flag (pass `-vv` for even more detail).
|
||||
|
||||
If you want to know which `Step` ran a command, you could invoke bootstrap like so:
|
||||
If you want to see verbose output of executed Cargo commands and other kinds of detailed logs, pass `-v` or `-vv` when invoking bootstrap. Note that the logs are unstructured and may be overwhelming.
|
||||
|
||||
```
|
||||
$ ./x dist rustc --dry-run -vv
|
||||
learning about cargo
|
||||
running: RUSTC_BOOTSTRAP="1" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "metadata" "--format-version" "1" "--no-deps" "--manifest-path" "/home/jyn/src/rust2/Cargo.toml" (failure_mode=Exit) (created at src/bootstrap/src/core/metadata.rs:81:25, executed at src/bootstrap/src/core/metadata.rs:92:50)
|
||||
running: RUSTC_BOOTSTRAP="1" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "metadata" "--format-version" "1" "--no-deps" "--manifest-path" "/home/jyn/src/rust2/library/Cargo.toml" (failure_mode=Exit) (created at src/bootstrap/src/core/metadata.rs:81:25, executed at src/bootstrap/src/core/metadata.rs:92:50)
|
||||
> Assemble { target_compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu } }
|
||||
> Libdir { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, target: x86_64-unknown-linux-gnu }
|
||||
> Sysroot { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, force_recompile: false }
|
||||
Removing sysroot /home/jyn/src/rust2/build/tmp-dry-run/x86_64-unknown-linux-gnu/stage1 to avoid caching bugs
|
||||
< Sysroot { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, force_recompile: false }
|
||||
< Libdir { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, target: x86_64-unknown-linux-gnu }
|
||||
...
|
||||
```
|
||||
|
||||
This will go through all the recursive dependency calculations, where `Step`s internally call `builder.ensure()`, without actually running cargo or the compiler.
|
||||
|
||||
In some cases, even this may not be enough logging (if so, please add more!). In that case, you can omit `--dry-run`, which will show the normal output inline with the debug logging:
|
||||
|
||||
```
|
||||
c Sysroot { compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu }, force_recompile: false }
|
||||
using sysroot /home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0-sysroot
|
||||
Building stage0 library artifacts (x86_64-unknown-linux-gnu)
|
||||
running: cd "/home/jyn/src/rust2" && env ... RUSTC_VERBOSE="2" RUSTC_WRAPPER="/home/jyn/src/rust2/build/bootstrap/debug/rustc" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnu" "-Zbinary-dep-depinfo" "-Zroot-dir=/home/jyn/src/rust2" "-v" "-v" "--manifest-path" "/home/jyn/src/rust2/library/sysroot/Cargo.toml" "--message-format" "json-render-diagnostics"
|
||||
0.293440230s INFO prepare_target{force=false package_id=sysroot v0.0.0 (/home/jyn/src/rust2/library/sysroot) target="sysroot"}: cargo::core::compiler::fingerprint: fingerprint error for sysroot v0.0.0 (/home/jyn/src/rust2/library/sysroot)/Build/TargetInner { name_inferred: true, ..: lib_target("sysroot", ["lib"], "/home/jyn/src/rust2/library/sysroot/src/lib.rs", Edition2021) }
|
||||
...
|
||||
```
|
||||
|
||||
In most cases this should not be necessary.
|
||||
|
||||
TODO: we should convert all this to structured logging so it's easier to control precisely.
|
||||
|
||||
## `tracing` in bootstrap
|
||||
|
||||
Bootstrap has conditional [`tracing`][tracing] setup to provide structured logging.
|
||||
Bootstrap has a conditional `tracing` feature, which provides the following features:
|
||||
- It enables structured logging using [`tracing`][tracing] events and spans.
|
||||
- It generates a [Chrome trace file] that can be used to visualize the hierarchy and durations of executed steps and commands.
|
||||
- You can open the generated `chrome-trace.json` file using Chrome, on the `chrome://tracing` tab, or e.g. using [Perfetto].
|
||||
- It generates [GraphViz] graphs that visualize the dependencies between executed steps.
|
||||
- You can open the generated `step-graph-*.dot` file using e.g. [xdot] to visualize the step graph, or use e.g. `dot -Tsvg` to convert the GraphViz file to an SVG file.
|
||||
- It generates a command execution summary, which shows which commands were executed, how many of their executions were cached, and what commands were the slowest to run.
|
||||
- The generated `command-stats.txt` file is in a simple human-readable format.
|
||||
|
||||
The structured logs will be written to standard error output (`stderr`), while the other outputs will be stored in files in the `<build-dir>/bootstrap-trace/<pid>` directory. For convenience, bootstrap will also create a symlink to the latest generated trace output directory at `<build-dir>/bootstrap-trace/latest`.
|
||||
|
||||
> Note that if you execute bootstrap with `--dry-run`, the tracing output directory might change. Bootstrap will always print a path where the tracing output files were stored at the end of its execution.
|
||||
|
||||
[tracing]: https://docs.rs/tracing/0.1.41/tracing/index.html
|
||||
[Chrome trace file]: https://www.chromium.org/developers/how-tos/trace-event-profiling-tool/
|
||||
[Perfetto]: https://ui.perfetto.dev/
|
||||
[GraphViz]: https://graphviz.org/doc/info/lang.html
|
||||
[xdot]: https://github.com/jrfonseca/xdot.py
|
||||
|
||||
### Enabling `tracing` output
|
||||
|
||||
Bootstrap will conditionally build `tracing` support and enable `tracing` output if the `BOOTSTRAP_TRACING` env var is set.
|
||||
To enable the conditional `tracing` feature, run bootstrap with the `BOOTSTRAP_TRACING` environment variable.
|
||||
|
||||
#### Basic usage
|
||||
|
||||
Example basic usage[^just-trace]:
|
||||
|
||||
[^just-trace]: It is not recommended to use *just* `BOOTSTRAP_TRACING=TRACE` because that will dump *everything* at `TRACE` level, including logs intentionally gated behind custom targets as they are too verbose even for `TRACE` level by default.
|
||||
[tracing_subscriber filter]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html
|
||||
|
||||
```bash
|
||||
$ BOOTSTRAP_TRACING=bootstrap=TRACE ./x build library --stage 1
|
||||
$ BOOTSTRAP_TRACING=trace ./x build library --stage 1
|
||||
```
|
||||
|
||||
Example output[^unstable]:
|
||||
|
||||
```
|
||||
$ BOOTSTRAP_TRACING=bootstrap=TRACE ./x check src/bootstrap/
|
||||
$ BOOTSTRAP_TRACING=trace ./x build library --stage 1 --dry-run
|
||||
Building bootstrap
|
||||
Compiling bootstrap v0.0.0 (/home/joe/repos/rust/src/bootstrap)
|
||||
Finished `dev` profile [unoptimized] target(s) in 2.74s
|
||||
DEBUG bootstrap parsing flags
|
||||
bootstrap::core::config::flags::Flags::parse args=["check", "src/bootstrap/"]
|
||||
DEBUG bootstrap parsing config based on flags
|
||||
DEBUG bootstrap creating new build based on config
|
||||
bootstrap::Build::build
|
||||
TRACE bootstrap setting up job management
|
||||
TRACE bootstrap downloading rustfmt early
|
||||
bootstrap::handling hardcoded subcommands (Format, Suggest, Perf)
|
||||
DEBUG bootstrap not a hardcoded subcommand; returning to normal handling, cmd=Check { all_targets: false }
|
||||
DEBUG bootstrap handling subcommand normally
|
||||
bootstrap::executing real run
|
||||
bootstrap::(1) executing dry-run sanity-check
|
||||
bootstrap::(2) executing actual run
|
||||
Checking stage0 library artifacts (x86_64-unknown-linux-gnu)
|
||||
Finished `release` profile [optimized + debuginfo] target(s) in 0.04s
|
||||
Checking stage0 compiler artifacts {rustc-main, rustc_abi, rustc_arena, rustc_ast, rustc_ast_ir, rustc_ast_lowering, rustc_ast_passes, rustc_ast_pretty, rustc_attr_data_structures, rustc_attr_parsing, rustc_baked_icu_data, rustc_borrowck, rustc_builtin_macros, rustc_codegen_llvm, rustc_codegen_ssa, rustc_const_eval, rustc_data_structures, rustc_driver, rustc_driver_impl, rustc_error_codes, rustc_error_messages, rustc_errors, rustc_expand, rustc_feature, rustc_fluent_macro, rustc_fs_util, rustc_graphviz, rustc_hir, rustc_hir_analysis, rustc_hir_pretty, rustc_hir_typeck, rustc_incremental, rustc_index, rustc_index_macros, rustc_infer, rustc_interface, rustc_lexer, rustc_lint, rustc_lint_defs, rustc_llvm, rustc_log, rustc_macros, rustc_metadata, rustc_middle, rustc_mir_build, rustc_mir_dataflow, rustc_mir_transform, rustc_monomorphize, rustc_next_trait_solver, rustc_parse, rustc_parse_format, rustc_passes, rustc_pattern_analysis, rustc_privacy, rustc_query_impl, rustc_query_system, rustc_resolve, rustc_sanitizers, rustc_serialize, rustc_session, rustc_smir, rustc_span, rustc_symbol_mangling, rustc_target, rustc_trait_selection, rustc_traits, rustc_transmute, rustc_ty_utils, rustc_type_ir, rustc_type_ir_macros, stable_mir} (x86_64-unknown-linux-gnu)
|
||||
Finished `release` profile [optimized + debuginfo] target(s) in 0.23s
|
||||
Checking stage0 bootstrap artifacts (x86_64-unknown-linux-gnu)
|
||||
Checking bootstrap v0.0.0 (/home/joe/repos/rust/src/bootstrap)
|
||||
Finished `release` profile [optimized + debuginfo] target(s) in 0.64s
|
||||
DEBUG bootstrap checking for postponed test failures from `test --no-fail-fast`
|
||||
Build completed successfully in 0:00:08
|
||||
```
|
||||
|
||||
#### Controlling tracing output
|
||||
|
||||
The env var `BOOTSTRAP_TRACING` accepts a [`tracing` env-filter][tracing-env-filter].
|
||||
|
||||
There are two orthogonal ways to control which kind of tracing logs you want:
|
||||
|
||||
1. You can specify the log **level**, e.g. `DEBUG` or `TRACE`.
|
||||
2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` vs custom targets like `CONFIG_HANDLING`.
|
||||
- Custom targets are used to limit what is output when `BOOTSTRAP_TRACING=bootstrap=TRACE` is used, as they can be too verbose even for `TRACE` level by default. Currently used custom targets:
|
||||
- `CONFIG_HANDLING`
|
||||
|
||||
The `TRACE` filter will enable *all* `trace` level or less verbose level tracing output.
|
||||
|
||||
You can of course combine them (custom target logs are typically gated behind `TRACE` log level additionally):
|
||||
|
||||
```bash
|
||||
$ BOOTSTRAP_TRACING=CONFIG_HANDLING=TRACE ./x build library --stage 1
|
||||
Finished `dev` profile [unoptimized] target(s) in 0.05s
|
||||
15:56:52.477 INFO > tool::LibcxxVersionTool {target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
|
||||
15:56:52.575 INFO > compile::Assemble {target_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }} (builder/mod.rs:1715)
|
||||
15:56:52.575 INFO > tool::Compiletest {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
|
||||
15:56:52.576 INFO > tool::ToolBuild {build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "compiletest", path: "src/tools/compiletest", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "internal_output_capture", cargo_args: [], artifact_kind: Binary} (builder/mod.rs:1715)
|
||||
15:56:52.576 INFO > builder::Libdir {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
|
||||
15:56:52.576 INFO > compile::Sysroot {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, force_recompile: false} (builder/mod.rs:1715)
|
||||
15:56:52.578 INFO > compile::Assemble {target_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }} (builder/mod.rs:1715)
|
||||
15:56:52.578 INFO > tool::Compiletest {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
|
||||
15:56:52.578 INFO > tool::ToolBuild {build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "compiletest", path: "src/tools/compiletest", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "internal_output_capture", cargo_args: [], artifact_kind: Binary} (builder/mod.rs:1715)
|
||||
15:56:52.578 INFO > builder::Libdir {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715)
|
||||
15:56:52.578 INFO > compile::Sysroot {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, force_recompile: false} (builder/mod.rs:1715)
|
||||
Finished `release` profile [optimized] target(s) in 0.11s
|
||||
Tracing/profiling output has been written to <src-root>/build/bootstrap-trace/latest
|
||||
Build completed successfully in 0:00:00
|
||||
```
|
||||
|
||||
[^unstable]: This output is always subject to further changes.
|
||||
|
||||
#### Controlling tracing output
|
||||
|
||||
The environment variable `BOOTSTRAP_TRACING` accepts a [`tracing_subscriber` filter][tracing-env-filter]. If you set `BOOTSTRAP_TRACING=trace`, you will enable all logs, but that can be overwhelming. You can thus use the filter to reduce the amount of data logged.
|
||||
|
||||
There are two orthogonal ways to control which kind of tracing logs you want:
|
||||
|
||||
1. You can specify the log **level**, e.g. `debug` or `trace`.
|
||||
- If you select a level, all events/spans with an equal or higher priority level will be shown.
|
||||
2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` or a custom target like `CONFIG_HANDLING` or `STEP`.
|
||||
- Custom targets are used to limit what kinds of spans you are interested in, as the `BOOTSTRAP_TRACING=trace` output can be quite verbose. Currently, you can use the following custom targets:
|
||||
- `CONFIG_HANDLING`: show spans related to config handling
|
||||
- `STEP`: show all executed steps. Note that executed commands have `info` event level.
|
||||
- `COMMAND`: show all executed commands. Note that executed commands have `trace` event level.
|
||||
|
||||
You can of course combine them (custom target logs are typically gated behind `TRACE` log level additionally):
|
||||
|
||||
```bash
|
||||
$ BOOTSTRAP_TRACING=CONFIG_HANDLING=trace,STEP=info,COMMAND=trace ./x build library --stage 1
|
||||
```
|
||||
|
||||
[tracing-env-filter]: https://docs.rs/tracing-subscriber/0.3.19/tracing_subscriber/filter/struct.EnvFilter.html
|
||||
|
||||
Note that the level that you specify using `BOOTSTRAP_TRACING` also has an effect on the spans that will be recorded in the Chrome trace file.
|
||||
|
||||
##### FIXME(#96176): specific tracing for `compiler()` vs `compiler_for()`
|
||||
|
||||
The additional targets `COMPILER` and `COMPILER_FOR` are used to help trace what
|
||||
|
|
@ -123,12 +103,6 @@ if [#96176][cleanup-compiler-for] is resolved.
|
|||
|
||||
[cleanup-compiler-for]: https://github.com/rust-lang/rust/issues/96176
|
||||
|
||||
### Rendering step graph
|
||||
|
||||
When you run bootstrap with the `BOOTSTRAP_TRACING` environment variable configured, bootstrap will automatically output a DOT file that shows all executed steps and their dependencies. The files will have a prefix `bootstrap-steps`. You can use e.g. `xdot` to visualize the file or e.g. `dot -Tsvg` to convert the DOT file to a SVG file.
|
||||
|
||||
A separate DOT file will be outputted for dry-run and non-dry-run execution.
|
||||
|
||||
### Using `tracing` in bootstrap
|
||||
|
||||
Both `tracing::*` macros and the `tracing::instrument` proc-macro attribute need to be gated behind `tracing` feature. Examples:
|
||||
|
|
@ -149,15 +123,6 @@ impl Step for Foo {
|
|||
todo!()
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
instrument(
|
||||
level = "trace",
|
||||
name = "Foo::run",
|
||||
skip_all,
|
||||
fields(compiler = ?builder.compiler),
|
||||
),
|
||||
)]
|
||||
fn run(self, builder: &Builder<'_>) -> Self::Output {
|
||||
trace!(?run, "entered Foo::run");
|
||||
|
||||
|
|
@ -172,21 +137,6 @@ For `#[instrument]`, it's recommended to:
|
|||
- Explicitly pick an instrumentation name via `name = ".."` to distinguish between e.g. `run` of different steps.
|
||||
- Take care to not cause diverging behavior via tracing, e.g. building extra things only when tracing infra is enabled.
|
||||
|
||||
### Profiling bootstrap
|
||||
|
||||
You can set the `BOOTSTRAP_PROFILE=1` environment variable to enable command execution profiling during bootstrap. This generates:
|
||||
|
||||
* A Chrome trace file (for visualization in `chrome://tracing` or [Perfetto](https://ui.perfetto.dev)) if tracing is enabled via `BOOTSTRAP_TRACING=COMMAND=trace`
|
||||
* A plain-text summary file, `bootstrap-profile-{pid}.txt`, listing all commands sorted by execution time (slowest first), along with cache hits and working directories
|
||||
|
||||
Note: the `.txt` report is always generated when `BOOTSTRAP_PROFILE=1` is set — tracing is not required.
|
||||
|
||||
Example usage:
|
||||
|
||||
```bash
|
||||
$ BOOTSTRAP_PROFILE=1 BOOTSTRAP_TRACING=COMMAND=trace ./x build library
|
||||
```
|
||||
|
||||
### rust-analyzer integration?
|
||||
|
||||
Unfortunately, because bootstrap is a `rust-analyzer.linkedProjects`, you can't ask r-a to check/build bootstrap itself with `tracing` feature enabled to get relevant completions, due to lack of support as described in <https://github.com/rust-lang/rust-analyzer/issues/8521>.
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ complete -c x -n "__fish_x_using_subcommand build" -l llvm-profile-use -d 'use P
|
|||
complete -c x -n "__fish_x_using_subcommand build" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r
|
||||
complete -c x -n "__fish_x_using_subcommand build" -l set -d 'override options in bootstrap.toml' -r -f
|
||||
complete -c x -n "__fish_x_using_subcommand build" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}"
|
||||
complete -c x -n "__fish_x_using_subcommand build" -l timings -d 'Pass `--timings` to Cargo to get crate build timings'
|
||||
complete -c x -n "__fish_x_using_subcommand build" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
|
||||
complete -c x -n "__fish_x_using_subcommand build" -s i -l incremental -d 'use incremental compilation'
|
||||
complete -c x -n "__fish_x_using_subcommand build" -l include-default-paths -d 'include default paths in addition to the provided ones'
|
||||
|
|
@ -133,6 +134,7 @@ complete -c x -n "__fish_x_using_subcommand check" -l reproducible-artifact -d '
|
|||
complete -c x -n "__fish_x_using_subcommand check" -l set -d 'override options in bootstrap.toml' -r -f
|
||||
complete -c x -n "__fish_x_using_subcommand check" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}"
|
||||
complete -c x -n "__fish_x_using_subcommand check" -l all-targets -d 'Check all targets'
|
||||
complete -c x -n "__fish_x_using_subcommand check" -l timings -d 'Pass `--timings` to Cargo to get crate build timings'
|
||||
complete -c x -n "__fish_x_using_subcommand check" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
|
||||
complete -c x -n "__fish_x_using_subcommand check" -s i -l incremental -d 'use incremental compilation'
|
||||
complete -c x -n "__fish_x_using_subcommand check" -l include-default-paths -d 'include default paths in addition to the provided ones'
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock {
|
|||
[CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive')
|
||||
[CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml')
|
||||
[CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not')
|
||||
[CompletionResult]::new('--timings', '--timings', [CompletionResultType]::ParameterName, 'Pass `--timings` to Cargo to get crate build timings')
|
||||
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
|
||||
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
|
||||
[CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation')
|
||||
|
|
@ -145,6 +146,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock {
|
|||
[CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml')
|
||||
[CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not')
|
||||
[CompletionResult]::new('--all-targets', '--all-targets', [CompletionResultType]::ParameterName, 'Check all targets')
|
||||
[CompletionResult]::new('--timings', '--timings', [CompletionResultType]::ParameterName, 'Pass `--timings` to Cargo to get crate build timings')
|
||||
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
|
||||
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
|
||||
[CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation')
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-profile-use -d
|
|||
complete -c x.py -n "__fish_x.py_using_subcommand build" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand build" -l set -d 'override options in bootstrap.toml' -r -f
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand build" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}"
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand build" -l timings -d 'Pass `--timings` to Cargo to get crate build timings'
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand build" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand build" -s i -l incremental -d 'use incremental compilation'
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand build" -l include-default-paths -d 'include default paths in addition to the provided ones'
|
||||
|
|
@ -133,6 +134,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand check" -l reproducible-artifac
|
|||
complete -c x.py -n "__fish_x.py_using_subcommand check" -l set -d 'override options in bootstrap.toml' -r -f
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand check" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}"
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand check" -l all-targets -d 'Check all targets'
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand check" -l timings -d 'Pass `--timings` to Cargo to get crate build timings'
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand check" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand check" -s i -l incremental -d 'use incremental compilation'
|
||||
complete -c x.py -n "__fish_x.py_using_subcommand check" -l include-default-paths -d 'include default paths in addition to the provided ones'
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
|
|||
[CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive')
|
||||
[CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml')
|
||||
[CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not')
|
||||
[CompletionResult]::new('--timings', '--timings', [CompletionResultType]::ParameterName, 'Pass `--timings` to Cargo to get crate build timings')
|
||||
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
|
||||
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
|
||||
[CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation')
|
||||
|
|
@ -145,6 +146,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
|
|||
[CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml')
|
||||
[CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not')
|
||||
[CompletionResult]::new('--all-targets', '--all-targets', [CompletionResultType]::ParameterName, 'Check all targets')
|
||||
[CompletionResult]::new('--timings', '--timings', [CompletionResultType]::ParameterName, 'Pass `--timings` to Cargo to get crate build timings')
|
||||
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
|
||||
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
|
||||
[CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation')
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ _x.py() {
|
|||
return 0
|
||||
;;
|
||||
x.py__build)
|
||||
opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
|
||||
opts="-v -i -j -h --timings --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
|
@ -644,7 +644,7 @@ _x.py() {
|
|||
return 0
|
||||
;;
|
||||
x.py__check)
|
||||
opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
|
||||
opts="-v -i -j -h --all-targets --timings --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ _arguments "${_arguments_options[@]}" : \
|
|||
'*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \
|
||||
'*--set=[override options in bootstrap.toml]:section.option=value:' \
|
||||
'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \
|
||||
'--timings[Pass \`--timings\` to Cargo to get crate build timings]' \
|
||||
'*-v[use verbose output (-vv for very verbose)]' \
|
||||
'*--verbose[use verbose output (-vv for very verbose)]' \
|
||||
'-i[use incremental compilation]' \
|
||||
|
|
@ -135,6 +136,7 @@ _arguments "${_arguments_options[@]}" : \
|
|||
'*--set=[override options in bootstrap.toml]:section.option=value:' \
|
||||
'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \
|
||||
'--all-targets[Check all targets]' \
|
||||
'--timings[Pass \`--timings\` to Cargo to get crate build timings]' \
|
||||
'*-v[use verbose output (-vv for very verbose)]' \
|
||||
'*--verbose[use verbose output (-vv for very verbose)]' \
|
||||
'-i[use incremental compilation]' \
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ _x() {
|
|||
return 0
|
||||
;;
|
||||
x__build)
|
||||
opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
|
||||
opts="-v -i -j -h --timings --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
|
@ -644,7 +644,7 @@ _x() {
|
|||
return 0
|
||||
;;
|
||||
x__check)
|
||||
opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
|
||||
opts="-v -i -j -h --all-targets --timings --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..."
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ _arguments "${_arguments_options[@]}" : \
|
|||
'*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \
|
||||
'*--set=[override options in bootstrap.toml]:section.option=value:' \
|
||||
'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \
|
||||
'--timings[Pass \`--timings\` to Cargo to get crate build timings]' \
|
||||
'*-v[use verbose output (-vv for very verbose)]' \
|
||||
'*--verbose[use verbose output (-vv for very verbose)]' \
|
||||
'-i[use incremental compilation]' \
|
||||
|
|
@ -135,6 +136,7 @@ _arguments "${_arguments_options[@]}" : \
|
|||
'*--set=[override options in bootstrap.toml]:section.option=value:' \
|
||||
'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \
|
||||
'--all-targets[Check all targets]' \
|
||||
'--timings[Pass \`--timings\` to Cargo to get crate build timings]' \
|
||||
'*-v[use verbose output (-vv for very verbose)]' \
|
||||
'*--verbose[use verbose output (-vv for very verbose)]' \
|
||||
'-i[use incremental compilation]' \
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ LL | Box::new(|| x)
|
|||
| |
|
||||
| captured by this `Fn` closure
|
||||
|
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | Box::new(|| x.clone())
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ LL | let _h = to_fn_once(move || -> isize { *bar });
|
|||
| |
|
||||
| `bar` is moved here
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/borrowck-move-by-capture.rs:3:37
|
||||
|
|
||||
LL | fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ LL |
|
|||
LL | self.b;
|
||||
| ^^^^^^ `self.b` is moved here
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/issue-103624.rs:7:36
|
||||
|
|
||||
LL | async fn spawn_blocking<T>(f: impl (Fn() -> T) + Send + Sync + 'static) -> T {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ LL |
|
|||
LL | let _foo: String = val;
|
||||
| ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/issue-87456-point-to-closure.rs:3:24
|
||||
|
|
||||
LL | fn take_mut(_val: impl FnMut()) {}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ LL | y.into_iter();
|
|||
| |
|
||||
| move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:5:28
|
||||
|
|
||||
LL | fn call<F>(f: F) where F : Fn() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//@ dont-require-annotations: NOTE
|
||||
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
|
||||
//@ normalize-stderr: "([[:xdigit:]]{2}\s){4}(__\s){4}\s+│\s+([?|\.]){4}\W{4}" -> "HEX_DUMP"
|
||||
|
||||
type Field1 = i32;
|
||||
type Field2 = f32;
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory
|
||||
--> $DIR/union-const-eval-field.rs:29:37
|
||||
--> $DIR/union-const-eval-field.rs:30:37
|
||||
|
|
||||
LL | const FIELD3: Field3 = unsafe { UNION.field3 };
|
||||
| ^^^^^^^^^^^^ evaluation of `read_field3::FIELD3` failed here
|
||||
|
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
00 00 80 3f __ __ __ __ │ ...?░░░░
|
||||
HEX_DUMP
|
||||
}
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/union-const-eval-field.rs:31:5
|
||||
--> $DIR/union-const-eval-field.rs:32:5
|
||||
|
|
||||
LL | FIELD3
|
||||
| ^^^^^^
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/union-const-eval-field.rs:31:5
|
||||
--> $DIR/union-const-eval-field.rs:32:5
|
||||
|
|
||||
LL | FIELD3
|
||||
| ^^^^^^
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
//@ normalize-stderr: "[[:xdigit:]]{2} __ ([[:xdigit:]]{2}\s){2}" -> "HEX_DUMP"
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
const RAW_EQ_PADDING: bool = unsafe {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:4:5
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:5:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_PADDING` failed here
|
||||
|
|
||||
= note: the raw bytes of the constant (size: 4, align: 2) {
|
||||
01 __ 02 00 │ .░..
|
||||
HEX_DUMP │ .░..
|
||||
}
|
||||
|
||||
error[E0080]: unable to turn pointer into integer
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:9:5
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:10:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(&(&0), &(&1))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_PTR` failed here
|
||||
|
|
@ -18,7 +18,7 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1))
|
|||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
||||
error[E0080]: accessing memory with alignment 1, but alignment 4 is required
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:16:5
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:17:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(aref, aref)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_NOT_ALIGNED` failed here
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ LL | id(Box::new(|| *v))
|
|||
| |
|
||||
| captured by this `FnMut` closure
|
||||
|
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
help: if `T` implemented `Clone`, you could clone the value
|
||||
--> $DIR/issue-4335.rs:5:10
|
||||
|
|
||||
|
|
|
|||
|
|
@ -8,10 +8,42 @@ fn print() {
|
|||
});
|
||||
}
|
||||
|
||||
fn arm_rhs_must_be_in_braces() -> i32 {
|
||||
fn print_2() {
|
||||
println!(cfg_select! {
|
||||
unix => "unix",
|
||||
_ => "not unix",
|
||||
});
|
||||
}
|
||||
|
||||
fn arm_rhs_expr_1() -> i32 {
|
||||
cfg_select! {
|
||||
true => 1
|
||||
//~^ ERROR: expected `{`, found `1`
|
||||
}
|
||||
}
|
||||
|
||||
fn arm_rhs_expr_2() -> i32 {
|
||||
cfg_select! {
|
||||
true => 1,
|
||||
false => 2
|
||||
}
|
||||
}
|
||||
|
||||
fn arm_rhs_expr_3() -> i32 {
|
||||
cfg_select! {
|
||||
true => 1,
|
||||
false => 2,
|
||||
true => { 42 }
|
||||
false => -1 as i32,
|
||||
true => 2 + 2,
|
||||
false => "",
|
||||
true => if true { 42 } else { 84 }
|
||||
false => if true { 42 } else { 84 },
|
||||
true => return 42,
|
||||
false => loop {}
|
||||
true => (1, 2),
|
||||
false => (1, 2,),
|
||||
true => todo!(),
|
||||
false => println!("hello"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
error: expected `{`, found `1`
|
||||
--> $DIR/cfg_select.rs:13:17
|
||||
|
|
||||
LL | true => 1
|
||||
| ^ expected `{`
|
||||
|
||||
warning: unreachable predicate
|
||||
--> $DIR/cfg_select.rs:20:5
|
||||
--> $DIR/cfg_select.rs:52:5
|
||||
|
|
||||
LL | _ => {}
|
||||
| - always matches
|
||||
|
|
@ -13,7 +7,7 @@ LL | true => {}
|
|||
| ^^^^ this predicate is never reached
|
||||
|
||||
error: none of the predicates in this `cfg_select` evaluated to true
|
||||
--> $DIR/cfg_select.rs:24:1
|
||||
--> $DIR/cfg_select.rs:56:1
|
||||
|
|
||||
LL | / cfg_select! {
|
||||
LL | |
|
||||
|
|
@ -22,10 +16,10 @@ LL | | }
|
|||
| |_^
|
||||
|
||||
error: none of the predicates in this `cfg_select` evaluated to true
|
||||
--> $DIR/cfg_select.rs:29:1
|
||||
--> $DIR/cfg_select.rs:61:1
|
||||
|
|
||||
LL | cfg_select! {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ LL | let _f = to_fn(|| test(i));
|
|||
| |
|
||||
| captured by this `Fn` closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:3:33
|
||||
|
|
||||
LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ LL | expect_fn(|| drop(x.0));
|
|||
| |
|
||||
| captured by this `Fn` closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/issue-52663-span-decl-captured-variable.rs:1:33
|
||||
|
|
||||
LL | fn expect_fn<F>(f: F) where F : Fn() {
|
||||
|
|
|
|||
18
tests/ui/or-patterns/issue-64879-trailing-before-guard.fixed
Normal file
18
tests/ui/or-patterns/issue-64879-trailing-before-guard.fixed
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// In this regression test we check that a trailing `|` in an or-pattern just
|
||||
// before the `if` token of a `match` guard will receive parser recovery with
|
||||
// an appropriate error message.
|
||||
//@ run-rustfix
|
||||
#![allow(dead_code)]
|
||||
|
||||
enum E { A, B }
|
||||
|
||||
fn main() {
|
||||
match E::A {
|
||||
E::A |
|
||||
E::B //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
if true => {
|
||||
let _recovery_witness: i32 = 0i32; //~ ERROR mismatched types
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
// In this regression test we check that a trailing `|` in an or-pattern just
|
||||
// before the `if` token of a `match` guard will receive parser recovery with
|
||||
// an appropriate error message.
|
||||
//@ run-rustfix
|
||||
#![allow(dead_code)]
|
||||
|
||||
enum E { A, B }
|
||||
|
||||
|
|
@ -9,7 +11,8 @@ fn main() {
|
|||
E::A |
|
||||
E::B | //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
if true => {
|
||||
let recovery_witness: bool = 0; //~ ERROR mismatched types
|
||||
let _recovery_witness: i32 = 0u32; //~ ERROR mismatched types
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/issue-64879-trailing-before-guard.rs:10:14
|
||||
--> $DIR/issue-64879-trailing-before-guard.rs:12:14
|
||||
|
|
||||
LL | E::A |
|
||||
| ---- while parsing this or-pattern starting here
|
||||
LL | E::B |
|
||||
| ^
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - E::B |
|
||||
LL + E::B
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-64879-trailing-before-guard.rs:12:42
|
||||
--> $DIR/issue-64879-trailing-before-guard.rs:14:42
|
||||
|
|
||||
LL | let _recovery_witness: i32 = 0u32;
|
||||
| --- ^^^^ expected `i32`, found `u32`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL - let _recovery_witness: i32 = 0u32;
|
||||
LL + let _recovery_witness: i32 = 0i32;
|
||||
|
|
||||
LL | let recovery_witness: bool = 0;
|
||||
| ---- ^ expected `bool`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -23,26 +23,26 @@ fn leading() {
|
|||
|
||||
#[cfg(false)]
|
||||
fn trailing() {
|
||||
let ( A ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let (a ,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let ( A | B ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let [ A | B ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let S { f: B }; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let ( A | B ): E; //~ ERROR unexpected token `||` in pattern
|
||||
let ( A ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let (a,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let ( A | B ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let [ A | B ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let S { f: B }; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let ( A | B ): E; //~ ERROR unexpected token `||` in pattern
|
||||
//~^ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
match A {
|
||||
A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
A | B => {} //~ ERROR unexpected token `||` in pattern
|
||||
A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
A => {} //~ ERROR a trailing `||` is not allowed in an or-pattern
|
||||
A | B => {} //~ ERROR unexpected token `||` in pattern
|
||||
//~^ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
| A | B => {}
|
||||
| A | B => {}
|
||||
//~^ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
}
|
||||
|
||||
// These test trailing-vert in `let` bindings, but they also test that we don't emit a
|
||||
// duplicate suggestion that would confuse rustfix.
|
||||
|
||||
let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ fn trailing() {
|
|||
//~^ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
match A {
|
||||
A | => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
A || => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
A || => {} //~ ERROR a trailing `||` is not allowed in an or-pattern
|
||||
A || B | => {} //~ ERROR unexpected token `||` in pattern
|
||||
//~^ ERROR a trailing `|` is not allowed in an or-pattern
|
||||
| A | B | => {}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,6 @@ error: function parameters require top-level or-patterns in parentheses
|
|||
|
|
||||
LL | fn fun1( | A: E) {}
|
||||
| ^^^
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - fn fun1( | A: E) {}
|
||||
LL + fn fun1( A: E) {}
|
||||
|
|
||||
|
||||
error: unexpected `||` before function parameter
|
||||
--> $DIR/remove-leading-vert.rs:12:14
|
||||
|
|
@ -78,12 +72,6 @@ LL | let ( A | ): E;
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let ( A | ): E;
|
||||
LL + let ( A ): E;
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:27:12
|
||||
|
|
@ -92,12 +80,6 @@ LL | let (a |,): (E,);
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let (a |,): (E,);
|
||||
LL + let (a ,): (E,);
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:28:17
|
||||
|
|
@ -106,12 +88,6 @@ LL | let ( A | B | ): E;
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let ( A | B | ): E;
|
||||
LL + let ( A | B ): E;
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:29:17
|
||||
|
|
@ -120,12 +96,6 @@ LL | let [ A | B | ]: [E; 1];
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let [ A | B | ]: [E; 1];
|
||||
LL + let [ A | B ]: [E; 1];
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:30:18
|
||||
|
|
@ -134,12 +104,6 @@ LL | let S { f: B | };
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let S { f: B | };
|
||||
LL + let S { f: B };
|
||||
|
|
||||
|
||||
error: unexpected token `||` in pattern
|
||||
--> $DIR/remove-leading-vert.rs:31:13
|
||||
|
|
@ -162,12 +126,6 @@ LL | let ( A || B | ): E;
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let ( A || B | ): E;
|
||||
LL + let ( A || B ): E;
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:34:11
|
||||
|
|
@ -176,14 +134,8 @@ LL | A | => {}
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - A | => {}
|
||||
LL + A => {}
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
error: a trailing `||` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:35:11
|
||||
|
|
||||
LL | A || => {}
|
||||
|
|
@ -192,11 +144,6 @@ LL | A || => {}
|
|||
| while parsing this or-pattern starting here
|
||||
|
|
||||
= note: alternatives in or-patterns are separated with `|`, not `||`
|
||||
help: remove the `||`
|
||||
|
|
||||
LL - A || => {}
|
||||
LL + A => {}
|
||||
|
|
||||
|
||||
error: unexpected token `||` in pattern
|
||||
--> $DIR/remove-leading-vert.rs:36:11
|
||||
|
|
@ -219,12 +166,6 @@ LL | A || B | => {}
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - A || B | => {}
|
||||
LL + A || B => {}
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:38:17
|
||||
|
|
@ -233,12 +174,6 @@ LL | | A | B | => {}
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - | A | B | => {}
|
||||
LL + | A | B => {}
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:45:11
|
||||
|
|
@ -247,12 +182,6 @@ LL | let a | : u8 = 0;
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let a | : u8 = 0;
|
||||
LL + let a : u8 = 0;
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:46:11
|
||||
|
|
@ -261,12 +190,6 @@ LL | let a | = 0;
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let a | = 0;
|
||||
LL + let a = 0;
|
||||
|
|
||||
|
||||
error: a trailing `|` is not allowed in an or-pattern
|
||||
--> $DIR/remove-leading-vert.rs:47:11
|
||||
|
|
@ -275,12 +198,6 @@ LL | let a | ;
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - let a | ;
|
||||
LL + let a ;
|
||||
|
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,6 @@ LL | ! |
|
|||
| - ^
|
||||
| |
|
||||
| while parsing this or-pattern starting here
|
||||
|
|
||||
help: remove the `|`
|
||||
|
|
||||
LL - ! |
|
||||
LL + !
|
||||
|
|
||||
|
||||
error: a never pattern is always unreachable
|
||||
--> $DIR/ICE-130779-never-arm-no-oatherwise-block.rs:10:20
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ LL |
|
|||
LL | foo(f);
|
||||
| ^ move occurs because `f` has type `{closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58}`, which does not implement the `Copy` trait
|
||||
|
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | foo(f.clone());
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ LL | let X(_t) = x;
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -37,7 +37,7 @@ LL | if let Either::One(_t) = e { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -62,7 +62,7 @@ LL | while let Either::One(_t) = e { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -90,7 +90,7 @@ LL | Either::One(_t)
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -118,7 +118,7 @@ LL | Either::One(_t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -143,7 +143,7 @@ LL | let X(mut _t) = x;
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -168,7 +168,7 @@ LL | if let Either::One(mut _t) = em { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -193,7 +193,7 @@ LL | while let Either::One(mut _t) = em { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -221,7 +221,7 @@ LL | Either::One(mut _t)
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -249,7 +249,7 @@ LL | Either::One(mut _t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:13:18
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -273,7 +273,7 @@ LL | let X(_t) = x;
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -298,7 +298,7 @@ LL | if let Either::One(_t) = e { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -323,7 +323,7 @@ LL | while let Either::One(_t) = e { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -351,7 +351,7 @@ LL | Either::One(_t)
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -379,7 +379,7 @@ LL | Either::One(_t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -404,7 +404,7 @@ LL | let X(mut _t) = x;
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -429,7 +429,7 @@ LL | if let Either::One(mut _t) = em { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -454,7 +454,7 @@ LL | while let Either::One(mut _t) = em { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -482,7 +482,7 @@ LL | Either::One(mut _t)
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -510,7 +510,7 @@ LL | Either::One(mut _t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:39:22
|
||||
|
|
||||
LL | fn consume_fn<F: Fn()>(_f: F) { }
|
||||
|
|
@ -534,7 +534,7 @@ LL | let X(_t) = x;
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -559,7 +559,7 @@ LL | if let Either::One(_t) = e { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -584,7 +584,7 @@ LL | while let Either::One(_t) = e { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -612,7 +612,7 @@ LL | Either::One(_t)
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -640,7 +640,7 @@ LL | Either::One(_t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -665,7 +665,7 @@ LL | let X(mut _t) = x;
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -690,7 +690,7 @@ LL | if let Either::One(mut _t) = em { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -715,7 +715,7 @@ LL | while let Either::One(mut _t) = em { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -743,7 +743,7 @@ LL | Either::One(mut _t)
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -771,7 +771,7 @@ LL | Either::One(mut _t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:50:29
|
||||
|
|
||||
LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { }
|
||||
|
|
@ -795,7 +795,7 @@ LL | let X(_t) = x;
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -820,7 +820,7 @@ LL | if let Either::One(_t) = e { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -845,7 +845,7 @@ LL | while let Either::One(_t) = e { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -873,7 +873,7 @@ LL | Either::One(_t)
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -901,7 +901,7 @@ LL | Either::One(_t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -926,7 +926,7 @@ LL | let X(mut _t) = x;
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -951,7 +951,7 @@ LL | if let Either::One(mut _t) = em { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -976,7 +976,7 @@ LL | while let Either::One(mut _t) = em { }
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -1004,7 +1004,7 @@ LL | Either::One(mut _t)
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -1032,7 +1032,7 @@ LL | Either::One(mut _t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
@ -1060,7 +1060,7 @@ LL | Either::One(mut _t) => (),
|
|||
| data moved here
|
||||
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/move-into-closure.rs:25:21
|
||||
|
|
||||
LL | fn consume_fnmut<F: FnMut()>(_f: F) { }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ LL |
|
|||
LL | var = Some(NotCopyable);
|
||||
| --- variable moved due to use in closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/option-content-move2.rs:5:12
|
||||
|
|
||||
LL | fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}
|
||||
|
|
@ -44,7 +44,7 @@ LL |
|
|||
LL | var = Some(NotCopyableButCloneable);
|
||||
| --- variable moved due to use in closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/option-content-move2.rs:5:12
|
||||
|
|
||||
LL | fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ LL | move || {
|
|||
LL | let x = var;
|
||||
| ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait
|
||||
|
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
note: if `NotCopyable` implemented `Clone`, you could clone the value
|
||||
--> $DIR/option-content-move3.rs:2:1
|
||||
|
|
||||
|
|
@ -38,7 +38,7 @@ LL | move || {
|
|||
LL | let x = var;
|
||||
| --- variable moved due to use in closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/option-content-move3.rs:6:12
|
||||
|
|
||||
LL | fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}
|
||||
|
|
@ -63,7 +63,7 @@ LL | move || {
|
|||
LL | let x = var;
|
||||
| ^^^ move occurs because `var` has type `NotCopyableButCloneable`, which does not implement the `Copy` trait
|
||||
|
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
= help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | let x = &var;
|
||||
|
|
@ -84,7 +84,7 @@ LL | move || {
|
|||
LL | let x = var;
|
||||
| --- variable moved due to use in closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/option-content-move3.rs:6:12
|
||||
|
|
||||
LL | fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ LL | let f = to_fn(|| drop(x));
|
|||
| |
|
||||
| captured by this `Fn` closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/unboxed-closure-illegal-move.rs:7:33
|
||||
|
|
||||
LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
|
||||
|
|
@ -32,7 +32,7 @@ LL | let f = to_fn_mut(|| drop(x));
|
|||
| |
|
||||
| captured by this `FnMut` closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/unboxed-closure-illegal-move.rs:8:37
|
||||
|
|
||||
LL | fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
|
||||
|
|
@ -54,7 +54,7 @@ LL | let f = to_fn(move || drop(x));
|
|||
| |
|
||||
| captured by this `Fn` closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/unboxed-closure-illegal-move.rs:7:33
|
||||
|
|
||||
LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
|
||||
|
|
@ -72,7 +72,7 @@ LL | let f = to_fn_mut(move || drop(x));
|
|||
| |
|
||||
| captured by this `FnMut` closure
|
||||
|
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
|
||||
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once
|
||||
--> $DIR/unboxed-closure-illegal-move.rs:8:37
|
||||
|
|
||||
LL | fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue