diff options
| -rw-r--r-- | compiler/rustc_infer/src/infer/mod.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/consts.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 48 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/delegate.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/fulfill.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 4 |
7 files changed, 94 insertions, 3 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fbc09327a4d..cc3ad921489 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -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 { self.inner.borrow_mut().type_variables().root_var(var) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 2fbaa2221a1..fd1aa4042bc 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -144,6 +144,19 @@ impl<'tcx> Const<'tcx> { let reported = tcx.dcx().span_delayed_bug(span, msg); 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> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8800afd79e7..425f5188cdb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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 /// `self`, in depth-first order. Note that just walks the types /// that appear in `self`, it does not descend into the fields of diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 83960847b26..3971ac13bbe 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1843,7 +1843,7 @@ impl<'tcx> Ty<'tcx> { ty::Infer(ty::TyVar(_)) => false, 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`]. pub fn primitive_symbol(self) -> Option<Symbol> { match self.kind() { diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index d37c954614b..d22529d56a4 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -143,6 +143,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< 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, } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3ec286d17f7..64a51e0550b 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -12,7 +12,7 @@ use rustc_middle::bug; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; 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 super::effects::{self, HostEffectObligation}; @@ -336,7 +336,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let infcx = self.selcx.infcx; 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() { @@ -543,6 +543,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { + if term.is_trivially_wf(self.selcx.tcx()) { + return ProcessResult::Changed(thin_vec![]); + } + match wf::obligations( self.selcx.infcx, obligation.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0f1a29aafe4..316b4dfc15f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -662,6 +662,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } 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 // are coinductive, like trait predicates with auto traits. // This means that we need to detect if we have recursively |
