Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions compiler/rustc_middle/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::profiling::QueryInvocationId;
use rustc_data_structures::sharded::{self, ShardedHashMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{AtomicU64, Lock};
use rustc_data_structures::sync::{AtomicU64, Lock, is_dyn_thread_safe};
use rustc_data_structures::unord::UnordMap;
use rustc_data_structures::{assert_matches, outline};
use rustc_errors::DiagInner;
Expand Down Expand Up @@ -1302,7 +1302,9 @@ impl CurrentDepGraph {
prev_graph: &SerializedDepGraph,
prev_index: SerializedDepNodeIndex,
) {
if let Some(ref nodes_in_current_session) = self.nodes_in_current_session {
if !is_dyn_thread_safe()
&& let Some(ref nodes_in_current_session) = self.nodes_in_current_session
{
debug_assert!(
!nodes_in_current_session
.lock()
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/query/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ pub(crate) fn query_feed<'tcx, C>(
// The query already has a cached value for this key.
// That's OK if both values are the same, i.e. they have the same hash,
// so now we check their hashes.
if let Some(hasher_fn) = query_vtable.hash_result {
if let Some(hash_value_fn) = query_vtable.hash_value_fn {
let (old_hash, value_hash) = tcx.with_stable_hashing_context(|ref mut hcx| {
(hasher_fn(hcx, &old), hasher_fn(hcx, &value))
(hash_value_fn(hcx, &old), hash_value_fn(hcx, &value))
});
if old_hash != value_hash {
// We have an inconsistency. This can happen if one of the two
Expand Down Expand Up @@ -151,7 +151,7 @@ pub(crate) fn query_feed<'tcx, C>(
dep_node,
tcx,
&value,
query_vtable.hash_result,
query_vtable.hash_value_fn,
query_vtable.format_value,
);
query_vtable.cache.complete(key, value, dep_node_index);
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_middle/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn(
pub type IsLoadableFromDiskFn<'tcx, Key> =
fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool;

pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;

#[derive(Clone, Debug)]
pub struct CycleError<I = QueryStackFrameExtra> {
/// The query and related span that uses the cycle.
Expand Down Expand Up @@ -146,7 +144,12 @@ pub struct QueryVTable<'tcx, C: QueryCache> {

pub try_load_from_disk_fn: Option<TryLoadFromDiskFn<'tcx, C::Key, C::Value>>,
pub is_loadable_from_disk_fn: Option<IsLoadableFromDiskFn<'tcx, C::Key>>,
pub hash_result: HashResult<C::Value>,

/// Function pointer that hashes this query's result values.
///
/// For `no_hash` queries, this function pointer is None.
pub hash_value_fn: Option<fn(&mut StableHashingContext<'_>, &C::Value) -> Fingerprint>,

pub value_from_cycle_error:
fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value,
pub format_value: fn(&C::Value) -> String,
Expand Down
32 changes: 16 additions & 16 deletions compiler/rustc_query_impl/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ fn execute_job<'tcx, C: QueryCache, const INCR: bool>(
debug_assert_eq!(tcx.dep_graph.is_fully_enabled(), INCR);

// Delegate to another function to actually execute the query job.
let (result, dep_node_index) = if INCR {
let (value, dep_node_index) = if INCR {
execute_job_incr(query, tcx, key, dep_node, id)
} else {
execute_job_non_incr(query, tcx, key, id)
Expand All @@ -384,18 +384,18 @@ fn execute_job<'tcx, C: QueryCache, const INCR: bool>(
// This can't happen, as query feeding adds the very dependencies to the fed query
// as its feeding query had. So if the fed query is red, so is its feeder, which will
// get evaluated first, and re-feed the query.
if let Some((cached_result, _)) = cache.lookup(&key) {
let Some(hasher) = query.hash_result else {
if let Some((cached_value, _)) = cache.lookup(&key) {
let Some(hash_value_fn) = query.hash_value_fn else {
panic!(
"no_hash fed query later has its value computed.\n\
Remove `no_hash` modifier to allow recomputation.\n\
The already cached value: {}",
(query.format_value)(&cached_result)
(query.format_value)(&cached_value)
);
};

let (old_hash, new_hash) = tcx.with_stable_hashing_context(|mut hcx| {
(hasher(&mut hcx, &cached_result), hasher(&mut hcx, &result))
(hash_value_fn(&mut hcx, &cached_value), hash_value_fn(&mut hcx, &value))
});
let formatter = query.format_value;
if old_hash != new_hash {
Expand All @@ -407,17 +407,17 @@ fn execute_job<'tcx, C: QueryCache, const INCR: bool>(
computed={:#?}\nfed={:#?}",
query.dep_kind,
key,
formatter(&result),
formatter(&cached_result),
formatter(&value),
formatter(&cached_value),
);
}
}
}

// Tell the guard to perform completion bookkeeping, and also to not poison the query.
job_guard.complete(cache, result, dep_node_index);
job_guard.complete(cache, value, dep_node_index);

(result, Some(dep_node_index))
(value, Some(dep_node_index))
}

// Fast path for when incr. comp. is off.
Expand All @@ -438,22 +438,22 @@ fn execute_job_non_incr<'tcx, C: QueryCache>(

let prof_timer = tcx.prof.query_provider();
// Call the query provider.
let result =
let value =
start_query(tcx, job_id, query.depth_limit, || (query.invoke_provider_fn)(tcx, key));
let dep_node_index = tcx.dep_graph.next_virtual_depnode_index();
prof_timer.finish_with_query_invocation_id(dep_node_index.into());

// Similarly, fingerprint the result to assert that
// it doesn't have anything not considered hashable.
if cfg!(debug_assertions)
&& let Some(hash_result) = query.hash_result
&& let Some(hash_value_fn) = query.hash_value_fn
{
tcx.with_stable_hashing_context(|mut hcx| {
hash_result(&mut hcx, &result);
hash_value_fn(&mut hcx, &value);
});
}

(result, dep_node_index)
(value, dep_node_index)
}

#[inline(always)]
Expand Down Expand Up @@ -509,7 +509,7 @@ fn execute_job_incr<'tcx, C: QueryCache>(
tcx,
(query, key),
|tcx, (query, key)| (query.invoke_provider_fn)(tcx, key),
query.hash_result,
query.hash_value_fn,
)
});

Expand Down Expand Up @@ -560,7 +560,7 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>(
dep_graph_data,
&value,
prev_index,
query.hash_result,
query.hash_value_fn,
query.format_value,
);
}
Expand Down Expand Up @@ -607,7 +607,7 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>(
dep_graph_data,
&value,
prev_index,
query.hash_result,
query.hash_value_fn,
query.format_value,
);

Expand Down
31 changes: 17 additions & 14 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,19 +165,13 @@ macro_rules! is_feedable {
};
}

macro_rules! hash_result {
([][$V:ty]) => {{
Some(|hcx, result| {
let result = rustc_middle::query::erase::restore_val::<$V>(*result);
rustc_middle::dep_graph::hash_result(hcx, &result)
})
}};
([(no_hash) $($rest:tt)*][$V:ty]) => {{
None
}};
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
hash_result!([$($modifiers)*][$($args)*])
};
/// Expands to `$yes` if the `no_hash` modifier is present, or `$no` otherwise.
macro_rules! if_no_hash {
([] $yes:tt $no:tt) => { $no };
([(no_hash) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
if_no_hash!([$($modifiers)*] $yes $no)
}
}

macro_rules! call_provider {
Expand Down Expand Up @@ -560,7 +554,16 @@ macro_rules! define_queries {
let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar);
erase::erase_val(result)
},
hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
hash_value_fn: if_no_hash!(
[$($modifiers)*]
None
{
Some(|hcx, erased_value: &erase::Erased<queries::$name::Value<'tcx>>| {
let value = erase::restore_val(*erased_value);
rustc_middle::dep_graph::hash_result(hcx, &value)
})
}
),
format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
description_fn: $crate::queries::_description_fns::$name,
execute_query_fn: if incremental {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,44 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
return false;
}

// If this is a zero-argument async closure directly passed as an argument
// and the expected type is `Future`, suggest using `async {}` block instead
// of `async || {}`
if let ty::CoroutineClosure(def_id, args) = *self_ty.kind()
&& let sig = args.as_coroutine_closure().coroutine_closure_sig().skip_binder()
&& let ty::Tuple(inputs) = *sig.tupled_inputs_ty.kind()
&& inputs.is_empty()
&& self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Future)
&& let Some(hir::Node::Expr(hir::Expr {
kind:
hir::ExprKind::Closure(hir::Closure {
kind: hir::ClosureKind::CoroutineClosure(CoroutineDesugaring::Async),
fn_arg_span: Some(arg_span),
..
}),
..
})) = self.tcx.hir_get_if_local(def_id)
&& obligation.cause.span.contains(*arg_span)
{
let sm = self.tcx.sess.source_map();
let removal_span = if let Ok(snippet) =
sm.span_to_snippet(arg_span.with_hi(arg_span.hi() + rustc_span::BytePos(1)))
&& snippet.ends_with(' ')
{
// There's a space after `||`, include it in the removal
arg_span.with_hi(arg_span.hi() + rustc_span::BytePos(1))
} else {
*arg_span
};
err.span_suggestion_verbose(
removal_span,
"use `async {}` instead of `async || {}` to introduce an async block",
"",
Applicability::MachineApplicable,
);
return true;
}

// Get the name of the callable and the arguments to be used in the suggestion.
let msg = match def_id_or_name {
DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,9 @@ impl Step for Tidy {
if builder.config.cmd.bless() {
cmd.arg("--bless");
}
if builder.config.is_running_on_ci() {
cmd.arg("--ci=true");
}
if let Some(s) =
builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
{
Expand Down
2 changes: 2 additions & 0 deletions src/tools/rustfmt/tests/target/field-representing-types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
type FRT = builtin # field_of(Type, ident);
type FRT2 = builtin # field_of(Type<A, B>, ident);
4 changes: 2 additions & 2 deletions src/tools/tidy/src/alphabetical/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::diagnostics::{TidyCtx, TidyFlags};

#[track_caller]
fn test(lines: &str, name: &str, expected_msg: &str, expected_bad: bool) {
let tidy_ctx = TidyCtx::new(Path::new("/"), false, TidyFlags::default());
let tidy_ctx = TidyCtx::new(Path::new("/"), false, None, TidyFlags::default());
let mut check = tidy_ctx.start_check("alphabetical-test");
check_lines(Path::new(name), lines, &tidy_ctx, &mut check);

Expand Down Expand Up @@ -37,7 +37,7 @@ fn bless_test(before: &str, after: &str) {
let temp_path = tempfile::Builder::new().tempfile().unwrap().into_temp_path();
std::fs::write(&temp_path, before).unwrap();

let tidy_ctx = TidyCtx::new(Path::new("/"), false, TidyFlags::new(true));
let tidy_ctx = TidyCtx::new(Path::new("/"), false, None, TidyFlags::new(true));

let mut check = tidy_ctx.start_check("alphabetical-test");
check_lines(&temp_path, before, &tidy_ctx, &mut check);
Expand Down
3 changes: 3 additions & 0 deletions src/tools/tidy/src/arg_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct TidyArgParser {
pub npm: PathBuf,
pub verbose: bool,
pub bless: bool,
pub ci: Option<bool>,
pub extra_checks: Option<Vec<String>>,
pub pos_args: Vec<String>,
}
Expand Down Expand Up @@ -59,6 +60,7 @@ impl TidyArgParser {
)
.arg(Arg::new("verbose").help("verbose").long("verbose").action(ArgAction::SetTrue))
.arg(Arg::new("bless").help("target files are modified").long("bless").action(ArgAction::SetTrue))
.arg(Arg::new("ci").help("ci flag").long("ci").default_missing_value("true").num_args(0..=1).value_parser(value_parser!(bool)))
.arg(
Arg::new("extra_checks")
.help("extra checks")
Expand All @@ -78,6 +80,7 @@ impl TidyArgParser {
npm: matches.get_one::<PathBuf>("npm").unwrap().clone(),
verbose: *matches.get_one::<bool>("verbose").unwrap(),
bless: *matches.get_one::<bool>("bless").unwrap(),
ci: matches.get_one::<bool>("ci").cloned(),
extra_checks: None,
pos_args: vec![],
};
Expand Down
46 changes: 46 additions & 0 deletions src/tools/tidy/src/arg_parser/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ fn test_tidy_parser_full() {
"yarn",
"--verbose",
"--bless",
"--ci",
"--extra-checks",
"if-installed:auto:js,auto:if-installed:py,if-installed:auto:cpp,if-installed:auto:spellcheck",
"--", // pos_args
Expand All @@ -38,6 +39,8 @@ fn test_tidy_parser_full() {
assert_eq!(parsed_args.npm, PathBuf::from("yarn"));
assert!(parsed_args.verbose);
assert!(parsed_args.bless);
assert!(parsed_args.ci.is_some());
assert!(parsed_args.ci.unwrap());
assert_eq!(
parsed_args.extra_checks,
Some(vec![
Expand Down Expand Up @@ -166,3 +169,46 @@ fn test_tidy_parser_missing_npm_path() {
let cmd = TidyArgParser::command();
assert!(cmd.try_get_matches_from(args).is_err());
}

// --ci has some variations
#[test]
fn test_tidy_parse_ci_flag() {
// They are requried
let base_args = vec![
"rust-tidy",
"--root-path",
"/home/user/rust",
"--cargo-path",
"/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo",
"--output-dir",
"/home/user/rust/build",
"--concurrency",
"16",
"--npm-path",
"yarn",
];

// No --ci
let parsed_args = TidyArgParser::build(TidyArgParser::command().get_matches_from(&base_args));
assert!(parsed_args.ci.is_none());

// --ci
let mut args1 = base_args.clone();
args1.push("--ci");
let parsed_args = TidyArgParser::build(TidyArgParser::command().get_matches_from(args1));
assert!(parsed_args.ci.is_some());

// --ci=true
let mut args2 = base_args.clone();
args2.extend_from_slice(&["--ci", "true"]);
let parsed_args = TidyArgParser::build(TidyArgParser::command().get_matches_from(args2));
assert!(parsed_args.ci.is_some());
assert!(parsed_args.ci.unwrap());

// --ci=false
let mut args2 = base_args.clone();
args2.extend_from_slice(&["--ci", "false"]);
let parsed_args = TidyArgParser::build(TidyArgParser::command().get_matches_from(args2));
assert!(parsed_args.ci.is_some());
assert!(!parsed_args.ci.unwrap());
}
Loading
Loading