2019-02-23 14:24:07 +00:00
|
|
|
//! Methods for lowering the HIR to types. There are two main cases here:
|
|
|
|
//!
|
|
|
|
//! - Lowering a type reference like `&usize` or `Option<foo::bar::Baz>` to a
|
2022-07-18 10:49:14 +00:00
|
|
|
//! type: The entry point for this is `TyLoweringContext::lower_ty`.
|
|
|
|
//! - Building the type for an item: This happens through the `ty` query.
|
2019-02-23 14:24:07 +00:00
|
|
|
//!
|
|
|
|
//! This usually involves resolving names, collecting generic arguments etc.
|
2022-06-23 18:08:29 +00:00
|
|
|
use std::{
|
2022-08-26 17:40:01 +00:00
|
|
|
cell::{Cell, RefCell, RefMut},
|
2022-06-23 18:08:29 +00:00
|
|
|
iter,
|
|
|
|
};
|
2020-04-10 20:05:46 +00:00
|
|
|
|
2024-02-10 14:36:26 +00:00
|
|
|
use base_db::{
|
|
|
|
salsa::{impl_intern_value_trivial, Cycle},
|
|
|
|
CrateId,
|
|
|
|
};
|
2022-07-03 07:22:10 +00:00
|
|
|
use chalk_ir::{
|
|
|
|
cast::Cast, fold::Shift, fold::TypeFoldable, interner::HasInterner, Mutability, Safety,
|
|
|
|
};
|
2022-06-23 18:08:29 +00:00
|
|
|
|
2024-03-18 10:18:59 +00:00
|
|
|
use either::Either;
|
2019-10-30 14:28:30 +00:00
|
|
|
use hir_def::{
|
2019-11-26 11:35:23 +00:00
|
|
|
builtin_type::BuiltinType,
|
2023-04-06 17:23:29 +00:00
|
|
|
data::adt::StructKind,
|
2023-04-17 15:31:39 +00:00
|
|
|
expander::Expander,
|
2022-06-23 18:08:29 +00:00
|
|
|
generics::{
|
2024-03-19 07:27:18 +00:00
|
|
|
GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
|
2024-03-08 19:38:35 +00:00
|
|
|
WherePredicateTypeTarget,
|
2022-06-23 18:08:29 +00:00
|
|
|
},
|
2023-07-07 11:37:29 +00:00
|
|
|
lang_item::LangItem,
|
2023-05-11 06:52:13 +00:00
|
|
|
nameres::MacroSubNs,
|
2023-03-08 17:28:52 +00:00
|
|
|
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
|
2024-03-06 11:09:24 +00:00
|
|
|
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
|
|
|
|
type_ref::{
|
|
|
|
ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
|
|
|
|
},
|
2023-03-08 17:28:52 +00:00
|
|
|
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
|
2024-03-08 12:35:44 +00:00
|
|
|
GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId,
|
|
|
|
Lookup, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
|
|
|
|
UnionId, VariantId,
|
2019-10-30 14:28:30 +00:00
|
|
|
};
|
2021-04-18 17:56:13 +00:00
|
|
|
use hir_expand::{name::Name, ExpandResult};
|
2023-01-09 18:29:28 +00:00
|
|
|
use intern::Interned;
|
2023-02-06 17:20:25 +00:00
|
|
|
use la_arena::{Arena, ArenaMap};
|
2021-06-06 18:41:15 +00:00
|
|
|
use rustc_hash::FxHashSet;
|
2020-07-13 14:16:53 +00:00
|
|
|
use smallvec::SmallVec;
|
2021-12-29 13:35:59 +00:00
|
|
|
use stdx::{impl_from, never};
|
2023-01-21 16:29:07 +00:00
|
|
|
use syntax::ast;
|
2023-05-02 14:12:22 +00:00
|
|
|
use triomphe::Arc;
|
2019-10-30 14:24:36 +00:00
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
use crate::{
|
2022-06-23 18:08:29 +00:00
|
|
|
all_super_traits,
|
2023-06-05 11:27:19 +00:00
|
|
|
consteval::{
|
|
|
|
intern_const_ref, intern_const_scalar, path_to_const, unknown_const,
|
|
|
|
unknown_const_as_generic,
|
|
|
|
},
|
2019-09-08 06:53:49 +00:00
|
|
|
db::HirDatabase,
|
2024-03-06 17:45:04 +00:00
|
|
|
error_lifetime, make_binders,
|
2024-03-06 11:09:24 +00:00
|
|
|
mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
|
2021-04-09 12:15:26 +00:00
|
|
|
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
|
2023-06-06 23:42:41 +00:00
|
|
|
utils::{
|
2024-03-06 11:09:24 +00:00
|
|
|
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
|
2023-06-06 23:42:41 +00:00
|
|
|
InTypeConstIdMetadata,
|
|
|
|
},
|
2023-06-05 11:27:19 +00:00
|
|
|
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
|
2024-03-06 11:09:24 +00:00
|
|
|
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
|
|
|
|
LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
|
|
|
|
QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
|
|
|
|
TyKind, WhereClause,
|
2019-02-23 14:24:07 +00:00
|
|
|
};
|
|
|
|
|
2023-02-06 17:20:25 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
enum ImplTraitLoweringState {
|
|
|
|
/// When turning `impl Trait` into opaque types, we have to collect the
|
|
|
|
/// bounds at the same time to get the IDs correct (without becoming too
|
|
|
|
/// complicated). I don't like using interior mutability (as for the
|
|
|
|
/// counter), but I've tried and failed to make the lifetimes work for
|
|
|
|
/// passing around a `&mut TyLoweringContext`. The core problem is that
|
|
|
|
/// we're grouping the mutable data (the counter and this field) together
|
|
|
|
/// with the immutable context (the references to the DB and resolver).
|
|
|
|
/// Splitting this up would be a possible fix.
|
2024-03-15 18:31:12 +00:00
|
|
|
Opaque(RefCell<Arena<ImplTrait>>),
|
2023-02-06 17:20:25 +00:00
|
|
|
Param(Cell<u16>),
|
|
|
|
Variable(Cell<u16>),
|
|
|
|
Disallowed,
|
|
|
|
}
|
|
|
|
impl ImplTraitLoweringState {
|
|
|
|
fn new(impl_trait_mode: ImplTraitLoweringMode) -> ImplTraitLoweringState {
|
|
|
|
match impl_trait_mode {
|
|
|
|
ImplTraitLoweringMode::Opaque => Self::Opaque(RefCell::new(Arena::new())),
|
|
|
|
ImplTraitLoweringMode::Param => Self::Param(Cell::new(0)),
|
|
|
|
ImplTraitLoweringMode::Variable => Self::Variable(Cell::new(0)),
|
|
|
|
ImplTraitLoweringMode::Disallowed => Self::Disallowed,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn take(&self) -> Self {
|
|
|
|
match self {
|
|
|
|
Self::Opaque(x) => Self::Opaque(RefCell::new(x.take())),
|
|
|
|
Self::Param(x) => Self::Param(Cell::new(x.get())),
|
|
|
|
Self::Variable(x) => Self::Variable(Cell::new(x.get())),
|
|
|
|
Self::Disallowed => Self::Disallowed,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn swap(&self, impl_trait_mode: &Self) {
|
|
|
|
match (self, impl_trait_mode) {
|
|
|
|
(Self::Opaque(x), Self::Opaque(y)) => x.swap(y),
|
|
|
|
(Self::Param(x), Self::Param(y)) => x.swap(y),
|
|
|
|
(Self::Variable(x), Self::Variable(y)) => x.swap(y),
|
|
|
|
(Self::Disallowed, Self::Disallowed) => (),
|
|
|
|
_ => panic!("mismatched lowering mode"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-25 22:38:33 +00:00
|
|
|
#[derive(Debug)]
|
2020-03-13 15:05:46 +00:00
|
|
|
pub struct TyLoweringContext<'a> {
|
|
|
|
pub db: &'a dyn HirDatabase,
|
2023-03-29 12:46:46 +00:00
|
|
|
resolver: &'a Resolver,
|
2020-04-17 20:48:29 +00:00
|
|
|
in_binders: DebruijnIndex,
|
2023-12-14 13:11:12 +00:00
|
|
|
// FIXME: Should not be an `Option` but `Resolver` currently does not return owners in all cases
|
|
|
|
// where expected
|
|
|
|
owner: Option<TypeOwnerId>,
|
2020-01-25 22:38:33 +00:00
|
|
|
/// Note: Conceptually, it's thinkable that we could be in a location where
|
2020-02-02 12:43:04 +00:00
|
|
|
/// some type params should be represented as placeholders, and others
|
|
|
|
/// should be converted to variables. I think in practice, this isn't
|
|
|
|
/// possible currently, so this should be fine for now.
|
2022-03-09 18:50:24 +00:00
|
|
|
pub type_param_mode: ParamLoweringMode,
|
2023-02-06 17:20:25 +00:00
|
|
|
impl_trait_mode: ImplTraitLoweringState,
|
2021-04-18 17:56:13 +00:00
|
|
|
expander: RefCell<Option<Expander>>,
|
2021-06-12 16:47:07 +00:00
|
|
|
/// Tracks types with explicit `?Sized` bounds.
|
|
|
|
pub(crate) unsized_types: RefCell<FxHashSet<Ty>>,
|
2020-01-24 14:22:00 +00:00
|
|
|
}
|
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
impl<'a> TyLoweringContext<'a> {
|
2023-06-05 11:27:19 +00:00
|
|
|
pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver, owner: TypeOwnerId) -> Self {
|
2023-12-14 13:11:12 +00:00
|
|
|
Self::new_maybe_unowned(db, resolver, Some(owner))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new_maybe_unowned(
|
|
|
|
db: &'a dyn HirDatabase,
|
|
|
|
resolver: &'a Resolver,
|
|
|
|
owner: Option<TypeOwnerId>,
|
|
|
|
) -> Self {
|
2023-02-06 17:20:25 +00:00
|
|
|
let impl_trait_mode = ImplTraitLoweringState::Disallowed;
|
2022-03-09 18:50:24 +00:00
|
|
|
let type_param_mode = ParamLoweringMode::Placeholder;
|
2020-04-17 20:48:29 +00:00
|
|
|
let in_binders = DebruijnIndex::INNERMOST;
|
2020-03-04 22:00:44 +00:00
|
|
|
Self {
|
|
|
|
db,
|
|
|
|
resolver,
|
2023-06-05 11:27:19 +00:00
|
|
|
owner,
|
2020-03-04 22:00:44 +00:00
|
|
|
in_binders,
|
|
|
|
impl_trait_mode,
|
|
|
|
type_param_mode,
|
2021-04-18 17:56:13 +00:00
|
|
|
expander: RefCell::new(None),
|
2021-06-06 18:41:15 +00:00
|
|
|
unsized_types: RefCell::default(),
|
2020-03-04 22:00:44 +00:00
|
|
|
}
|
2020-04-17 20:48:29 +00:00
|
|
|
}
|
|
|
|
|
2020-03-04 22:00:44 +00:00
|
|
|
pub fn with_debruijn<T>(
|
2020-04-17 20:48:29 +00:00
|
|
|
&self,
|
|
|
|
debruijn: DebruijnIndex,
|
2022-07-20 13:02:08 +00:00
|
|
|
f: impl FnOnce(&TyLoweringContext<'_>) -> T,
|
2020-04-17 20:48:29 +00:00
|
|
|
) -> T {
|
2023-02-06 17:20:25 +00:00
|
|
|
let impl_trait_mode = self.impl_trait_mode.take();
|
2021-12-09 17:28:10 +00:00
|
|
|
let expander = self.expander.take();
|
|
|
|
let unsized_types = self.unsized_types.take();
|
2020-04-17 20:48:29 +00:00
|
|
|
let new_ctx = Self {
|
2020-03-04 22:00:44 +00:00
|
|
|
in_binders: debruijn,
|
2023-02-06 17:20:25 +00:00
|
|
|
impl_trait_mode,
|
2021-04-18 17:56:13 +00:00
|
|
|
expander: RefCell::new(expander),
|
2021-06-06 18:41:15 +00:00
|
|
|
unsized_types: RefCell::new(unsized_types),
|
2020-04-17 20:48:29 +00:00
|
|
|
..*self
|
|
|
|
};
|
|
|
|
let result = f(&new_ctx);
|
2023-02-06 17:20:25 +00:00
|
|
|
self.impl_trait_mode.swap(&new_ctx.impl_trait_mode);
|
2021-04-18 17:56:13 +00:00
|
|
|
self.expander.replace(new_ctx.expander.into_inner());
|
2021-06-06 18:41:15 +00:00
|
|
|
self.unsized_types.replace(new_ctx.unsized_types.into_inner());
|
2020-04-17 20:48:29 +00:00
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2020-03-04 22:00:44 +00:00
|
|
|
pub fn with_shifted_in<T>(
|
|
|
|
&self,
|
|
|
|
debruijn: DebruijnIndex,
|
2022-07-20 13:02:08 +00:00
|
|
|
f: impl FnOnce(&TyLoweringContext<'_>) -> T,
|
2020-03-04 22:00:44 +00:00
|
|
|
) -> T {
|
|
|
|
self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f)
|
2020-01-25 22:38:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
|
2023-02-06 17:20:25 +00:00
|
|
|
Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self }
|
2020-01-25 22:38:33 +00:00
|
|
|
}
|
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
pub fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self {
|
2020-01-25 22:38:33 +00:00
|
|
|
Self { type_param_mode, ..self }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-31 14:57:44 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2020-01-24 14:22:00 +00:00
|
|
|
pub enum ImplTraitLoweringMode {
|
2020-01-24 15:46:43 +00:00
|
|
|
/// `impl Trait` gets lowered into an opaque type that doesn't unify with
|
|
|
|
/// anything except itself. This is used in places where values flow 'out',
|
|
|
|
/// i.e. for arguments of the function we're currently checking, and return
|
|
|
|
/// types of functions we're calling.
|
2020-01-24 14:22:00 +00:00
|
|
|
Opaque,
|
2020-01-31 15:05:58 +00:00
|
|
|
/// `impl Trait` gets lowered into a type variable. Used for argument
|
2020-02-02 12:43:04 +00:00
|
|
|
/// position impl Trait when inside the respective function, since it allows
|
|
|
|
/// us to support that without Chalk.
|
2020-01-31 15:05:58 +00:00
|
|
|
Param,
|
2020-01-25 22:38:33 +00:00
|
|
|
/// `impl Trait` gets lowered into a variable that can unify with some
|
2020-01-24 15:46:43 +00:00
|
|
|
/// type. This is used in places where values flow 'in', i.e. for arguments
|
|
|
|
/// of functions we're calling, and the return type of the function we're
|
|
|
|
/// currently checking.
|
2020-01-25 22:38:33 +00:00
|
|
|
Variable,
|
2020-01-24 15:46:43 +00:00
|
|
|
/// `impl Trait` is disallowed and will be an error.
|
2020-01-24 14:22:00 +00:00
|
|
|
Disallowed,
|
2020-01-24 13:32:47 +00:00
|
|
|
}
|
|
|
|
|
2020-01-31 14:57:44 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2022-03-09 18:50:24 +00:00
|
|
|
pub enum ParamLoweringMode {
|
2020-01-25 22:38:33 +00:00
|
|
|
Placeholder,
|
|
|
|
Variable,
|
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
impl<'a> TyLoweringContext<'a> {
|
|
|
|
pub fn lower_ty(&self, type_ref: &TypeRef) -> Ty {
|
|
|
|
self.lower_ty_ext(type_ref).0
|
2020-03-06 17:08:10 +00:00
|
|
|
}
|
2021-03-13 21:44:36 +00:00
|
|
|
|
2023-06-30 13:31:04 +00:00
|
|
|
pub fn lower_const(&self, const_ref: &ConstRef, const_type: Ty) -> Const {
|
2023-12-14 13:11:12 +00:00
|
|
|
let Some(owner) = self.owner else { return unknown_const(const_type) };
|
2023-06-30 13:31:04 +00:00
|
|
|
const_or_path_to_chalk(
|
|
|
|
self.db,
|
|
|
|
self.resolver,
|
2023-12-14 13:11:12 +00:00
|
|
|
owner,
|
2023-06-30 13:31:04 +00:00
|
|
|
const_type,
|
|
|
|
const_ref,
|
|
|
|
self.type_param_mode,
|
|
|
|
|| self.generics(),
|
|
|
|
self.in_binders,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
fn generics(&self) -> Generics {
|
|
|
|
generics(
|
|
|
|
self.db.upcast(),
|
|
|
|
self.resolver
|
|
|
|
.generic_def()
|
|
|
|
.expect("there should be generics if there's a generic param"),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-04-01 19:52:07 +00:00
|
|
|
pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
|
2020-03-06 17:08:10 +00:00
|
|
|
let mut res = None;
|
|
|
|
let ty = match type_ref {
|
2021-12-19 16:58:39 +00:00
|
|
|
TypeRef::Never => TyKind::Never.intern(Interner),
|
2019-02-23 14:24:07 +00:00
|
|
|
TypeRef::Tuple(inner) => {
|
2021-03-15 18:13:49 +00:00
|
|
|
let inner_tys = inner.iter().map(|tr| self.lower_ty(tr));
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
|
|
|
|
.intern(Interner)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2020-03-06 17:08:10 +00:00
|
|
|
TypeRef::Path(path) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let (ty, res_) = self.lower_path(path);
|
2020-03-06 17:08:10 +00:00
|
|
|
res = res_;
|
|
|
|
ty
|
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
TypeRef::RawPtr(inner, mutability) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let inner_ty = self.lower_ty(inner);
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(Interner)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2021-05-12 11:39:48 +00:00
|
|
|
TypeRef::Array(inner, len) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let inner_ty = self.lower_ty(inner);
|
2023-06-30 13:31:04 +00:00
|
|
|
let const_len = self.lower_const(len, TyBuilder::usize());
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Array(inner_ty, const_len).intern(Interner)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
TypeRef::Slice(inner) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let inner_ty = self.lower_ty(inner);
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Slice(inner_ty).intern(Interner)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2024-03-06 11:09:24 +00:00
|
|
|
TypeRef::Reference(inner, lifetime, mutability) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let inner_ty = self.lower_ty(inner);
|
2024-03-18 10:18:59 +00:00
|
|
|
// FIXME: It should infer the eldided lifetimes instead of stubbing with static
|
2024-03-06 11:09:24 +00:00
|
|
|
let lifetime =
|
|
|
|
lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr));
|
2021-04-05 20:08:16 +00:00
|
|
|
TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
TypeRef::Placeholder => TyKind::Error.intern(Interner),
|
2024-01-17 17:23:14 +00:00
|
|
|
&TypeRef::Fn(ref params, variadic, is_unsafe, ref abi) => {
|
2021-04-05 20:32:58 +00:00
|
|
|
let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
|
2022-02-15 14:55:21 +00:00
|
|
|
Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr)))
|
2021-04-05 20:32:58 +00:00
|
|
|
});
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::Function(FnPointer {
|
2021-04-05 20:23:16 +00:00
|
|
|
num_binders: 0, // FIXME lower `for<'a> fn()` correctly
|
2022-11-04 20:07:15 +00:00
|
|
|
sig: FnSig {
|
2024-01-17 17:23:14 +00:00
|
|
|
abi: abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str),
|
2022-11-04 20:07:15 +00:00
|
|
|
safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe },
|
|
|
|
variadic,
|
|
|
|
},
|
2021-04-05 20:23:16 +00:00
|
|
|
substitution: FnSubst(substs),
|
2021-02-28 21:12:07 +00:00
|
|
|
})
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2022-08-17 16:30:04 +00:00
|
|
|
TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
|
2019-08-13 21:09:08 +00:00
|
|
|
TypeRef::ImplTrait(bounds) => {
|
2023-02-06 17:20:25 +00:00
|
|
|
match &self.impl_trait_mode {
|
|
|
|
ImplTraitLoweringState::Opaque(opaque_type_data) => {
|
2024-03-18 09:25:41 +00:00
|
|
|
let origin = match self.resolver.generic_def() {
|
|
|
|
Some(GenericDefId::FunctionId(it)) => Either::Left(it),
|
|
|
|
Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
|
2024-03-15 18:31:12 +00:00
|
|
|
_ => panic!(
|
|
|
|
"opaque impl trait lowering must be in function or type alias"
|
|
|
|
),
|
2021-06-15 08:53:20 +00:00
|
|
|
};
|
2020-03-04 22:00:44 +00:00
|
|
|
|
|
|
|
// this dance is to make sure the data is in the right
|
|
|
|
// place even if we encounter more opaque types while
|
|
|
|
// lowering the bounds
|
2024-03-15 18:31:12 +00:00
|
|
|
let idx = opaque_type_data.borrow_mut().alloc(ImplTrait {
|
2022-03-09 18:50:24 +00:00
|
|
|
bounds: crate::make_single_type_binders(Vec::new()),
|
2021-04-05 15:45:18 +00:00
|
|
|
});
|
2020-03-04 22:00:44 +00:00
|
|
|
// We don't want to lower the bounds inside the binders
|
|
|
|
// we're currently in, because they don't end up inside
|
|
|
|
// those binders. E.g. when we have `impl Trait<impl
|
|
|
|
// OtherTrait<T>>`, the `impl OtherTrait<T>` can't refer
|
|
|
|
// to the self parameter from `impl Trait`, and the
|
|
|
|
// bounds aren't actually stored nested within each
|
|
|
|
// other, but separately. So if the `T` refers to a type
|
|
|
|
// parameter of the outer function, it's just one binder
|
|
|
|
// away instead of two.
|
2021-03-13 21:44:36 +00:00
|
|
|
let actual_opaque_type_data = self
|
2020-03-04 22:00:44 +00:00
|
|
|
.with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
|
2024-03-18 09:25:41 +00:00
|
|
|
ctx.lower_impl_trait(bounds, self.resolver.krate())
|
2020-03-04 22:00:44 +00:00
|
|
|
});
|
2023-02-06 17:20:25 +00:00
|
|
|
opaque_type_data.borrow_mut()[idx] = actual_opaque_type_data;
|
2020-03-04 22:00:44 +00:00
|
|
|
|
2024-03-15 18:31:12 +00:00
|
|
|
let impl_trait_id = origin.either(
|
|
|
|
|f| ImplTraitId::ReturnTypeImplTrait(f, idx),
|
|
|
|
|a| ImplTraitId::AssociatedTypeImplTrait(a, idx),
|
|
|
|
);
|
2021-03-13 21:44:36 +00:00
|
|
|
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
|
2024-03-15 18:31:12 +00:00
|
|
|
let generics =
|
|
|
|
generics(self.db.upcast(), origin.either(|f| f.into(), |a| a.into()));
|
2022-03-09 18:50:24 +00:00
|
|
|
let parameters = generics.bound_vars_subst(self.db, self.in_binders);
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner)
|
2020-01-25 22:38:33 +00:00
|
|
|
}
|
2023-02-06 17:20:25 +00:00
|
|
|
ImplTraitLoweringState::Param(counter) => {
|
|
|
|
let idx = counter.get();
|
2020-03-04 22:00:44 +00:00
|
|
|
// FIXME we're probably doing something wrong here
|
2023-02-06 17:20:25 +00:00
|
|
|
counter.set(idx + count_impl_traits(type_ref) as u16);
|
2021-03-13 21:44:36 +00:00
|
|
|
if let Some(def) = self.resolver.generic_def() {
|
|
|
|
let generics = generics(self.db.upcast(), def);
|
2020-01-31 15:52:43 +00:00
|
|
|
let param = generics
|
2022-06-12 12:40:37 +00:00
|
|
|
.iter()
|
2020-02-02 16:11:54 +00:00
|
|
|
.filter(|(_, data)| {
|
2022-06-12 12:40:37 +00:00
|
|
|
matches!(
|
|
|
|
data,
|
2024-03-19 07:27:18 +00:00
|
|
|
GenericParamDataRef::TypeParamData(data)
|
2022-06-12 12:40:37 +00:00
|
|
|
if data.provenance == TypeParamProvenance::ArgumentImplTrait
|
|
|
|
)
|
2020-02-02 16:11:54 +00:00
|
|
|
})
|
2020-01-31 15:52:43 +00:00
|
|
|
.nth(idx as usize)
|
2021-04-05 12:37:11 +00:00
|
|
|
.map_or(TyKind::Error, |(id, _)| {
|
2024-03-08 19:38:35 +00:00
|
|
|
if let GenericParamId::TypeParamId(id) = id {
|
|
|
|
TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
|
|
|
|
} else {
|
|
|
|
// we just filtered them out
|
|
|
|
unreachable!("Unexpected lifetime or const argument");
|
|
|
|
}
|
2021-03-13 18:47:34 +00:00
|
|
|
});
|
2021-12-19 16:58:39 +00:00
|
|
|
param.intern(Interner)
|
2020-01-31 15:52:43 +00:00
|
|
|
} else {
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Error.intern(Interner)
|
2020-01-31 15:52:43 +00:00
|
|
|
}
|
2020-01-31 15:05:58 +00:00
|
|
|
}
|
2023-02-06 17:20:25 +00:00
|
|
|
ImplTraitLoweringState::Variable(counter) => {
|
|
|
|
let idx = counter.get();
|
2020-03-04 22:00:44 +00:00
|
|
|
// FIXME we're probably doing something wrong here
|
2023-02-06 17:20:25 +00:00
|
|
|
counter.set(idx + count_impl_traits(type_ref) as u16);
|
2022-03-08 16:21:35 +00:00
|
|
|
let (
|
2022-10-02 13:15:57 +00:00
|
|
|
_parent_params,
|
2022-03-08 16:21:35 +00:00
|
|
|
self_params,
|
|
|
|
list_params,
|
|
|
|
const_params,
|
|
|
|
_impl_trait_params,
|
2024-03-10 20:36:47 +00:00
|
|
|
_lifetime_params,
|
2022-03-08 16:21:35 +00:00
|
|
|
) = if let Some(def) = self.resolver.generic_def() {
|
|
|
|
let generics = generics(self.db.upcast(), def);
|
|
|
|
generics.provenance_split()
|
|
|
|
} else {
|
2024-03-08 12:35:44 +00:00
|
|
|
(0, 0, 0, 0, 0, 0)
|
2022-03-08 16:21:35 +00:00
|
|
|
};
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::BoundVar(BoundVar::new(
|
2021-03-13 21:44:36 +00:00
|
|
|
self.in_binders,
|
2024-03-10 20:36:47 +00:00
|
|
|
idx as usize + self_params + list_params + const_params,
|
2020-04-05 16:24:18 +00:00
|
|
|
))
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2020-01-25 22:38:33 +00:00
|
|
|
}
|
2023-02-06 17:20:25 +00:00
|
|
|
ImplTraitLoweringState::Disallowed => {
|
2020-01-24 15:46:43 +00:00
|
|
|
// FIXME: report error
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Error.intern(Interner)
|
2020-01-25 22:38:33 +00:00
|
|
|
}
|
2020-01-24 15:46:43 +00:00
|
|
|
}
|
2019-08-13 21:09:08 +00:00
|
|
|
}
|
2021-04-18 17:56:13 +00:00
|
|
|
TypeRef::Macro(macro_call) => {
|
2022-08-26 17:40:01 +00:00
|
|
|
let (mut expander, recursion_start) = {
|
|
|
|
match RefMut::filter_map(self.expander.borrow_mut(), Option::as_mut) {
|
2022-08-31 08:04:01 +00:00
|
|
|
// There already is an expander here, this means we are already recursing
|
2022-08-26 17:40:01 +00:00
|
|
|
Ok(expander) => (expander, false),
|
2022-08-31 08:04:01 +00:00
|
|
|
// No expander was created yet, so we are at the start of the expansion recursion
|
|
|
|
// and therefore have to create an expander.
|
2022-08-26 17:40:01 +00:00
|
|
|
Err(expander) => (
|
|
|
|
RefMut::map(expander, |it| {
|
|
|
|
it.insert(Expander::new(
|
|
|
|
self.db.upcast(),
|
|
|
|
macro_call.file_id,
|
|
|
|
self.resolver.module(),
|
|
|
|
))
|
|
|
|
}),
|
|
|
|
true,
|
|
|
|
),
|
2021-04-18 17:56:13 +00:00
|
|
|
}
|
|
|
|
};
|
2022-08-26 17:40:01 +00:00
|
|
|
let ty = {
|
2021-04-18 17:56:13 +00:00
|
|
|
let macro_call = macro_call.to_node(self.db.upcast());
|
2023-05-11 06:52:13 +00:00
|
|
|
let resolver = |path| {
|
2023-08-17 08:52:13 +00:00
|
|
|
self.resolver
|
|
|
|
.resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
|
|
|
|
.map(|(it, _)| it)
|
2023-05-11 06:52:13 +00:00
|
|
|
};
|
|
|
|
match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, resolver)
|
|
|
|
{
|
2021-04-18 17:56:13 +00:00
|
|
|
Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
|
2023-04-06 19:16:11 +00:00
|
|
|
let ctx = expander.ctx(self.db.upcast());
|
2023-04-16 15:22:06 +00:00
|
|
|
// FIXME: Report syntax errors in expansion here
|
|
|
|
let type_ref = TypeRef::from_ast(&ctx, expanded.tree());
|
2021-04-18 17:56:13 +00:00
|
|
|
|
|
|
|
drop(expander);
|
|
|
|
let ty = self.lower_ty(&type_ref);
|
|
|
|
|
2023-12-02 12:03:46 +00:00
|
|
|
self.expander.borrow_mut().as_mut().unwrap().exit(mark);
|
2021-04-18 17:56:13 +00:00
|
|
|
Some(ty)
|
|
|
|
}
|
2022-08-31 08:04:01 +00:00
|
|
|
_ => {
|
|
|
|
drop(expander);
|
|
|
|
None
|
|
|
|
}
|
2021-04-10 15:49:12 +00:00
|
|
|
}
|
2021-04-18 17:56:13 +00:00
|
|
|
};
|
2022-08-31 08:04:01 +00:00
|
|
|
|
|
|
|
// drop the expander, resetting it to pre-recursion state
|
2021-04-18 17:56:13 +00:00
|
|
|
if recursion_start {
|
|
|
|
*self.expander.borrow_mut() = None;
|
2021-04-10 15:49:12 +00:00
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
ty.unwrap_or_else(|| TyKind::Error.intern(Interner))
|
2021-04-10 15:49:12 +00:00
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
TypeRef::Error => TyKind::Error.intern(Interner),
|
2020-03-06 17:08:10 +00:00
|
|
|
};
|
|
|
|
(ty, res)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2019-09-22 18:01:12 +00:00
|
|
|
/// This is only for `generic_predicates_for_param`, where we can't just
|
|
|
|
/// lower the self types of the predicates since that could lead to cycles.
|
|
|
|
/// So we just check here if the `type_ref` resolves to a generic param, and which.
|
2021-12-29 13:35:59 +00:00
|
|
|
fn lower_ty_only_param(&self, type_ref: &TypeRef) -> Option<TypeOrConstParamId> {
|
2019-09-22 18:01:12 +00:00
|
|
|
let path = match type_ref {
|
|
|
|
TypeRef::Path(path) => path,
|
|
|
|
_ => return None,
|
|
|
|
};
|
2019-12-18 16:41:33 +00:00
|
|
|
if path.type_anchor().is_some() {
|
2019-09-22 18:01:12 +00:00
|
|
|
return None;
|
|
|
|
}
|
2019-12-13 11:12:36 +00:00
|
|
|
if path.segments().len() > 1 {
|
2019-09-22 18:01:12 +00:00
|
|
|
return None;
|
|
|
|
}
|
2023-03-08 17:28:52 +00:00
|
|
|
let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
|
2023-08-17 08:52:13 +00:00
|
|
|
Some((it, None, _)) => it,
|
2023-03-08 17:28:52 +00:00
|
|
|
_ => return None,
|
|
|
|
};
|
2021-10-03 12:53:01 +00:00
|
|
|
match resolution {
|
2022-03-04 09:00:53 +00:00
|
|
|
TypeNs::GenericParam(param_id) => Some(param_id.into()),
|
2021-10-03 12:53:01 +00:00
|
|
|
_ => None,
|
2019-09-22 18:01:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
pub(crate) fn lower_ty_relative_path(
|
|
|
|
&self,
|
2019-09-16 19:38:27 +00:00
|
|
|
ty: Ty,
|
2020-03-06 17:08:10 +00:00
|
|
|
// We need the original resolution to lower `Self::AssocTy` correctly
|
|
|
|
res: Option<TypeNs>,
|
2019-12-13 11:12:36 +00:00
|
|
|
remaining_segments: PathSegments<'_>,
|
2020-03-06 17:08:10 +00:00
|
|
|
) -> (Ty, Option<TypeNs>) {
|
2021-09-03 14:00:50 +00:00
|
|
|
match remaining_segments.len() {
|
|
|
|
0 => (ty, res),
|
|
|
|
1 => {
|
|
|
|
// resolve unselected assoc types
|
|
|
|
let segment = remaining_segments.first().unwrap();
|
|
|
|
(self.select_associated_type(res, segment), None)
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
// FIXME report error (ambiguous associated type)
|
2021-12-19 16:58:39 +00:00
|
|
|
(TyKind::Error.intern(Interner), None)
|
2021-09-03 14:00:50 +00:00
|
|
|
}
|
2019-09-16 19:38:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
pub(crate) fn lower_partly_resolved_path(
|
|
|
|
&self,
|
2019-09-15 10:50:57 +00:00
|
|
|
resolution: TypeNs,
|
2019-12-13 11:12:36 +00:00
|
|
|
resolved_segment: PathSegment<'_>,
|
|
|
|
remaining_segments: PathSegments<'_>,
|
2020-05-29 17:14:04 +00:00
|
|
|
infer_args: bool,
|
2020-03-06 17:08:10 +00:00
|
|
|
) -> (Ty, Option<TypeNs>) {
|
2019-09-14 11:25:05 +00:00
|
|
|
let ty = match resolution {
|
2019-11-21 09:21:46 +00:00
|
|
|
TypeNs::TraitId(trait_) => {
|
2021-09-13 16:50:19 +00:00
|
|
|
let ty = match remaining_segments.len() {
|
|
|
|
1 => {
|
|
|
|
let trait_ref =
|
|
|
|
self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, None);
|
|
|
|
let segment = remaining_segments.first().unwrap();
|
|
|
|
let found = self
|
|
|
|
.db
|
|
|
|
.trait_data(trait_ref.hir_trait_id())
|
|
|
|
.associated_type_by_name(segment.name);
|
2022-10-26 08:21:08 +00:00
|
|
|
|
2021-09-13 16:50:19 +00:00
|
|
|
match found {
|
|
|
|
Some(associated_ty) => {
|
2022-10-26 08:21:08 +00:00
|
|
|
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
|
|
|
|
// generic params. It's inefficient to splice the `Substitution`s, so we may want
|
|
|
|
// that method to optionally take parent `Substitution` as we already know them at
|
|
|
|
// this point (`trait_ref.substitution`).
|
|
|
|
let substitution = self.substs_from_path_segment(
|
|
|
|
segment,
|
|
|
|
Some(associated_ty.into()),
|
|
|
|
false,
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
let len_self =
|
|
|
|
generics(self.db.upcast(), associated_ty.into()).len_self();
|
|
|
|
let substitution = Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
substitution
|
|
|
|
.iter(Interner)
|
|
|
|
.take(len_self)
|
|
|
|
.chain(trait_ref.substitution.iter(Interner)),
|
|
|
|
);
|
2021-09-13 16:50:19 +00:00
|
|
|
TyKind::Alias(AliasTy::Projection(ProjectionTy {
|
|
|
|
associated_ty_id: to_assoc_type_id(associated_ty),
|
2022-10-26 08:21:08 +00:00
|
|
|
substitution,
|
2021-09-13 16:50:19 +00:00
|
|
|
}))
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2021-09-13 16:50:19 +00:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
// FIXME: report error (associated type not found)
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Error.intern(Interner)
|
2021-09-13 16:50:19 +00:00
|
|
|
}
|
2019-09-12 20:35:53 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-13 16:50:19 +00:00
|
|
|
0 => {
|
2022-08-17 16:30:04 +00:00
|
|
|
// Trait object type without dyn; this should be handled in upstream. See
|
|
|
|
// `lower_path()`.
|
|
|
|
stdx::never!("unexpected fully resolved trait path");
|
|
|
|
TyKind::Error.intern(Interner)
|
2021-09-13 16:50:19 +00:00
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
// FIXME report error (ambiguous associated type)
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Error.intern(Interner)
|
2021-09-13 16:50:19 +00:00
|
|
|
}
|
2019-09-12 20:35:53 +00:00
|
|
|
};
|
2020-03-06 17:08:10 +00:00
|
|
|
return (ty, None);
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2023-03-03 15:24:07 +00:00
|
|
|
TypeNs::TraitAliasId(_) => {
|
|
|
|
// FIXME(trait_alias): Implement trait alias.
|
|
|
|
return (TyKind::Error.intern(Interner), None);
|
|
|
|
}
|
2019-12-07 10:50:36 +00:00
|
|
|
TypeNs::GenericParam(param_id) => {
|
2020-03-13 15:05:46 +00:00
|
|
|
let generics = generics(
|
2021-03-13 21:44:36 +00:00
|
|
|
self.db.upcast(),
|
|
|
|
self.resolver.generic_def().expect("generics in scope"),
|
2020-03-13 15:05:46 +00:00
|
|
|
);
|
2021-03-13 21:44:36 +00:00
|
|
|
match self.type_param_mode {
|
2022-03-09 18:50:24 +00:00
|
|
|
ParamLoweringMode::Placeholder => {
|
2021-12-29 13:35:59 +00:00
|
|
|
TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
|
2021-03-13 18:47:34 +00:00
|
|
|
}
|
2022-03-09 18:50:24 +00:00
|
|
|
ParamLoweringMode::Variable => {
|
2022-08-16 15:30:17 +00:00
|
|
|
let idx = match generics.param_idx(param_id.into()) {
|
|
|
|
None => {
|
|
|
|
never!("no matching generics");
|
|
|
|
return (TyKind::Error.intern(Interner), None);
|
|
|
|
}
|
|
|
|
Some(idx) => idx,
|
|
|
|
};
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
|
2020-01-31 14:57:44 +00:00
|
|
|
}
|
2020-01-25 22:38:33 +00:00
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2020-01-25 22:38:33 +00:00
|
|
|
TypeNs::SelfType(impl_id) => {
|
2022-10-02 13:15:57 +00:00
|
|
|
let def =
|
|
|
|
self.resolver.generic_def().expect("impl should have generic param scope");
|
|
|
|
let generics = generics(self.db.upcast(), def);
|
|
|
|
|
|
|
|
match self.type_param_mode {
|
|
|
|
ParamLoweringMode::Placeholder => {
|
|
|
|
// `def` can be either impl itself or item within, and we need impl itself
|
|
|
|
// now.
|
|
|
|
let generics = generics.parent_generics().unwrap_or(&generics);
|
|
|
|
let subst = generics.placeholder_subst(self.db);
|
|
|
|
self.db.impl_self_ty(impl_id).substitute(Interner, &subst)
|
|
|
|
}
|
2022-03-09 18:50:24 +00:00
|
|
|
ParamLoweringMode::Variable => {
|
2022-10-02 13:15:57 +00:00
|
|
|
let starting_from = match def {
|
|
|
|
GenericDefId::ImplId(_) => 0,
|
|
|
|
// `def` is an item within impl. We need to substitute `BoundVar`s but
|
|
|
|
// remember that they are for parent (i.e. impl) generic params so they
|
|
|
|
// come after our own params.
|
|
|
|
_ => generics.len_self(),
|
|
|
|
};
|
|
|
|
TyBuilder::impl_self_ty(self.db, impl_id)
|
|
|
|
.fill_with_bound_vars(self.in_binders, starting_from)
|
|
|
|
.build()
|
2022-03-09 18:50:24 +00:00
|
|
|
}
|
2022-10-02 13:15:57 +00:00
|
|
|
}
|
2020-01-31 14:57:44 +00:00
|
|
|
}
|
2020-01-25 22:38:33 +00:00
|
|
|
TypeNs::AdtSelfType(adt) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let generics = generics(self.db.upcast(), adt.into());
|
|
|
|
let substs = match self.type_param_mode {
|
2022-03-09 18:50:24 +00:00
|
|
|
ParamLoweringMode::Placeholder => generics.placeholder_subst(self.db),
|
|
|
|
ParamLoweringMode::Variable => {
|
|
|
|
generics.bound_vars_subst(self.db, self.in_binders)
|
|
|
|
}
|
2020-01-25 22:38:33 +00:00
|
|
|
};
|
2021-12-19 16:58:39 +00:00
|
|
|
self.db.ty(adt.into()).substitute(Interner, &substs)
|
2020-01-31 14:57:44 +00:00
|
|
|
}
|
2019-09-12 20:35:53 +00:00
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
TypeNs::AdtId(it) => self.lower_path_inner(resolved_segment, it.into(), infer_args),
|
2020-05-29 17:14:04 +00:00
|
|
|
TypeNs::BuiltinType(it) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
self.lower_path_inner(resolved_segment, it.into(), infer_args)
|
2020-05-29 17:14:04 +00:00
|
|
|
}
|
|
|
|
TypeNs::TypeAliasId(it) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
self.lower_path_inner(resolved_segment, it.into(), infer_args)
|
2020-05-29 17:14:04 +00:00
|
|
|
}
|
2019-09-12 20:35:53 +00:00
|
|
|
// FIXME: report error
|
2021-12-19 16:58:39 +00:00
|
|
|
TypeNs::EnumVariantId(_) => return (TyKind::Error.intern(Interner), None),
|
2019-02-23 14:24:07 +00:00
|
|
|
};
|
2021-03-13 21:44:36 +00:00
|
|
|
self.lower_ty_relative_path(ty, Some(resolution), remaining_segments)
|
2019-09-14 11:25:05 +00:00
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
pub(crate) fn lower_path(&self, path: &Path) -> (Ty, Option<TypeNs>) {
|
2019-09-15 10:50:57 +00:00
|
|
|
// Resolve the path (in type namespace)
|
2019-12-18 16:41:33 +00:00
|
|
|
if let Some(type_ref) = path.type_anchor() {
|
2021-06-13 03:54:16 +00:00
|
|
|
let (ty, res) = self.lower_ty_ext(type_ref);
|
2021-03-13 21:44:36 +00:00
|
|
|
return self.lower_ty_relative_path(ty, res, path.segments());
|
2019-09-16 19:38:27 +00:00
|
|
|
}
|
2022-08-17 16:30:04 +00:00
|
|
|
|
2023-08-17 08:52:13 +00:00
|
|
|
let (resolution, remaining_index, _) =
|
2023-03-08 17:28:52 +00:00
|
|
|
match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
|
2019-12-13 11:12:36 +00:00
|
|
|
Some(it) => it,
|
2021-12-19 16:58:39 +00:00
|
|
|
None => return (TyKind::Error.intern(Interner), None),
|
2019-12-13 11:12:36 +00:00
|
|
|
};
|
2022-08-17 16:30:04 +00:00
|
|
|
|
|
|
|
if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
|
|
|
|
// trait object type without dyn
|
|
|
|
let bound = TypeBound::Path(path.clone(), TraitBoundModifier::None);
|
|
|
|
let ty = self.lower_dyn_trait(&[Interned::new(bound)]);
|
|
|
|
return (ty, None);
|
|
|
|
}
|
|
|
|
|
2019-09-15 10:50:57 +00:00
|
|
|
let (resolved_segment, remaining_segments) = match remaining_index {
|
|
|
|
None => (
|
2019-12-13 11:12:36 +00:00
|
|
|
path.segments().last().expect("resolved path has at least one element"),
|
|
|
|
PathSegments::EMPTY,
|
2019-09-15 10:50:57 +00:00
|
|
|
),
|
2019-12-13 11:12:36 +00:00
|
|
|
Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)),
|
2019-09-15 10:50:57 +00:00
|
|
|
};
|
2021-03-13 21:44:36 +00:00
|
|
|
self.lower_partly_resolved_path(resolution, resolved_segment, remaining_segments, false)
|
2019-09-15 10:50:57 +00:00
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
fn select_associated_type(&self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty {
|
2022-12-08 11:41:42 +00:00
|
|
|
let Some((def, res)) = self.resolver.generic_def().zip(res) else {
|
|
|
|
return TyKind::Error.intern(Interner);
|
2022-02-03 11:43:15 +00:00
|
|
|
};
|
|
|
|
let ty = named_associated_type_shorthand_candidates(
|
|
|
|
self.db,
|
|
|
|
def,
|
|
|
|
res,
|
|
|
|
Some(segment.name.clone()),
|
|
|
|
move |name, t, associated_ty| {
|
2022-10-26 08:21:08 +00:00
|
|
|
if name != segment.name {
|
|
|
|
return None;
|
2022-02-03 11:43:15 +00:00
|
|
|
}
|
2022-10-26 08:21:08 +00:00
|
|
|
|
2022-12-08 11:41:42 +00:00
|
|
|
let parent_subst = t.substitution.clone();
|
|
|
|
let parent_subst = match self.type_param_mode {
|
|
|
|
ParamLoweringMode::Placeholder => {
|
|
|
|
// if we're lowering to placeholders, we have to put them in now.
|
|
|
|
let generics = generics(self.db.upcast(), def);
|
|
|
|
let s = generics.placeholder_subst(self.db);
|
|
|
|
s.apply(parent_subst, Interner)
|
|
|
|
}
|
|
|
|
ParamLoweringMode::Variable => {
|
|
|
|
// We need to shift in the bound vars, since
|
|
|
|
// `named_associated_type_shorthand_candidates` does not do that.
|
|
|
|
parent_subst.shifted_in_from(Interner, self.in_binders)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-10-26 08:21:08 +00:00
|
|
|
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
|
|
|
|
// generic params. It's inefficient to splice the `Substitution`s, so we may want
|
|
|
|
// that method to optionally take parent `Substitution` as we already know them at
|
|
|
|
// this point (`t.substitution`).
|
|
|
|
let substs = self.substs_from_path_segment(
|
|
|
|
segment.clone(),
|
|
|
|
Some(associated_ty.into()),
|
|
|
|
false,
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
|
|
|
|
let len_self = generics(self.db.upcast(), associated_ty.into()).len_self();
|
|
|
|
|
|
|
|
let substs = Substitution::from_iter(
|
|
|
|
Interner,
|
2022-12-08 11:41:42 +00:00
|
|
|
substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)),
|
2022-10-26 08:21:08 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
Some(
|
|
|
|
TyKind::Alias(AliasTy::Projection(ProjectionTy {
|
|
|
|
associated_ty_id: to_assoc_type_id(associated_ty),
|
|
|
|
substitution: substs,
|
|
|
|
}))
|
|
|
|
.intern(Interner),
|
|
|
|
)
|
2022-02-03 11:43:15 +00:00
|
|
|
},
|
|
|
|
);
|
2020-04-27 22:40:32 +00:00
|
|
|
|
2022-02-03 11:43:15 +00:00
|
|
|
ty.unwrap_or_else(|| TyKind::Error.intern(Interner))
|
2019-09-14 11:25:05 +00:00
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
fn lower_path_inner(
|
|
|
|
&self,
|
2019-12-13 11:12:36 +00:00
|
|
|
segment: PathSegment<'_>,
|
2021-01-08 14:41:32 +00:00
|
|
|
typeable: TyDefId,
|
2020-05-29 17:14:04 +00:00
|
|
|
infer_args: bool,
|
2019-09-14 11:25:05 +00:00
|
|
|
) -> Ty {
|
2021-01-08 14:41:32 +00:00
|
|
|
let generic_def = match typeable {
|
2019-11-26 18:04:24 +00:00
|
|
|
TyDefId::BuiltinType(_) => None,
|
|
|
|
TyDefId::AdtId(it) => Some(it.into()),
|
|
|
|
TyDefId::TypeAliasId(it) => Some(it.into()),
|
2019-02-23 14:24:07 +00:00
|
|
|
};
|
2021-03-22 18:13:43 +00:00
|
|
|
let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None);
|
2021-12-19 16:58:39 +00:00
|
|
|
self.db.ty(typeable).substitute(Interner, &substs)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2019-02-23 21:59:01 +00:00
|
|
|
|
|
|
|
/// Collect generic arguments from a path into a `Substs`. See also
|
|
|
|
/// `create_substs_for_ast_path` and `def_to_ty` in rustc.
|
|
|
|
pub(super) fn substs_from_path(
|
2021-03-13 21:44:36 +00:00
|
|
|
&self,
|
2019-02-23 21:59:01 +00:00
|
|
|
path: &Path,
|
2019-11-26 18:04:24 +00:00
|
|
|
// Note that we don't call `db.value_type(resolved)` here,
|
|
|
|
// `ValueTyDefId` is just a convenient way to pass generics and
|
|
|
|
// special-case enum variants
|
|
|
|
resolved: ValueTyDefId,
|
2020-05-29 17:14:04 +00:00
|
|
|
infer_args: bool,
|
2021-03-15 20:02:34 +00:00
|
|
|
) -> Substitution {
|
2023-03-08 17:28:52 +00:00
|
|
|
let last = path.segments().last();
|
2022-10-03 15:07:34 +00:00
|
|
|
let (segment, generic_def) = match resolved {
|
|
|
|
ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
|
|
|
|
ValueTyDefId::StructId(it) => (last, Some(it.into())),
|
|
|
|
ValueTyDefId::UnionId(it) => (last, Some(it.into())),
|
|
|
|
ValueTyDefId::ConstId(it) => (last, Some(it.into())),
|
|
|
|
ValueTyDefId::StaticId(_) => (last, None),
|
|
|
|
ValueTyDefId::EnumVariantId(var) => {
|
2019-02-23 21:59:01 +00:00
|
|
|
// the generic args for an enum variant may be either specified
|
|
|
|
// on the segment referring to the enum, or on the segment
|
|
|
|
// referring to the variant. So `Option::<T>::None` and
|
|
|
|
// `Option::None::<T>` are both allowed (though the former is
|
|
|
|
// preferred). See also `def_ids_for_path_segments` in rustc.
|
2019-12-13 11:12:36 +00:00
|
|
|
let len = path.segments().len();
|
2021-12-09 17:28:10 +00:00
|
|
|
let penultimate = len.checked_sub(2).and_then(|idx| path.segments().get(idx));
|
2022-10-03 15:07:34 +00:00
|
|
|
let segment = match penultimate {
|
2023-03-08 17:28:52 +00:00
|
|
|
Some(segment) if segment.args_and_bindings.is_some() => Some(segment),
|
2019-12-13 11:12:36 +00:00
|
|
|
_ => last,
|
2022-10-03 15:07:34 +00:00
|
|
|
};
|
2024-01-15 09:24:14 +00:00
|
|
|
(segment, Some(var.lookup(self.db.upcast()).parent.into()))
|
2019-02-23 21:59:01 +00:00
|
|
|
}
|
|
|
|
};
|
2023-03-08 17:28:52 +00:00
|
|
|
if let Some(segment) = segment {
|
|
|
|
self.substs_from_path_segment(segment, generic_def, infer_args, None)
|
|
|
|
} else if let Some(generic_def) = generic_def {
|
|
|
|
// lang item
|
|
|
|
self.substs_from_args_and_bindings(None, Some(generic_def), infer_args, None)
|
|
|
|
} else {
|
|
|
|
Substitution::empty(Interner)
|
|
|
|
}
|
2019-02-23 21:59:01 +00:00
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
|
2023-11-26 12:46:02 +00:00
|
|
|
pub(super) fn substs_from_path_segment(
|
2021-03-13 21:44:36 +00:00
|
|
|
&self,
|
|
|
|
segment: PathSegment<'_>,
|
2022-10-02 13:15:57 +00:00
|
|
|
def: Option<GenericDefId>,
|
2021-03-13 21:44:36 +00:00
|
|
|
infer_args: bool,
|
2021-03-22 18:13:43 +00:00
|
|
|
explicit_self_ty: Option<Ty>,
|
2023-03-08 17:28:52 +00:00
|
|
|
) -> Substitution {
|
|
|
|
self.substs_from_args_and_bindings(
|
|
|
|
segment.args_and_bindings,
|
|
|
|
def,
|
|
|
|
infer_args,
|
|
|
|
explicit_self_ty,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn substs_from_args_and_bindings(
|
|
|
|
&self,
|
|
|
|
args_and_bindings: Option<&GenericArgs>,
|
|
|
|
def: Option<GenericDefId>,
|
|
|
|
infer_args: bool,
|
|
|
|
explicit_self_ty: Option<Ty>,
|
2021-03-15 20:02:34 +00:00
|
|
|
) -> Substitution {
|
2022-10-02 13:15:57 +00:00
|
|
|
// Remember that the item's own generic args come before its parent's.
|
2021-03-13 21:44:36 +00:00
|
|
|
let mut substs = Vec::new();
|
2022-10-02 13:15:57 +00:00
|
|
|
let def = if let Some(d) = def {
|
|
|
|
d
|
2022-03-09 18:50:24 +00:00
|
|
|
} else {
|
|
|
|
return Substitution::empty(Interner);
|
|
|
|
};
|
2022-10-02 13:15:57 +00:00
|
|
|
let def_generics = generics(self.db.upcast(), def);
|
2024-03-08 12:35:44 +00:00
|
|
|
let (
|
|
|
|
parent_params,
|
|
|
|
self_params,
|
|
|
|
type_params,
|
|
|
|
const_params,
|
|
|
|
impl_trait_params,
|
|
|
|
lifetime_params,
|
|
|
|
) = def_generics.provenance_split();
|
|
|
|
let item_len =
|
|
|
|
self_params + type_params + const_params + impl_trait_params + lifetime_params;
|
2022-10-02 13:15:57 +00:00
|
|
|
let total_len = parent_params + item_len;
|
2020-05-29 17:14:04 +00:00
|
|
|
|
2022-10-02 09:39:42 +00:00
|
|
|
let ty_error = TyKind::Error.intern(Interner).cast(Interner);
|
2022-03-09 18:50:24 +00:00
|
|
|
|
2024-03-08 19:38:35 +00:00
|
|
|
let mut def_generic_iter = def_generics.iter_id();
|
2022-04-21 21:05:28 +00:00
|
|
|
|
2021-03-22 18:13:43 +00:00
|
|
|
let fill_self_params = || {
|
2022-04-21 21:05:28 +00:00
|
|
|
for x in explicit_self_ty
|
|
|
|
.into_iter()
|
2022-10-02 09:39:42 +00:00
|
|
|
.map(|x| x.cast(Interner))
|
2022-04-21 21:05:28 +00:00
|
|
|
.chain(iter::repeat(ty_error.clone()))
|
|
|
|
.take(self_params)
|
|
|
|
{
|
|
|
|
if let Some(id) = def_generic_iter.next() {
|
2024-03-08 12:35:44 +00:00
|
|
|
assert!(matches!(
|
|
|
|
id,
|
|
|
|
GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_)
|
|
|
|
));
|
2022-04-21 21:05:28 +00:00
|
|
|
substs.push(x);
|
|
|
|
}
|
|
|
|
}
|
2021-03-22 18:13:43 +00:00
|
|
|
};
|
2022-03-09 18:50:24 +00:00
|
|
|
let mut had_explicit_args = false;
|
2020-05-29 17:14:04 +00:00
|
|
|
|
2023-03-08 17:28:52 +00:00
|
|
|
if let Some(generic_args) = &args_and_bindings {
|
2021-03-13 21:44:36 +00:00
|
|
|
if !generic_args.has_self_type {
|
2021-03-22 18:13:43 +00:00
|
|
|
fill_self_params();
|
2021-03-13 21:44:36 +00:00
|
|
|
}
|
2022-03-09 18:50:24 +00:00
|
|
|
let expected_num = if generic_args.has_self_type {
|
2024-03-18 10:18:59 +00:00
|
|
|
self_params + type_params + const_params
|
2022-03-09 18:50:24 +00:00
|
|
|
} else {
|
2024-03-18 10:18:59 +00:00
|
|
|
type_params + const_params
|
2022-03-09 18:50:24 +00:00
|
|
|
};
|
2021-03-13 21:44:36 +00:00
|
|
|
let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
|
|
|
|
// if args are provided, it should be all of them, but we can't rely on that
|
2024-03-10 20:36:47 +00:00
|
|
|
for arg in generic_args
|
|
|
|
.args
|
|
|
|
.iter()
|
|
|
|
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
|
|
|
|
.skip(skip)
|
|
|
|
.take(expected_num)
|
|
|
|
{
|
2022-04-21 21:05:28 +00:00
|
|
|
if let Some(id) = def_generic_iter.next() {
|
|
|
|
if let Some(x) = generic_arg_to_chalk(
|
|
|
|
self.db,
|
|
|
|
id,
|
|
|
|
arg,
|
|
|
|
&mut (),
|
|
|
|
|_, type_ref| self.lower_ty(type_ref),
|
2023-06-30 13:31:04 +00:00
|
|
|
|_, const_ref, ty| self.lower_const(const_ref, ty),
|
2024-03-08 12:35:44 +00:00
|
|
|
|_, lifetime_ref| self.lower_lifetime(lifetime_ref),
|
2022-04-21 21:05:28 +00:00
|
|
|
) {
|
|
|
|
had_explicit_args = true;
|
|
|
|
substs.push(x);
|
|
|
|
} else {
|
2022-04-22 14:52:18 +00:00
|
|
|
// we just filtered them out
|
|
|
|
never!("Unexpected lifetime argument");
|
2022-04-21 21:05:28 +00:00
|
|
|
}
|
2019-03-26 22:07:26 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-10 20:36:47 +00:00
|
|
|
|
|
|
|
for arg in generic_args
|
|
|
|
.args
|
|
|
|
.iter()
|
|
|
|
.filter(|arg| matches!(arg, GenericArg::Lifetime(_)))
|
2024-03-18 10:18:59 +00:00
|
|
|
.take(lifetime_params)
|
2024-03-10 20:36:47 +00:00
|
|
|
{
|
|
|
|
// Taking into the fact that def_generic_iter will always have lifetimes at the end
|
|
|
|
// Should have some test cases tho to test this behaviour more properly
|
|
|
|
if let Some(id) = def_generic_iter.next() {
|
|
|
|
if let Some(x) = generic_arg_to_chalk(
|
|
|
|
self.db,
|
|
|
|
id,
|
|
|
|
arg,
|
|
|
|
&mut (),
|
|
|
|
|_, type_ref| self.lower_ty(type_ref),
|
|
|
|
|_, const_ref, ty| self.lower_const(const_ref, ty),
|
|
|
|
|_, lifetime_ref| self.lower_lifetime(lifetime_ref),
|
|
|
|
) {
|
|
|
|
had_explicit_args = true;
|
2024-03-11 04:33:40 +00:00
|
|
|
substs.push(x);
|
2024-03-10 20:36:47 +00:00
|
|
|
} else {
|
2024-03-11 04:33:40 +00:00
|
|
|
// Never return a None explicitly
|
|
|
|
never!("Unexpected None by generic_arg_to_chalk");
|
2024-03-10 20:36:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-22 18:13:43 +00:00
|
|
|
} else {
|
|
|
|
fill_self_params();
|
2019-03-26 22:07:26 +00:00
|
|
|
}
|
2019-05-19 13:08:16 +00:00
|
|
|
|
2022-10-02 13:15:57 +00:00
|
|
|
// These params include those of parent.
|
|
|
|
let remaining_params: SmallVec<[_; 2]> = def_generic_iter
|
2024-03-08 12:35:44 +00:00
|
|
|
.map(|id| match id {
|
|
|
|
GenericParamId::ConstParamId(x) => {
|
|
|
|
unknown_const_as_generic(self.db.const_param_ty(x))
|
|
|
|
}
|
|
|
|
GenericParamId::TypeParamId(_) => ty_error.clone(),
|
|
|
|
GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
|
2022-10-02 13:15:57 +00:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
assert_eq!(remaining_params.len() + substs.len(), total_len);
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
// handle defaults. In expression or pattern path segments without
|
|
|
|
// explicitly specified type arguments, missing type arguments are inferred
|
|
|
|
// (i.e. defaults aren't used).
|
2022-10-27 08:11:16 +00:00
|
|
|
// Generic parameters for associated types are not supposed to have defaults, so we just
|
|
|
|
// ignore them.
|
|
|
|
let is_assoc_ty = if let GenericDefId::TypeAliasId(id) = def {
|
|
|
|
let container = id.lookup(self.db.upcast()).container;
|
|
|
|
matches!(container, ItemContainerId::TraitId(_))
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
if !is_assoc_ty && (!infer_args || had_explicit_args) {
|
2022-10-02 13:15:57 +00:00
|
|
|
let defaults = self.db.generic_defaults(def);
|
|
|
|
assert_eq!(total_len, defaults.len());
|
|
|
|
let parent_from = item_len - substs.len();
|
|
|
|
|
|
|
|
for (idx, default_ty) in defaults[substs.len()..item_len].iter().enumerate() {
|
|
|
|
// each default can depend on the previous parameters
|
|
|
|
let substs_so_far = Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
substs.iter().cloned().chain(remaining_params[idx..].iter().cloned()),
|
|
|
|
);
|
|
|
|
substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
|
2019-05-19 13:08:16 +00:00
|
|
|
}
|
|
|
|
|
2022-10-02 13:15:57 +00:00
|
|
|
// Keep parent's params as unknown.
|
|
|
|
let mut remaining_params = remaining_params;
|
|
|
|
substs.extend(remaining_params.drain(parent_from..));
|
|
|
|
} else {
|
|
|
|
substs.extend(remaining_params);
|
2021-03-13 21:44:36 +00:00
|
|
|
}
|
2020-05-29 17:14:04 +00:00
|
|
|
|
2022-10-02 13:15:57 +00:00
|
|
|
assert_eq!(substs.len(), total_len);
|
2021-12-19 16:58:39 +00:00
|
|
|
Substitution::from_iter(Interner, substs)
|
2021-03-13 21:44:36 +00:00
|
|
|
}
|
2019-03-26 22:07:26 +00:00
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
fn lower_trait_ref_from_path(
|
|
|
|
&self,
|
2019-05-05 12:21:00 +00:00
|
|
|
path: &Path,
|
2019-03-31 18:02:16 +00:00
|
|
|
explicit_self_ty: Option<Ty>,
|
2021-03-13 21:44:36 +00:00
|
|
|
) -> Option<TraitRef> {
|
2023-03-08 17:28:52 +00:00
|
|
|
let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? {
|
|
|
|
// FIXME(trait_alias): We need to handle trait alias here.
|
|
|
|
TypeNs::TraitId(tr) => tr,
|
|
|
|
_ => return None,
|
|
|
|
};
|
2019-12-13 11:12:36 +00:00
|
|
|
let segment = path.segments().last().expect("path should have at least one segment");
|
2021-03-13 21:44:36 +00:00
|
|
|
Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty))
|
2019-08-05 20:42:38 +00:00
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
pub(crate) fn lower_trait_ref_from_resolved_path(
|
|
|
|
&self,
|
2019-11-27 13:48:48 +00:00
|
|
|
resolved: TraitId,
|
2019-12-13 11:12:36 +00:00
|
|
|
segment: PathSegment<'_>,
|
2019-08-05 20:42:38 +00:00
|
|
|
explicit_self_ty: Option<Ty>,
|
2021-03-13 21:44:36 +00:00
|
|
|
) -> TraitRef {
|
2021-03-22 18:13:43 +00:00
|
|
|
let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty);
|
2021-03-18 20:53:19 +00:00
|
|
|
TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
|
2019-03-26 22:07:26 +00:00
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
fn lower_trait_ref(
|
|
|
|
&self,
|
2021-03-24 16:00:29 +00:00
|
|
|
trait_ref: &HirTraitRef,
|
2019-05-05 12:21:00 +00:00
|
|
|
explicit_self_ty: Option<Ty>,
|
2021-03-13 21:44:36 +00:00
|
|
|
) -> Option<TraitRef> {
|
2021-03-29 16:39:58 +00:00
|
|
|
self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty)
|
2019-05-05 12:21:00 +00:00
|
|
|
}
|
|
|
|
|
2021-03-15 20:02:34 +00:00
|
|
|
fn trait_ref_substs_from_path(
|
|
|
|
&self,
|
|
|
|
segment: PathSegment<'_>,
|
|
|
|
resolved: TraitId,
|
2021-03-22 18:13:43 +00:00
|
|
|
explicit_self_ty: Option<Ty>,
|
2021-03-15 20:02:34 +00:00
|
|
|
) -> Substitution {
|
2021-03-22 18:13:43 +00:00
|
|
|
self.substs_from_path_segment(segment, Some(resolved.into()), false, explicit_self_ty)
|
2019-03-26 22:07:26 +00:00
|
|
|
}
|
2019-08-13 21:09:08 +00:00
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
pub(crate) fn lower_where_predicate(
|
2023-06-29 14:27:28 +00:00
|
|
|
&self,
|
|
|
|
where_predicate: &WherePredicate,
|
2021-03-20 19:07:36 +00:00
|
|
|
ignore_bindings: bool,
|
2023-06-29 14:27:28 +00:00
|
|
|
) -> impl Iterator<Item = QuantifiedWhereClause> {
|
2020-12-11 12:49:32 +00:00
|
|
|
match where_predicate {
|
2020-12-17 21:01:42 +00:00
|
|
|
WherePredicate::ForLifetime { target, bound, .. }
|
|
|
|
| WherePredicate::TypeBound { target, bound } => {
|
2020-12-11 12:49:32 +00:00
|
|
|
let self_ty = match target {
|
2021-03-13 21:44:36 +00:00
|
|
|
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref),
|
2021-12-29 13:35:59 +00:00
|
|
|
WherePredicateTypeTarget::TypeOrConstParam(param_id) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let generic_def = self.resolver.generic_def().expect("generics in scope");
|
|
|
|
let generics = generics(self.db.upcast(), generic_def);
|
2021-12-29 13:35:59 +00:00
|
|
|
let param_id = hir_def::TypeOrConstParamId {
|
|
|
|
parent: generic_def,
|
|
|
|
local_id: *param_id,
|
|
|
|
};
|
2021-03-13 21:44:36 +00:00
|
|
|
let placeholder = to_placeholder_idx(self.db, param_id);
|
|
|
|
match self.type_param_mode {
|
2022-03-09 18:50:24 +00:00
|
|
|
ParamLoweringMode::Placeholder => TyKind::Placeholder(placeholder),
|
|
|
|
ParamLoweringMode::Variable => {
|
2020-12-11 12:49:32 +00:00
|
|
|
let idx = generics.param_idx(param_id).expect("matching generics");
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
|
2020-12-11 12:49:32 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2020-01-31 14:57:44 +00:00
|
|
|
}
|
2020-12-11 12:49:32 +00:00
|
|
|
};
|
2021-03-20 19:07:36 +00:00
|
|
|
self.lower_type_bound(bound, self_ty, ignore_bindings)
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.into_iter()
|
2020-01-31 14:57:44 +00:00
|
|
|
}
|
2020-12-11 12:49:32 +00:00
|
|
|
WherePredicate::Lifetime { .. } => vec![].into_iter(),
|
|
|
|
}
|
2019-08-13 21:09:08 +00:00
|
|
|
}
|
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
pub(crate) fn lower_type_bound(
|
|
|
|
&'a self,
|
2024-03-06 12:16:41 +00:00
|
|
|
bound: &'a Interned<TypeBound>,
|
2019-08-13 21:09:08 +00:00
|
|
|
self_ty: Ty,
|
2021-03-20 19:07:36 +00:00
|
|
|
ignore_bindings: bool,
|
2021-03-21 12:22:22 +00:00
|
|
|
) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
|
2021-02-20 17:51:42 +00:00
|
|
|
let mut bindings = None;
|
2024-03-06 12:16:41 +00:00
|
|
|
let trait_ref = match bound.as_ref() {
|
2021-06-06 18:41:15 +00:00
|
|
|
TypeBound::Path(path, TraitBoundModifier::None) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
|
2022-04-08 12:29:43 +00:00
|
|
|
bindings
|
|
|
|
.clone()
|
|
|
|
.filter(|tr| {
|
|
|
|
// ignore `T: Drop` or `T: Destruct` bounds.
|
|
|
|
// - `T: ~const Drop` has a special meaning in Rust 1.61 that we don't implement.
|
|
|
|
// (So ideally, we'd only ignore `~const Drop` here)
|
2023-04-07 07:34:04 +00:00
|
|
|
// - `Destruct` impls are built-in in 1.62 (current nightly as of 08-04-2022), so until
|
2022-04-08 12:29:43 +00:00
|
|
|
// the builtin impls are supported by Chalk, we ignore them here.
|
2023-07-07 11:37:29 +00:00
|
|
|
if let Some(lang) = self.db.lang_attr(tr.hir_trait_id().into()) {
|
2023-02-03 11:16:25 +00:00
|
|
|
if matches!(lang, LangItem::Drop | LangItem::Destruct) {
|
2022-04-08 12:29:43 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
|
|
|
})
|
|
|
|
.map(WhereClause::Implemented)
|
|
|
|
.map(crate::wrap_empty_binders)
|
2021-02-20 17:51:42 +00:00
|
|
|
}
|
2021-06-06 18:41:15 +00:00
|
|
|
TypeBound::Path(path, TraitBoundModifier::Maybe) => {
|
|
|
|
let sized_trait = self
|
2022-03-31 09:12:08 +00:00
|
|
|
.db
|
2023-01-21 16:29:07 +00:00
|
|
|
.lang_item(self.resolver.krate(), LangItem::Sized)
|
2021-06-06 18:41:15 +00:00
|
|
|
.and_then(|lang_item| lang_item.as_trait());
|
|
|
|
// Don't lower associated type bindings as the only possible relaxed trait bound
|
2021-06-12 16:47:07 +00:00
|
|
|
// `?Sized` has no of them.
|
2021-06-06 18:41:15 +00:00
|
|
|
// If we got another trait here ignore the bound completely.
|
|
|
|
let trait_id = self
|
|
|
|
.lower_trait_ref_from_path(path, Some(self_ty.clone()))
|
|
|
|
.map(|trait_ref| trait_ref.hir_trait_id());
|
|
|
|
if trait_id == sized_trait {
|
|
|
|
self.unsized_types.borrow_mut().insert(self_ty);
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
2021-06-29 23:34:51 +00:00
|
|
|
TypeBound::ForLifetime(_, path) => {
|
|
|
|
// FIXME Don't silently drop the hrtb lifetimes here
|
|
|
|
bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
|
|
|
|
bindings.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
|
|
|
|
}
|
2021-02-20 17:51:42 +00:00
|
|
|
TypeBound::Lifetime(_) => None,
|
2021-03-20 09:51:00 +00:00
|
|
|
TypeBound::Error => None,
|
2021-02-20 17:51:42 +00:00
|
|
|
};
|
|
|
|
trait_ref.into_iter().chain(
|
|
|
|
bindings
|
|
|
|
.into_iter()
|
2021-03-20 19:07:36 +00:00
|
|
|
.filter(move |_| !ignore_bindings)
|
2021-03-13 21:44:36 +00:00
|
|
|
.flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)),
|
2021-02-20 17:51:42 +00:00
|
|
|
)
|
2019-05-05 12:21:00 +00:00
|
|
|
}
|
2019-03-26 22:07:26 +00:00
|
|
|
|
2021-03-13 21:44:36 +00:00
|
|
|
fn assoc_type_bindings_from_type_bound(
|
|
|
|
&'a self,
|
2024-03-06 12:16:41 +00:00
|
|
|
bound: &'a Interned<TypeBound>,
|
2021-03-13 21:44:36 +00:00
|
|
|
trait_ref: TraitRef,
|
2021-03-21 12:22:22 +00:00
|
|
|
) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
|
2024-03-06 12:16:41 +00:00
|
|
|
let last_segment = match bound.as_ref() {
|
2021-08-03 12:01:00 +00:00
|
|
|
TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => {
|
|
|
|
path.segments().last()
|
|
|
|
}
|
2021-06-06 18:41:15 +00:00
|
|
|
TypeBound::Path(_, TraitBoundModifier::Maybe)
|
|
|
|
| TypeBound::Error
|
|
|
|
| TypeBound::Lifetime(_) => None,
|
2021-03-13 21:44:36 +00:00
|
|
|
};
|
|
|
|
last_segment
|
|
|
|
.into_iter()
|
2021-12-09 17:28:10 +00:00
|
|
|
.filter_map(|segment| segment.args_and_bindings)
|
2023-02-14 16:24:40 +00:00
|
|
|
.flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
|
2021-03-13 21:44:36 +00:00
|
|
|
.flat_map(move |binding| {
|
|
|
|
let found = associated_type_by_name_including_super_traits(
|
|
|
|
self.db,
|
|
|
|
trait_ref.clone(),
|
|
|
|
&binding.name,
|
|
|
|
);
|
|
|
|
let (super_trait_ref, associated_ty) = match found {
|
2021-12-09 17:28:10 +00:00
|
|
|
None => return SmallVec::new(),
|
2021-03-13 21:44:36 +00:00
|
|
|
Some(t) => t,
|
|
|
|
};
|
2022-10-27 08:11:16 +00:00
|
|
|
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
|
|
|
|
// generic params. It's inefficient to splice the `Substitution`s, so we may want
|
|
|
|
// that method to optionally take parent `Substitution` as we already know them at
|
|
|
|
// this point (`super_trait_ref.substitution`).
|
|
|
|
let substitution = self.substs_from_path_segment(
|
|
|
|
// FIXME: This is hack. We shouldn't really build `PathSegment` directly.
|
|
|
|
PathSegment { name: &binding.name, args_and_bindings: binding.args.as_deref() },
|
|
|
|
Some(associated_ty.into()),
|
|
|
|
false, // this is not relevant
|
|
|
|
Some(super_trait_ref.self_type_parameter(Interner)),
|
|
|
|
);
|
|
|
|
let self_params = generics(self.db.upcast(), associated_ty.into()).len_self();
|
|
|
|
let substitution = Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
substitution
|
|
|
|
.iter(Interner)
|
|
|
|
.take(self_params)
|
|
|
|
.chain(super_trait_ref.substitution.iter(Interner)),
|
|
|
|
);
|
2021-03-13 21:44:36 +00:00
|
|
|
let projection_ty = ProjectionTy {
|
2021-03-14 15:26:12 +00:00
|
|
|
associated_ty_id: to_assoc_type_id(associated_ty),
|
2022-10-27 08:11:16 +00:00
|
|
|
substitution,
|
2021-03-13 21:44:36 +00:00
|
|
|
};
|
2023-04-07 07:34:04 +00:00
|
|
|
let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity(
|
2021-03-13 21:44:36 +00:00
|
|
|
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
|
|
|
|
);
|
|
|
|
if let Some(type_ref) = &binding.type_ref {
|
2024-03-13 16:59:27 +00:00
|
|
|
if let (
|
|
|
|
TypeRef::ImplTrait(bounds),
|
|
|
|
ImplTraitLoweringState::Param(_)
|
|
|
|
| ImplTraitLoweringState::Variable(_)
|
|
|
|
| ImplTraitLoweringState::Disallowed,
|
|
|
|
) = (type_ref, &self.impl_trait_mode)
|
2023-11-02 14:37:50 +00:00
|
|
|
{
|
|
|
|
for bound in bounds {
|
|
|
|
predicates.extend(
|
|
|
|
self.lower_type_bound(
|
|
|
|
bound,
|
|
|
|
TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
|
|
|
|
.intern(Interner),
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
2024-03-06 12:16:41 +00:00
|
|
|
let ty = 'ty: {
|
|
|
|
if matches!(
|
|
|
|
self.impl_trait_mode,
|
|
|
|
ImplTraitLoweringState::Param(_)
|
|
|
|
| ImplTraitLoweringState::Variable(_)
|
|
|
|
) {
|
|
|
|
// Find the generic index for the target of our `bound`
|
|
|
|
let target_param_idx = self
|
|
|
|
.resolver
|
|
|
|
.where_predicates_in_scope()
|
|
|
|
.find_map(|p| match p {
|
|
|
|
WherePredicate::TypeBound {
|
|
|
|
target: WherePredicateTypeTarget::TypeOrConstParam(idx),
|
|
|
|
bound: b,
|
|
|
|
} if b == bound => Some(idx),
|
|
|
|
_ => None,
|
|
|
|
});
|
|
|
|
if let Some(target_param_idx) = target_param_idx {
|
|
|
|
let mut counter = 0;
|
|
|
|
for (idx, data) in self.generics().params.type_or_consts.iter()
|
|
|
|
{
|
|
|
|
// Count the number of `impl Trait` things that appear before
|
|
|
|
// the target of our `bound`.
|
|
|
|
// Our counter within `impl_trait_mode` should be that number
|
|
|
|
// to properly lower each types within `type_ref`
|
|
|
|
if data.type_param().is_some_and(|p| {
|
|
|
|
p.provenance == TypeParamProvenance::ArgumentImplTrait
|
|
|
|
}) {
|
|
|
|
counter += 1;
|
|
|
|
}
|
|
|
|
if idx == *target_param_idx {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let mut ext = TyLoweringContext::new_maybe_unowned(
|
|
|
|
self.db,
|
|
|
|
self.resolver,
|
|
|
|
self.owner,
|
|
|
|
)
|
|
|
|
.with_type_param_mode(self.type_param_mode);
|
|
|
|
match &self.impl_trait_mode {
|
|
|
|
ImplTraitLoweringState::Param(_) => {
|
|
|
|
ext.impl_trait_mode =
|
|
|
|
ImplTraitLoweringState::Param(Cell::new(counter));
|
|
|
|
}
|
|
|
|
ImplTraitLoweringState::Variable(_) => {
|
|
|
|
ext.impl_trait_mode = ImplTraitLoweringState::Variable(
|
|
|
|
Cell::new(counter),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
break 'ty ext.lower_ty(type_ref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.lower_ty(type_ref)
|
|
|
|
};
|
2023-11-02 14:37:50 +00:00
|
|
|
let alias_eq =
|
|
|
|
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
|
|
|
|
predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
|
|
|
|
}
|
2021-03-13 21:44:36 +00:00
|
|
|
}
|
2023-02-14 16:18:46 +00:00
|
|
|
for bound in binding.bounds.iter() {
|
2023-04-07 07:34:04 +00:00
|
|
|
predicates.extend(self.lower_type_bound(
|
2021-03-13 21:44:36 +00:00
|
|
|
bound,
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(Interner),
|
2021-03-20 19:07:36 +00:00
|
|
|
false,
|
2021-03-13 21:44:36 +00:00
|
|
|
));
|
|
|
|
}
|
2023-04-07 07:34:04 +00:00
|
|
|
predicates
|
2021-03-13 21:44:36 +00:00
|
|
|
})
|
|
|
|
}
|
2019-08-23 15:19:37 +00:00
|
|
|
|
2022-08-17 16:30:04 +00:00
|
|
|
fn lower_dyn_trait(&self, bounds: &[Interned<TypeBound>]) -> Ty {
|
|
|
|
let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
|
2022-09-19 19:20:43 +00:00
|
|
|
// INVARIANT: The principal trait bound, if present, must come first. Others may be in any
|
|
|
|
// order but should be in the same order for the same set but possibly different order of
|
|
|
|
// bounds in the input.
|
|
|
|
// INVARIANT: If this function returns `DynTy`, there should be at least one trait bound.
|
|
|
|
// These invariants are utilized by `TyExt::dyn_trait()` and chalk.
|
2022-08-17 16:30:04 +00:00
|
|
|
let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
|
2022-09-05 09:35:50 +00:00
|
|
|
let mut bounds: Vec<_> = bounds
|
|
|
|
.iter()
|
|
|
|
.flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false))
|
|
|
|
.collect();
|
2022-07-18 10:49:14 +00:00
|
|
|
|
2022-09-05 09:35:50 +00:00
|
|
|
let mut multiple_regular_traits = false;
|
|
|
|
let mut multiple_same_projection = false;
|
|
|
|
bounds.sort_unstable_by(|lhs, rhs| {
|
|
|
|
use std::cmp::Ordering;
|
|
|
|
match (lhs.skip_binders(), rhs.skip_binders()) {
|
|
|
|
(WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => {
|
|
|
|
let lhs_id = lhs.trait_id;
|
|
|
|
let lhs_is_auto = ctx.db.trait_data(from_chalk_trait_id(lhs_id)).is_auto;
|
|
|
|
let rhs_id = rhs.trait_id;
|
|
|
|
let rhs_is_auto = ctx.db.trait_data(from_chalk_trait_id(rhs_id)).is_auto;
|
|
|
|
|
|
|
|
if !lhs_is_auto && !rhs_is_auto {
|
|
|
|
multiple_regular_traits = true;
|
|
|
|
}
|
|
|
|
// Note that the ordering here is important; this ensures the invariant
|
|
|
|
// mentioned above.
|
|
|
|
(lhs_is_auto, lhs_id).cmp(&(rhs_is_auto, rhs_id))
|
2022-07-18 10:49:14 +00:00
|
|
|
}
|
2022-09-05 09:35:50 +00:00
|
|
|
(WhereClause::Implemented(_), _) => Ordering::Less,
|
|
|
|
(_, WhereClause::Implemented(_)) => Ordering::Greater,
|
|
|
|
(WhereClause::AliasEq(lhs), WhereClause::AliasEq(rhs)) => {
|
|
|
|
match (&lhs.alias, &rhs.alias) {
|
|
|
|
(AliasTy::Projection(lhs_proj), AliasTy::Projection(rhs_proj)) => {
|
|
|
|
// We only compare the `associated_ty_id`s. We shouldn't have
|
|
|
|
// multiple bounds for an associated type in the correct Rust code,
|
|
|
|
// and if we do, we error out.
|
|
|
|
if lhs_proj.associated_ty_id == rhs_proj.associated_ty_id {
|
|
|
|
multiple_same_projection = true;
|
|
|
|
}
|
|
|
|
lhs_proj.associated_ty_id.cmp(&rhs_proj.associated_ty_id)
|
|
|
|
}
|
|
|
|
// We don't produce `AliasTy::Opaque`s yet.
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We don't produce `WhereClause::{TypeOutlives, LifetimeOutlives}` yet.
|
|
|
|
_ => unreachable!(),
|
2022-07-18 10:49:14 +00:00
|
|
|
}
|
2022-09-05 09:35:50 +00:00
|
|
|
});
|
2022-07-18 10:49:14 +00:00
|
|
|
|
2022-09-05 09:35:50 +00:00
|
|
|
if multiple_regular_traits || multiple_same_projection {
|
2022-07-18 10:49:14 +00:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2024-01-18 12:59:49 +00:00
|
|
|
bounds.first().and_then(|b| b.trait_id())?;
|
2022-09-19 19:20:43 +00:00
|
|
|
|
2023-04-07 07:34:04 +00:00
|
|
|
// As multiple occurrences of the same auto traits *are* permitted, we deduplicate the
|
2022-09-05 09:35:50 +00:00
|
|
|
// bounds. We shouldn't have repeated elements besides auto traits at this point.
|
|
|
|
bounds.dedup();
|
2022-07-18 10:49:14 +00:00
|
|
|
|
2022-09-05 09:35:50 +00:00
|
|
|
Some(QuantifiedWhereClauses::from_iter(Interner, bounds))
|
2022-08-17 16:30:04 +00:00
|
|
|
});
|
2022-07-18 10:49:14 +00:00
|
|
|
|
|
|
|
if let Some(bounds) = bounds {
|
|
|
|
let bounds = crate::make_single_type_binders(bounds);
|
|
|
|
TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
|
|
|
|
} else {
|
2022-09-19 19:20:43 +00:00
|
|
|
// FIXME: report error
|
|
|
|
// (additional non-auto traits, associated type rebound, or no resolved trait)
|
2022-07-18 10:49:14 +00:00
|
|
|
TyKind::Error.intern(Interner)
|
|
|
|
}
|
2022-08-17 16:30:04 +00:00
|
|
|
}
|
|
|
|
|
2024-03-15 18:31:12 +00:00
|
|
|
fn lower_impl_trait(&self, bounds: &[Interned<TypeBound>], krate: CrateId) -> ImplTrait {
|
2021-03-08 20:19:44 +00:00
|
|
|
cov_mark::hit!(lower_rpit);
|
2021-12-19 16:58:39 +00:00
|
|
|
let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
|
2021-03-13 21:44:36 +00:00
|
|
|
let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
|
2021-06-15 08:53:20 +00:00
|
|
|
let mut predicates: Vec<_> = bounds
|
|
|
|
.iter()
|
|
|
|
.flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
if !ctx.unsized_types.borrow().contains(&self_ty) {
|
|
|
|
let sized_trait = ctx
|
|
|
|
.db
|
2023-01-21 16:29:07 +00:00
|
|
|
.lang_item(krate, LangItem::Sized)
|
2021-06-15 08:53:20 +00:00
|
|
|
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
|
|
|
|
let sized_clause = sized_trait.map(|trait_id| {
|
|
|
|
let clause = WhereClause::Implemented(TraitRef {
|
|
|
|
trait_id,
|
2021-12-19 16:58:39 +00:00
|
|
|
substitution: Substitution::from1(Interner, self_ty.clone()),
|
2021-06-15 08:53:20 +00:00
|
|
|
});
|
|
|
|
crate::wrap_empty_binders(clause)
|
|
|
|
});
|
2024-01-18 12:59:49 +00:00
|
|
|
predicates.extend(sized_clause);
|
2021-06-15 08:53:20 +00:00
|
|
|
predicates.shrink_to_fit();
|
|
|
|
}
|
|
|
|
predicates
|
2020-03-04 22:00:44 +00:00
|
|
|
});
|
2024-03-15 18:31:12 +00:00
|
|
|
ImplTrait { bounds: crate::make_single_type_binders(predicates) }
|
2020-03-04 22:00:44 +00:00
|
|
|
}
|
2024-03-06 11:09:24 +00:00
|
|
|
|
2024-03-19 04:44:45 +00:00
|
|
|
pub fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime {
|
2024-03-06 11:09:24 +00:00
|
|
|
match self.resolver.resolve_lifetime(lifetime) {
|
|
|
|
Some(resolution) => match resolution {
|
|
|
|
LifetimeNs::Static => static_lifetime(),
|
|
|
|
LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
|
|
|
|
ParamLoweringMode::Placeholder => {
|
|
|
|
LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id))
|
|
|
|
}
|
|
|
|
ParamLoweringMode::Variable => {
|
|
|
|
let generics = generics(
|
|
|
|
self.db.upcast(),
|
|
|
|
self.resolver.generic_def().expect("generics in scope"),
|
|
|
|
);
|
|
|
|
let idx = match generics.lifetime_idx(id) {
|
2024-03-06 17:45:04 +00:00
|
|
|
None => return error_lifetime(),
|
2024-03-06 11:09:24 +00:00
|
|
|
Some(idx) => idx,
|
|
|
|
};
|
|
|
|
|
|
|
|
LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.intern(Interner),
|
|
|
|
},
|
2024-03-06 17:45:04 +00:00
|
|
|
None => error_lifetime(),
|
2024-03-06 11:09:24 +00:00
|
|
|
}
|
|
|
|
}
|
2020-03-04 22:00:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn count_impl_traits(type_ref: &TypeRef) -> usize {
|
|
|
|
let mut count = 0;
|
|
|
|
type_ref.walk(&mut |type_ref| {
|
|
|
|
if matches!(type_ref, TypeRef::ImplTrait(_)) {
|
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
count
|
|
|
|
}
|
|
|
|
|
2019-03-16 16:29:55 +00:00
|
|
|
/// Build the signature of a callable item (function, struct or enum variant).
|
2022-07-21 08:17:57 +00:00
|
|
|
pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
|
2019-03-16 16:29:55 +00:00
|
|
|
match def {
|
2020-07-16 11:15:00 +00:00
|
|
|
CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
|
|
|
|
CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
|
|
|
|
CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
|
2019-03-16 16:29:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-29 22:03:36 +00:00
|
|
|
pub fn associated_type_shorthand_candidates<R>(
|
2020-04-27 22:40:32 +00:00
|
|
|
db: &dyn HirDatabase,
|
2022-02-03 11:43:15 +00:00
|
|
|
def: GenericDefId,
|
2020-04-27 22:40:32 +00:00
|
|
|
res: TypeNs,
|
2022-12-07 14:22:37 +00:00
|
|
|
mut cb: impl FnMut(&Name, TypeAliasId) -> Option<R>,
|
2021-10-04 15:39:55 +00:00
|
|
|
) -> Option<R> {
|
2022-12-07 14:22:37 +00:00
|
|
|
named_associated_type_shorthand_candidates(db, def, res, None, |name, _, id| cb(name, id))
|
2021-10-04 15:39:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn named_associated_type_shorthand_candidates<R>(
|
|
|
|
db: &dyn HirDatabase,
|
2022-02-03 11:43:15 +00:00
|
|
|
// If the type parameter is defined in an impl and we're in a method, there
|
|
|
|
// might be additional where clauses to consider
|
|
|
|
def: GenericDefId,
|
2021-10-04 15:39:55 +00:00
|
|
|
res: TypeNs,
|
|
|
|
assoc_name: Option<Name>,
|
2022-12-07 14:22:37 +00:00
|
|
|
// Do NOT let `cb` touch `TraitRef` outside of `TyLoweringContext`. Its substitution contains
|
|
|
|
// free `BoundVar`s that need to be shifted and only `TyLoweringContext` knows how to do that
|
|
|
|
// properly (see `TyLoweringContext::select_associated_type()`).
|
2020-04-27 22:40:32 +00:00
|
|
|
mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
|
|
|
|
) -> Option<R> {
|
2021-04-02 00:09:12 +00:00
|
|
|
let mut search = |t| {
|
2023-02-10 13:34:58 +00:00
|
|
|
all_super_trait_refs(db, t, |t| {
|
2021-04-02 00:09:12 +00:00
|
|
|
let data = db.trait_data(t.hir_trait_id());
|
|
|
|
|
|
|
|
for (name, assoc_id) in &data.items {
|
|
|
|
if let AssocItemId::TypeAliasId(alias) = assoc_id {
|
|
|
|
if let Some(result) = cb(name, &t, *alias) {
|
|
|
|
return Some(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-10 13:34:58 +00:00
|
|
|
None
|
|
|
|
})
|
2021-04-02 00:09:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
match res {
|
2022-10-04 15:20:01 +00:00
|
|
|
TypeNs::SelfType(impl_id) => {
|
2021-04-05 17:15:13 +00:00
|
|
|
// we're _in_ the impl -- the binders get added back later. Correct,
|
|
|
|
// but it would be nice to make this more explicit
|
2022-10-04 15:20:01 +00:00
|
|
|
let trait_ref = db.impl_trait(impl_id)?.into_value_and_skipped_binders().0;
|
|
|
|
|
|
|
|
let impl_id_as_generic_def: GenericDefId = impl_id.into();
|
|
|
|
if impl_id_as_generic_def != def {
|
|
|
|
// `trait_ref` contains `BoundVar`s bound by impl's `Binders`, but here we need
|
|
|
|
// `BoundVar`s from `def`'s point of view.
|
|
|
|
// FIXME: A `HirDatabase` query may be handy if this process is needed in more
|
|
|
|
// places. It'd be almost identical as `impl_trait_query` where `resolver` would be
|
|
|
|
// of `def` instead of `impl_id`.
|
|
|
|
let starting_idx = generics(db.upcast(), def).len_self();
|
|
|
|
let subst = TyBuilder::subst_for_def(db, impl_id, None)
|
|
|
|
.fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx)
|
|
|
|
.build();
|
|
|
|
let trait_ref = subst.apply(trait_ref, Interner);
|
|
|
|
search(trait_ref)
|
|
|
|
} else {
|
|
|
|
search(trait_ref)
|
|
|
|
}
|
|
|
|
}
|
2020-04-27 22:40:32 +00:00
|
|
|
TypeNs::GenericParam(param_id) => {
|
2021-12-29 13:35:59 +00:00
|
|
|
let predicates = db.generic_predicates_for_param(def, param_id.into(), assoc_name);
|
2021-04-05 15:13:50 +00:00
|
|
|
let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() {
|
2021-04-02 00:09:12 +00:00
|
|
|
// FIXME: how to correctly handle higher-ranked bounds here?
|
2021-04-05 17:15:13 +00:00
|
|
|
WhereClause::Implemented(tr) => search(
|
|
|
|
tr.clone()
|
2021-12-19 16:58:39 +00:00
|
|
|
.shifted_out_to(Interner, DebruijnIndex::ONE)
|
2021-04-05 17:15:13 +00:00
|
|
|
.expect("FIXME unexpected higher-ranked trait bound"),
|
|
|
|
),
|
2021-04-02 00:09:12 +00:00
|
|
|
_ => None,
|
|
|
|
});
|
2024-01-19 15:51:08 +00:00
|
|
|
if res.is_some() {
|
2021-04-02 00:09:12 +00:00
|
|
|
return res;
|
|
|
|
}
|
2020-04-27 22:40:32 +00:00
|
|
|
// Handle `Self::Type` referring to own associated type in trait definitions
|
2022-03-04 09:00:53 +00:00
|
|
|
if let GenericDefId::TraitId(trait_id) = param_id.parent() {
|
2022-10-02 13:15:57 +00:00
|
|
|
let trait_generics = generics(db.upcast(), trait_id.into());
|
|
|
|
if trait_generics.params.type_or_consts[param_id.local_id()].is_trait_self() {
|
|
|
|
let def_generics = generics(db.upcast(), def);
|
|
|
|
let starting_idx = match def {
|
|
|
|
GenericDefId::TraitId(_) => 0,
|
|
|
|
// `def` is an item within trait. We need to substitute `BoundVar`s but
|
|
|
|
// remember that they are for parent (i.e. trait) generic params so they
|
|
|
|
// come after our own params.
|
|
|
|
_ => def_generics.len_self(),
|
|
|
|
};
|
2021-04-03 20:45:31 +00:00
|
|
|
let trait_ref = TyBuilder::trait_ref(db, trait_id)
|
2022-10-02 13:15:57 +00:00
|
|
|
.fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx)
|
2021-04-03 20:45:31 +00:00
|
|
|
.build();
|
2021-04-02 00:09:12 +00:00
|
|
|
return search(trait_ref);
|
2020-04-27 22:40:32 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-02 00:09:12 +00:00
|
|
|
None
|
2020-04-27 22:40:32 +00:00
|
|
|
}
|
2021-04-02 00:09:12 +00:00
|
|
|
_ => None,
|
2020-04-27 22:40:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-24 20:48:39 +00:00
|
|
|
/// Build the type of all specific fields of a struct or enum variant.
|
|
|
|
pub(crate) fn field_types_query(
|
2020-03-13 15:05:46 +00:00
|
|
|
db: &dyn HirDatabase,
|
2019-11-24 20:48:39 +00:00
|
|
|
variant_id: VariantId,
|
2020-04-25 12:23:34 +00:00
|
|
|
) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> {
|
2021-04-06 15:59:18 +00:00
|
|
|
let var_data = variant_id.variant_data(db.upcast());
|
2020-01-31 15:52:43 +00:00
|
|
|
let (resolver, def): (_, GenericDefId) = match variant_id {
|
2020-03-13 15:05:46 +00:00
|
|
|
VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
|
|
|
|
VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()),
|
2024-01-15 09:24:14 +00:00
|
|
|
VariantId::EnumVariantId(it) => {
|
|
|
|
(it.resolver(db.upcast()), it.lookup(db.upcast()).parent.into())
|
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
};
|
2020-03-13 15:05:46 +00:00
|
|
|
let generics = generics(db.upcast(), def);
|
2019-11-24 20:48:39 +00:00
|
|
|
let mut res = ArenaMap::default();
|
2024-01-15 09:24:14 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
2023-06-05 11:27:19 +00:00
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2019-11-24 20:48:39 +00:00
|
|
|
for (field_id, field_data) in var_data.fields().iter() {
|
2022-08-06 20:48:52 +00:00
|
|
|
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref)));
|
2019-11-24 20:48:39 +00:00
|
|
|
}
|
|
|
|
Arc::new(res)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2019-09-22 18:01:12 +00:00
|
|
|
/// This query exists only to be used when resolving short-hand associated types
|
|
|
|
/// like `T::Item`.
|
|
|
|
///
|
|
|
|
/// See the analogous query in rustc and its comment:
|
2021-06-14 04:57:10 +00:00
|
|
|
/// <https://github.com/rust-lang/rust/blob/9150f844e2624eb013ec78ca08c1d416e6644026/src/librustc_typeck/astconv.rs#L46>
|
2019-09-22 18:01:12 +00:00
|
|
|
/// This is a query mostly to handle cycles somewhat gracefully; e.g. the
|
|
|
|
/// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but
|
|
|
|
/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
|
|
|
|
pub(crate) fn generic_predicates_for_param_query(
|
2020-03-13 15:05:46 +00:00
|
|
|
db: &dyn HirDatabase,
|
2022-02-03 11:43:15 +00:00
|
|
|
def: GenericDefId,
|
2021-12-29 13:35:59 +00:00
|
|
|
param_id: TypeOrConstParamId,
|
2021-10-04 15:39:55 +00:00
|
|
|
assoc_name: Option<Name>,
|
2021-03-21 16:40:14 +00:00
|
|
|
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
2022-02-03 11:43:15 +00:00
|
|
|
let resolver = def.resolver(db.upcast());
|
2024-03-06 12:16:41 +00:00
|
|
|
let ctx = if let GenericDefId::FunctionId(_) = def {
|
|
|
|
TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Variable)
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable)
|
|
|
|
} else {
|
|
|
|
TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable)
|
|
|
|
};
|
2022-02-03 11:43:15 +00:00
|
|
|
let generics = generics(db.upcast(), def);
|
2021-10-04 15:39:55 +00:00
|
|
|
|
2023-11-14 09:08:19 +00:00
|
|
|
// we have to filter out all other predicates *first*, before attempting to lower them
|
|
|
|
let predicate = |pred: &&_| match pred {
|
|
|
|
WherePredicate::ForLifetime { target, bound, .. }
|
|
|
|
| WherePredicate::TypeBound { target, bound, .. } => {
|
|
|
|
let invalid_target = match target {
|
|
|
|
WherePredicateTypeTarget::TypeRef(type_ref) => {
|
|
|
|
ctx.lower_ty_only_param(type_ref) != Some(param_id)
|
|
|
|
}
|
|
|
|
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
|
|
|
|
let target_id = TypeOrConstParamId { parent: def, local_id };
|
|
|
|
target_id != param_id
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if invalid_target {
|
|
|
|
return false;
|
|
|
|
}
|
2021-10-04 15:39:55 +00:00
|
|
|
|
2023-11-14 09:08:19 +00:00
|
|
|
match &**bound {
|
|
|
|
TypeBound::ForLifetime(_, path) | TypeBound::Path(path, _) => {
|
|
|
|
// Only lower the bound if the trait could possibly define the associated
|
|
|
|
// type we're looking for.
|
|
|
|
|
|
|
|
let Some(assoc_name) = &assoc_name else { return true };
|
|
|
|
let Some(TypeNs::TraitId(tr)) =
|
|
|
|
resolver.resolve_path_in_type_ns_fully(db.upcast(), path)
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
};
|
2021-10-04 15:39:55 +00:00
|
|
|
|
2023-11-14 09:08:19 +00:00
|
|
|
all_super_traits(db.upcast(), tr).iter().any(|tr| {
|
|
|
|
db.trait_data(*tr).items.iter().any(|(name, item)| {
|
|
|
|
matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
|
2021-10-04 15:39:55 +00:00
|
|
|
})
|
2023-11-14 09:08:19 +00:00
|
|
|
})
|
2020-12-17 21:01:42 +00:00
|
|
|
}
|
2023-11-14 09:08:19 +00:00
|
|
|
TypeBound::Lifetime(_) | TypeBound::Error => false,
|
2021-10-04 15:39:55 +00:00
|
|
|
}
|
2023-11-14 09:08:19 +00:00
|
|
|
}
|
|
|
|
WherePredicate::Lifetime { .. } => false,
|
|
|
|
};
|
|
|
|
let mut predicates: Vec<_> = resolver
|
|
|
|
.where_predicates_in_scope()
|
|
|
|
.filter(predicate)
|
2022-03-09 18:50:24 +00:00
|
|
|
.flat_map(|pred| {
|
|
|
|
ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p))
|
|
|
|
})
|
2021-09-07 07:36:15 +00:00
|
|
|
.collect();
|
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
2021-09-07 07:36:15 +00:00
|
|
|
let explicitly_unsized_tys = ctx.unsized_types.into_inner();
|
|
|
|
let implicitly_sized_predicates =
|
|
|
|
implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &subst, &resolver)
|
2022-03-09 18:50:24 +00:00
|
|
|
.map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p)));
|
2021-09-07 07:36:15 +00:00
|
|
|
predicates.extend(implicitly_sized_predicates);
|
|
|
|
predicates.into()
|
2019-09-22 18:01:12 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 11:39:21 +00:00
|
|
|
pub(crate) fn generic_predicates_for_param_recover(
|
2020-03-13 15:05:46 +00:00
|
|
|
_db: &dyn HirDatabase,
|
2023-12-07 09:57:51 +00:00
|
|
|
_cycle: &Cycle,
|
2022-02-03 11:43:15 +00:00
|
|
|
_def: &GenericDefId,
|
2021-12-29 13:35:59 +00:00
|
|
|
_param_id: &TypeOrConstParamId,
|
2021-10-04 15:39:55 +00:00
|
|
|
_assoc_name: &Option<Name>,
|
2021-03-21 16:40:14 +00:00
|
|
|
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
2023-11-28 15:36:01 +00:00
|
|
|
Arc::from_iter(None)
|
2019-11-30 11:39:21 +00:00
|
|
|
}
|
|
|
|
|
2023-03-08 17:28:52 +00:00
|
|
|
pub(crate) fn trait_environment_for_body_query(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: DefWithBodyId,
|
|
|
|
) -> Arc<TraitEnvironment> {
|
|
|
|
let Some(def) = def.as_generic_def_id() else {
|
|
|
|
let krate = def.module(db.upcast()).krate();
|
2023-12-08 09:47:36 +00:00
|
|
|
return TraitEnvironment::empty(krate);
|
2023-03-08 17:28:52 +00:00
|
|
|
};
|
|
|
|
db.trait_environment(def)
|
|
|
|
}
|
|
|
|
|
2021-03-13 19:38:11 +00:00
|
|
|
pub(crate) fn trait_environment_query(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: GenericDefId,
|
|
|
|
) -> Arc<TraitEnvironment> {
|
|
|
|
let resolver = def.resolver(db.upcast());
|
2024-03-06 12:16:41 +00:00
|
|
|
let ctx = if let GenericDefId::FunctionId(_) = def {
|
|
|
|
TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Param)
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Placeholder)
|
|
|
|
} else {
|
|
|
|
TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Placeholder)
|
|
|
|
};
|
2021-03-13 19:38:11 +00:00
|
|
|
let mut traits_in_scope = Vec::new();
|
|
|
|
let mut clauses = Vec::new();
|
|
|
|
for pred in resolver.where_predicates_in_scope() {
|
2021-03-20 19:07:36 +00:00
|
|
|
for pred in ctx.lower_where_predicate(pred, false) {
|
2021-03-21 12:22:22 +00:00
|
|
|
if let WhereClause::Implemented(tr) = &pred.skip_binders() {
|
2021-12-19 16:58:39 +00:00
|
|
|
traits_in_scope.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
|
2020-02-14 18:16:42 +00:00
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(Interner);
|
|
|
|
clauses.push(program_clause.into_from_env_clause(Interner));
|
2020-02-14 18:16:42 +00:00
|
|
|
}
|
2021-03-13 19:38:11 +00:00
|
|
|
}
|
2020-02-14 18:16:42 +00:00
|
|
|
|
2021-12-07 16:31:26 +00:00
|
|
|
let container: Option<ItemContainerId> = match def {
|
2021-03-13 19:38:11 +00:00
|
|
|
// FIXME: is there a function for this?
|
|
|
|
GenericDefId::FunctionId(f) => Some(f.lookup(db.upcast()).container),
|
|
|
|
GenericDefId::AdtId(_) => None,
|
|
|
|
GenericDefId::TraitId(_) => None,
|
2023-03-03 15:24:07 +00:00
|
|
|
GenericDefId::TraitAliasId(_) => None,
|
2021-03-13 19:38:11 +00:00
|
|
|
GenericDefId::TypeAliasId(t) => Some(t.lookup(db.upcast()).container),
|
|
|
|
GenericDefId::ImplId(_) => None,
|
|
|
|
GenericDefId::EnumVariantId(_) => None,
|
|
|
|
GenericDefId::ConstId(c) => Some(c.lookup(db.upcast()).container),
|
|
|
|
};
|
2021-12-07 16:31:26 +00:00
|
|
|
if let Some(ItemContainerId::TraitId(trait_id)) = container {
|
2021-03-13 19:38:11 +00:00
|
|
|
// add `Self: Trait<T1, T2, ...>` to the environment in trait
|
2021-05-24 19:21:25 +00:00
|
|
|
// function default implementations (and speculative code
|
2021-03-13 19:38:11 +00:00
|
|
|
// inside consts or type aliases)
|
|
|
|
cov_mark::hit!(trait_self_implements_self);
|
2022-03-09 18:50:24 +00:00
|
|
|
let substs = TyBuilder::placeholder_subst(db, trait_id);
|
2021-03-18 20:53:19 +00:00
|
|
|
let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
|
2021-03-20 09:46:36 +00:00
|
|
|
let pred = WhereClause::Implemented(trait_ref);
|
2021-12-19 16:58:39 +00:00
|
|
|
let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(Interner);
|
|
|
|
clauses.push(program_clause.into_from_env_clause(Interner));
|
2019-11-25 10:10:26 +00:00
|
|
|
}
|
2021-03-13 19:38:11 +00:00
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
let subst = generics(db.upcast(), def).placeholder_subst(db);
|
2021-06-10 11:57:58 +00:00
|
|
|
let explicitly_unsized_tys = ctx.unsized_types.into_inner();
|
|
|
|
let implicitly_sized_clauses =
|
|
|
|
implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver).map(|pred| {
|
2021-12-19 16:58:39 +00:00
|
|
|
let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(Interner);
|
|
|
|
program_clause.into_from_env_clause(Interner)
|
2021-06-10 11:57:58 +00:00
|
|
|
});
|
|
|
|
clauses.extend(implicitly_sized_clauses);
|
|
|
|
|
2021-05-16 13:50:28 +00:00
|
|
|
let krate = def.module(db.upcast()).krate();
|
|
|
|
|
2021-12-19 16:58:39 +00:00
|
|
|
let env = chalk_ir::Environment::new(Interner).add_clauses(Interner, clauses);
|
2021-03-13 19:38:11 +00:00
|
|
|
|
2023-12-08 09:47:36 +00:00
|
|
|
TraitEnvironment::new(krate, None, traits_in_scope.into_boxed_slice(), env)
|
2019-06-29 17:14:52 +00:00
|
|
|
}
|
|
|
|
|
2019-05-05 12:21:00 +00:00
|
|
|
/// Resolve the where clause(s) of an item with generics.
|
2019-07-06 14:41:04 +00:00
|
|
|
pub(crate) fn generic_predicates_query(
|
2020-03-13 15:05:46 +00:00
|
|
|
db: &dyn HirDatabase,
|
2019-11-25 12:39:12 +00:00
|
|
|
def: GenericDefId,
|
2021-03-21 16:40:14 +00:00
|
|
|
) -> Arc<[Binders<QuantifiedWhereClause>]> {
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = def.resolver(db.upcast());
|
2024-03-06 12:16:41 +00:00
|
|
|
let ctx = if let GenericDefId::FunctionId(_) = def {
|
|
|
|
TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Variable)
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable)
|
|
|
|
} else {
|
|
|
|
TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable)
|
|
|
|
};
|
2020-03-13 15:05:46 +00:00
|
|
|
let generics = generics(db.upcast(), def);
|
2021-06-06 18:41:15 +00:00
|
|
|
|
|
|
|
let mut predicates = resolver
|
2019-07-06 14:41:04 +00:00
|
|
|
.where_predicates_in_scope()
|
2022-03-09 18:50:24 +00:00
|
|
|
.flat_map(|pred| {
|
|
|
|
ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p))
|
|
|
|
})
|
2021-06-06 18:41:15 +00:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
2021-06-06 18:41:15 +00:00
|
|
|
let explicitly_unsized_tys = ctx.unsized_types.into_inner();
|
2021-06-10 11:57:58 +00:00
|
|
|
let implicitly_sized_predicates =
|
|
|
|
implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
|
2022-03-09 18:50:24 +00:00
|
|
|
.map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p)));
|
2021-06-10 11:57:58 +00:00
|
|
|
predicates.extend(implicitly_sized_predicates);
|
|
|
|
predicates.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
|
|
|
|
/// Exception is Self of a trait def.
|
|
|
|
fn implicitly_sized_clauses<'a>(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: GenericDefId,
|
|
|
|
explicitly_unsized_tys: &'a FxHashSet<Ty>,
|
|
|
|
substitution: &'a Substitution,
|
|
|
|
resolver: &Resolver,
|
|
|
|
) -> impl Iterator<Item = WhereClause> + 'a {
|
|
|
|
let is_trait_def = matches!(def, GenericDefId::TraitId(..));
|
2021-12-19 16:58:39 +00:00
|
|
|
let generic_args = &substitution.as_slice(Interner)[is_trait_def as usize..];
|
2022-03-31 09:12:08 +00:00
|
|
|
let sized_trait = db
|
2023-01-21 16:29:07 +00:00
|
|
|
.lang_item(resolver.krate(), LangItem::Sized)
|
2021-06-06 18:41:15 +00:00
|
|
|
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
|
2021-06-10 11:57:58 +00:00
|
|
|
|
|
|
|
sized_trait.into_iter().flat_map(move |sized_trait| {
|
|
|
|
let implicitly_sized_tys = generic_args
|
|
|
|
.iter()
|
2021-12-19 16:58:39 +00:00
|
|
|
.filter_map(|generic_arg| generic_arg.ty(Interner))
|
2021-06-10 11:57:58 +00:00
|
|
|
.filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty));
|
|
|
|
implicitly_sized_tys.map(move |self_ty| {
|
|
|
|
WhereClause::Implemented(TraitRef {
|
|
|
|
trait_id: sized_trait,
|
2021-12-19 16:58:39 +00:00
|
|
|
substitution: Substitution::from1(Interner, self_ty.clone()),
|
2021-06-06 18:41:15 +00:00
|
|
|
})
|
|
|
|
})
|
2021-06-10 11:57:58 +00:00
|
|
|
})
|
2019-05-05 12:21:00 +00:00
|
|
|
}
|
|
|
|
|
2019-05-19 13:08:16 +00:00
|
|
|
/// Resolve the default type params from generics
|
2020-06-26 14:36:59 +00:00
|
|
|
pub(crate) fn generic_defaults_query(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: GenericDefId,
|
2024-01-09 19:43:17 +00:00
|
|
|
) -> Arc<[Binders<crate::GenericArg>]> {
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = def.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2020-03-13 15:05:46 +00:00
|
|
|
let generic_params = generics(db.upcast(), def);
|
2022-10-02 13:15:57 +00:00
|
|
|
let parent_start_idx = generic_params.len_self();
|
2019-05-19 13:08:16 +00:00
|
|
|
|
2024-03-08 19:38:35 +00:00
|
|
|
let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| {
|
2023-11-28 15:36:01 +00:00
|
|
|
match p {
|
2024-03-19 07:27:18 +00:00
|
|
|
GenericParamDataRef::TypeParamData(p) => {
|
2023-11-28 15:36:01 +00:00
|
|
|
let mut ty =
|
|
|
|
p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
|
|
|
|
// Each default can only refer to previous parameters.
|
|
|
|
// Type variable default referring to parameter coming
|
|
|
|
// after it is forbidden (FIXME: report diagnostic)
|
|
|
|
ty = fallback_bound_vars(ty, idx, parent_start_idx);
|
|
|
|
crate::make_binders(db, &generic_params, ty.cast(Interner))
|
|
|
|
}
|
2024-03-19 07:27:18 +00:00
|
|
|
GenericParamDataRef::ConstParamData(p) => {
|
2024-03-08 19:38:35 +00:00
|
|
|
let GenericParamId::ConstParamId(id) = id else {
|
|
|
|
unreachable!("Unexpected lifetime or type argument")
|
|
|
|
};
|
|
|
|
|
2023-11-28 15:36:01 +00:00
|
|
|
let mut val = p.default.as_ref().map_or_else(
|
2024-03-11 18:35:37 +00:00
|
|
|
|| unknown_const_as_generic(db.const_param_ty(id)),
|
2023-11-28 15:36:01 +00:00
|
|
|
|c| {
|
|
|
|
let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
|
|
|
|
c.cast(Interner)
|
|
|
|
},
|
|
|
|
);
|
|
|
|
// Each default can only refer to previous parameters, see above.
|
|
|
|
val = fallback_bound_vars(val, idx, parent_start_idx);
|
|
|
|
make_binders(db, &generic_params, val)
|
|
|
|
}
|
2024-03-19 07:27:18 +00:00
|
|
|
GenericParamDataRef::LifetimeParamData(_) => {
|
2024-03-08 19:38:35 +00:00
|
|
|
// using static because it requires defaults
|
|
|
|
make_binders(db, &generic_params, static_lifetime().cast(Interner))
|
|
|
|
}
|
2023-11-28 15:36:01 +00:00
|
|
|
}
|
2024-03-08 19:38:35 +00:00
|
|
|
}));
|
2021-04-29 18:00:43 +00:00
|
|
|
|
|
|
|
defaults
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn generic_defaults_recover(
|
|
|
|
db: &dyn HirDatabase,
|
2023-12-07 09:57:51 +00:00
|
|
|
_cycle: &Cycle,
|
2021-04-29 18:00:43 +00:00
|
|
|
def: &GenericDefId,
|
2022-03-09 18:50:24 +00:00
|
|
|
) -> Arc<[Binders<crate::GenericArg>]> {
|
2021-04-29 18:00:43 +00:00
|
|
|
let generic_params = generics(db.upcast(), *def);
|
2022-03-09 18:50:24 +00:00
|
|
|
// FIXME: this code is not covered in tests.
|
2021-04-29 18:00:43 +00:00
|
|
|
// we still need one default per parameter
|
2023-11-28 15:36:01 +00:00
|
|
|
let defaults = Arc::from_iter(generic_params.iter_id().map(|id| {
|
|
|
|
let val = match id {
|
2024-03-08 19:38:35 +00:00
|
|
|
GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
|
|
|
|
GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
|
|
|
|
GenericParamId::LifetimeParamId(_) => static_lifetime().cast(Interner),
|
2023-11-28 15:36:01 +00:00
|
|
|
};
|
|
|
|
crate::make_binders(db, &generic_params, val)
|
|
|
|
}));
|
2019-05-19 13:08:16 +00:00
|
|
|
|
2020-06-26 14:36:59 +00:00
|
|
|
defaults
|
2019-05-19 13:08:16 +00:00
|
|
|
}
|
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
|
2019-11-25 13:16:41 +00:00
|
|
|
let data = db.function_data(def);
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = def.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx_params = TyLoweringContext::new(db, &resolver, def.into())
|
2020-01-25 22:38:33 +00:00
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Variable)
|
2022-03-09 18:50:24 +00:00
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2023-04-06 18:14:51 +00:00
|
|
|
let params = data.params.iter().map(|tr| ctx_params.lower_ty(tr)).collect::<Vec<_>>();
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx_ret = TyLoweringContext::new(db, &resolver, def.into())
|
2020-03-04 22:00:44 +00:00
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
|
2022-03-09 18:50:24 +00:00
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2021-04-05 15:45:18 +00:00
|
|
|
let ret = ctx_ret.lower_ty(&data.ret_type);
|
2020-03-13 15:05:46 +00:00
|
|
|
let generics = generics(db.upcast(), def.into());
|
2022-11-04 20:07:15 +00:00
|
|
|
let sig = CallableSig::from_params_and_return(
|
|
|
|
params,
|
|
|
|
ret,
|
|
|
|
data.is_varargs(),
|
|
|
|
if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe },
|
2024-01-17 17:23:14 +00:00
|
|
|
data.abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str),
|
2022-11-04 20:07:15 +00:00
|
|
|
);
|
2022-03-09 18:50:24 +00:00
|
|
|
make_binders(db, &generics, sig)
|
2019-03-16 16:21:32 +00:00
|
|
|
}
|
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
/// Build the declared type of a function. This should not need to look at the
|
|
|
|
/// function body.
|
2020-03-13 15:05:46 +00:00
|
|
|
fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
|
|
|
|
let generics = generics(db.upcast(), def.into());
|
2022-03-09 18:50:24 +00:00
|
|
|
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
2021-04-05 15:45:18 +00:00
|
|
|
make_binders(
|
2022-03-09 18:50:24 +00:00
|
|
|
db,
|
2021-04-05 15:45:18 +00:00
|
|
|
&generics,
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(Interner),
|
2021-03-13 16:55:50 +00:00
|
|
|
)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2019-02-25 07:27:47 +00:00
|
|
|
/// Build the declared type of a const.
|
2020-03-13 15:05:46 +00:00
|
|
|
fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> {
|
2019-11-26 18:04:24 +00:00
|
|
|
let data = db.const_data(def);
|
2020-03-13 15:05:46 +00:00
|
|
|
let generics = generics(db.upcast(), def.into());
|
|
|
|
let resolver = def.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2019-02-25 07:27:47 +00:00
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
make_binders(db, &generics, ctx.lower_ty(&data.type_ref))
|
2019-02-25 07:27:47 +00:00
|
|
|
}
|
|
|
|
|
2019-02-25 08:21:01 +00:00
|
|
|
/// Build the declared type of a static.
|
2020-03-13 15:05:46 +00:00
|
|
|
fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders<Ty> {
|
2019-11-26 18:04:24 +00:00
|
|
|
let data = db.static_data(def);
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = def.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, def.into());
|
2019-02-25 08:21:01 +00:00
|
|
|
|
2021-12-19 16:58:39 +00:00
|
|
|
Binders::empty(Interner, ctx.lower_ty(&data.type_ref))
|
2019-02-25 08:21:01 +00:00
|
|
|
}
|
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig {
|
2020-02-18 12:53:02 +00:00
|
|
|
let struct_data = db.struct_data(def);
|
2019-11-24 19:44:24 +00:00
|
|
|
let fields = struct_data.variant_data.fields();
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = def.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, AdtId::from(def).into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2021-03-13 21:44:36 +00:00
|
|
|
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
|
2021-04-05 15:13:50 +00:00
|
|
|
let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders();
|
2024-01-17 17:23:14 +00:00
|
|
|
Binders::new(
|
|
|
|
binders,
|
|
|
|
CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall),
|
|
|
|
)
|
2019-03-16 16:21:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Build the type of a tuple struct constructor.
|
2024-01-16 11:09:40 +00:00
|
|
|
fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option<Binders<Ty>> {
|
2020-02-18 12:53:02 +00:00
|
|
|
let struct_data = db.struct_data(def);
|
2024-01-15 11:03:31 +00:00
|
|
|
match struct_data.variant_data.kind() {
|
2024-01-16 11:09:40 +00:00
|
|
|
StructKind::Record => None,
|
|
|
|
StructKind::Unit => Some(type_for_adt(db, def.into())),
|
2024-01-15 11:03:31 +00:00
|
|
|
StructKind::Tuple => {
|
|
|
|
let generics = generics(db.upcast(), AdtId::from(def).into());
|
|
|
|
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
2024-01-16 11:09:40 +00:00
|
|
|
Some(make_binders(
|
2024-01-15 11:03:31 +00:00
|
|
|
db,
|
|
|
|
&generics,
|
|
|
|
TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(Interner),
|
2024-01-16 11:09:40 +00:00
|
|
|
))
|
2024-01-15 11:03:31 +00:00
|
|
|
}
|
2019-03-16 16:21:32 +00:00
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
|
2024-01-15 09:24:14 +00:00
|
|
|
let var_data = db.enum_variant_data(def);
|
2019-11-25 13:16:41 +00:00
|
|
|
let fields = var_data.variant_data.fields();
|
2024-01-15 09:24:14 +00:00
|
|
|
let resolver = def.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2021-03-13 21:44:36 +00:00
|
|
|
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
|
2024-01-15 09:24:14 +00:00
|
|
|
let (ret, binders) =
|
|
|
|
type_for_adt(db, def.lookup(db.upcast()).parent.into()).into_value_and_skipped_binders();
|
2024-01-17 17:23:14 +00:00
|
|
|
Binders::new(
|
|
|
|
binders,
|
|
|
|
CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall),
|
|
|
|
)
|
2019-03-16 16:21:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Build the type of a tuple enum variant constructor.
|
2024-01-16 11:09:40 +00:00
|
|
|
fn type_for_enum_variant_constructor(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: EnumVariantId,
|
|
|
|
) -> Option<Binders<Ty>> {
|
2024-01-15 09:24:14 +00:00
|
|
|
let e = def.lookup(db.upcast()).parent;
|
2024-01-15 11:03:31 +00:00
|
|
|
match db.enum_variant_data(def).variant_data.kind() {
|
2024-01-16 11:09:40 +00:00
|
|
|
StructKind::Record => None,
|
|
|
|
StructKind::Unit => Some(type_for_adt(db, e.into())),
|
2024-01-15 11:03:31 +00:00
|
|
|
StructKind::Tuple => {
|
|
|
|
let generics = generics(db.upcast(), e.into());
|
|
|
|
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
2024-01-16 11:09:40 +00:00
|
|
|
Some(make_binders(
|
2024-01-15 11:03:31 +00:00
|
|
|
db,
|
|
|
|
&generics,
|
|
|
|
TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs)
|
|
|
|
.intern(Interner),
|
2024-01-16 11:09:40 +00:00
|
|
|
))
|
2024-01-15 11:03:31 +00:00
|
|
|
}
|
2019-03-16 16:21:32 +00:00
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
|
2021-04-05 15:45:18 +00:00
|
|
|
let generics = generics(db.upcast(), adt.into());
|
2022-03-09 18:50:24 +00:00
|
|
|
let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
|
|
|
let ty = TyKind::Adt(crate::AdtId(adt), subst).intern(Interner);
|
|
|
|
make_binders(db, &generics, ty)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
|
|
|
|
let generics = generics(db.upcast(), t.into());
|
|
|
|
let resolver = t.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, t.into())
|
2024-03-15 18:31:12 +00:00
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
|
2023-06-05 11:27:19 +00:00
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2023-12-14 13:11:12 +00:00
|
|
|
let type_alias_data = db.type_alias_data(t);
|
|
|
|
if type_alias_data.is_extern {
|
2021-12-19 16:58:39 +00:00
|
|
|
Binders::empty(Interner, TyKind::Foreign(crate::to_foreign_def_id(t)).intern(Interner))
|
2020-09-16 12:57:14 +00:00
|
|
|
} else {
|
2023-12-14 13:11:12 +00:00
|
|
|
let type_ref = &type_alias_data.type_ref;
|
2021-04-01 17:46:43 +00:00
|
|
|
let inner = ctx.lower_ty(type_ref.as_deref().unwrap_or(&TypeRef::Error));
|
2022-03-09 18:50:24 +00:00
|
|
|
make_binders(db, &generics, inner)
|
2020-09-16 16:50:24 +00:00
|
|
|
}
|
2019-02-24 16:25:41 +00:00
|
|
|
}
|
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
2020-07-16 11:15:00 +00:00
|
|
|
pub enum CallableDefId {
|
2019-11-25 13:26:52 +00:00
|
|
|
FunctionId(FunctionId),
|
|
|
|
StructId(StructId),
|
|
|
|
EnumVariantId(EnumVariantId),
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2024-02-10 14:36:26 +00:00
|
|
|
impl_intern_value_trivial!(CallableDefId);
|
2020-07-16 11:15:00 +00:00
|
|
|
impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId);
|
2023-01-14 12:27:32 +00:00
|
|
|
impl From<CallableDefId> for ModuleDefId {
|
|
|
|
fn from(def: CallableDefId) -> ModuleDefId {
|
|
|
|
match def {
|
|
|
|
CallableDefId::FunctionId(f) => ModuleDefId::FunctionId(f),
|
|
|
|
CallableDefId::StructId(s) => ModuleDefId::AdtId(AdtId::StructId(s)),
|
|
|
|
CallableDefId::EnumVariantId(e) => ModuleDefId::EnumVariantId(e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-07-06 15:43:13 +00:00
|
|
|
|
2020-07-16 11:15:00 +00:00
|
|
|
impl CallableDefId {
|
2020-03-13 15:05:46 +00:00
|
|
|
pub fn krate(self, db: &dyn HirDatabase) -> CrateId {
|
|
|
|
let db = db.upcast();
|
2019-09-26 19:37:03 +00:00
|
|
|
match self {
|
2024-02-10 10:37:59 +00:00
|
|
|
CallableDefId::FunctionId(f) => f.krate(db),
|
|
|
|
CallableDefId::StructId(s) => s.krate(db),
|
|
|
|
CallableDefId::EnumVariantId(e) => e.krate(db),
|
2019-09-26 19:37:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-16 11:15:00 +00:00
|
|
|
impl From<CallableDefId> for GenericDefId {
|
|
|
|
fn from(def: CallableDefId) -> GenericDefId {
|
2019-07-06 15:43:13 +00:00
|
|
|
match def {
|
2020-07-16 11:15:00 +00:00
|
|
|
CallableDefId::FunctionId(f) => f.into(),
|
|
|
|
CallableDefId::StructId(s) => s.into(),
|
|
|
|
CallableDefId::EnumVariantId(e) => e.into(),
|
2019-07-06 15:43:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-26 18:04:24 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub enum TyDefId {
|
|
|
|
BuiltinType(BuiltinType),
|
|
|
|
AdtId(AdtId),
|
|
|
|
TypeAliasId(TypeAliasId),
|
|
|
|
}
|
2020-07-13 14:16:53 +00:00
|
|
|
impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId);
|
2019-11-26 18:04:24 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub enum ValueTyDefId {
|
|
|
|
FunctionId(FunctionId),
|
|
|
|
StructId(StructId),
|
2020-08-07 13:24:20 +00:00
|
|
|
UnionId(UnionId),
|
2019-11-26 18:04:24 +00:00
|
|
|
EnumVariantId(EnumVariantId),
|
|
|
|
ConstId(ConstId),
|
|
|
|
StaticId(StaticId),
|
|
|
|
}
|
2020-08-07 13:24:20 +00:00
|
|
|
impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
|
2019-11-26 18:04:24 +00:00
|
|
|
|
Change generic parameter/argument order
This commit "inverts" the order of generic parameters/arguments of an
item and its parent. This is to fulfill chalk's expectation on the
order of `Substitution` for generic associated types and it's one step
forward for their support (hopefully).
Although chalk doesn't put any constraint on the order of `Substitution`
for other items, it feels natural to get everything aligned rather than
special casing GATs.
One complication is that `TyBuilder` now demands its users to pass in
parent's `Substitution` upon construction unless it's obvious that the
the item has no parent (e.g. an ADT never has parent). All users
*should* already know the parent of the item in question, and without
this, it cannot be easily reasoned about whether we're pushing the
argument for the item or for its parent.
Quick comparison of how this commit changes `Substitution`:
```rust
trait Trait<TP, const CP: usize> {
type Type<TC, const CC: usize> = ();
fn f<TC, const CC: usize>() {}
}
```
- before this commit: `[Self, TP, CP, TC, CC]` for each trait item
- after this commit: `[TC, CC, Self, TP, CP]` for each trait item
2022-10-02 12:13:21 +00:00
|
|
|
impl ValueTyDefId {
|
|
|
|
pub(crate) fn to_generic_def_id(self) -> Option<GenericDefId> {
|
|
|
|
match self {
|
|
|
|
Self::FunctionId(id) => Some(id.into()),
|
|
|
|
Self::StructId(id) => Some(id.into()),
|
|
|
|
Self::UnionId(id) => Some(id.into()),
|
2022-10-03 15:07:34 +00:00
|
|
|
Self::EnumVariantId(var) => Some(var.into()),
|
Change generic parameter/argument order
This commit "inverts" the order of generic parameters/arguments of an
item and its parent. This is to fulfill chalk's expectation on the
order of `Substitution` for generic associated types and it's one step
forward for their support (hopefully).
Although chalk doesn't put any constraint on the order of `Substitution`
for other items, it feels natural to get everything aligned rather than
special casing GATs.
One complication is that `TyBuilder` now demands its users to pass in
parent's `Substitution` upon construction unless it's obvious that the
the item has no parent (e.g. an ADT never has parent). All users
*should* already know the parent of the item in question, and without
this, it cannot be easily reasoned about whether we're pushing the
argument for the item or for its parent.
Quick comparison of how this commit changes `Substitution`:
```rust
trait Trait<TP, const CP: usize> {
type Type<TC, const CC: usize> = ();
fn f<TC, const CC: usize>() {}
}
```
- before this commit: `[Self, TP, CP, TC, CC]` for each trait item
- after this commit: `[TC, CC, Self, TP, CP]` for each trait item
2022-10-02 12:13:21 +00:00
|
|
|
Self::ConstId(id) => Some(id.into()),
|
|
|
|
Self::StaticId(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-26 18:04:24 +00:00
|
|
|
/// Build the declared type of an item. This depends on the namespace; e.g. for
|
|
|
|
/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
|
|
|
|
/// the constructor function `(usize) -> Foo` which lives in the values
|
|
|
|
/// namespace.
|
2020-03-13 15:05:46 +00:00
|
|
|
pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> {
|
2019-11-26 18:04:24 +00:00
|
|
|
match def {
|
2021-12-19 16:58:39 +00:00
|
|
|
TyDefId::BuiltinType(it) => Binders::empty(Interner, TyBuilder::builtin(it)),
|
2019-11-26 18:04:24 +00:00
|
|
|
TyDefId::AdtId(it) => type_for_adt(db, it),
|
|
|
|
TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
|
|
|
|
}
|
|
|
|
}
|
2019-11-30 11:48:51 +00:00
|
|
|
|
2023-12-07 09:57:51 +00:00
|
|
|
pub(crate) fn ty_recover(db: &dyn HirDatabase, _cycle: &Cycle, def: &TyDefId) -> Binders<Ty> {
|
2021-04-05 15:45:18 +00:00
|
|
|
let generics = match *def {
|
2021-12-19 16:58:39 +00:00
|
|
|
TyDefId::BuiltinType(_) => return Binders::empty(Interner, TyKind::Error.intern(Interner)),
|
2021-04-05 15:45:18 +00:00
|
|
|
TyDefId::AdtId(it) => generics(db.upcast(), it.into()),
|
|
|
|
TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()),
|
2020-02-07 17:17:23 +00:00
|
|
|
};
|
2022-03-09 18:50:24 +00:00
|
|
|
make_binders(db, &generics, TyKind::Error.intern(Interner))
|
2019-11-30 11:48:51 +00:00
|
|
|
}
|
|
|
|
|
2024-01-16 11:09:40 +00:00
|
|
|
pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Option<Binders<Ty>> {
|
2019-11-26 18:04:24 +00:00
|
|
|
match def {
|
2024-01-16 11:09:40 +00:00
|
|
|
ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
|
2019-11-26 18:04:24 +00:00
|
|
|
ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
|
2024-01-16 11:09:40 +00:00
|
|
|
ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
|
2019-11-26 18:04:24 +00:00
|
|
|
ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
|
2024-01-16 11:09:40 +00:00
|
|
|
ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
|
|
|
|
ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
|
2019-11-26 18:04:24 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-27 19:12:09 +00:00
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders<Ty> {
|
2019-11-27 19:12:09 +00:00
|
|
|
let impl_data = db.impl_data(impl_id);
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = impl_id.resolver(db.upcast());
|
|
|
|
let generics = generics(db.upcast(), impl_id.into());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2022-03-09 18:50:24 +00:00
|
|
|
make_binders(db, &generics, ctx.lower_ty(&impl_data.self_ty))
|
2019-11-30 11:35:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-29 13:35:59 +00:00
|
|
|
// returns None if def is a type arg
|
2021-01-01 09:06:42 +00:00
|
|
|
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
|
2021-12-29 13:35:59 +00:00
|
|
|
let parent_data = db.generic_params(def.parent());
|
2022-03-09 18:50:24 +00:00
|
|
|
let data = &parent_data.type_or_consts[def.local_id()];
|
2021-12-29 13:35:59 +00:00
|
|
|
let resolver = def.parent().resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, def.parent().into());
|
2021-12-29 13:35:59 +00:00
|
|
|
match data {
|
|
|
|
TypeOrConstParamData::TypeParamData(_) => {
|
|
|
|
never!();
|
|
|
|
Ty::new(Interner, TyKind::Error)
|
|
|
|
}
|
|
|
|
TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(&d.ty),
|
|
|
|
}
|
2021-01-01 09:06:42 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 11:35:37 +00:00
|
|
|
pub(crate) fn impl_self_ty_recover(
|
2020-03-13 15:05:46 +00:00
|
|
|
db: &dyn HirDatabase,
|
2023-12-07 09:57:51 +00:00
|
|
|
_cycle: &Cycle,
|
2020-01-25 22:38:33 +00:00
|
|
|
impl_id: &ImplId,
|
|
|
|
) -> Binders<Ty> {
|
2020-03-13 15:05:46 +00:00
|
|
|
let generics = generics(db.upcast(), (*impl_id).into());
|
2022-03-09 18:50:24 +00:00
|
|
|
make_binders(db, &generics, TyKind::Error.intern(Interner))
|
2019-11-30 11:35:37 +00:00
|
|
|
}
|
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
|
2019-11-30 11:35:37 +00:00
|
|
|
let impl_data = db.impl_data(impl_id);
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = impl_id.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2021-04-05 15:13:50 +00:00
|
|
|
let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
|
2019-11-30 11:35:37 +00:00
|
|
|
let target_trait = impl_data.target_trait.as_ref()?;
|
2021-04-05 15:13:50 +00:00
|
|
|
Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, Some(self_ty))?))
|
2019-11-27 19:12:09 +00:00
|
|
|
}
|
2020-03-04 22:00:44 +00:00
|
|
|
|
|
|
|
pub(crate) fn return_type_impl_traits(
|
2020-07-07 08:14:48 +00:00
|
|
|
db: &dyn HirDatabase,
|
2020-03-04 22:00:44 +00:00
|
|
|
def: hir_def::FunctionId,
|
2024-03-15 18:31:12 +00:00
|
|
|
) -> Option<Arc<Binders<ImplTraits>>> {
|
2020-03-04 22:00:44 +00:00
|
|
|
// FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
|
|
|
|
let data = db.function_data(def);
|
|
|
|
let resolver = def.resolver(db.upcast());
|
2023-06-05 11:27:19 +00:00
|
|
|
let ctx_ret = TyLoweringContext::new(db, &resolver, def.into())
|
2020-03-04 22:00:44 +00:00
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
|
2022-03-09 18:50:24 +00:00
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
2022-12-30 08:05:03 +00:00
|
|
|
let _ret = ctx_ret.lower_ty(&data.ret_type);
|
2020-03-04 22:00:44 +00:00
|
|
|
let generics = generics(db.upcast(), def.into());
|
2024-03-15 18:31:12 +00:00
|
|
|
let return_type_impl_traits = ImplTraits {
|
2023-02-06 17:20:25 +00:00
|
|
|
impl_traits: match ctx_ret.impl_trait_mode {
|
|
|
|
ImplTraitLoweringState::Opaque(x) => x.into_inner(),
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
};
|
2020-03-04 22:00:44 +00:00
|
|
|
if return_type_impl_traits.impl_traits.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
2022-03-09 18:50:24 +00:00
|
|
|
Some(Arc::new(make_binders(db, &generics, return_type_impl_traits)))
|
2020-03-04 22:00:44 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-01 18:30:34 +00:00
|
|
|
|
2024-03-15 18:31:12 +00:00
|
|
|
pub(crate) fn type_alias_impl_traits(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
def: hir_def::TypeAliasId,
|
|
|
|
) -> Option<Arc<Binders<ImplTraits>>> {
|
|
|
|
let data = db.type_alias_data(def);
|
|
|
|
let resolver = def.resolver(db.upcast());
|
|
|
|
let ctx = TyLoweringContext::new(db, &resolver, def.into())
|
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
|
|
|
|
.with_type_param_mode(ParamLoweringMode::Variable);
|
|
|
|
if let Some(type_ref) = &data.type_ref {
|
|
|
|
let _ty = ctx.lower_ty(type_ref);
|
|
|
|
}
|
|
|
|
let generics = generics(db.upcast(), def.into());
|
|
|
|
let type_alias_impl_traits = ImplTraits {
|
|
|
|
impl_traits: match ctx.impl_trait_mode {
|
|
|
|
ImplTraitLoweringState::Opaque(x) => x.into_inner(),
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
};
|
|
|
|
if type_alias_impl_traits.impl_traits.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(Arc::new(make_binders(db, &generics, type_alias_impl_traits)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-01 18:30:34 +00:00
|
|
|
pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
|
|
|
|
match m {
|
|
|
|
hir_def::type_ref::Mutability::Shared => Mutability::Not,
|
|
|
|
hir_def::type_ref::Mutability::Mut => Mutability::Mut,
|
|
|
|
}
|
|
|
|
}
|
2021-04-05 15:45:18 +00:00
|
|
|
|
2022-04-22 14:52:18 +00:00
|
|
|
/// Checks if the provided generic arg matches its expected kind, then lower them via
|
|
|
|
/// provided closures. Use unknown if there was kind mismatch.
|
2022-04-22 14:59:10 +00:00
|
|
|
///
|
2022-04-22 14:52:18 +00:00
|
|
|
/// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime.
|
2022-03-09 18:50:24 +00:00
|
|
|
pub(crate) fn generic_arg_to_chalk<'a, T>(
|
|
|
|
db: &dyn HirDatabase,
|
2024-03-08 12:35:44 +00:00
|
|
|
kind_id: GenericParamId,
|
2022-03-09 18:50:24 +00:00
|
|
|
arg: &'a GenericArg,
|
|
|
|
this: &mut T,
|
|
|
|
for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a,
|
2023-06-05 11:27:19 +00:00
|
|
|
for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a,
|
2024-03-08 12:35:44 +00:00
|
|
|
for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a,
|
2022-03-09 18:50:24 +00:00
|
|
|
) -> Option<crate::GenericArg> {
|
|
|
|
let kind = match kind_id {
|
2024-03-08 12:35:44 +00:00
|
|
|
GenericParamId::TypeParamId(_) => ParamKind::Type,
|
|
|
|
GenericParamId::ConstParamId(id) => {
|
2022-03-09 18:50:24 +00:00
|
|
|
let ty = db.const_param_ty(id);
|
|
|
|
ParamKind::Const(ty)
|
|
|
|
}
|
2024-03-08 12:35:44 +00:00
|
|
|
GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
|
2022-03-09 18:50:24 +00:00
|
|
|
};
|
|
|
|
Some(match (arg, kind) {
|
2023-08-08 15:47:29 +00:00
|
|
|
(GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner),
|
|
|
|
(GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner),
|
2024-03-08 12:35:44 +00:00
|
|
|
(GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => {
|
|
|
|
for_lifetime(this, lifetime_ref).cast(Interner)
|
|
|
|
}
|
2023-08-08 15:47:29 +00:00
|
|
|
(GenericArg::Const(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
|
2024-03-08 12:35:44 +00:00
|
|
|
(GenericArg::Lifetime(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
|
2022-04-07 01:00:33 +00:00
|
|
|
(GenericArg::Type(t), ParamKind::Const(c_ty)) => {
|
2022-03-09 18:50:24 +00:00
|
|
|
// We want to recover simple idents, which parser detects them
|
|
|
|
// as types. Maybe here is not the best place to do it, but
|
|
|
|
// it works.
|
|
|
|
if let TypeRef::Path(p) = t {
|
2023-03-08 17:28:52 +00:00
|
|
|
let p = p.mod_path()?;
|
2022-03-09 18:50:24 +00:00
|
|
|
if p.kind == PathKind::Plain {
|
|
|
|
if let [n] = p.segments() {
|
2023-06-05 11:27:19 +00:00
|
|
|
let c = ConstRef::Path(n.clone());
|
2023-08-08 15:47:29 +00:00
|
|
|
return Some(for_const(this, &c, c_ty).cast(Interner));
|
2022-03-09 18:50:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-07 01:00:33 +00:00
|
|
|
unknown_const_as_generic(c_ty)
|
2022-03-09 18:50:24 +00:00
|
|
|
}
|
2024-03-08 12:35:44 +00:00
|
|
|
(GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => unknown_const_as_generic(c_ty),
|
|
|
|
(GenericArg::Type(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
|
|
|
|
(GenericArg::Const(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
|
2022-03-09 18:50:24 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn const_or_path_to_chalk(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
resolver: &Resolver,
|
2023-06-05 11:27:19 +00:00
|
|
|
owner: TypeOwnerId,
|
2022-04-07 01:00:33 +00:00
|
|
|
expected_ty: Ty,
|
2023-06-05 11:27:19 +00:00
|
|
|
value: &ConstRef,
|
2022-03-09 18:50:24 +00:00
|
|
|
mode: ParamLoweringMode,
|
|
|
|
args: impl FnOnce() -> Generics,
|
|
|
|
debruijn: DebruijnIndex,
|
|
|
|
) -> Const {
|
|
|
|
match value {
|
2023-06-05 11:27:19 +00:00
|
|
|
ConstRef::Scalar(s) => intern_const_ref(db, s, expected_ty, resolver.krate()),
|
|
|
|
ConstRef::Path(n) => {
|
2022-03-09 18:50:24 +00:00
|
|
|
let path = ModPath::from_segments(PathKind::Plain, Some(n.clone()));
|
2023-03-08 17:28:52 +00:00
|
|
|
path_to_const(
|
|
|
|
db,
|
|
|
|
resolver,
|
|
|
|
&Path::from_known_path_with_no_generic(path),
|
|
|
|
mode,
|
|
|
|
args,
|
|
|
|
debruijn,
|
2023-05-03 15:24:30 +00:00
|
|
|
expected_ty.clone(),
|
2023-03-08 17:28:52 +00:00
|
|
|
)
|
|
|
|
.unwrap_or_else(|| unknown_const(expected_ty))
|
2022-03-09 18:50:24 +00:00
|
|
|
}
|
2023-06-12 16:21:17 +00:00
|
|
|
&ConstRef::Complex(it) => {
|
2023-06-05 11:27:19 +00:00
|
|
|
let crate_data = &db.crate_graph()[owner.module(db.upcast()).krate()];
|
|
|
|
if crate_data.env.get("__ra_is_test_fixture").is_none() && crate_data.origin.is_local()
|
|
|
|
{
|
|
|
|
// FIXME: current `InTypeConstId` is very unstable, so we only use it in non local crate
|
|
|
|
// that are unlikely to be edited.
|
|
|
|
return unknown_const(expected_ty);
|
|
|
|
}
|
2023-06-06 23:42:41 +00:00
|
|
|
let c = db
|
2023-06-12 16:21:17 +00:00
|
|
|
.intern_in_type_const(InTypeConstLoc {
|
|
|
|
id: it,
|
2023-06-06 23:42:41 +00:00
|
|
|
owner,
|
2023-12-14 13:11:12 +00:00
|
|
|
expected_ty: Box::new(InTypeConstIdMetadata(expected_ty.clone())),
|
2023-06-12 16:21:17 +00:00
|
|
|
})
|
2023-06-06 23:42:41 +00:00
|
|
|
.into();
|
2023-06-05 11:27:19 +00:00
|
|
|
intern_const_scalar(
|
|
|
|
ConstScalar::UnevaluatedConst(c, Substitution::empty(Interner)),
|
|
|
|
expected_ty,
|
|
|
|
)
|
|
|
|
}
|
2022-03-09 18:50:24 +00:00
|
|
|
}
|
2021-04-05 15:45:18 +00:00
|
|
|
}
|
2022-03-17 16:08:43 +00:00
|
|
|
|
2022-10-02 13:15:57 +00:00
|
|
|
/// Replaces any 'free' `BoundVar`s in `s` by `TyKind::Error` from the perspective of generic
|
|
|
|
/// parameter whose index is `param_index`. A `BoundVar` is free when it is or (syntactically)
|
|
|
|
/// appears after the generic parameter of `param_index`.
|
2022-07-03 07:22:10 +00:00
|
|
|
fn fallback_bound_vars<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
|
2022-03-17 16:08:43 +00:00
|
|
|
s: T,
|
2022-10-02 13:15:57 +00:00
|
|
|
param_index: usize,
|
|
|
|
parent_start: usize,
|
2022-07-03 07:22:10 +00:00
|
|
|
) -> T {
|
2022-10-02 13:15:57 +00:00
|
|
|
// Keep in mind that parent generic parameters, if any, come *after* those of the item in
|
|
|
|
// question. In the diagrams below, `c*` and `p*` represent generic parameters of the item and
|
|
|
|
// its parent respectively.
|
|
|
|
let is_allowed = |index| {
|
|
|
|
if param_index < parent_start {
|
|
|
|
// The parameter of `param_index` is one from the item in question. Any parent generic
|
|
|
|
// parameters or the item's generic parameters that come before `param_index` is
|
|
|
|
// allowed.
|
|
|
|
// [c1, .., cj, .., ck, p1, .., pl] where cj is `param_index`
|
|
|
|
// ^^^^^^ ^^^^^^^^^^ these are allowed
|
|
|
|
!(param_index..parent_start).contains(&index)
|
|
|
|
} else {
|
|
|
|
// The parameter of `param_index` is one from the parent generics. Only parent generic
|
|
|
|
// parameters that come before `param_index` are allowed.
|
|
|
|
// [c1, .., ck, p1, .., pj, .., pl] where pj is `param_index`
|
|
|
|
// ^^^^^^ these are allowed
|
|
|
|
(parent_start..param_index).contains(&index)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-03-17 16:08:43 +00:00
|
|
|
crate::fold_free_vars(
|
|
|
|
s,
|
|
|
|
|bound, binders| {
|
2022-10-02 13:15:57 +00:00
|
|
|
if bound.index_if_innermost().map_or(true, is_allowed) {
|
2022-03-17 16:08:43 +00:00
|
|
|
bound.shifted_in_from(binders).to_ty(Interner)
|
2022-10-02 13:15:57 +00:00
|
|
|
} else {
|
|
|
|
TyKind::Error.intern(Interner)
|
2022-03-17 16:08:43 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|ty, bound, binders| {
|
2022-10-02 13:15:57 +00:00
|
|
|
if bound.index_if_innermost().map_or(true, is_allowed) {
|
2022-03-17 16:08:43 +00:00
|
|
|
bound.shifted_in_from(binders).to_const(Interner, ty)
|
2022-10-02 13:15:57 +00:00
|
|
|
} else {
|
2022-12-23 07:08:08 +00:00
|
|
|
unknown_const(ty)
|
2022-03-17 16:08:43 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|