Skip to content

Commit f1da288

Browse files
Tweak fast path trait handling
1 parent 38081f2 commit f1da288

File tree

5 files changed

+54
-34
lines changed

5 files changed

+54
-34
lines changed

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,10 +1882,8 @@ 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::Placeholder(..) | ty::Infer(..) | ty::Error(..) => false,
1886-
1887-
ty::Bound(..) => {
1888-
bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
1885+
ty::Param(..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(..) => {
1886+
false
18891887
}
18901888
}
18911889
}

compiler/rustc_next_trait_solver/src/delegate.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ 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-
86
pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
97
type Infcx: InferCtxtLike<Interner = Self::Interner>;
108
type Interner: Interner;
@@ -23,7 +21,7 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
2321
&self,
2422
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
2523
span: <Self::Interner as Interner>::Span,
26-
) -> Option<HasChanged>;
24+
) -> Option<Certainty>;
2725

2826
fn fresh_var_for_kind_with_span(
2927
&self,

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,10 +671,13 @@ where
671671
// If this loop did not result in any progress, what's our final certainty.
672672
let mut unchanged_certainty = Some(Certainty::Yes);
673673
for (source, goal, stalled_on) in mem::take(&mut self.nested_goals) {
674-
if let Some(has_changed) = self.delegate.compute_goal_fast_path(goal, self.origin_span)
675-
{
676-
if matches!(has_changed, HasChanged::Yes) {
677-
unchanged_certainty = None;
674+
if let Some(certainty) = self.delegate.compute_goal_fast_path(goal, self.origin_span) {
675+
match certainty {
676+
Certainty::Yes => {}
677+
Certainty::Maybe(_) => {
678+
self.nested_goals.push((source, goal, None));
679+
unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
680+
}
678681
}
679682
continue;
680683
}

compiler/rustc_trait_selection/src/solve/delegate.rs

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TyCtx
1111
use rustc_infer::traits::solve::Goal;
1212
use rustc_middle::traits::query::NoSolution;
1313
use rustc_middle::traits::solve::Certainty;
14-
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, TypingMode};
15-
use rustc_next_trait_solver::solve::HasChanged;
14+
use rustc_middle::ty::{
15+
self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
16+
};
1617
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
1718

1819
use crate::traits::{EvaluateConstErr, ObligationCause, specialization_graph};
@@ -61,19 +62,49 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
6162
&self,
6263
goal: Goal<'tcx, ty::Predicate<'tcx>>,
6364
span: Span,
64-
) -> Option<HasChanged> {
65+
) -> Option<Certainty> {
66+
if let Some(trait_pred) = goal.predicate.as_trait_clause() {
67+
if trait_pred.polarity() == ty::PredicatePolarity::Positive {
68+
match self.0.tcx.as_lang_item(trait_pred.def_id()) {
69+
Some(LangItem::Sized)
70+
if self
71+
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
72+
.is_trivially_sized(self.0.tcx) =>
73+
{
74+
return Some(Certainty::Yes);
75+
}
76+
Some(LangItem::Copy | LangItem::Clone) => {
77+
let self_ty =
78+
self.resolve_vars_if_possible(trait_pred.self_ty().skip_binder());
79+
// Unlike `Sized` traits, which always prefer the built-in impl,
80+
// `Copy`/`Clone` may be shadowed by a param-env candidate which
81+
// could force a lifetime error or guide inference. While that's
82+
// not generally desirable, it is observable, so for now let's
83+
// ignore this fast path for types that have regions or infer.
84+
if !self_ty
85+
.has_type_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_INFER)
86+
&& self_ty.is_trivially_pure_clone_copy()
87+
{
88+
return Some(Certainty::Yes);
89+
}
90+
}
91+
_ => {}
92+
}
93+
}
94+
}
95+
6596
let pred = goal.predicate.kind();
6697
match pred.no_bound_vars()? {
6798
ty::PredicateKind::DynCompatible(def_id) if self.0.tcx.is_dyn_compatible(def_id) => {
68-
Some(HasChanged::No)
99+
Some(Certainty::Yes)
69100
}
70101
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(outlives)) => {
71102
self.0.sub_regions(
72103
SubregionOrigin::RelateRegionParamBound(span, None),
73104
outlives.1,
74105
outlives.0,
75106
);
76-
Some(HasChanged::No)
107+
Some(Certainty::Yes)
77108
}
78109
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
79110
self.0.register_type_outlives_constraint(
@@ -82,22 +113,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
82113
&ObligationCause::dummy_with_span(span),
83114
);
84115

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-
}
116+
Some(Certainty::Yes)
101117
}
102118
_ => None,
103119
}

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,15 @@ where
195195

196196
let goal = obligation.as_goal();
197197
let delegate = <&SolverDelegate<'tcx>>::from(infcx);
198-
if let Some(fast_path_has_changed) =
198+
if let Some(certainty) =
199199
delegate.compute_goal_fast_path(goal, obligation.cause.span)
200200
{
201-
any_changed |= matches!(fast_path_has_changed, HasChanged::Yes);
201+
match certainty {
202+
Certainty::Yes => {}
203+
Certainty::Maybe(_) => {
204+
self.obligations.register(obligation, None);
205+
}
206+
}
202207
continue;
203208
}
204209

0 commit comments

Comments
 (0)