Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/utils.rs')
-rw-r--r--crates/hir-ty/src/utils.rs148
1 files changed, 61 insertions, 87 deletions
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 209ec7926e..427c4bb684 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -3,11 +3,11 @@
use std::{cell::LazyCell, iter};
-use base_db::Crate;
-use chalk_ir::{
- DebruijnIndex,
- fold::{FallibleTypeFolder, Shift},
+use base_db::{
+ Crate,
+ target::{self, TargetData},
};
+use chalk_ir::{DebruijnIndex, fold::FallibleTypeFolder};
use hir_def::{
EnumId, EnumVariantId, FunctionId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId,
db::DefDatabase,
@@ -20,17 +20,23 @@ use hir_expand::name::Name;
use intern::sym;
use rustc_abi::TargetDataLayout;
use rustc_hash::FxHashSet;
+use rustc_type_ir::inherent::{GenericArgs, IntoKind, SliceLike};
use smallvec::{SmallVec, smallvec};
use span::Edition;
-use stdx::never;
+use crate::next_solver::mapping::NextSolverToChalk;
use crate::{
- ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TargetFeatures, TraitRef,
- TraitRefExt, Ty, WhereClause,
+ ChalkTraitId, Const, ConstScalar, Interner, Substitution, TargetFeatures, TraitRef,
+ TraitRefExt, Ty,
consteval::unknown_const,
db::HirDatabase,
layout::{Layout, TagEncoding},
mir::pad16,
+ next_solver::{
+ DbInterner,
+ mapping::{ChalkToNextSolver, convert_args_for_result},
+ },
+ to_chalk_trait_id,
};
pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator<Item = TraitId> + '_ {
@@ -114,52 +120,6 @@ impl Iterator for SuperTraits<'_> {
}
}
-pub(super) fn elaborate_clause_supertraits(
- db: &dyn HirDatabase,
- clauses: impl Iterator<Item = WhereClause>,
-) -> ClauseElaborator<'_> {
- let mut elaborator = ClauseElaborator { db, stack: Vec::new(), seen: FxHashSet::default() };
- elaborator.extend_deduped(clauses);
-
- elaborator
-}
-
-pub(super) struct ClauseElaborator<'a> {
- db: &'a dyn HirDatabase,
- stack: Vec<WhereClause>,
- seen: FxHashSet<WhereClause>,
-}
-
-impl ClauseElaborator<'_> {
- fn extend_deduped(&mut self, clauses: impl IntoIterator<Item = WhereClause>) {
- self.stack.extend(clauses.into_iter().filter(|c| self.seen.insert(c.clone())))
- }
-
- fn elaborate_supertrait(&mut self, clause: &WhereClause) {
- if let WhereClause::Implemented(trait_ref) = clause {
- direct_super_trait_refs(self.db, trait_ref, |t| {
- let clause = WhereClause::Implemented(t);
- if self.seen.insert(clause.clone()) {
- self.stack.push(clause);
- }
- });
- }
- }
-}
-
-impl Iterator for ClauseElaborator<'_> {
- type Item = WhereClause;
-
- fn next(&mut self) -> Option<Self::Item> {
- if let Some(next) = self.stack.pop() {
- self.elaborate_supertrait(&next);
- Some(next)
- } else {
- None
- }
- }
-}
-
fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
let resolver = LazyCell::new(|| trait_.resolver(db));
let (generic_params, store) = db.generic_params_and_store(trait_.into());
@@ -191,25 +151,34 @@ fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(
}
fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef, cb: impl FnMut(TraitRef)) {
+ let interner = DbInterner::new_with(db, None, None);
let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
let trait_self = match generic_params.trait_self_param() {
Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p },
None => return,
};
- db.generic_predicates_for_param(trait_self.parent, trait_self, None)
+ let trait_ref_args: crate::next_solver::GenericArgs<'_> =
+ trait_ref.substitution.to_nextsolver(interner);
+ db.generic_predicates_for_param_ns(trait_self.parent, trait_self, None)
.iter()
.filter_map(|pred| {
- pred.as_ref().filter_map(|pred| match pred.skip_binders() {
- // FIXME: how to correctly handle higher-ranked bounds here?
- WhereClause::Implemented(tr) => Some(
- tr.clone()
- .shifted_out_to(Interner, DebruijnIndex::ONE)
- .expect("FIXME unexpected higher-ranked trait bound"),
- ),
+ let pred = pred.kind();
+ // FIXME: how to correctly handle higher-ranked bounds here?
+ let pred = pred.no_bound_vars().expect("FIXME unexpected higher-ranked trait bound");
+ match pred {
+ rustc_type_ir::ClauseKind::Trait(t) => {
+ let t =
+ rustc_type_ir::EarlyBinder::bind(t).instantiate(interner, trait_ref_args);
+ let trait_id = to_chalk_trait_id(t.def_id().0);
+
+ let substitution =
+ convert_args_for_result(interner, t.trait_ref.args.as_slice());
+ let tr = chalk_ir::TraitRef { trait_id, substitution };
+ Some(tr)
+ }
_ => None,
- })
+ }
})
- .map(|pred| pred.substitute(Interner, &trait_ref.substitution))
.for_each(cb);
}
@@ -224,34 +193,25 @@ pub(super) fn associated_type_by_name_including_super_traits(
})
}
-/// It is a bit different from the rustc equivalent. Currently it stores:
-/// - 0..n-1: generics of the parent
-/// - n: the function signature, encoded as a function pointer type
-///
-/// and it doesn't store the closure types and fields.
-///
-/// Codes should not assume this ordering, and should always use methods available
-/// on this struct for retrieving, and `TyBuilder::substs_for_closure` for creating.
pub(crate) struct ClosureSubst<'a>(pub(crate) &'a Substitution);
impl<'a> ClosureSubst<'a> {
- pub(crate) fn parent_subst(&self) -> &'a [GenericArg] {
- match self.0.as_slice(Interner) {
- [x @ .., _] => x,
- _ => {
- never!("Closure missing parameter");
- &[]
- }
- }
+ pub(crate) fn parent_subst(&self, db: &dyn HirDatabase) -> Substitution {
+ let interner = DbInterner::new_with(db, None, None);
+ let subst =
+ <Substitution as ChalkToNextSolver<crate::next_solver::GenericArgs<'_>>>::to_nextsolver(
+ self.0, interner,
+ );
+ subst.split_closure_args().parent_args.to_chalk(interner)
}
- pub(crate) fn sig_ty(&self) -> &'a Ty {
- match self.0.as_slice(Interner) {
- [.., x] => x.assert_ty_ref(Interner),
- _ => {
- unreachable!("Closure missing sig_ty parameter");
- }
- }
+ pub(crate) fn sig_ty(&self, db: &dyn HirDatabase) -> Ty {
+ let interner = DbInterner::new_with(db, None, None);
+ let subst =
+ <Substitution as ChalkToNextSolver<crate::next_solver::GenericArgs<'_>>>::to_nextsolver(
+ self.0, interner,
+ );
+ subst.split_closure_args_untupled().closure_sig_as_fn_ptr_ty.to_chalk(interner)
}
}
@@ -263,18 +223,32 @@ pub enum Unsafety {
DeprecatedSafe2024,
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum TargetFeatureIsSafeInTarget {
+ No,
+ Yes,
+}
+
+pub fn target_feature_is_safe_in_target(target: &TargetData) -> TargetFeatureIsSafeInTarget {
+ match target.arch {
+ target::Arch::Wasm32 | target::Arch::Wasm64 => TargetFeatureIsSafeInTarget::Yes,
+ _ => TargetFeatureIsSafeInTarget::No,
+ }
+}
+
pub fn is_fn_unsafe_to_call(
db: &dyn HirDatabase,
func: FunctionId,
caller_target_features: &TargetFeatures,
call_edition: Edition,
+ target_feature_is_safe: TargetFeatureIsSafeInTarget,
) -> Unsafety {
let data = db.function_signature(func);
if data.is_unsafe() {
return Unsafety::Unsafe;
}
- if data.has_target_feature() {
+ if data.has_target_feature() && target_feature_is_safe == TargetFeatureIsSafeInTarget::No {
// RFC 2396 <https://rust-lang.github.io/rfcs/2396-target-feature-1.1.html>.
let callee_target_features =
TargetFeatures::from_attrs_no_implications(&db.attrs(func.into()));