Skip to content

Commit e484b4d

Browse files
Auto merge of #142223 - compiler-errors:perf-wf, r=<try>
[perf] Fast path for WF goals in new solver I'll clean this up obviously, but I don't want to do that if this is worthless.
2 parents 14863ea + ec2a6d1 commit e484b4d

File tree

7 files changed

+90
-2
lines changed

7 files changed

+90
-2
lines changed

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,13 @@ impl<'tcx> InferCtxt<'tcx> {
10461046
}
10471047
}
10481048

1049+
pub fn shallow_resolve_term(&self, term: ty::Term<'tcx>) -> ty::Term<'tcx> {
1050+
match term.kind() {
1051+
ty::TermKind::Ty(ty) => self.shallow_resolve(ty).into(),
1052+
ty::TermKind::Const(ct) => self.shallow_resolve_const(ct).into(),
1053+
}
1054+
}
1055+
10491056
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
10501057
self.inner.borrow_mut().type_variables().root_var(var)
10511058
}

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,19 @@ impl<'tcx> Const<'tcx> {
144144
let reported = tcx.dcx().span_delayed_bug(span, msg);
145145
Const::new_error(tcx, reported)
146146
}
147+
148+
pub fn is_trivially_wf(self) -> bool {
149+
match self.kind() {
150+
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) => {
151+
true
152+
}
153+
ty::ConstKind::Infer(_)
154+
| ty::ConstKind::Unevaluated(..)
155+
| ty::ConstKind::Value(_)
156+
| ty::ConstKind::Error(_)
157+
| ty::ConstKind::Expr(_) => false,
158+
}
159+
}
147160
}
148161

149162
impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,13 @@ impl<'tcx> Term<'tcx> {
651651
}
652652
}
653653

654+
pub fn is_trivially_wf(&self, tcx: TyCtxt<'tcx>) -> bool {
655+
match self.kind() {
656+
TermKind::Ty(ty) => ty.is_trivially_wf(tcx),
657+
TermKind::Const(ct) => ct.is_trivially_wf(),
658+
}
659+
}
660+
654661
/// Iterator that walks `self` and any types reachable from
655662
/// `self`, in depth-first order. Note that just walks the types
656663
/// that appear in `self`, it does not descend into the fields of

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,50 @@ impl<'tcx> Ty<'tcx> {
18881888
}
18891889
}
18901890

1891+
pub fn is_trivially_wf(self, tcx: TyCtxt<'tcx>) -> bool {
1892+
match *self.kind() {
1893+
ty::Bool
1894+
| ty::Char
1895+
| ty::Int(_)
1896+
| ty::Uint(_)
1897+
| ty::Float(_)
1898+
| ty::Str
1899+
| ty::Never
1900+
| ty::Param(_)
1901+
| ty::Placeholder(_)
1902+
| ty::Bound(..) => true,
1903+
1904+
ty::Slice(ty) => ty.is_trivially_wf(tcx) && ty.is_trivially_sized(tcx),
1905+
ty::RawPtr(ty, _) => ty.is_trivially_wf(tcx),
1906+
1907+
ty::FnPtr(sig_tys, _) => {
1908+
sig_tys.skip_binder().inputs_and_output.iter().all(|ty| ty.is_trivially_wf(tcx))
1909+
}
1910+
ty::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(tcx),
1911+
1912+
ty::Infer(infer) => match infer {
1913+
ty::TyVar(_) => false,
1914+
ty::IntVar(_) | ty::FloatVar(_) => true,
1915+
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => true,
1916+
},
1917+
1918+
ty::Adt(_, _)
1919+
| ty::Tuple(_)
1920+
| ty::Array(..)
1921+
| ty::Foreign(_)
1922+
| ty::Pat(_, _)
1923+
| ty::FnDef(..)
1924+
| ty::UnsafeBinder(..)
1925+
| ty::Dynamic(..)
1926+
| ty::Closure(..)
1927+
| ty::CoroutineClosure(..)
1928+
| ty::Coroutine(..)
1929+
| ty::CoroutineWitness(..)
1930+
| ty::Alias(..)
1931+
| ty::Error(_) => false,
1932+
}
1933+
}
1934+
18911935
/// If `self` is a primitive, return its [`Symbol`].
18921936
pub fn primitive_symbol(self) -> Option<Symbol> {
18931937
match self.kind() {

compiler/rustc_trait_selection/src/solve/delegate.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
136136
None
137137
}
138138
}
139+
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
140+
if arg.is_trivially_wf(self.tcx) {
141+
Some(Certainty::Yes)
142+
} else if self.shallow_resolve_term(arg).is_infer() {
143+
Some(Certainty::AMBIGUOUS)
144+
} else {
145+
None
146+
}
147+
}
139148
_ => None,
140149
}
141150
}

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_middle::bug;
1212
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
1313
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1414
use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode};
15-
use thin_vec::ThinVec;
15+
use thin_vec::{ThinVec, thin_vec};
1616
use tracing::{debug, debug_span, instrument};
1717

1818
use super::effects::{self, HostEffectObligation};
@@ -336,7 +336,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
336336
let infcx = self.selcx.infcx;
337337

338338
if sizedness_fast_path(infcx.tcx, obligation.predicate) {
339-
return ProcessResult::Changed(thin_vec::thin_vec![]);
339+
return ProcessResult::Changed(thin_vec![]);
340340
}
341341

342342
if obligation.predicate.has_aliases() {
@@ -541,6 +541,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
541541
}
542542

543543
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
544+
if term.is_trivially_wf(self.selcx.tcx()) {
545+
return ProcessResult::Changed(thin_vec![]);
546+
}
547+
544548
match wf::obligations(
545549
self.selcx.infcx,
546550
obligation.param_env,

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
660660
}
661661

662662
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
663+
if term.is_trivially_wf(self.tcx()) {
664+
return Ok(EvaluatedToOk);
665+
}
666+
663667
// So, there is a bit going on here. First, `WellFormed` predicates
664668
// are coinductive, like trait predicates with auto traits.
665669
// This means that we need to detect if we have recursively

0 commit comments

Comments
 (0)