Auto merge of #142223 - compiler-errors:perf-wf, r=lcnr
Fast path for WF goals in new solver Hopefully self-explanatory.
This commit is contained in:
@@ -1044,6 +1044,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shallow_resolve_term(&self, term: ty::Term<'tcx>) -> ty::Term<'tcx> {
|
||||||
|
match term.kind() {
|
||||||
|
ty::TermKind::Ty(ty) => self.shallow_resolve(ty).into(),
|
||||||
|
ty::TermKind::Const(ct) => self.shallow_resolve_const(ct).into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||||
self.inner.borrow_mut().type_variables().root_var(var)
|
self.inner.borrow_mut().type_variables().root_var(var)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,19 @@ impl<'tcx> Const<'tcx> {
|
|||||||
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
||||||
Const::new_error(tcx, reported)
|
Const::new_error(tcx, reported)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_trivially_wf(self) -> bool {
|
||||||
|
match self.kind() {
|
||||||
|
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
ty::ConstKind::Infer(_)
|
||||||
|
| ty::ConstKind::Unevaluated(..)
|
||||||
|
| ty::ConstKind::Value(_)
|
||||||
|
| ty::ConstKind::Error(_)
|
||||||
|
| ty::ConstKind::Expr(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
||||||
|
|||||||
@@ -652,6 +652,13 @@ impl<'tcx> Term<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_trivially_wf(&self, tcx: TyCtxt<'tcx>) -> bool {
|
||||||
|
match self.kind() {
|
||||||
|
TermKind::Ty(ty) => ty.is_trivially_wf(tcx),
|
||||||
|
TermKind::Const(ct) => ct.is_trivially_wf(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterator that walks `self` and any types reachable from
|
/// Iterator that walks `self` and any types reachable from
|
||||||
/// `self`, in depth-first order. Note that just walks the types
|
/// `self`, in depth-first order. Note that just walks the types
|
||||||
/// that appear in `self`, it does not descend into the fields of
|
/// that appear in `self`, it does not descend into the fields of
|
||||||
|
|||||||
@@ -1843,7 +1843,7 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
ty::Infer(ty::TyVar(_)) => false,
|
ty::Infer(ty::TyVar(_)) => false,
|
||||||
|
|
||||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||||
bug!("`is_trivially_sized` applied to unexpected type: {:?}", self)
|
bug!("`has_trivial_sizedness` applied to unexpected type: {:?}", self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1907,6 +1907,52 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_trivially_wf(self, tcx: TyCtxt<'tcx>) -> bool {
|
||||||
|
match *self.kind() {
|
||||||
|
ty::Bool
|
||||||
|
| ty::Char
|
||||||
|
| ty::Int(_)
|
||||||
|
| ty::Uint(_)
|
||||||
|
| ty::Float(_)
|
||||||
|
| ty::Str
|
||||||
|
| ty::Never
|
||||||
|
| ty::Param(_)
|
||||||
|
| ty::Placeholder(_)
|
||||||
|
| ty::Bound(..) => true,
|
||||||
|
|
||||||
|
ty::Slice(ty) => {
|
||||||
|
ty.is_trivially_wf(tcx) && ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized)
|
||||||
|
}
|
||||||
|
ty::RawPtr(ty, _) => ty.is_trivially_wf(tcx),
|
||||||
|
|
||||||
|
ty::FnPtr(sig_tys, _) => {
|
||||||
|
sig_tys.skip_binder().inputs_and_output.iter().all(|ty| ty.is_trivially_wf(tcx))
|
||||||
|
}
|
||||||
|
ty::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(tcx),
|
||||||
|
|
||||||
|
ty::Infer(infer) => match infer {
|
||||||
|
ty::TyVar(_) => false,
|
||||||
|
ty::IntVar(_) | ty::FloatVar(_) => true,
|
||||||
|
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => true,
|
||||||
|
},
|
||||||
|
|
||||||
|
ty::Adt(_, _)
|
||||||
|
| ty::Tuple(_)
|
||||||
|
| ty::Array(..)
|
||||||
|
| ty::Foreign(_)
|
||||||
|
| ty::Pat(_, _)
|
||||||
|
| ty::FnDef(..)
|
||||||
|
| ty::UnsafeBinder(..)
|
||||||
|
| ty::Dynamic(..)
|
||||||
|
| ty::Closure(..)
|
||||||
|
| ty::CoroutineClosure(..)
|
||||||
|
| ty::Coroutine(..)
|
||||||
|
| ty::CoroutineWitness(..)
|
||||||
|
| ty::Alias(..)
|
||||||
|
| ty::Error(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// If `self` is a primitive, return its [`Symbol`].
|
/// If `self` is a primitive, return its [`Symbol`].
|
||||||
pub fn primitive_symbol(self) -> Option<Symbol> {
|
pub fn primitive_symbol(self) -> Option<Symbol> {
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
|
|||||||
@@ -143,6 +143,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||||
|
let arg = self.shallow_resolve_term(arg);
|
||||||
|
if arg.is_trivially_wf(self.tcx) {
|
||||||
|
Some(Certainty::Yes)
|
||||||
|
} else if arg.is_infer() {
|
||||||
|
Some(Certainty::AMBIGUOUS)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use rustc_middle::bug;
|
|||||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode};
|
use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode};
|
||||||
use thin_vec::ThinVec;
|
use thin_vec::{ThinVec, thin_vec};
|
||||||
use tracing::{debug, debug_span, instrument};
|
use tracing::{debug, debug_span, instrument};
|
||||||
|
|
||||||
use super::effects::{self, HostEffectObligation};
|
use super::effects::{self, HostEffectObligation};
|
||||||
@@ -336,7 +336,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||||||
let infcx = self.selcx.infcx;
|
let infcx = self.selcx.infcx;
|
||||||
|
|
||||||
if sizedness_fast_path(infcx.tcx, obligation.predicate) {
|
if sizedness_fast_path(infcx.tcx, obligation.predicate) {
|
||||||
return ProcessResult::Changed(thin_vec::thin_vec![]);
|
return ProcessResult::Changed(thin_vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if obligation.predicate.has_aliases() {
|
if obligation.predicate.has_aliases() {
|
||||||
@@ -543,6 +543,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||||
|
if term.is_trivially_wf(self.selcx.tcx()) {
|
||||||
|
return ProcessResult::Changed(thin_vec![]);
|
||||||
|
}
|
||||||
|
|
||||||
match wf::obligations(
|
match wf::obligations(
|
||||||
self.selcx.infcx,
|
self.selcx.infcx,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
|
|||||||
@@ -662,6 +662,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||||
|
if term.is_trivially_wf(self.tcx()) {
|
||||||
|
return Ok(EvaluatedToOk);
|
||||||
|
}
|
||||||
|
|
||||||
// So, there is a bit going on here. First, `WellFormed` predicates
|
// So, there is a bit going on here. First, `WellFormed` predicates
|
||||||
// are coinductive, like trait predicates with auto traits.
|
// are coinductive, like trait predicates with auto traits.
|
||||||
// This means that we need to detect if we have recursively
|
// This means that we need to detect if we have recursively
|
||||||
|
|||||||
Reference in New Issue
Block a user