Skip to content

Commit df32e15

Browse files
committed
Auto merge of #142223 - compiler-errors:perf-wf, r=lcnr
Fast path for WF goals in new solver Hopefully self-explanatory.
2 parents e61dd43 + 92e60e9 commit df32e15

File tree

7 files changed

+94
-3
lines changed

7 files changed

+94
-3
lines changed

compiler/rustc_infer/src/infer/mod.rs

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

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

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
@@ -652,6 +652,13 @@ impl<'tcx> Term<'tcx> {
652652
}
653653
}
654654

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

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ impl<'tcx> Ty<'tcx> {
18431843
ty::Infer(ty::TyVar(_)) => false,
18441844

18451845
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1846-
bug!("`is_trivially_sized` applied to unexpected type: {:?}", self)
1846+
bug!("`has_trivial_sizedness` applied to unexpected type: {:?}", self)
18471847
}
18481848
}
18491849
}
@@ -1907,6 +1907,52 @@ impl<'tcx> Ty<'tcx> {
19071907
}
19081908
}
19091909

1910+
pub fn is_trivially_wf(self, tcx: TyCtxt<'tcx>) -> bool {
1911+
match *self.kind() {
1912+
ty::Bool
1913+
| ty::Char
1914+
| ty::Int(_)
1915+
| ty::Uint(_)
1916+
| ty::Float(_)
1917+
| ty::Str
1918+
| ty::Never
1919+
| ty::Param(_)
1920+
| ty::Placeholder(_)
1921+
| ty::Bound(..) => true,
1922+
1923+
ty::Slice(ty) => {
1924+
ty.is_trivially_wf(tcx) && ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized)
1925+
}
1926+
ty::RawPtr(ty, _) => ty.is_trivially_wf(tcx),
1927+
1928+
ty::FnPtr(sig_tys, _) => {
1929+
sig_tys.skip_binder().inputs_and_output.iter().all(|ty| ty.is_trivially_wf(tcx))
1930+
}
1931+
ty::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(tcx),
1932+
1933+
ty::Infer(infer) => match infer {
1934+
ty::TyVar(_) => false,
1935+
ty::IntVar(_) | ty::FloatVar(_) => true,
1936+
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => true,
1937+
},
1938+
1939+
ty::Adt(_, _)
1940+
| ty::Tuple(_)
1941+
| ty::Array(..)
1942+
| ty::Foreign(_)
1943+
| ty::Pat(_, _)
1944+
| ty::FnDef(..)
1945+
| ty::UnsafeBinder(..)
1946+
| ty::Dynamic(..)
1947+
| ty::Closure(..)
1948+
| ty::CoroutineClosure(..)
1949+
| ty::Coroutine(..)
1950+
| ty::CoroutineWitness(..)
1951+
| ty::Alias(..)
1952+
| ty::Error(_) => false,
1953+
}
1954+
}
1955+
19101956
/// If `self` is a primitive, return its [`Symbol`].
19111957
pub fn primitive_symbol(self) -> Option<Symbol> {
19121958
match self.kind() {

compiler/rustc_trait_selection/src/solve/delegate.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
143143
None
144144
}
145145
}
146+
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
147+
let arg = self.shallow_resolve_term(arg);
148+
if arg.is_trivially_wf(self.tcx) {
149+
Some(Certainty::Yes)
150+
} else if arg.is_infer() {
151+
Some(Certainty::AMBIGUOUS)
152+
} else {
153+
None
154+
}
155+
}
146156
_ => None,
147157
}
148158
}

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() {
@@ -543,6 +543,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
543543
}
544544

545545
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
546+
if term.is_trivially_wf(self.selcx.tcx()) {
547+
return ProcessResult::Changed(thin_vec![]);
548+
}
549+
546550
match wf::obligations(
547551
self.selcx.infcx,
548552
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
@@ -662,6 +662,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
662662
}
663663

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

0 commit comments

Comments
 (0)