Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #113330

Merged
merged 14 commits into from
Jul 5, 2023
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3937,6 +3937,7 @@ dependencies = [
"rustc_hir",
"rustc_middle",
"rustc_span",
"scoped-tls",
"tracing",
]

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,14 @@ pub enum TraitSolver {
NextCoherence,
}

#[derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum DumpSolverProofTree {
Always,
OnError,
#[default]
Never,
}

pub enum Input {
/// Load source code from a file.
File(PathBuf),
Expand Down
21 changes: 19 additions & 2 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ mod desc {
"a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`";
pub const parse_proc_macro_execution_strategy: &str =
"one of supported execution strategies (`same-thread`, or `cross-thread`)";
pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`";
}

mod parse {
Expand Down Expand Up @@ -1237,6 +1238,19 @@ mod parse {
};
true
}

pub(crate) fn parse_dump_solver_proof_tree(
slot: &mut DumpSolverProofTree,
v: Option<&str>,
) -> bool {
match v {
None | Some("always") => *slot = DumpSolverProofTree::Always,
Some("never") => *slot = DumpSolverProofTree::Never,
Some("on-error") => *slot = DumpSolverProofTree::OnError,
_ => return false,
};
true
}
}

options! {
Expand Down Expand Up @@ -1462,8 +1476,11 @@ options! {
"output statistics about monomorphization collection"),
dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED],
"the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"),
dump_solver_proof_tree: bool = (false, parse_bool, [UNTRACKED],
"dump a proof tree for every goal evaluated by the new trait solver"),
dump_solver_proof_tree: DumpSolverProofTree = (DumpSolverProofTree::Never, parse_dump_solver_proof_tree, [UNTRACKED],
"dump a proof tree for every goal evaluated by the new trait solver. If the flag is specified without any options after it
then it defaults to `always`. If the flag is not specified at all it defaults to `on-request`."),
dump_solver_proof_tree_use_cache: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
"determines whether dumped proof trees use the global cache"),
dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
dylib_lto: bool = (false, parse_bool, [UNTRACKED],
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_smir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ rustc_hir = { path = "../rustc_hir" }
rustc_middle = { path = "../rustc_middle", optional = true }
rustc_span = { path = "../rustc_span", optional = true }
tracing = "0.1"
scoped-tls = "1.0"

[features]
default = [
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_smir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ pub mod stable_mir;

// Make this module private for now since external users should not call these directly.
mod rustc_smir;

#[macro_use]
extern crate scoped_tls;
28 changes: 14 additions & 14 deletions compiler/rustc_smir/src/stable_mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,28 +100,28 @@ pub trait Context {
fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>));
}

thread_local! {
/// A thread local variable that stores a pointer to the tables mapping between TyCtxt
/// datastructures and stable MIR datastructures.
static TLV: Cell<*mut ()> = const { Cell::new(std::ptr::null_mut()) };
}
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
// datastructures and stable MIR datastructures
scoped_thread_local! (static TLV: Cell<*mut ()>);

pub fn run(mut context: impl Context, f: impl FnOnce()) {
assert!(TLV.get().is_null());
assert!(!TLV.is_set());
fn g<'a>(mut context: &mut (dyn Context + 'a), f: impl FnOnce()) {
TLV.set(&mut context as *mut &mut _ as _);
f();
TLV.replace(std::ptr::null_mut());
let ptr: *mut () = &mut context as *mut &mut _ as _;
TLV.set(&Cell::new(ptr), || {
f();
});
}
g(&mut context, f);
}

/// Loads the current context and calls a function with it.
/// Do not nest these, as that will ICE.
pub(crate) fn with<R>(f: impl FnOnce(&mut dyn Context) -> R) -> R {
let ptr = TLV.replace(std::ptr::null_mut()) as *mut &mut dyn Context;
assert!(!ptr.is_null());
let ret = f(unsafe { *ptr });
TLV.set(ptr as _);
ret
assert!(TLV.is_set());
TLV.with(|tlv| {
let ptr = tlv.get();
assert!(!ptr.is_null());
f(unsafe { *(ptr as *mut &mut dyn Context) })
})
}
17 changes: 13 additions & 4 deletions compiler/rustc_trait_selection/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,11 +331,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
candidates
}

/// If the self type of a goal is an alias, computing the relevant candidates is difficult.
/// If the self type of a goal is an alias we first try to normalize the self type
/// and compute the candidates for the normalized self type in case that succeeds.
///
/// To deal with this, we first try to normalize the self type and add the candidates for the normalized
/// self type to the list of candidates in case that succeeds. We also have to consider candidates with the
/// projection as a self type as well
/// These candidates are used in addition to the ones with the alias as a self type.
/// We do this to simplify both builtin candidates and for better performance.
///
/// We generate the builtin candidates on the fly by looking at the self type, e.g.
/// add `FnPtr` candidates if the self type is a function pointer. Handling builtin
/// candidates while the self type is still an alias seems difficult. This is similar
/// to `try_structurally_resolve_type` during hir typeck (FIXME once implemented).
///
/// Looking at all impls for some trait goal is prohibitively expensive. We therefore
/// only look at implementations with a matching self type. Because of this function,
/// we can avoid looking at all existing impls if the self type is an alias.
#[instrument(level = "debug", skip_all)]
fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'tcx>>(
&mut self,
Expand Down
41 changes: 28 additions & 13 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ use rustc_middle::ty::{
self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor,
};
use rustc_session::config::DumpSolverProofTree;
use rustc_span::DUMMY_SP;
use std::io::Write;
use std::ops::ControlFlow;

use crate::traits::specialization_graph;
Expand Down Expand Up @@ -113,9 +115,23 @@ impl NestedGoals<'_> {

#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
pub enum GenerateProofTree {
Yes(UseGlobalCache),
No,
}

#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
pub enum UseGlobalCache {
Yes,
No,
}
impl UseGlobalCache {
pub fn from_bool(use_cache: bool) -> Self {
match use_cache {
true => UseGlobalCache::Yes,
false => UseGlobalCache::No,
}
}
}

pub trait InferCtxtEvalExt<'tcx> {
/// Evaluates a goal from **outside** of the trait solver.
Expand Down Expand Up @@ -177,17 +193,17 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
var_values: CanonicalVarValues::dummy(),
nested_goals: NestedGoals::new(),
tainted: Ok(()),
inspect: (infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree
|| matches!(generate_proof_tree, GenerateProofTree::Yes))
.then(ProofTreeBuilder::new_root)
.unwrap_or_else(ProofTreeBuilder::new_noop),
inspect: ProofTreeBuilder::new_maybe_root(infcx.tcx, generate_proof_tree),
};
let result = f(&mut ecx);

let tree = ecx.inspect.finalize();
if let Some(tree) = &tree {
// module to allow more granular RUSTC_LOG filtering to just proof tree output
super::inspect::dump::print_tree(tree);
if let (Some(tree), DumpSolverProofTree::Always) =
(&tree, infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree)
{
let mut lock = std::io::stdout().lock();
let _ = lock.write_fmt(format_args!("{tree:?}"));
let _ = lock.flush();
}

assert!(
Expand Down Expand Up @@ -425,12 +441,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
self.compute_well_formed_goal(Goal { param_env, predicate: arg })
}
ty::PredicateKind::Ambiguous => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
// FIXME: implement this predicate :)
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(_)) => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
}
ty::PredicateKind::ConstEquate(_, _) => {
bug!("ConstEquate should not be emitted when `-Ztrait-solver=next` is active")
Expand All @@ -440,6 +452,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
param_env,
predicate: (lhs, rhs, direction),
}),
ty::PredicateKind::Ambiguous => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
}
} else {
let kind = self.infcx.instantiate_binder_with_placeholders(kind);
Expand Down
Loading