convert some GenericArg to Term
This commit is contained in:
parent
e3e432d4d6
commit
855035b038
27 changed files with 180 additions and 154 deletions
|
|
@ -379,13 +379,13 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
// Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?))
|
||||
// will give back the well-formed predicate of the same array.
|
||||
let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect();
|
||||
while let Some(arg) = wf_args.pop() {
|
||||
while let Some(term) = wf_args.pop() {
|
||||
let Some(obligations) = rustc_trait_selection::traits::wf::obligations(
|
||||
infcx,
|
||||
param_env,
|
||||
impl_m_def_id,
|
||||
0,
|
||||
arg,
|
||||
term,
|
||||
impl_m_span,
|
||||
) else {
|
||||
continue;
|
||||
|
|
@ -402,9 +402,9 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
| ty::ClauseKind::TypeOutlives(..)
|
||||
| ty::ClauseKind::Projection(..),
|
||||
) => ocx.register_obligation(obligation),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
if wf_args_seen.insert(arg) {
|
||||
wf_args.push(arg)
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||
if wf_args_seen.insert(term) {
|
||||
wf_args.push(term)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -76,12 +76,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
fn register_wf_obligation(
|
||||
&self,
|
||||
span: Span,
|
||||
loc: Option<WellFormedLoc>,
|
||||
arg: ty::GenericArg<'tcx>,
|
||||
) {
|
||||
fn register_wf_obligation(&self, span: Span, loc: Option<WellFormedLoc>, term: ty::Term<'tcx>) {
|
||||
let cause = traits::ObligationCause::new(
|
||||
span,
|
||||
self.body_def_id,
|
||||
|
|
@ -91,7 +86,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
self.tcx(),
|
||||
cause,
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
|
||||
ty::ClauseKind::WellFormed(term),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -1486,7 +1481,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||
tcx.def_span(param.def_id),
|
||||
matches!(param.kind, GenericParamDefKind::Type { .. })
|
||||
.then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
|
||||
default,
|
||||
default.as_term().unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -374,9 +374,12 @@ fn check_predicates<'tcx>(
|
|||
|
||||
// Include the well-formed predicates of the type parameters of the impl.
|
||||
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args {
|
||||
let Some(term) = arg.as_term() else {
|
||||
continue;
|
||||
};
|
||||
let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
||||
let obligations =
|
||||
wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
|
||||
wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, term, span)
|
||||
.unwrap();
|
||||
|
||||
assert!(!obligations.has_infer());
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
|
|||
use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, CanonicalUserType, GenericArgKind, GenericArgsRef, GenericParamDefKind,
|
||||
IsIdentity, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy,
|
||||
self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity, Ty, TyCtxt,
|
||||
TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
|
|
@ -573,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Registers an obligation for checking later, during regionck, that `arg` is well-formed.
|
||||
pub(crate) fn register_wf_obligation(
|
||||
&self,
|
||||
arg: ty::GenericArg<'tcx>,
|
||||
term: ty::Term<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>,
|
||||
) {
|
||||
|
|
@ -583,16 +583,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.tcx,
|
||||
cause,
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
|
||||
ty::ClauseKind::WellFormed(term),
|
||||
));
|
||||
}
|
||||
|
||||
/// Registers obligations that all `args` are well-formed.
|
||||
pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, span: Span) {
|
||||
for arg in args.iter().filter(|arg| {
|
||||
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
|
||||
}) {
|
||||
self.register_wf_obligation(arg, span, ObligationCauseCode::WellFormed(None));
|
||||
for term in args.iter().filter_map(ty::GenericArg::as_term) {
|
||||
self.register_wf_obligation(term, span, ObligationCauseCode::WellFormed(None));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -863,7 +863,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
|
|||
Resolver { fcx, span, body, nested_goals, should_normalize }
|
||||
}
|
||||
|
||||
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
|
||||
fn report_error(&self, p: impl Into<ty::Term<'tcx>>) -> ErrorGuaranteed {
|
||||
if let Some(guar) = self.fcx.tainted_by_errors() {
|
||||
guar
|
||||
} else {
|
||||
|
|
@ -887,7 +887,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
|
|||
new_err: impl Fn(TyCtxt<'tcx>, ErrorGuaranteed) -> T,
|
||||
) -> T
|
||||
where
|
||||
T: Into<ty::GenericArg<'tcx>> + TypeSuperFoldable<TyCtxt<'tcx>> + Copy,
|
||||
T: Into<ty::Term<'tcx>> + TypeSuperFoldable<TyCtxt<'tcx>> + Copy,
|
||||
{
|
||||
let tcx = self.fcx.tcx;
|
||||
// We must deeply normalize in the new solver, since later lints expect
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ use rustc_middle::traits::solve::Goal;
|
|||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{
|
||||
self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs,
|
||||
GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt,
|
||||
TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv,
|
||||
TypingMode, fold_regions,
|
||||
GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Term, TermKind,
|
||||
Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
|
||||
TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
|
||||
};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use snapshot::undo_log::InferCtxtUndoLogs;
|
||||
|
|
@ -1401,6 +1401,16 @@ impl<'tcx> TyOrConstInferVar {
|
|||
}
|
||||
}
|
||||
|
||||
/// Tries to extract an inference variable from a type or a constant, returns `None`
|
||||
/// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
|
||||
/// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
|
||||
pub fn maybe_from_term(term: Term<'tcx>) -> Option<Self> {
|
||||
match term.unpack() {
|
||||
TermKind::Ty(ty) => Self::maybe_from_ty(ty),
|
||||
TermKind::Const(ct) => Self::maybe_from_const(ct),
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to extract an inference variable from a type, returns `None`
|
||||
/// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`).
|
||||
fn maybe_from_ty(ty: Ty<'tcx>) -> Option<Self> {
|
||||
|
|
|
|||
|
|
@ -250,17 +250,17 @@ impl<'tcx> GenericArg<'tcx> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_type(self) -> Option<Ty<'tcx>> {
|
||||
pub fn as_region(self) -> Option<ty::Region<'tcx>> {
|
||||
match self.unpack() {
|
||||
GenericArgKind::Type(ty) => Some(ty),
|
||||
GenericArgKind::Lifetime(re) => Some(re),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_region(self) -> Option<ty::Region<'tcx>> {
|
||||
pub fn as_type(self) -> Option<Ty<'tcx>> {
|
||||
match self.unpack() {
|
||||
GenericArgKind::Lifetime(re) => Some(re),
|
||||
GenericArgKind::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -273,6 +273,15 @@ impl<'tcx> GenericArg<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_term(self) -> Option<ty::Term<'tcx>> {
|
||||
match self.unpack() {
|
||||
GenericArgKind::Lifetime(_) => None,
|
||||
GenericArgKind::Type(ty) => Some(ty.into()),
|
||||
GenericArgKind::Const(ct) => Some(ct.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Unpack the `GenericArg` as a region when it is known certainly to be a region.
|
||||
pub fn expect_region(self) -> ty::Region<'tcx> {
|
||||
self.as_region().unwrap_or_else(|| bug!("expected a region, but found another kind"))
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ use crate::ty::codec::{TyDecoder, TyEncoder};
|
|||
pub use crate::ty::diagnostics::*;
|
||||
use crate::ty::fast_reject::SimplifiedType;
|
||||
use crate::ty::util::Discr;
|
||||
use crate::ty::walk::TypeWalker;
|
||||
|
||||
pub mod abstract_const;
|
||||
pub mod adjustment;
|
||||
|
|
@ -631,6 +632,20 @@ impl<'tcx> Term<'tcx> {
|
|||
TermKind::Const(ct) => ct.is_ct_infer(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// structs or variants. For example:
|
||||
///
|
||||
/// ```text
|
||||
/// isize => { isize }
|
||||
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
|
||||
/// [isize] => { [isize], isize }
|
||||
/// ```
|
||||
pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
|
||||
TypeWalker::new(self.into())
|
||||
}
|
||||
}
|
||||
|
||||
const TAG_MASK: usize = 0b11;
|
||||
|
|
|
|||
|
|
@ -3247,7 +3247,7 @@ define_print! {
|
|||
ty::ClauseKind::ConstArgHasType(ct, ty) => {
|
||||
p!("the constant `", print(ct), "` has type `", print(ty), "`")
|
||||
},
|
||||
ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"),
|
||||
ty::ClauseKind::WellFormed(term) => p!(print(term), " well-formed"),
|
||||
ty::ClauseKind::ConstEvaluatable(ct) => {
|
||||
p!("the constant `", print(ct), "` can be evaluated")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
|
|||
fn well_formed_goals(
|
||||
&self,
|
||||
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||
arg: <Self::Interner as Interner>::GenericArg,
|
||||
term: <Self::Interner as Interner>::Term,
|
||||
) -> Option<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>>;
|
||||
|
||||
fn clone_opaque_types_for_query_response(
|
||||
|
|
|
|||
|
|
@ -533,8 +533,8 @@ where
|
|||
ty::PredicateKind::DynCompatible(trait_def_id) => {
|
||||
self.compute_dyn_compatible_goal(trait_def_id)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
self.compute_well_formed_goal(Goal { param_env, predicate: arg })
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||
self.compute_well_formed_goal(Goal { param_env, predicate: term })
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
|
||||
self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
|
||||
|
|
@ -1012,9 +1012,9 @@ where
|
|||
pub(super) fn well_formed_goals(
|
||||
&self,
|
||||
param_env: I::ParamEnv,
|
||||
arg: I::GenericArg,
|
||||
term: I::Term,
|
||||
) -> Option<Vec<Goal<I, I::Predicate>>> {
|
||||
self.delegate.well_formed_goals(param_env, arg)
|
||||
self.delegate.well_formed_goals(param_env, term)
|
||||
}
|
||||
|
||||
pub(super) fn trait_ref_is_knowable(
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ where
|
|||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn compute_well_formed_goal(&mut self, goal: Goal<I, I::GenericArg>) -> QueryResult<I> {
|
||||
fn compute_well_formed_goal(&mut self, goal: Goal<I, I::Term>) -> QueryResult<I> {
|
||||
match self.well_formed_goals(goal.param_env, goal.predicate) {
|
||||
Some(goals) => {
|
||||
self.add_goals(GoalSource::Misc, goals);
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ where
|
|||
ty.visit_with(self)
|
||||
}
|
||||
ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
|
||||
ty::ClauseKind::WellFormed(arg) => arg.visit_with(self),
|
||||
ty::ClauseKind::WellFormed(term) => term.visit_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -638,8 +638,8 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
|
|||
const_.stable(tables),
|
||||
ty.stable(tables),
|
||||
),
|
||||
ClauseKind::WellFormed(generic_arg) => {
|
||||
stable_mir::ty::ClauseKind::WellFormed(generic_arg.unpack().stable(tables))
|
||||
ClauseKind::WellFormed(term) => {
|
||||
stable_mir::ty::ClauseKind::WellFormed(term.unpack().stable(tables))
|
||||
}
|
||||
ClauseKind::ConstEvaluatable(const_) => {
|
||||
stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables))
|
||||
|
|
|
|||
|
|
@ -1462,7 +1462,7 @@ pub enum ClauseKind {
|
|||
TypeOutlives(TypeOutlivesPredicate),
|
||||
Projection(ProjectionPredicate),
|
||||
ConstArgHasType(TyConst, Ty),
|
||||
WellFormed(GenericArgKind),
|
||||
WellFormed(TermKind),
|
||||
ConstEvaluatable(TyConst),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ use rustc_middle::hir::nested_filter;
|
|||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt,
|
||||
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
|
||||
self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind,
|
||||
Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
|
||||
};
|
||||
use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym};
|
||||
use rustc_type_ir::TypeVisitableExt;
|
||||
|
|
@ -344,12 +344,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
/// which were stuck during inference.
|
||||
pub fn extract_inference_diagnostics_data(
|
||||
&self,
|
||||
arg: GenericArg<'tcx>,
|
||||
term: Term<'tcx>,
|
||||
highlight: ty::print::RegionHighlightMode<'tcx>,
|
||||
) -> InferenceDiagnosticsData {
|
||||
let tcx = self.tcx;
|
||||
match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => {
|
||||
match term.unpack() {
|
||||
TermKind::Ty(ty) => {
|
||||
if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
|
||||
let var_origin = self.infcx.type_var_origin(ty_vid);
|
||||
if let Some(def_id) = var_origin.param_def_id
|
||||
|
|
@ -375,7 +375,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
parent: None,
|
||||
}
|
||||
}
|
||||
GenericArgKind::Const(ct) => {
|
||||
TermKind::Const(ct) => {
|
||||
if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
|
||||
let origin = self.const_var_origin(vid).expect("expected unresolved const var");
|
||||
if let Some(def_id) = origin.param_def_id {
|
||||
|
|
@ -411,7 +411,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -472,13 +471,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
body_def_id: LocalDefId,
|
||||
failure_span: Span,
|
||||
arg: GenericArg<'tcx>,
|
||||
term: Term<'tcx>,
|
||||
error_code: TypeAnnotationNeeded,
|
||||
should_label_span: bool,
|
||||
) -> Diag<'a> {
|
||||
let arg = self.resolve_vars_if_possible(arg);
|
||||
let arg_data =
|
||||
self.extract_inference_diagnostics_data(arg, ty::print::RegionHighlightMode::default());
|
||||
let term = self.resolve_vars_if_possible(term);
|
||||
let arg_data = self
|
||||
.extract_inference_diagnostics_data(term, ty::print::RegionHighlightMode::default());
|
||||
|
||||
let Some(typeck_results) = &self.typeck_results else {
|
||||
// If we don't have any typeck results we're outside
|
||||
|
|
@ -487,7 +486,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
|
||||
};
|
||||
|
||||
let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg);
|
||||
let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, term);
|
||||
if let Some(body) = self.tcx.hir_maybe_body_owned_by(
|
||||
self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(),
|
||||
) {
|
||||
|
|
@ -542,7 +541,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
have_turbofish,
|
||||
} => {
|
||||
let generics = self.tcx.generics_of(generics_def_id);
|
||||
let is_type = matches!(arg.unpack(), GenericArgKind::Type(_));
|
||||
let is_type = term.as_type().is_some();
|
||||
|
||||
let (parent_exists, parent_prefix, parent_name) =
|
||||
InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id)
|
||||
|
|
@ -811,7 +810,7 @@ struct FindInferSourceVisitor<'a, 'tcx> {
|
|||
tecx: &'a TypeErrCtxt<'a, 'tcx>,
|
||||
typeck_results: &'a TypeckResults<'tcx>,
|
||||
|
||||
target: GenericArg<'tcx>,
|
||||
target: Term<'tcx>,
|
||||
|
||||
attempt: usize,
|
||||
infer_source_cost: usize,
|
||||
|
|
@ -822,7 +821,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
|||
fn new(
|
||||
tecx: &'a TypeErrCtxt<'a, 'tcx>,
|
||||
typeck_results: &'a TypeckResults<'tcx>,
|
||||
target: GenericArg<'tcx>,
|
||||
target: Term<'tcx>,
|
||||
) -> Self {
|
||||
FindInferSourceVisitor {
|
||||
tecx,
|
||||
|
|
@ -938,12 +937,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
|||
// Check whether this generic argument is the inference variable we
|
||||
// are looking for.
|
||||
fn generic_arg_is_target(&self, arg: GenericArg<'tcx>) -> bool {
|
||||
if arg == self.target {
|
||||
if arg == self.target.into() {
|
||||
return true;
|
||||
}
|
||||
|
||||
match (arg.unpack(), self.target.unpack()) {
|
||||
(GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
|
||||
(GenericArgKind::Type(inner_ty), TermKind::Ty(target_ty)) => {
|
||||
use ty::{Infer, TyVar};
|
||||
match (inner_ty.kind(), target_ty.kind()) {
|
||||
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
|
||||
|
|
@ -952,7 +951,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
(GenericArgKind::Const(inner_ct), GenericArgKind::Const(target_ct)) => {
|
||||
(GenericArgKind::Const(inner_ct), TermKind::Const(target_ct)) => {
|
||||
use ty::InferConst::*;
|
||||
match (inner_ct.kind(), target_ct.kind()) {
|
||||
(ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => {
|
||||
|
|
|
|||
|
|
@ -228,13 +228,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
// Pick the first generic parameter that still contains inference variables as the one
|
||||
// we're going to emit an error for. If there are none (see above), fall back to
|
||||
// a more general error.
|
||||
let arg = data.trait_ref.args.iter().find(|s| s.has_non_region_infer());
|
||||
let term = data
|
||||
.trait_ref
|
||||
.args
|
||||
.iter()
|
||||
.filter_map(ty::GenericArg::as_term)
|
||||
.find(|s| s.has_non_region_infer());
|
||||
|
||||
let mut err = if let Some(arg) = arg {
|
||||
let mut err = if let Some(term) = term {
|
||||
self.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
arg,
|
||||
term,
|
||||
TypeAnnotationNeeded::E0283,
|
||||
true,
|
||||
)
|
||||
|
|
@ -276,7 +281,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
|
||||
if let Some(e) = self.tainted_by_errors()
|
||||
&& arg.is_none()
|
||||
&& term.is_none()
|
||||
{
|
||||
// If `arg.is_none()`, then this is probably two param-env
|
||||
// candidates or impl candidates that are equal modulo lifetimes.
|
||||
|
|
@ -313,7 +318,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id());
|
||||
}
|
||||
|
||||
if let Some(ty::GenericArgKind::Type(_)) = arg.map(|arg| arg.unpack())
|
||||
if term.is_some_and(|term| term.as_type().is_some())
|
||||
&& let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id)
|
||||
{
|
||||
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
|
||||
|
|
@ -464,11 +469,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
err
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||
// Same hacky approach as above to avoid deluging user
|
||||
// with error messages.
|
||||
|
||||
if let Err(e) = arg.error_reported() {
|
||||
if let Err(e) = term.error_reported() {
|
||||
return e;
|
||||
}
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
|
|
@ -478,7 +483,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
self.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
arg,
|
||||
term,
|
||||
TypeAnnotationNeeded::E0282,
|
||||
false,
|
||||
)
|
||||
|
|
@ -519,18 +524,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
// other `Foo` impls are incoherent.
|
||||
return guar;
|
||||
}
|
||||
let arg = data
|
||||
let term = data
|
||||
.projection_term
|
||||
.args
|
||||
.iter()
|
||||
.chain(Some(data.term.into_arg()))
|
||||
.filter_map(ty::GenericArg::as_term)
|
||||
.chain([data.term])
|
||||
.find(|g| g.has_non_region_infer());
|
||||
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||
if let Some(arg) = arg {
|
||||
if let Some(term) = term {
|
||||
self.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
arg,
|
||||
term,
|
||||
TypeAnnotationNeeded::E0284,
|
||||
true,
|
||||
)
|
||||
|
|
@ -554,12 +560,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
let arg = data.walk().find(|g| g.is_non_region_infer());
|
||||
if let Some(arg) = arg {
|
||||
let term =
|
||||
data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
|
||||
if let Some(term) = term {
|
||||
let err = self.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
arg,
|
||||
term,
|
||||
TypeAnnotationNeeded::E0284,
|
||||
true,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -92,12 +92,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
|||
fn well_formed_goals(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
arg: ty::GenericArg<'tcx>,
|
||||
term: ty::Term<'tcx>,
|
||||
) -> Option<Vec<Goal<'tcx, ty::Predicate<'tcx>>>> {
|
||||
crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg, DUMMY_SP, CRATE_DEF_ID)
|
||||
.map(|obligations| {
|
||||
obligations.into_iter().map(|obligation| obligation.as_goal()).collect()
|
||||
})
|
||||
crate::traits::wf::unnormalized_obligations(
|
||||
&self.0,
|
||||
param_env,
|
||||
term,
|
||||
DUMMY_SP,
|
||||
CRATE_DEF_ID,
|
||||
)
|
||||
.map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect())
|
||||
}
|
||||
|
||||
fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
|
|
|
|||
|
|
@ -241,13 +241,13 @@ impl<'tcx> BestObligation<'tcx> {
|
|||
fn visit_well_formed_goal(
|
||||
&mut self,
|
||||
candidate: &inspect::InspectCandidate<'_, 'tcx>,
|
||||
arg: ty::GenericArg<'tcx>,
|
||||
term: ty::Term<'tcx>,
|
||||
) -> ControlFlow<PredicateObligation<'tcx>> {
|
||||
let infcx = candidate.goal().infcx();
|
||||
let param_env = candidate.goal().goal().param_env;
|
||||
let body_id = self.obligation.cause.body_id;
|
||||
|
||||
for obligation in wf::unnormalized_obligations(infcx, param_env, arg, self.span(), body_id)
|
||||
for obligation in wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_id)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
|
|
@ -443,8 +443,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
|||
polarity: ty::PredicatePolarity::Positive,
|
||||
}))
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
return self.visit_well_formed_goal(candidate, arg);
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||
return self.visit_well_formed_goal(candidate, term);
|
||||
}
|
||||
_ => ChildMode::PassThrough,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -540,18 +540,18 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||
self.selcx.infcx.err_ctxt().report_overflow_obligation(&obligation, false);
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||
match wf::obligations(
|
||||
self.selcx.infcx,
|
||||
obligation.param_env,
|
||||
obligation.cause.body_id,
|
||||
obligation.recursion_depth + 1,
|
||||
arg,
|
||||
term,
|
||||
obligation.cause.span,
|
||||
) {
|
||||
None => {
|
||||
pending_obligation.stalled_on =
|
||||
vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()];
|
||||
vec![TyOrConstInferVar::maybe_from_term(term).unwrap()];
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
Some(os) => ProcessResult::Changed(mk_pending(obligation, os)),
|
||||
|
|
|
|||
|
|
@ -131,12 +131,12 @@ fn relate_mir_and_user_args<'tcx>(
|
|||
// const CONST: () = { /* arbitrary code that depends on T being WF */ };
|
||||
// }
|
||||
// ```
|
||||
for arg in args {
|
||||
for term in args.iter().filter_map(ty::GenericArg::as_term) {
|
||||
ocx.register_obligation(Obligation::new(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::ClauseKind::WellFormed(arg),
|
||||
ty::ClauseKind::WellFormed(term),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,8 +113,8 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
|
|||
| ty::PredicateKind::AliasRelate(..) => {}
|
||||
|
||||
// We need to search through *all* WellFormed predicates
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
wf_args.push(arg);
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||
wf_args.push(term);
|
||||
}
|
||||
|
||||
// We need to register region relationships
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
|
|||
return Some(());
|
||||
}
|
||||
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) =
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) =
|
||||
key.value.predicate.kind().skip_binder()
|
||||
{
|
||||
match arg.as_type()?.kind() {
|
||||
match term.as_type()?.kind() {
|
||||
ty::Param(_)
|
||||
| ty::Bool
|
||||
| ty::Char
|
||||
|
|
|
|||
|
|
@ -658,7 +658,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||
// 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
|
||||
|
|
@ -682,11 +682,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let cache = previous_stack.cache;
|
||||
let dfn = cache.next_dfn();
|
||||
|
||||
for stack_arg in previous_stack.cache.wf_args.borrow().iter().rev() {
|
||||
if stack_arg.0 != arg {
|
||||
for stack_term in previous_stack.cache.wf_args.borrow().iter().rev() {
|
||||
if stack_term.0 != term {
|
||||
continue;
|
||||
}
|
||||
debug!("WellFormed({:?}) on stack", arg);
|
||||
debug!("WellFormed({:?}) on stack", term);
|
||||
if let Some(stack) = previous_stack.head {
|
||||
// Okay, let's imagine we have two different stacks:
|
||||
// `T: NonAutoTrait -> WF(T) -> T: NonAutoTrait`
|
||||
|
|
@ -702,11 +702,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// would contain `(T, 1)`. We want to check all
|
||||
// trait predicates greater than `1`. The previous
|
||||
// stack would be `T: Auto`.
|
||||
let cycle = stack.iter().take_while(|s| s.depth > stack_arg.1);
|
||||
let cycle = stack.iter().take_while(|s| s.depth > stack_term.1);
|
||||
let tcx = self.tcx();
|
||||
let cycle = cycle.map(|stack| stack.obligation.predicate.upcast(tcx));
|
||||
if self.coinductive_match(cycle) {
|
||||
stack.update_reached_depth(stack_arg.1);
|
||||
stack.update_reached_depth(stack_term.1);
|
||||
return Ok(EvaluatedToOk);
|
||||
} else {
|
||||
return Ok(EvaluatedToAmbigStackDependent);
|
||||
|
|
@ -720,11 +720,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
obligation.param_env,
|
||||
obligation.cause.body_id,
|
||||
obligation.recursion_depth + 1,
|
||||
arg,
|
||||
term,
|
||||
obligation.cause.span,
|
||||
) {
|
||||
Some(obligations) => {
|
||||
cache.wf_args.borrow_mut().push((arg, previous_stack.depth()));
|
||||
cache.wf_args.borrow_mut().push((term, previous_stack.depth()));
|
||||
let result =
|
||||
self.evaluate_predicates_recursively(previous_stack, obligations);
|
||||
cache.wf_args.borrow_mut().pop();
|
||||
|
|
@ -2969,14 +2969,14 @@ struct ProvisionalEvaluationCache<'tcx> {
|
|||
/// means the cached value for `F`.
|
||||
map: RefCell<FxIndexMap<ty::PolyTraitPredicate<'tcx>, ProvisionalEvaluation>>,
|
||||
|
||||
/// The stack of args that we assume to be true because a `WF(arg)` predicate
|
||||
/// The stack of terms that we assume to be well-formed because a `WF(term)` predicate
|
||||
/// is on the stack above (and because of wellformedness is coinductive).
|
||||
/// In an "ideal" world, this would share a stack with trait predicates in
|
||||
/// `TraitObligationStack`. However, trait predicates are *much* hotter than
|
||||
/// `WellFormed` predicates, and it's very likely that the additional matches
|
||||
/// will have a perf effect. The value here is the well-formed `GenericArg`
|
||||
/// and the depth of the trait predicate *above* that well-formed predicate.
|
||||
wf_args: RefCell<Vec<(ty::GenericArg<'tcx>, usize)>>,
|
||||
wf_args: RefCell<Vec<(ty::Term<'tcx>, usize)>>,
|
||||
}
|
||||
|
||||
/// A cache value for the provisional cache: contains the depth-first
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use rustc_hir::lang_items::LangItem;
|
|||
use rustc_infer::traits::{ObligationCauseCode, PredicateObligations};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||
self, GenericArgsRef, Term, TermKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor,
|
||||
};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
|
|
@ -32,12 +32,12 @@ pub fn obligations<'tcx>(
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: LocalDefId,
|
||||
recursion_depth: usize,
|
||||
arg: GenericArg<'tcx>,
|
||||
term: Term<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<PredicateObligations<'tcx>> {
|
||||
// Handle the "cycle" case (see comment above) by bailing out if necessary.
|
||||
let arg = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => {
|
||||
let term = match term.unpack() {
|
||||
TermKind::Ty(ty) => {
|
||||
match ty.kind() {
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
let resolved_ty = infcx.shallow_resolve(ty);
|
||||
|
|
@ -52,7 +52,7 @@ pub fn obligations<'tcx>(
|
|||
}
|
||||
.into()
|
||||
}
|
||||
GenericArgKind::Const(ct) => {
|
||||
TermKind::Const(ct) => {
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Infer(_) => {
|
||||
let resolved = infcx.shallow_resolve_const(ct);
|
||||
|
|
@ -67,8 +67,6 @@ pub fn obligations<'tcx>(
|
|||
}
|
||||
.into()
|
||||
}
|
||||
// There is nothing we have to do for lifetimes.
|
||||
GenericArgKind::Lifetime(..) => return Some(PredicateObligations::new()),
|
||||
};
|
||||
|
||||
let mut wf = WfPredicates {
|
||||
|
|
@ -80,11 +78,11 @@ pub fn obligations<'tcx>(
|
|||
recursion_depth,
|
||||
item: None,
|
||||
};
|
||||
wf.add_wf_preds_for_generic_arg(arg);
|
||||
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
|
||||
wf.add_wf_preds_for_term(term);
|
||||
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", term, body_id, wf.out);
|
||||
|
||||
let result = wf.normalize(infcx);
|
||||
debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", arg, body_id, result);
|
||||
debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", term, body_id, result);
|
||||
Some(result)
|
||||
}
|
||||
|
||||
|
|
@ -95,23 +93,19 @@ pub fn obligations<'tcx>(
|
|||
pub fn unnormalized_obligations<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
arg: GenericArg<'tcx>,
|
||||
term: Term<'tcx>,
|
||||
span: Span,
|
||||
body_id: LocalDefId,
|
||||
) -> Option<PredicateObligations<'tcx>> {
|
||||
debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
|
||||
debug_assert_eq!(term, infcx.resolve_vars_if_possible(term));
|
||||
|
||||
// However, if `arg` IS an unresolved inference variable, returns `None`,
|
||||
// because we are not able to make any progress at all. This is to prevent
|
||||
// cycles where we say "?0 is WF if ?0 is WF".
|
||||
if arg.is_non_region_infer() {
|
||||
if term.is_infer() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let ty::GenericArgKind::Lifetime(..) = arg.unpack() {
|
||||
return Some(PredicateObligations::new());
|
||||
}
|
||||
|
||||
let mut wf = WfPredicates {
|
||||
infcx,
|
||||
param_env,
|
||||
|
|
@ -121,7 +115,7 @@ pub fn unnormalized_obligations<'tcx>(
|
|||
recursion_depth: 0,
|
||||
item: None,
|
||||
};
|
||||
wf.add_wf_preds_for_generic_arg(arg);
|
||||
wf.add_wf_preds_for_term(term);
|
||||
Some(wf.out)
|
||||
}
|
||||
|
||||
|
|
@ -185,22 +179,22 @@ pub fn clause_obligations<'tcx>(
|
|||
}
|
||||
ty::ClauseKind::RegionOutlives(..) => {}
|
||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
|
||||
wf.add_wf_preds_for_generic_arg(ty.into());
|
||||
wf.add_wf_preds_for_term(ty.into());
|
||||
}
|
||||
ty::ClauseKind::Projection(t) => {
|
||||
wf.add_wf_preds_for_alias_term(t.projection_term);
|
||||
wf.add_wf_preds_for_generic_arg(t.term.into_arg());
|
||||
wf.add_wf_preds_for_term(t.term);
|
||||
}
|
||||
ty::ClauseKind::ConstArgHasType(ct, ty) => {
|
||||
wf.add_wf_preds_for_generic_arg(ct.into());
|
||||
wf.add_wf_preds_for_generic_arg(ty.into());
|
||||
wf.add_wf_preds_for_term(ct.into());
|
||||
wf.add_wf_preds_for_term(ty.into());
|
||||
}
|
||||
ty::ClauseKind::WellFormed(arg) => {
|
||||
wf.add_wf_preds_for_generic_arg(arg);
|
||||
ty::ClauseKind::WellFormed(term) => {
|
||||
wf.add_wf_preds_for_term(term);
|
||||
}
|
||||
|
||||
ty::ClauseKind::ConstEvaluatable(ct) => {
|
||||
wf.add_wf_preds_for_generic_arg(ct.into());
|
||||
wf.add_wf_preds_for_term(ct.into());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -426,11 +420,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
.args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, arg)| {
|
||||
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
|
||||
})
|
||||
.filter(|(_, arg)| !arg.has_escaping_bound_vars())
|
||||
.map(|(i, arg)| {
|
||||
.filter_map(|(i, arg)| arg.as_term().map(|t| (i, t)))
|
||||
.filter(|(_, term)| !term.has_escaping_bound_vars())
|
||||
.map(|(i, term)| {
|
||||
let mut cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||
// The first arg is the self ty - use the correct span for it.
|
||||
if i == 0 {
|
||||
|
|
@ -445,9 +437,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
cause,
|
||||
depth,
|
||||
param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
|
||||
arg,
|
||||
))),
|
||||
ty::ClauseKind::WellFormed(term),
|
||||
)
|
||||
}),
|
||||
);
|
||||
|
|
@ -457,7 +447,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
// given that it is a *negative* trait predicate.
|
||||
fn add_wf_preds_for_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
|
||||
for arg in trait_ref.args {
|
||||
self.add_wf_preds_for_generic_arg(arg);
|
||||
if let Some(term) = arg.as_term() {
|
||||
self.add_wf_preds_for_term(term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -529,19 +521,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
|
||||
self.out.extend(
|
||||
args.iter()
|
||||
.filter(|arg| {
|
||||
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
|
||||
})
|
||||
.filter(|arg| !arg.has_escaping_bound_vars())
|
||||
.map(|arg| {
|
||||
.filter_map(|arg| arg.as_term())
|
||||
.filter(|term| !term.has_escaping_bound_vars())
|
||||
.map(|term| {
|
||||
traits::Obligation::with_depth(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
depth,
|
||||
param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
|
||||
arg,
|
||||
))),
|
||||
ty::ClauseKind::WellFormed(term),
|
||||
)
|
||||
}),
|
||||
);
|
||||
|
|
@ -565,10 +553,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Pushes all the predicates needed to validate that `ty` is WF into `out`.
|
||||
/// Pushes all the predicates needed to validate that `term` is WF into `out`.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn add_wf_preds_for_generic_arg(&mut self, arg: GenericArg<'tcx>) {
|
||||
arg.visit_with(self);
|
||||
fn add_wf_preds_for_term(&mut self, term: Term<'tcx>) {
|
||||
term.visit_with(self);
|
||||
debug!(?self.out);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
use std::slice;
|
||||
|
||||
use crate::inherent::*;
|
||||
use crate::visit::Flags;
|
||||
use crate::{self as ty, Interner};
|
||||
|
|
@ -388,8 +386,8 @@ impl<I: Interner> FlagComputation<I> {
|
|||
self.add_alias_term(projection_term);
|
||||
self.add_term(term);
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
self.add_args(slice::from_ref(&arg));
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
|
||||
self.add_term(term);
|
||||
}
|
||||
ty::PredicateKind::DynCompatible(_def_id) => {}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ pub enum ClauseKind<I: Interner> {
|
|||
ConstArgHasType(I::Const, I::Ty),
|
||||
|
||||
/// No syntax: `T` well-formed.
|
||||
WellFormed(I::GenericArg),
|
||||
WellFormed(I::Term),
|
||||
|
||||
/// Constant initializer must evaluate successfully.
|
||||
ConstEvaluatable(I::Const),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue