Skip to content

Commit 3ecd0ba

Browse files
committed
Auto merge of rust-lang#141135 - compiler-errors:fast-path-2, r=<try>
Fast path for processing some obligations in the new solver (volume 2) r? `@ghost`
2 parents ae3b909 + 322224d commit 3ecd0ba

File tree

6 files changed

+85
-9
lines changed

6 files changed

+85
-9
lines changed

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,9 +1882,9 @@ impl<'tcx> Ty<'tcx> {
18821882
// Needs normalization or revealing to determine, so no is the safe answer.
18831883
ty::Alias(..) => false,
18841884

1885-
ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
1885+
ty::Param(..) | ty::Placeholder(..) | ty::Infer(..) | ty::Error(..) => false,
18861886

1887-
ty::Bound(..) | ty::Placeholder(..) => {
1887+
ty::Bound(..) => {
18881888
bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
18891889
}
18901890
}

compiler/rustc_next_trait_solver/src/delegate.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::ops::Deref;
33
use rustc_type_ir::solve::{Certainty, Goal, NoSolution};
44
use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable};
55

6+
use crate::solve::HasChanged;
7+
68
pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
79
type Infcx: InferCtxtLike<Interner = Self::Interner>;
810
type Interner: Interner;
@@ -17,6 +19,12 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
1719
where
1820
V: TypeFoldable<Self::Interner>;
1921

22+
fn compute_goal_fast_path(
23+
&self,
24+
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
25+
span: <Self::Interner as Interner>::Span,
26+
) -> Option<HasChanged>;
27+
2028
fn fresh_var_for_kind_with_span(
2129
&self,
2230
arg: <Self::Interner as Interner>::GenericArg,

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use std::iter;
1313

1414
use rustc_index::IndexVec;
15+
use rustc_type_ir::data_structures::HashSet;
1516
use rustc_type_ir::inherent::*;
1617
use rustc_type_ir::relate::solver_relating::RelateExt;
1718
use rustc_type_ir::{
@@ -158,10 +159,12 @@ where
158159
self.compute_external_query_constraints(certainty, normalization_nested_goals);
159160
let (var_values, mut external_constraints) = (self.var_values, external_constraints)
160161
.fold_with(&mut EagerResolver::new(self.delegate));
161-
// Remove any trivial region constraints once we've resolved regions
162-
external_constraints
163-
.region_constraints
164-
.retain(|outlives| outlives.0.as_region().is_none_or(|re| re != outlives.1));
162+
163+
// Remove any trivial or duplicated region constraints once we've resolved regions
164+
let mut unique = HashSet::default();
165+
external_constraints.region_constraints.retain(|outlives| {
166+
outlives.0.as_region().is_none_or(|re| re != outlives.1) && unique.insert(*outlives)
167+
});
165168

166169
let canonical = Canonicalizer::canonicalize_response(
167170
self.delegate,

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,14 @@ where
603603
// If this loop did not result in any progress, what's our final certainty.
604604
let mut unchanged_certainty = Some(Certainty::Yes);
605605
for (source, goal) in mem::take(&mut self.nested_goals) {
606+
if let Some(has_changed) = self.delegate.compute_goal_fast_path(goal, self.origin_span)
607+
{
608+
if matches!(has_changed, HasChanged::Yes) {
609+
unchanged_certainty = None;
610+
}
611+
continue;
612+
}
613+
606614
// We treat normalizes-to goals specially here. In each iteration we take the
607615
// RHS of the projection, replace it with a fresh inference variable, and only
608616
// after evaluating that goal do we equate the fresh inference variable with the

compiler/rustc_trait_selection/src/solve/delegate.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
use std::ops::Deref;
22

33
use rustc_data_structures::fx::FxHashSet;
4+
use rustc_hir::LangItem;
45
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
56
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
67
use rustc_infer::infer::canonical::{
78
Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
89
};
9-
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt};
10+
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt};
1011
use rustc_infer::traits::solve::Goal;
1112
use rustc_middle::traits::query::NoSolution;
1213
use rustc_middle::traits::solve::Certainty;
1314
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, TypingMode};
15+
use rustc_next_trait_solver::solve::HasChanged;
1416
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
1517

16-
use crate::traits::{EvaluateConstErr, specialization_graph};
18+
use crate::traits::{EvaluateConstErr, ObligationCause, specialization_graph};
1719

1820
#[repr(transparent)]
1921
pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>);
@@ -55,6 +57,52 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
5557
(SolverDelegate(infcx), value, vars)
5658
}
5759

60+
fn compute_goal_fast_path(
61+
&self,
62+
goal: Goal<'tcx, ty::Predicate<'tcx>>,
63+
span: Span,
64+
) -> Option<HasChanged> {
65+
let pred = goal.predicate.kind();
66+
match pred.no_bound_vars()? {
67+
ty::PredicateKind::DynCompatible(def_id) if self.0.tcx.is_dyn_compatible(def_id) => {
68+
Some(HasChanged::No)
69+
}
70+
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(outlives)) => {
71+
self.0.sub_regions(
72+
SubregionOrigin::RelateRegionParamBound(span, None),
73+
outlives.1,
74+
outlives.0,
75+
);
76+
Some(HasChanged::No)
77+
}
78+
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
79+
self.0.register_region_obligation_with_cause(
80+
outlives.0,
81+
outlives.1,
82+
&ObligationCause::dummy_with_span(span),
83+
);
84+
85+
Some(HasChanged::No)
86+
}
87+
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
88+
match self.0.tcx.as_lang_item(trait_pred.def_id()) {
89+
Some(LangItem::Sized)
90+
if trait_pred.self_ty().is_trivially_sized(self.0.tcx) =>
91+
{
92+
Some(HasChanged::No)
93+
}
94+
Some(LangItem::Copy | LangItem::Clone)
95+
if trait_pred.self_ty().is_trivially_pure_clone_copy() =>
96+
{
97+
Some(HasChanged::No)
98+
}
99+
_ => None,
100+
}
101+
}
102+
_ => None,
103+
}
104+
}
105+
58106
fn fresh_var_for_kind_with_span(
59107
&self,
60108
arg: ty::GenericArg<'tcx>,

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_infer::traits::{
1212
use rustc_middle::ty::{
1313
self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode,
1414
};
15+
use rustc_next_trait_solver::delegate::SolverDelegate as _;
1516
use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
1617
use rustc_span::Span;
1718
use tracing::instrument;
@@ -172,7 +173,15 @@ where
172173
}
173174

174175
let goal = obligation.as_goal();
175-
let result = <&SolverDelegate<'tcx>>::from(infcx)
176+
let delegate = <&SolverDelegate<'tcx>>::from(infcx);
177+
if let Some(fast_path_has_changed) =
178+
delegate.compute_goal_fast_path(goal, obligation.cause.span)
179+
{
180+
has_changed |= matches!(fast_path_has_changed, HasChanged::Yes);
181+
continue;
182+
}
183+
184+
let result = delegate
176185
.evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span)
177186
.0;
178187
self.inspect_evaluated_obligation(infcx, &obligation, &result);

0 commit comments

Comments
 (0)