//! - Building the type for an item: This happens through the `type_for_def` query.
//!
//! This usually involves resolving names, collecting generic arguments etc.
+use std::cell::{Cell, RefCell};
use std::{iter, sync::Arc};
use base_db::CrateId;
-use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
+use chalk_ir::{
+ cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety, Scalar, UintTy,
+};
use hir_def::{
adt::StructKind,
+ body::{Expander, LowerCtx},
builtin_type::BuiltinType,
generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
path::{GenericArg, Path, PathSegment, PathSegments},
GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
TypeAliasId, TypeParamId, UnionId, VariantId,
};
-use hir_expand::name::Name;
+use hir_expand::{name::Name, ExpandResult};
use la_arena::ArenaMap;
use smallvec::SmallVec;
use stdx::impl_from;
+use syntax::ast;
use crate::{
db::HirDatabase,
- dummy_usize_const, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
- chalk_db::ToChalk,
- Interner,
+ mapping::ToChalk,
+ static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
utils::{
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
},
- AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
- FnSubst, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
- QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution,
- TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
+ AliasEq, AliasTy, Binders, BoundVar, CallableSig, ConstData, ConstValue, DebruijnIndex, DynTy,
+ FnPointer, FnSig, FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy,
+ QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits,
+ Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
};
#[derive(Debug)]
/// possible currently, so this should be fine for now.
pub type_param_mode: TypeParamLoweringMode,
pub impl_trait_mode: ImplTraitLoweringMode,
- impl_trait_counter: std::cell::Cell<u16>,
+ impl_trait_counter: Cell<u16>,
/// 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
/// 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.
- opaque_type_data: std::cell::RefCell<Vec<ReturnTypeImplTrait>>,
+ opaque_type_data: RefCell<Vec<ReturnTypeImplTrait>>,
+ expander: RefCell<Option<Expander>>,
}
impl<'a> TyLoweringContext<'a> {
pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver) -> Self {
- let impl_trait_counter = std::cell::Cell::new(0);
+ let impl_trait_counter = Cell::new(0);
let impl_trait_mode = ImplTraitLoweringMode::Disallowed;
let type_param_mode = TypeParamLoweringMode::Placeholder;
let in_binders = DebruijnIndex::INNERMOST;
- let opaque_type_data = std::cell::RefCell::new(Vec::new());
+ let opaque_type_data = RefCell::new(Vec::new());
Self {
db,
resolver,
impl_trait_counter,
type_param_mode,
opaque_type_data,
+ expander: RefCell::new(None),
}
}
f: impl FnOnce(&TyLoweringContext) -> T,
) -> T {
let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new());
+ let expander = self.expander.replace(None);
let new_ctx = Self {
in_binders: debruijn,
- impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()),
- opaque_type_data: std::cell::RefCell::new(opaque_ty_data_vec),
+ impl_trait_counter: Cell::new(self.impl_trait_counter.get()),
+ opaque_type_data: RefCell::new(opaque_ty_data_vec),
+ expander: RefCell::new(expander),
..*self
};
let result = f(&new_ctx);
self.impl_trait_counter.set(new_ctx.impl_trait_counter.get());
self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner());
+ self.expander.replace(new_ctx.expander.into_inner());
result
}
let inner_ty = self.lower_ty(inner);
TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
}
- TypeRef::Array(inner) => {
+ TypeRef::Array(inner, len) => {
let inner_ty = self.lower_ty(inner);
- TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner)
+
+ let const_len = ConstData {
+ ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
+ value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: *len }),
+ }
+ .intern(&Interner);
+
+ TyKind::Array(inner_ty, const_len).intern(&Interner)
}
TypeRef::Slice(inner) => {
let inner_ty = self.lower_ty(inner);
}
}
}
+ TypeRef::Macro(macro_call) => {
+ let (expander, recursion_start) = {
+ let mut expander = self.expander.borrow_mut();
+ if expander.is_some() {
+ (Some(expander), false)
+ } else {
+ if let Some(module_id) = self.resolver.module() {
+ *expander = Some(Expander::new(
+ self.db.upcast(),
+ macro_call.file_id,
+ module_id,
+ ));
+ (Some(expander), true)
+ } else {
+ (None, false)
+ }
+ }
+ };
+ let ty = if let Some(mut expander) = expander {
+ let expander_mut = expander.as_mut().unwrap();
+ let macro_call = macro_call.to_node(self.db.upcast());
+ match expander_mut.enter_expand::<ast::Type>(self.db.upcast(), macro_call) {
+ Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
+ let ctx =
+ LowerCtx::new(self.db.upcast(), expander_mut.current_file_id());
+ let type_ref = TypeRef::from_ast(&ctx, expanded);
+
+ drop(expander);
+ let ty = self.lower_ty(&type_ref);
+
+ self.expander
+ .borrow_mut()
+ .as_mut()
+ .unwrap()
+ .exit(self.db.upcast(), mark);
+ Some(ty)
+ }
+ _ => None,
+ }
+ } else {
+ None
+ };
+ if recursion_start {
+ *self.expander.borrow_mut() = None;
+ }
+ ty.unwrap_or_else(|| TyKind::Error.intern(&Interner))
+ }
TypeRef::Error => TyKind::Error.intern(&Interner),
};
(ty, res)
self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, self_ty);
let ty = if remaining_segments.len() == 1 {
let segment = remaining_segments.first().unwrap();
- let found = associated_type_by_name_including_super_traits(
- self.db,
- trait_ref,
- &segment.name,
- );
+ let found = self
+ .db
+ .trait_data(trait_ref.hir_trait_id())
+ .associated_type_by_name(&segment.name);
match found {
- Some((super_trait_ref, associated_ty)) => {
+ Some(associated_ty) => {
// FIXME handle type parameters on the segment
TyKind::Alias(AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(associated_ty),
- substitution: super_trait_ref.substitution,
+ substitution: trait_ref.substitution,
}))
.intern(&Interner)
}
defaults
}
+pub(crate) fn generic_defaults_recover(
+ db: &dyn HirDatabase,
+ _cycle: &[String],
+ def: &GenericDefId,
+) -> Arc<[Binders<Ty>]> {
+ let generic_params = generics(db.upcast(), *def);
+
+ // we still need one default per parameter
+ let defaults = generic_params
+ .iter()
+ .enumerate()
+ .map(|(idx, _)| {
+ let ty = TyKind::Error.intern(&Interner);
+
+ crate::make_only_type_binders(idx, ty)
+ })
+ .collect();
+
+ defaults
+}
+
fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
let data = db.function_data(def);
let resolver = def.resolver(db.upcast());