Uplift GenericArgKind, CanonicalVarValues, QueryInput
and make NestedGoals generic
This commit is contained in:
parent
c00957a3e2
commit
05e0f8740a
25 changed files with 377 additions and 268 deletions
|
@ -28,6 +28,7 @@ rustc_hir = { path = "../rustc_hir" }
|
|||
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
|
|
|
@ -23,23 +23,20 @@
|
|||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||
use rustc_type_ir::Canonical as IrCanonical;
|
||||
use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo;
|
||||
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
|
||||
pub use rustc_type_ir as ir;
|
||||
pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::ops::Index;
|
||||
|
||||
use crate::infer::MemberConstraint;
|
||||
use crate::mir::ConstraintCategory;
|
||||
use crate::ty::GenericArg;
|
||||
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
|
||||
|
||||
pub type Canonical<'tcx, V> = IrCanonical<TyCtxt<'tcx>, V>;
|
||||
|
||||
pub type CanonicalVarInfo<'tcx> = IrCanonicalVarInfo<TyCtxt<'tcx>>;
|
||||
use crate::ty::{self, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
|
||||
|
||||
pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>;
|
||||
pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo<TyCtxt<'tcx>>;
|
||||
pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>;
|
||||
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
|
||||
|
||||
impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
|
||||
|
@ -51,74 +48,6 @@ impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A set of values corresponding to the canonical variables from some
|
||||
/// `Canonical`. You can give these values to
|
||||
/// `canonical_value.instantiate` to instantiate them into the canonical
|
||||
/// value at the right places.
|
||||
///
|
||||
/// When you canonicalize a value `V`, you get back one of these
|
||||
/// vectors with the original values that were replaced by canonical
|
||||
/// variables. You will need to supply it later to instantiate the
|
||||
/// canonicalized query response.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct CanonicalVarValues<'tcx> {
|
||||
pub var_values: ty::GenericArgsRef<'tcx>,
|
||||
}
|
||||
|
||||
impl CanonicalVarValues<'_> {
|
||||
pub fn is_identity(&self) -> bool {
|
||||
self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
|
||||
ty::GenericArgKind::Lifetime(r) => {
|
||||
matches!(*r, ty::ReBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
|
||||
}
|
||||
ty::GenericArgKind::Type(ty) => {
|
||||
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
|
||||
}
|
||||
ty::GenericArgKind::Const(ct) => {
|
||||
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_identity_modulo_regions(&self) -> bool {
|
||||
let mut var = ty::BoundVar::ZERO;
|
||||
for arg in self.var_values {
|
||||
match arg.unpack() {
|
||||
ty::GenericArgKind::Lifetime(r) => {
|
||||
if let ty::ReBound(ty::INNERMOST, br) = *r
|
||||
&& var == br.var
|
||||
{
|
||||
var = var + 1;
|
||||
} else {
|
||||
// It's ok if this region var isn't unique
|
||||
}
|
||||
}
|
||||
ty::GenericArgKind::Type(ty) => {
|
||||
if let ty::Bound(ty::INNERMOST, bt) = *ty.kind()
|
||||
&& var == bt.var
|
||||
{
|
||||
var = var + 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ty::GenericArgKind::Const(ct) => {
|
||||
if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind()
|
||||
&& var == bc
|
||||
{
|
||||
var = var + 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// When we canonicalize a value to form a query, we wind up replacing
|
||||
/// various parts of it with canonical variables. This struct stores
|
||||
/// those replaced bits to remember for when we process the query
|
||||
|
@ -218,78 +147,6 @@ TrivialTypeTraversalImpls! {
|
|||
crate::infer::canonical::Certainty,
|
||||
}
|
||||
|
||||
impl<'tcx> CanonicalVarValues<'tcx> {
|
||||
// Given a list of canonical variables, construct a set of values which are
|
||||
// the identity response.
|
||||
pub fn make_identity(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
infos: CanonicalVarInfos<'tcx>,
|
||||
) -> CanonicalVarValues<'tcx> {
|
||||
CanonicalVarValues {
|
||||
var_values: tcx.mk_args_from_iter(infos.iter().enumerate().map(
|
||||
|(i, info)| -> ty::GenericArg<'tcx> {
|
||||
match info.kind {
|
||||
CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
|
||||
Ty::new_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i).into())
|
||||
.into()
|
||||
}
|
||||
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
|
||||
let br = ty::BoundRegion {
|
||||
var: ty::BoundVar::from_usize(i),
|
||||
kind: ty::BrAnon,
|
||||
};
|
||||
ty::Region::new_bound(tcx, ty::INNERMOST, br).into()
|
||||
}
|
||||
CanonicalVarKind::Effect => ty::Const::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundVar::from_usize(i),
|
||||
tcx.types.bool,
|
||||
)
|
||||
.into(),
|
||||
CanonicalVarKind::Const(_, ty)
|
||||
| CanonicalVarKind::PlaceholderConst(_, ty) => ty::Const::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundVar::from_usize(i),
|
||||
ty,
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
},
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates dummy var values which should not be used in a
|
||||
/// canonical response.
|
||||
pub fn dummy() -> CanonicalVarValues<'tcx> {
|
||||
CanonicalVarValues { var_values: ty::List::empty() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.var_values.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
|
||||
type Item = GenericArg<'tcx>;
|
||||
type IntoIter = ::std::iter::Copied<::std::slice::Iter<'a, GenericArg<'tcx>>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.var_values.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
|
||||
type Output = GenericArg<'tcx>;
|
||||
|
||||
fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
|
||||
&self.var_values[value.as_usize()]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CanonicalParamEnvCache<'tcx> {
|
||||
map: Lock<
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use rustc_ast_ir::try_visit;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
|
||||
use rustc_next_trait_solver as ir;
|
||||
pub use rustc_next_trait_solver::solve::*;
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
|
||||
|
@ -9,8 +11,6 @@ use crate::traits::Canonical;
|
|||
use crate::ty::{
|
||||
self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
|
||||
};
|
||||
// FIXME(compiler-errors): remove this import in favor of `use rustc_middle::ty::Goal`.
|
||||
pub use crate::ty::Goal;
|
||||
|
||||
use super::BuiltinImplSource;
|
||||
|
||||
|
@ -19,6 +19,9 @@ pub mod inspect;
|
|||
|
||||
pub use cache::{CacheData, EvaluationCache};
|
||||
|
||||
pub type Goal<'tcx, P> = ir_solve::Goal<TyCtxt<'tcx>, P>;
|
||||
pub type QueryInput<'tcx, P> = ir_solve::QueryInput<TyCtxt<'tcx>, P>;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct Response<'tcx> {
|
||||
pub certainty: Certainty,
|
||||
|
@ -87,12 +90,6 @@ impl MaybeCause {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct QueryInput<'tcx, T> {
|
||||
pub goal: Goal<'tcx, T>,
|
||||
pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
|
||||
}
|
||||
|
||||
/// Additional constraints returned on success.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)]
|
||||
pub struct PredefinedOpaquesData<'tcx> {
|
||||
|
@ -229,29 +226,6 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Why a specific goal has to be proven.
|
||||
///
|
||||
/// This is necessary as we treat nested goals different depending on
|
||||
/// their source.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TypeVisitable, TypeFoldable)]
|
||||
pub enum GoalSource {
|
||||
Misc,
|
||||
/// We're proving a where-bound of an impl.
|
||||
///
|
||||
/// FIXME(-Znext-solver=coinductive): Explain how and why this
|
||||
/// changes whether cycles are coinductive.
|
||||
///
|
||||
/// This also impacts whether we erase constraints on overflow.
|
||||
/// Erasing constraints is generally very useful for perf and also
|
||||
/// results in better error messages by avoiding spurious errors.
|
||||
/// We do not erase overflow constraints in `normalizes-to` goals unless
|
||||
/// they are from an impl where-clause. This is necessary due to
|
||||
/// backwards compatability, cc trait-system-refactor-initiatitive#70.
|
||||
ImplWhereBound,
|
||||
/// Instantiating a higher-ranked goal and re-proving it.
|
||||
InstantiateHigherRanked,
|
||||
}
|
||||
|
||||
/// Possible ways the given goal can be proven.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CandidateSource {
|
||||
|
|
|
@ -90,6 +90,7 @@ use std::ops::{Bound, Deref};
|
|||
impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
type DefId = DefId;
|
||||
type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
|
||||
type PredefinedOpaques = solve::PredefinedOpaques<'tcx>;
|
||||
type AdtDef = ty::AdtDef<'tcx>;
|
||||
type GenericArgs = ty::GenericArgsRef<'tcx>;
|
||||
type OwnItemArgs = &'tcx [ty::GenericArg<'tcx>];
|
||||
|
|
|
@ -11,6 +11,7 @@ use rustc_ast_ir::walk_visitable_list;
|
|||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_errors::{DiagArgValue, IntoDiagArg};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::extension;
|
||||
use rustc_macros::{
|
||||
Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
|
||||
};
|
||||
|
@ -25,6 +26,8 @@ use std::num::NonZero;
|
|||
use std::ops::Deref;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind<TyCtxt<'tcx>>;
|
||||
|
||||
/// An entity in the Rust type system, which can be one of
|
||||
/// several kinds (types, lifetimes, and consts).
|
||||
/// To reduce memory usage, a `GenericArg` is an interned pointer,
|
||||
|
@ -49,6 +52,14 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> {
|
||||
type Kind = GenericArgKind<'tcx>;
|
||||
|
||||
fn kind(self) -> Self::Kind {
|
||||
self.unpack()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl<'tcx> rustc_data_structures::sync::DynSend for GenericArg<'tcx> where
|
||||
&'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): rustc_data_structures::sync::DynSend
|
||||
|
@ -79,13 +90,7 @@ const TYPE_TAG: usize = 0b00;
|
|||
const REGION_TAG: usize = 0b01;
|
||||
const CONST_TAG: usize = 0b10;
|
||||
|
||||
#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, HashStable)]
|
||||
pub enum GenericArgKind<'tcx> {
|
||||
Lifetime(ty::Region<'tcx>),
|
||||
Type(Ty<'tcx>),
|
||||
Const(ty::Const<'tcx>),
|
||||
}
|
||||
|
||||
#[extension(trait GenericArgPackExt<'tcx>)]
|
||||
impl<'tcx> GenericArgKind<'tcx> {
|
||||
#[inline]
|
||||
fn pack(self) -> GenericArg<'tcx> {
|
||||
|
|
|
@ -28,7 +28,7 @@ use crate::ty::fast_reject::SimplifiedType;
|
|||
use crate::ty::util::Discr;
|
||||
pub use adt::*;
|
||||
pub use assoc::*;
|
||||
pub use generic_args::*;
|
||||
pub use generic_args::{GenericArgKind, *};
|
||||
pub use generics::*;
|
||||
pub use intrinsic::IntrinsicDef;
|
||||
use rustc_ast as ast;
|
||||
|
@ -97,13 +97,12 @@ pub use self::parameterized::ParameterizedOverTcx;
|
|||
pub use self::pattern::{Pattern, PatternKind};
|
||||
pub use self::predicate::{
|
||||
AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
|
||||
ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, Goal,
|
||||
NormalizesTo, OutlivesPredicate, PolyCoercePredicate, PolyExistentialPredicate,
|
||||
PolyExistentialProjection, PolyExistentialTraitRef, PolyProjectionPredicate,
|
||||
PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef,
|
||||
PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
|
||||
RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, TraitPredicate, TraitRef,
|
||||
TypeOutlivesPredicate,
|
||||
ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, NormalizesTo,
|
||||
OutlivesPredicate, PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
|
||||
PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
|
||||
PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate,
|
||||
PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
|
||||
TraitPredicate, TraitRef, TypeOutlivesPredicate,
|
||||
};
|
||||
pub use self::region::{
|
||||
BoundRegion, BoundRegionKind, BoundRegionKind::*, EarlyParamRegion, LateParamRegion, Region,
|
||||
|
|
|
@ -12,7 +12,6 @@ use crate::ty::{
|
|||
Upcast, UpcastFrom, WithCachedTypeInfo,
|
||||
};
|
||||
|
||||
pub type Goal<'tcx, P> = ir::Goal<TyCtxt<'tcx>, P>;
|
||||
pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
|
||||
pub type AliasTerm<'tcx> = ir::AliasTerm<TyCtxt<'tcx>>;
|
||||
pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>;
|
||||
|
|
|
@ -396,6 +396,12 @@ pub struct BoundRegion {
|
|||
pub kind: BoundRegionKind,
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundRegion {
|
||||
fn var(self) -> BoundVar {
|
||||
self.var
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for BoundRegion {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self.kind {
|
||||
|
|
|
@ -1204,6 +1204,12 @@ pub struct BoundTy {
|
|||
pub kind: BoundTyKind,
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundTy {
|
||||
fn var(self) -> BoundVar {
|
||||
self.var
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub enum BoundTyKind {
|
||||
|
@ -1606,6 +1612,10 @@ impl<'tcx> Ty<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
fn new_bool(tcx: TyCtxt<'tcx>) -> Self {
|
||||
tcx.types.bool
|
||||
}
|
||||
|
||||
fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
|
||||
Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue