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 #130281

Merged
merged 13 commits into from
Sep 12, 2024
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
60 changes: 27 additions & 33 deletions compiler/rustc_mir_transform/src/coverage/counters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,14 @@ impl CoverageCounters {
BcbCounter::Expression { id }
}

/// Variant of `make_expression` that makes `lhs` optional and assumes [`Op::Add`].
/// Creates a counter that is the sum of the given counters.
///
/// This is useful when using [`Iterator::fold`] to build an arbitrary-length sum.
fn make_sum_expression(&mut self, lhs: Option<BcbCounter>, rhs: BcbCounter) -> BcbCounter {
let Some(lhs) = lhs else { return rhs };
self.make_expression(lhs, Op::Add, rhs)
/// Returns `None` if the given list of counters was empty.
fn make_sum(&mut self, counters: &[BcbCounter]) -> Option<BcbCounter> {
counters
.iter()
.copied()
.reduce(|accum, counter| self.make_expression(accum, Op::Add, counter))
}

pub(super) fn num_counters(&self) -> usize {
Expand Down Expand Up @@ -315,20 +317,17 @@ impl<'a> MakeBcbCounters<'a> {
// For each out-edge other than the one that was chosen to get an expression,
// ensure that it has a counter (existing counter/expression or a new counter),
// and accumulate the corresponding counters into a single sum expression.
let sum_of_all_other_out_edges: BcbCounter = {
let _span = debug_span!("sum_of_all_other_out_edges", ?expression_to_bcb).entered();
successors
.iter()
.copied()
// Skip the chosen edge, since we'll calculate its count from this sum.
.filter(|&to_bcb| to_bcb != expression_to_bcb)
.fold(None, |accum, to_bcb| {
let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered();
let edge_counter = self.get_or_make_edge_counter(from_bcb, to_bcb);
Some(self.coverage_counters.make_sum_expression(accum, edge_counter))
})
.expect("there must be at least one other out-edge")
};
let other_out_edge_counters = successors
.iter()
.copied()
// Skip the chosen edge, since we'll calculate its count from this sum.
.filter(|&to_bcb| to_bcb != expression_to_bcb)
.map(|to_bcb| self.get_or_make_edge_counter(from_bcb, to_bcb))
.collect::<Vec<_>>();
let sum_of_all_other_out_edges: BcbCounter = self
.coverage_counters
.make_sum(&other_out_edge_counters)
.expect("there must be at least one other out-edge");

// Now create an expression for the chosen edge, by taking the counter
// for its source node and subtracting the sum of its sibling out-edges.
Expand Down Expand Up @@ -375,20 +374,15 @@ impl<'a> MakeBcbCounters<'a> {

// A BCB with multiple incoming edges can compute its count by ensuring that counters
// exist for each of those edges, and then adding them up to get a total count.
let sum_of_in_edges: BcbCounter = {
let _span = debug_span!("sum_of_in_edges", ?bcb).entered();
// We avoid calling `self.bcb_predecessors` here so that we can
// call methods on `&mut self` inside the fold.
self.basic_coverage_blocks.predecessors[bcb]
.iter()
.copied()
.fold(None, |accum, from_bcb| {
let _span = debug_span!("from_bcb", ?accum, ?from_bcb).entered();
let edge_counter = self.get_or_make_edge_counter(from_bcb, bcb);
Some(self.coverage_counters.make_sum_expression(accum, edge_counter))
})
.expect("there must be at least one in-edge")
};
let in_edge_counters = self.basic_coverage_blocks.predecessors[bcb]
.iter()
.copied()
.map(|from_bcb| self.get_or_make_edge_counter(from_bcb, bcb))
.collect::<Vec<_>>();
let sum_of_in_edges: BcbCounter = self
.coverage_counters
.make_sum(&in_edge_counters)
.expect("there must be at least one in-edge");

debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}");
self.coverage_counters.set_bcb_counter(bcb, sum_of_in_edges)
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_mir_transform/src/pass_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn to_profiler_name(type_name: &'static str) -> &'static str {

// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }`
const fn c_name(name: &'static str) -> &'static str {
// FIXME Simplify the implementation once more `str` methods get const-stable.
// FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable.
// and inline into call site
let bytes = name.as_bytes();
let mut i = bytes.len();
Expand All @@ -61,7 +61,7 @@ const fn c_name(name: &'static str) -> &'static str {
/// loop that goes over each available MIR and applies `run_pass`.
pub(super) trait MirPass<'tcx> {
fn name(&self) -> &'static str {
// FIXME Simplify the implementation once more `str` methods get const-stable.
// FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable.
// See copypaste in `MirLint`
const {
let name = std::any::type_name::<Self>();
Expand Down Expand Up @@ -89,7 +89,7 @@ pub(super) trait MirPass<'tcx> {
/// disabled (via the `Lint` adapter).
pub(super) trait MirLint<'tcx> {
fn name(&self) -> &'static str {
// FIXME Simplify the implementation once more `str` methods get const-stable.
// FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable.
// See copypaste in `MirPass`
const {
let name = std::any::type_name::<Self>();
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,21 @@ where
(certainty, NestedNormalizationGoals::empty())
};

if let Certainty::Maybe(cause @ MaybeCause::Overflow { .. }) = certainty {
// If we have overflow, it's probable that we're substituting a type
// into itself infinitely and any partial substitutions in the query
// response are probably not useful anyways, so just return an empty
// query response.
//
// This may prevent us from potentially useful inference, e.g.
// 2 candidates, one ambiguous and one overflow, which both
// have the same inference constraints.
//
// Changing this to retain some constraints in the future
// won't be a breaking change, so this is good enough for now.
return Ok(self.make_ambiguous_response_no_constraints(cause));
}

let external_constraints =
self.compute_external_query_constraints(certainty, normalization_nested_goals);
let (var_values, mut external_constraints) = (self.var_values, external_constraints)
Expand Down
33 changes: 7 additions & 26 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::delegate::SolverDelegate;
use crate::solve::inspect::{self, ProofTreeBuilder};
use crate::solve::search_graph::SearchGraph;
use crate::solve::{
CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind, GoalSource, MaybeCause,
CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind, GoalSource,
NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, SolverMode,
FIXPOINT_STEP_LIMIT,
};
Expand Down Expand Up @@ -370,20 +370,19 @@ where
canonical_goal,
&mut goal_evaluation,
);
let canonical_response = match canonical_response {
let response = match canonical_response {
Err(e) => {
self.inspect.goal_evaluation(goal_evaluation);
return Err(e);
}
Ok(response) => response,
};

let (normalization_nested_goals, certainty, has_changed) = self
.instantiate_response_discarding_overflow(
goal.param_env,
orig_values,
canonical_response,
);
let has_changed = !response.value.var_values.is_identity_modulo_regions()
|| !response.value.external_constraints.opaque_types.is_empty();

let (normalization_nested_goals, certainty) =
self.instantiate_and_apply_query_response(goal.param_env, orig_values, response);
self.inspect.goal_evaluation(goal_evaluation);
// FIXME: We previously had an assert here that checked that recomputing
// a goal after applying its constraints did not change its response.
Expand All @@ -398,24 +397,6 @@ where
Ok((normalization_nested_goals, has_changed, certainty))
}

fn instantiate_response_discarding_overflow(
&mut self,
param_env: I::ParamEnv,
original_values: Vec<I::GenericArg>,
response: CanonicalResponse<I>,
) -> (NestedNormalizationGoals<I>, Certainty, bool) {
if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty {
return (NestedNormalizationGoals::empty(), response.value.certainty, false);
}

let has_changed = !response.value.var_values.is_identity_modulo_regions()
|| !response.value.external_constraints.opaque_types.is_empty();

let (normalization_nested_goals, certainty) =
self.instantiate_and_apply_query_response(param_env, original_values, response);
(normalization_nested_goals, certainty, has_changed)
}

fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
let Goal { param_env, predicate } = goal;
let kind = predicate.kind();
Expand Down
Loading
Loading