Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/util.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/util.rs | 242 |
1 files changed, 73 insertions, 169 deletions
diff --git a/crates/hir-ty/src/next_solver/util.rs b/crates/hir-ty/src/next_solver/util.rs index d113f76a32..34ecfed08f 100644 --- a/crates/hir-ty/src/next_solver/util.rs +++ b/crates/hir-ty/src/next_solver/util.rs @@ -1,39 +1,30 @@ //! Various utilities for the next-trait-solver. -use std::{ - iter, - ops::{self, ControlFlow}, -}; +use std::ops::ControlFlow; -use base_db::Crate; -use hir_def::{BlockId, HasModule, lang_item::LangItem}; -use la_arena::Idx; +use hir_def::TraitId; use rustc_abi::{Float, HasDataLayout, Integer, IntegerType, Primitive, ReprOptions}; use rustc_type_ir::{ ConstKind, CoroutineArgs, DebruijnIndex, FloatTy, INNERMOST, IntTy, Interner, PredicatePolarity, RegionKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitableExt, TypeVisitor, UintTy, UniverseIndex, - inherent::{ - AdtDef, GenericArg as _, GenericArgs as _, IntoKind, ParamEnv as _, SliceLike, Ty as _, - }, + TypeVisitableExt, TypeVisitor, UintTy, UniverseIndex, elaborate, + inherent::{AdtDef, GenericArg as _, IntoKind, ParamEnv as _, SliceLike, Ty as _}, lang_items::SolverTraitLangItem, solve::SizedTraitKind, }; -use crate::{ - db::HirDatabase, - lower::{LifetimeElisionKind, TyLoweringContext}, - method_resolution::{TraitImpls, TyFingerprint}, - next_solver::{ - BoundConst, FxIndexMap, ParamEnv, Placeholder, PlaceholderConst, PlaceholderRegion, - infer::InferCtxt, +use crate::next_solver::{ + BoundConst, FxIndexMap, ParamEnv, Placeholder, PlaceholderConst, PlaceholderRegion, + PolyTraitRef, + infer::{ + InferCtxt, + traits::{Obligation, ObligationCause, PredicateObligation}, }, }; use super::{ - Binder, BoundRegion, BoundTy, Clause, ClauseKind, Clauses, Const, DbInterner, EarlyBinder, - GenericArgs, Predicate, PredicateKind, Region, SolverDefId, TraitPredicate, TraitRef, Ty, - TyKind, + Binder, BoundRegion, BoundTy, Clause, ClauseKind, Const, DbInterner, EarlyBinder, GenericArgs, + Predicate, PredicateKind, Region, SolverDefId, Ty, TyKind, fold::{BoundVarReplacer, FnMutDelegate}, }; @@ -86,9 +77,10 @@ pub trait IntegerTypeExt { impl IntegerTypeExt for IntegerType { fn to_ty<'db>(&self, interner: DbInterner<'db>) -> Ty<'db> { + let types = interner.default_types(); match self { - IntegerType::Pointer(true) => Ty::new(interner, TyKind::Int(IntTy::Isize)), - IntegerType::Pointer(false) => Ty::new(interner, TyKind::Uint(UintTy::Usize)), + IntegerType::Pointer(true) => types.types.isize, + IntegerType::Pointer(false) => types.types.usize, IntegerType::Fixed(i, s) => i.to_ty(interner, *s), } } @@ -129,17 +121,18 @@ impl IntegerExt for Integer { #[inline] fn to_ty<'db>(&self, interner: DbInterner<'db>, signed: bool) -> Ty<'db> { use Integer::*; + let types = interner.default_types(); match (*self, signed) { - (I8, false) => Ty::new(interner, TyKind::Uint(UintTy::U8)), - (I16, false) => Ty::new(interner, TyKind::Uint(UintTy::U16)), - (I32, false) => Ty::new(interner, TyKind::Uint(UintTy::U32)), - (I64, false) => Ty::new(interner, TyKind::Uint(UintTy::U64)), - (I128, false) => Ty::new(interner, TyKind::Uint(UintTy::U128)), - (I8, true) => Ty::new(interner, TyKind::Int(IntTy::I8)), - (I16, true) => Ty::new(interner, TyKind::Int(IntTy::I16)), - (I32, true) => Ty::new(interner, TyKind::Int(IntTy::I32)), - (I64, true) => Ty::new(interner, TyKind::Int(IntTy::I64)), - (I128, true) => Ty::new(interner, TyKind::Int(IntTy::I128)), + (I8, false) => types.types.u8, + (I16, false) => types.types.u16, + (I32, false) => types.types.u32, + (I64, false) => types.types.u64, + (I128, false) => types.types.u128, + (I8, true) => types.types.i8, + (I16, true) => types.types.i16, + (I32, true) => types.types.i32, + (I64, true) => types.types.i64, + (I128, true) => types.types.i128, } } @@ -223,11 +216,12 @@ impl FloatExt for Float { #[inline] fn to_ty<'db>(&self, interner: DbInterner<'db>) -> Ty<'db> { use Float::*; + let types = interner.default_types(); match *self { - F16 => Ty::new(interner, TyKind::Float(FloatTy::F16)), - F32 => Ty::new(interner, TyKind::Float(FloatTy::F32)), - F64 => Ty::new(interner, TyKind::Float(FloatTy::F64)), - F128 => Ty::new(interner, TyKind::Float(FloatTy::F128)), + F16 => types.types.f16, + F32 => types.types.f32, + F64 => types.types.f64, + F128 => types.types.f128, } } @@ -253,13 +247,7 @@ impl PrimitiveExt for Primitive { match *self { Primitive::Int(i, signed) => i.to_ty(interner, signed), Primitive::Float(f) => f.to_ty(interner), - Primitive::Pointer(_) => Ty::new( - interner, - TyKind::RawPtr( - Ty::new(interner, TyKind::Tuple(Default::default())), - rustc_ast_ir::Mutability::Mut, - ), - ), + Primitive::Pointer(_) => interner.default_types().types.mut_unit_ptr, } } @@ -292,7 +280,7 @@ impl<'db> CoroutineArgsExt<'db> for CoroutineArgs<DbInterner<'db>> { /// The type of the state discriminant used in the coroutine type. #[inline] fn discr_ty(&self, interner: DbInterner<'db>) -> Ty<'db> { - Ty::new(interner, TyKind::Uint(UintTy::U32)) + interner.default_types().types.u32 } } @@ -388,54 +376,6 @@ where } } -pub(crate) fn for_trait_impls( - db: &dyn HirDatabase, - krate: Crate, - block: Option<BlockId>, - trait_id: hir_def::TraitId, - self_ty_fp: Option<TyFingerprint>, - mut f: impl FnMut(&TraitImpls) -> ControlFlow<()>, -) -> ControlFlow<()> { - // Note: Since we're using `impls_for_trait` and `impl_provided_for`, - // only impls where the trait can be resolved should ever reach Chalk. - // `impl_datum` relies on that and will panic if the trait can't be resolved. - let in_self_and_deps = db.trait_impls_in_deps(krate); - let trait_module = trait_id.module(db); - let type_module = match self_ty_fp { - Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(db)), - Some(TyFingerprint::ForeignType(type_id)) => Some(type_id.module(db)), - Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(db)), - _ => None, - }; - - let mut def_blocks = - [trait_module.containing_block(), type_module.and_then(|it| it.containing_block())]; - - let block_impls = iter::successors(block, |&block_id| { - cov_mark::hit!(block_local_impls); - block_id.loc(db).module.containing_block() - }) - .inspect(|&block_id| { - // make sure we don't search the same block twice - def_blocks.iter_mut().for_each(|block| { - if *block == Some(block_id) { - *block = None; - } - }); - }) - .filter_map(|block_id| db.trait_impls_in_block(block_id)); - for it in in_self_and_deps.iter().map(ops::Deref::deref) { - f(it)?; - } - for it in block_impls { - f(&it)?; - } - for it in def_blocks.into_iter().flatten().filter_map(|it| db.trait_impls_in_block(it)) { - f(&it)?; - } - ControlFlow::Continue(()) -} - // FIXME(next-trait-solver): uplift pub fn sizedness_constraint_for_ty<'db>( interner: DbInterner<'db>, @@ -479,12 +419,10 @@ pub fn sizedness_constraint_for_ty<'db>( .next_back() .and_then(|ty| sizedness_constraint_for_ty(interner, sizedness, ty)), - Adt(adt, args) => { - let tail_ty = - EarlyBinder::bind(adt.all_field_tys(interner).skip_binder().into_iter().last()?) - .instantiate(interner, args); + Adt(adt, args) => adt.struct_tail_ty(interner).and_then(|tail_ty| { + let tail_ty = tail_ty.instantiate(interner, args); sizedness_constraint_for_ty(interner, sizedness, tail_ty) - } + }), Placeholder(..) | Bound(..) | Infer(..) => { panic!("unexpected type `{ty:?}` in sizedness_constraint_for_ty") @@ -507,79 +445,14 @@ pub fn apply_args_to_binder<'db, T: TypeFoldable<DbInterner<'db>>>( pub fn explicit_item_bounds<'db>( interner: DbInterner<'db>, def_id: SolverDefId, -) -> EarlyBinder<'db, Clauses<'db>> { +) -> EarlyBinder<'db, impl DoubleEndedIterator<Item = Clause<'db>> + ExactSizeIterator> { let db = interner.db(); - match def_id { - SolverDefId::TypeAliasId(type_alias) => { - // Lower bounds -- we could/should maybe move this to a separate query in `lower` - let type_alias_data = db.type_alias_signature(type_alias); - let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &type_alias_data.store, - type_alias.into(), - LifetimeElisionKind::AnonymousReportError, - ); - - let item_args = GenericArgs::identity_for_item(interner, def_id); - let interner_ty = Ty::new_projection_from_args(interner, def_id, item_args); - - let mut bounds = Vec::new(); - for bound in &type_alias_data.bounds { - ctx.lower_type_bound(bound, interner_ty, false).for_each(|pred| { - bounds.push(pred); - }); - } - - if !ctx.unsized_types.contains(&interner_ty) { - let sized_trait = LangItem::Sized - .resolve_trait(ctx.db, interner.krate.expect("Must have interner.krate")); - let sized_bound = sized_trait.map(|trait_id| { - let trait_ref = TraitRef::new_from_args( - interner, - trait_id.into(), - GenericArgs::new_from_iter(interner, [interner_ty.into()]), - ); - Clause(Predicate::new( - interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - )) - }); - bounds.extend(sized_bound); - bounds.shrink_to_fit(); - } - - rustc_type_ir::EarlyBinder::bind(Clauses::new_from_iter(interner, bounds)) - } - SolverDefId::InternedOpaqueTyId(id) => { - let full_id = db.lookup_intern_impl_trait_id(id); - match full_id { - crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { - let datas = db - .return_type_impl_traits(func) - .expect("impl trait id without impl traits"); - let datas = (*datas).as_ref().skip_binder(); - let data = &datas.impl_traits[Idx::from_raw(idx.into_raw())]; - EarlyBinder::bind(Clauses::new_from_iter(interner, data.predicates.clone())) - } - crate::ImplTraitId::TypeAliasImplTrait(alias, idx) => { - let datas = db - .type_alias_impl_traits(alias) - .expect("impl trait id without impl traits"); - let datas = (*datas).as_ref().skip_binder(); - let data = &datas.impl_traits[Idx::from_raw(idx.into_raw())]; - EarlyBinder::bind(Clauses::new_from_iter(interner, data.predicates.clone())) - } - } - } + let clauses = match def_id { + SolverDefId::TypeAliasId(type_alias) => crate::lower::type_alias_bounds(db, type_alias), + SolverDefId::InternedOpaqueTyId(id) => id.predicates(db), _ => panic!("Unexpected GenericDefId"), - } + }; + clauses.map_bound(|clauses| clauses.iter().copied()) } pub struct ContainsTypeErrors; @@ -792,3 +665,34 @@ pub fn sizedness_fast_path<'db>( false } + +/// Casts a trait reference into a reference to one of its super +/// traits; returns `None` if `target_trait_def_id` is not a +/// supertrait. +pub(crate) fn upcast_choices<'db>( + interner: DbInterner<'db>, + source_trait_ref: PolyTraitRef<'db>, + target_trait_def_id: TraitId, +) -> Vec<PolyTraitRef<'db>> { + if source_trait_ref.def_id().0 == target_trait_def_id { + return vec![source_trait_ref]; // Shortcut the most common case. + } + + elaborate::supertraits(interner, source_trait_ref) + .filter(|r| r.def_id().0 == target_trait_def_id) + .collect() +} + +#[inline] +pub(crate) fn clauses_as_obligations<'db>( + clauses: impl IntoIterator<Item = Clause<'db>>, + cause: ObligationCause, + param_env: ParamEnv<'db>, +) -> impl Iterator<Item = PredicateObligation<'db>> { + clauses.into_iter().map(move |clause| Obligation { + cause: cause.clone(), + param_env, + predicate: clause.as_predicate(), + recursion_depth: 0, + }) +} |