Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower.rs')
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 635 |
1 files changed, 206 insertions, 429 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 5238a65510..630f43d362 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -25,43 +25,40 @@ use chalk_ir::{ use either::Either; use hir_def::{ AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, - FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, LocalFieldId, - Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, UnionId, VariantId, + FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, + StructId, TypeAliasId, TypeOrConstParamId, UnionId, VariantId, builtin_type::BuiltinType, - data::{TraitFlags, adt::StructKind}, - expander::Expander, - generics::{ - GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, - WherePredicateTypeTarget, + expr_store::{ + ExpressionStore, + path::{GenericArg, Path}, }, + hir::generics::{ + GenericParamDataRef, TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget, + }, + item_tree::FieldsShape, lang_item::LangItem, - nameres::MacroSubNs, - path::{GenericArg, ModPath, Path, PathKind}, resolver::{HasResolver, LifetimeNs, Resolver, TypeNs}, + signatures::{TraitFlags, TypeAliasFlags}, type_ref::{ - ConstRef, LifetimeRef, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, - TypeRef, TypeRefId, TypesMap, TypesSourceMap, + ConstRef, LifetimeRef, LiteralConstRef, PathId, TraitBoundModifier, + TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId, }, }; -use hir_expand::{ExpandResult, name::Name}; +use hir_expand::name::Name; use la_arena::{Arena, ArenaMap}; use rustc_hash::FxHashSet; use rustc_pattern_analysis::Captures; use salsa::Cycle; use stdx::{impl_from, never}; -use syntax::ast; use triomphe::{Arc, ThinArc}; use crate::{ - AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, FnAbi, - FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, - LifetimeData, LifetimeOutlives, ParamKind, PolyFnSig, ProgramClause, QuantifiedWhereClause, + AliasTy, Binders, BoundVar, CallableSig, Const, DebruijnIndex, DynTy, FnAbi, FnPointer, FnSig, + FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, LifetimeData, + LifetimeOutlives, ParamKind, PolyFnSig, ProgramClause, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, all_super_traits, - consteval::{ - intern_const_ref, intern_const_scalar, path_to_const, unknown_const, - unknown_const_as_generic, - }, + consteval::{intern_const_ref, path_to_const, unknown_const, unknown_const_as_generic}, db::{HirDatabase, HirDatabaseData}, error_lifetime, generics::{Generics, generics, trait_self_param_idx}, @@ -72,7 +69,7 @@ use crate::{ make_binders, mapping::{ToChalk, from_chalk_trait_id, lt_to_placeholder_idx}, static_lifetime, to_chalk_trait_id, to_placeholder_idx, - utils::{InTypeConstIdMetadata, all_super_trait_refs}, + utils::all_super_trait_refs, }; #[derive(Debug, Default)] @@ -83,25 +80,10 @@ struct ImplTraitLoweringState { mode: ImplTraitLoweringMode, // This is structured as a struct with fields and not as an enum because it helps with the borrow checker. opaque_type_data: Arena<ImplTrait>, - param_and_variable_counter: u16, } impl ImplTraitLoweringState { fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState { - Self { mode, opaque_type_data: Arena::new(), param_and_variable_counter: 0 } - } - fn param(counter: u16) -> Self { - Self { - mode: ImplTraitLoweringMode::Param, - opaque_type_data: Arena::new(), - param_and_variable_counter: counter, - } - } - fn variable(counter: u16) -> Self { - Self { - mode: ImplTraitLoweringMode::Variable, - opaque_type_data: Arena::new(), - param_and_variable_counter: counter, - } + Self { mode, opaque_type_data: Arena::new() } } } @@ -111,23 +93,16 @@ pub(crate) struct PathDiagnosticCallbackData(TypeRefId); pub struct TyLoweringContext<'a> { pub db: &'a dyn HirDatabase, resolver: &'a Resolver, - generics: OnceCell<Option<Generics>>, - types_map: &'a TypesMap, - /// If this is set, that means we're in a context of a freshly expanded macro, and that means - /// we should not use `TypeRefId` in diagnostics because the caller won't have the `TypesMap`, - /// instead we need to put `TypeSource` from the source map. - types_source_map: Option<&'a TypesSourceMap>, + store: &'a ExpressionStore, + def: GenericDefId, + generics: OnceCell<Generics>, in_binders: DebruijnIndex, - // FIXME: Should not be an `Option` but `Resolver` currently does not return owners in all cases - // where expected - owner: Option<TypeOwnerId>, /// Note: Conceptually, it's thinkable that we could be in a location where /// 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. pub type_param_mode: ParamLoweringMode, impl_trait_mode: ImplTraitLoweringState, - expander: Option<Expander>, /// Tracks types with explicit `?Sized` bounds. pub(crate) unsized_types: FxHashSet<Ty>, pub(crate) diagnostics: Vec<TyLoweringDiagnostic>, @@ -137,18 +112,8 @@ impl<'a> TyLoweringContext<'a> { pub fn new( db: &'a dyn HirDatabase, resolver: &'a Resolver, - types_map: &'a TypesMap, - owner: TypeOwnerId, - ) -> Self { - Self::new_maybe_unowned(db, resolver, types_map, None, Some(owner)) - } - - pub fn new_maybe_unowned( - db: &'a dyn HirDatabase, - resolver: &'a Resolver, - types_map: &'a TypesMap, - types_source_map: Option<&'a TypesSourceMap>, - owner: Option<TypeOwnerId>, + store: &'a ExpressionStore, + def: GenericDefId, ) -> Self { let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed); let type_param_mode = ParamLoweringMode::Placeholder; @@ -156,14 +121,12 @@ impl<'a> TyLoweringContext<'a> { Self { db, resolver, - generics: OnceCell::new(), - types_map, - types_source_map, - owner, + def, + generics: Default::default(), + store, in_binders, impl_trait_mode, type_param_mode, - expander: None, unsized_types: FxHashSet::default(), diagnostics: Vec::new(), } @@ -207,17 +170,7 @@ impl<'a> TyLoweringContext<'a> { } pub fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { - let source = match self.types_source_map { - Some(source_map) => { - let Ok(source) = source_map.type_syntax(type_ref) else { - stdx::never!("error in synthetic type"); - return; - }; - Either::Right(source) - } - None => Either::Left(type_ref), - }; - self.diagnostics.push(TyLoweringDiagnostic { source, kind }); + self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind }); } } @@ -228,15 +181,6 @@ pub enum ImplTraitLoweringMode { /// i.e. for arguments of the function we're currently checking, and return /// types of functions we're calling. Opaque, - /// `impl Trait` gets lowered into a type variable. Used for argument - /// position impl Trait when inside the respective function, since it allows - /// us to support that without Chalk. - Param, - /// `impl Trait` gets lowered into a variable that can unify with some - /// 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. - Variable, /// `impl Trait` is disallowed and will be an error. #[default] Disallowed, @@ -254,29 +198,57 @@ impl<'a> TyLoweringContext<'a> { } pub fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const { - let Some(owner) = self.owner else { return unknown_const(const_type) }; - let debruijn = self.in_binders; - const_or_path_to_chalk( + let const_ref = &self.store[const_ref.expr]; + match const_ref { + hir_def::hir::Expr::Path(path) => path_to_const( + self.db, + self.resolver, + path, + self.type_param_mode, + || self.generics(), + self.in_binders, + const_type.clone(), + ) + .unwrap_or_else(|| unknown_const(const_type)), + hir_def::hir::Expr::Literal(literal) => intern_const_ref( + self.db, + &match *literal { + hir_def::hir::Literal::Float(_, _) + | hir_def::hir::Literal::String(_) + | hir_def::hir::Literal::ByteString(_) + | hir_def::hir::Literal::CString(_) => LiteralConstRef::Unknown, + hir_def::hir::Literal::Char(c) => LiteralConstRef::Char(c), + hir_def::hir::Literal::Bool(b) => LiteralConstRef::Bool(b), + hir_def::hir::Literal::Int(val, _) => LiteralConstRef::Int(val), + hir_def::hir::Literal::Uint(val, _) => LiteralConstRef::UInt(val), + }, + const_type, + self.resolver.krate(), + ), + _ => unknown_const(const_type), + } + } + + pub fn lower_path_as_const(&mut self, path: &Path, const_type: Ty) -> Const { + path_to_const( self.db, self.resolver, - owner, - const_type, - const_ref, + path, self.type_param_mode, || self.generics(), - debruijn, + self.in_binders, + const_type.clone(), ) + .unwrap_or_else(|| unknown_const(const_type)) } - fn generics(&self) -> Option<&Generics> { - self.generics - .get_or_init(|| self.resolver.generic_def().map(|def| generics(self.db.upcast(), def))) - .as_ref() + fn generics(&self) -> &Generics { + self.generics.get_or_init(|| generics(self.db.upcast(), self.def)) } pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) { let mut res = None; - let type_ref = &self.types_map[type_ref_id]; + let type_ref = &self.store[type_ref_id]; let ty = match type_ref { TypeRef::Never => TyKind::Never.intern(Interner), TypeRef::Tuple(inner) => { @@ -290,6 +262,20 @@ impl<'a> TyLoweringContext<'a> { res = res_; ty } + &TypeRef::TypeParam(type_param_id) => { + res = Some(TypeNs::GenericParam(type_param_id)); + match self.type_param_mode { + ParamLoweringMode::Placeholder => { + TyKind::Placeholder(to_placeholder_idx(self.db, type_param_id.into())) + } + ParamLoweringMode::Variable => { + let idx = + self.generics().type_or_const_param_idx(type_param_id.into()).unwrap(); + TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) + } + } + .intern(Interner) + } &TypeRef::RawPtr(inner, mutability) => { let inner_ty = self.lower_ty(inner); TyKind::Raw(lower_to_chalk_mutability(mutability), inner_ty).intern(Interner) @@ -336,9 +322,9 @@ impl<'a> TyLoweringContext<'a> { TypeRef::ImplTrait(bounds) => { match self.impl_trait_mode.mode { ImplTraitLoweringMode::Opaque => { - let origin = match self.resolver.generic_def() { - Some(GenericDefId::FunctionId(it)) => Either::Left(it), - Some(GenericDefId::TypeAliasId(it)) => Either::Right(it), + let origin = match self.def { + GenericDefId::FunctionId(it) => Either::Left(it), + GenericDefId::TypeAliasId(it) => Either::Right(it), _ => panic!( "opaque impl trait lowering must be in function or type alias" ), @@ -375,139 +361,12 @@ impl<'a> TyLoweringContext<'a> { let parameters = generics.bound_vars_subst(self.db, self.in_binders); TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner) } - ImplTraitLoweringMode::Param => { - let idx = self.impl_trait_mode.param_and_variable_counter; - // Count the number of `impl Trait` things that appear within our bounds. - // Since those have been emitted as implicit type args already. - self.impl_trait_mode.param_and_variable_counter = - idx + self.count_impl_traits(type_ref_id) as u16; - let db = self.db; - let kind = self - .generics() - .expect("param impl trait lowering must be in a generic def") - .iter() - .filter_map(|(id, data)| match (id, data) { - ( - GenericParamId::TypeParamId(id), - GenericParamDataRef::TypeParamData(data), - ) if data.provenance == TypeParamProvenance::ArgumentImplTrait => { - Some(id) - } - _ => None, - }) - .nth(idx as usize) - .map_or(TyKind::Error, |id| { - TyKind::Placeholder(to_placeholder_idx(db, id.into())) - }); - kind.intern(Interner) - } - ImplTraitLoweringMode::Variable => { - let idx = self.impl_trait_mode.param_and_variable_counter; - // Count the number of `impl Trait` things that appear within our bounds. - // Since t hose have been emitted as implicit type args already. - self.impl_trait_mode.param_and_variable_counter = - idx + self.count_impl_traits(type_ref_id) as u16; - let debruijn = self.in_binders; - let kind = self - .generics() - .expect("variable impl trait lowering must be in a generic def") - .iter() - .enumerate() - .filter_map(|(i, (id, data))| match (id, data) { - ( - GenericParamId::TypeParamId(_), - GenericParamDataRef::TypeParamData(data), - ) if data.provenance == TypeParamProvenance::ArgumentImplTrait => { - Some(i) - } - _ => None, - }) - .nth(idx as usize) - .map_or(TyKind::Error, |id| { - TyKind::BoundVar(BoundVar { debruijn, index: id }) - }); - kind.intern(Interner) - } ImplTraitLoweringMode::Disallowed => { // FIXME: report error TyKind::Error.intern(Interner) } } } - TypeRef::Macro(macro_call) => { - let (expander, recursion_start) = { - match &mut self.expander { - // There already is an expander here, this means we are already recursing - Some(expander) => (expander, false), - // No expander was created yet, so we are at the start of the expansion recursion - // and therefore have to create an expander. - None => { - let expander = self.expander.insert(Expander::new( - self.db.upcast(), - macro_call.file_id, - self.resolver.module(), - )); - (expander, true) - } - } - }; - let ty = { - let macro_call = macro_call.to_node(self.db.upcast()); - let resolver = |path: &_| { - self.resolver - .resolve_path_as_macro(self.db.upcast(), path, Some(MacroSubNs::Bang)) - .map(|(it, _)| it) - }; - match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, resolver) - { - Ok(ExpandResult { value: Some((mark, expanded)), .. }) => { - let (mut types_map, mut types_source_map) = - (TypesMap::default(), TypesSourceMap::default()); - - let mut ctx = expander.ctx( - self.db.upcast(), - &mut types_map, - &mut types_source_map, - ); - // FIXME: Report syntax errors in expansion here - let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree()); - - // Can't mutate `self`, must create a new instance, because of the lifetimes. - let mut inner_ctx = TyLoweringContext { - db: self.db, - resolver: self.resolver, - generics: self.generics.clone(), - types_map: &types_map, - types_source_map: Some(&types_source_map), - in_binders: self.in_binders, - owner: self.owner, - type_param_mode: self.type_param_mode, - impl_trait_mode: mem::take(&mut self.impl_trait_mode), - expander: self.expander.take(), - unsized_types: mem::take(&mut self.unsized_types), - diagnostics: mem::take(&mut self.diagnostics), - }; - - let ty = inner_ctx.lower_ty(type_ref); - - self.impl_trait_mode = inner_ctx.impl_trait_mode; - self.expander = inner_ctx.expander; - self.unsized_types = inner_ctx.unsized_types; - self.diagnostics = inner_ctx.diagnostics; - - self.expander.as_mut().unwrap().exit(mark); - Some(ty) - } - _ => None, - } - }; - - // drop the expander, resetting it to pre-recursion state - if recursion_start { - self.expander = None; - } - ty.unwrap_or_else(|| TyKind::Error.intern(Interner)) - } TypeRef::Error => TyKind::Error.intern(Interner), }; (ty, res) @@ -517,9 +376,10 @@ impl<'a> TyLoweringContext<'a> { /// 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. fn lower_ty_only_param(&mut self, type_ref_id: TypeRefId) -> Option<TypeOrConstParamId> { - let type_ref = &self.types_map[type_ref_id]; + let type_ref = &self.store[type_ref_id]; let path = match type_ref { TypeRef::Path(path) => path, + &TypeRef::TypeParam(idx) => return Some(idx.into()), _ => return None, }; if path.type_anchor().is_some() { @@ -555,7 +415,7 @@ impl<'a> TyLoweringContext<'a> { PathLoweringContext::new( self, Self::on_path_diagnostic_callback(path_id.type_ref()), - &self.types_map[path_id], + &self.store[path_id], ) } @@ -608,7 +468,7 @@ impl<'a> TyLoweringContext<'a> { pub(crate) fn lower_where_predicate<'b>( &'b mut self, where_predicate: &'b WherePredicate, - &def: &GenericDefId, + generics: &'b Generics, ignore_bindings: bool, ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> { match where_predicate { @@ -617,13 +477,14 @@ impl<'a> TyLoweringContext<'a> { let self_ty = match target { WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(*type_ref), &WherePredicateTypeTarget::TypeOrConstParam(local_id) => { - let param_id = hir_def::TypeOrConstParamId { parent: def, local_id }; + let param_id = + hir_def::TypeOrConstParamId { parent: generics.def(), local_id }; match self.type_param_mode { ParamLoweringMode::Placeholder => { TyKind::Placeholder(to_placeholder_idx(self.db, param_id)) } ParamLoweringMode::Variable => { - let idx = generics(self.db.upcast(), def) + let idx = generics .type_or_const_param_idx(param_id) .expect("matching generics"); TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx)) @@ -657,8 +518,7 @@ impl<'a> TyLoweringContext<'a> { // FIXME Don't silently drop the hrtb lifetimes here if let Some((trait_ref, ctx)) = self.lower_trait_ref_from_path(path, self_ty) { if !ignore_bindings { - assoc_bounds = - ctx.assoc_type_bindings_from_type_bound(bound, trait_ref.clone()); + assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref.clone()); } clause = Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref))); } @@ -725,13 +585,13 @@ impl<'a> TyLoweringContext<'a> { let lhs_id = lhs.trait_id; let lhs_is_auto = ctx .db - .trait_data(from_chalk_trait_id(lhs_id)) + .trait_signature(from_chalk_trait_id(lhs_id)) .flags .contains(TraitFlags::IS_AUTO); let rhs_id = rhs.trait_id; let rhs_is_auto = ctx .db - .trait_data(from_chalk_trait_id(rhs_id)) + .trait_signature(from_chalk_trait_id(rhs_id)) .flags .contains(TraitFlags::IS_AUTO); @@ -838,8 +698,7 @@ impl<'a> TyLoweringContext<'a> { LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id)) } ParamLoweringMode::Variable => { - let generics = self.generics().expect("generics in scope"); - let idx = match generics.lifetime_idx(id) { + let idx = match self.generics().lifetime_idx(id) { None => return error_lifetime(), Some(idx) => idx, }; @@ -852,17 +711,6 @@ impl<'a> TyLoweringContext<'a> { None => error_lifetime(), } } - - // FIXME: This does not handle macros! - fn count_impl_traits(&self, type_ref: TypeRefId) -> usize { - let mut count = 0; - TypeRef::walk(type_ref, self.types_map, &mut |type_ref| { - if matches!(type_ref, TypeRef::ImplTrait(_)) { - count += 1; - } - }); - count - } } /// Build the signature of a callable item (function, struct or enum variant). @@ -989,7 +837,7 @@ pub(crate) fn field_types_with_diagnostics_query( db: &dyn HirDatabase, variant_id: VariantId, ) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics) { - let var_data = variant_id.variant_data(db.upcast()); + let var_data = db.variant_fields(variant_id); let (resolver, def): (_, GenericDefId) = match variant_id { VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()), VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()), @@ -999,7 +847,7 @@ pub(crate) fn field_types_with_diagnostics_query( }; let generics = generics(db.upcast(), def); let mut res = ArenaMap::default(); - let mut ctx = TyLoweringContext::new(db, &resolver, var_data.types_map(), def.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &var_data.store, def) .with_type_param_mode(ParamLoweringMode::Variable); for (field_id, field_data) in var_data.fields().iter() { res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref))); @@ -1021,19 +869,13 @@ pub(crate) fn generic_predicates_for_param_query( param_id: TypeOrConstParamId, assoc_name: Option<Name>, ) -> GenericPredicates { - let resolver = def.resolver(db.upcast()); - let mut ctx = if let GenericDefId::FunctionId(_) = def { - TyLoweringContext::new(db, &resolver, TypesMap::EMPTY, def.into()) - .with_impl_trait_mode(ImplTraitLoweringMode::Variable) - .with_type_param_mode(ParamLoweringMode::Variable) - } else { - TyLoweringContext::new(db, &resolver, TypesMap::EMPTY, def.into()) - .with_type_param_mode(ParamLoweringMode::Variable) - }; let generics = generics(db.upcast(), def); + let resolver = def.resolver(db.upcast()); + let mut ctx = TyLoweringContext::new(db, &resolver, generics.store(), def) + .with_type_param_mode(ParamLoweringMode::Variable); // we have to filter out all other predicates *first*, before attempting to lower them - let predicate = |pred: &_, def: &_, ctx: &mut TyLoweringContext<'_>| match pred { + let predicate = |pred: &_, generics: &Generics, ctx: &mut TyLoweringContext<'_>| match pred { WherePredicate::ForLifetime { target, bound, .. } | WherePredicate::TypeBound { target, bound, .. } => { let invalid_target = match target { @@ -1041,14 +883,14 @@ pub(crate) fn generic_predicates_for_param_query( ctx.lower_ty_only_param(*type_ref) != Some(param_id) } &WherePredicateTypeTarget::TypeOrConstParam(local_id) => { - let target_id = TypeOrConstParamId { parent: *def, local_id }; + let target_id = TypeOrConstParamId { parent: generics.def(), local_id }; target_id != param_id } }; if invalid_target { // If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types` if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound { - ctx.lower_where_predicate(pred, def, true).for_each(drop); + ctx.lower_where_predicate(pred, generics, true).for_each(drop); } return false; } @@ -1057,7 +899,7 @@ pub(crate) fn generic_predicates_for_param_query( &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => { // Only lower the bound if the trait could possibly define the associated // type we're looking for. - let path = &ctx.types_map[path]; + let path = &ctx.store[path]; let Some(assoc_name) = &assoc_name else { return true }; let Some(TypeNs::TraitId(tr)) = @@ -1078,12 +920,14 @@ pub(crate) fn generic_predicates_for_param_query( WherePredicate::Lifetime { .. } => false, }; let mut predicates = Vec::new(); - for (params, def) in resolver.all_generic_params() { - ctx.types_map = ¶ms.types_map; - for pred in params.where_predicates() { - if predicate(pred, def, &mut ctx) { + for maybe_parent_generics in + std::iter::successors(Some(&generics), |generics| generics.parent_generics()) + { + ctx.store = maybe_parent_generics.store(); + for pred in maybe_parent_generics.where_predicates() { + if predicate(pred, maybe_parent_generics, &mut ctx) { predicates.extend( - ctx.lower_where_predicate(pred, def, true) + ctx.lower_where_predicate(pred, maybe_parent_generics, true) .map(|p| make_binders(db, &generics, p)), ); } @@ -1135,21 +979,18 @@ pub(crate) fn trait_environment_query( db: &dyn HirDatabase, def: GenericDefId, ) -> Arc<TraitEnvironment> { + let generics = generics(db.upcast(), def); let resolver = def.resolver(db.upcast()); - let mut ctx = if let GenericDefId::FunctionId(_) = def { - TyLoweringContext::new(db, &resolver, TypesMap::EMPTY, def.into()) - .with_impl_trait_mode(ImplTraitLoweringMode::Param) - .with_type_param_mode(ParamLoweringMode::Placeholder) - } else { - TyLoweringContext::new(db, &resolver, TypesMap::EMPTY, def.into()) - .with_type_param_mode(ParamLoweringMode::Placeholder) - }; + let mut ctx = TyLoweringContext::new(db, &resolver, generics.store(), def) + .with_type_param_mode(ParamLoweringMode::Placeholder); let mut traits_in_scope = Vec::new(); let mut clauses = Vec::new(); - for (params, def) in resolver.all_generic_params() { - ctx.types_map = ¶ms.types_map; - for pred in params.where_predicates() { - for pred in ctx.lower_where_predicate(pred, def, false) { + for maybe_parent_generics in + std::iter::successors(Some(&generics), |generics| generics.parent_generics()) + { + ctx.store = maybe_parent_generics.store(); + for pred in maybe_parent_generics.where_predicates() { + for pred in ctx.lower_where_predicate(pred, maybe_parent_generics, false) { if let WhereClause::Implemented(tr) = pred.skip_binders() { traits_in_scope .push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id())); @@ -1171,7 +1012,7 @@ pub(crate) fn trait_environment_query( clauses.push(pred.cast::<ProgramClause>(Interner).into_from_env_clause(Interner)); } - let subst = generics(db.upcast(), def).placeholder_subst(db); + let subst = generics.placeholder_subst(db); if !subst.is_empty(Interner) { let explicitly_unsized_tys = ctx.unsized_types; if let Some(implicitly_sized_clauses) = @@ -1222,7 +1063,7 @@ pub(crate) fn generic_predicates_without_parent_with_diagnostics_query( db: &dyn HirDatabase, def: GenericDefId, ) -> (GenericPredicates, Diagnostics) { - generic_predicates_filtered_by(db, def, |_, d| *d == def) + generic_predicates_filtered_by(db, def, |_, d| d == def) } /// Resolve the where clause(s) of an item with generics, @@ -1233,27 +1074,22 @@ fn generic_predicates_filtered_by<F>( filter: F, ) -> (GenericPredicates, Diagnostics) where - F: Fn(&WherePredicate, &GenericDefId) -> bool, + F: Fn(&WherePredicate, GenericDefId) -> bool, { - let resolver = def.resolver(db.upcast()); - let (impl_trait_lowering, param_lowering) = match def { - GenericDefId::FunctionId(_) => { - (ImplTraitLoweringMode::Variable, ParamLoweringMode::Variable) - } - _ => (ImplTraitLoweringMode::Disallowed, ParamLoweringMode::Variable), - }; - let mut ctx = TyLoweringContext::new(db, &resolver, TypesMap::EMPTY, def.into()) - .with_impl_trait_mode(impl_trait_lowering) - .with_type_param_mode(param_lowering); let generics = generics(db.upcast(), def); + let resolver = def.resolver(db.upcast()); + let mut ctx = TyLoweringContext::new(db, &resolver, generics.store(), def) + .with_type_param_mode(ParamLoweringMode::Variable); let mut predicates = Vec::new(); - for (params, def) in resolver.all_generic_params() { - ctx.types_map = ¶ms.types_map; - for pred in params.where_predicates() { - if filter(pred, def) { + for maybe_parent_generics in + std::iter::successors(Some(&generics), |generics| generics.parent_generics()) + { + ctx.store = maybe_parent_generics.store(); + for pred in maybe_parent_generics.where_predicates() { + if filter(pred, maybe_parent_generics.def()) { predicates.extend( - ctx.lower_where_predicate(pred, def, false) + ctx.lower_where_predicate(pred, maybe_parent_generics, false) .map(|p| make_binders(db, &generics, p)), ); } @@ -1343,10 +1179,9 @@ pub(crate) fn generic_defaults_with_diagnostics_query( let resolver = def.resolver(db.upcast()); let parent_start_idx = generic_params.len_self(); - let mut ctx = - TyLoweringContext::new(db, &resolver, generic_params.self_types_map(), def.into()) - .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed) - .with_type_param_mode(ParamLoweringMode::Variable); + let mut ctx = TyLoweringContext::new(db, &resolver, generic_params.store(), def) + .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed) + .with_type_param_mode(ParamLoweringMode::Variable); let mut idx = 0; let mut defaults = generic_params .iter_self() @@ -1358,8 +1193,8 @@ pub(crate) fn generic_defaults_with_diagnostics_query( }) .collect::<Vec<_>>(); let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics)); - defaults.extend(generic_params.iter_parents_with_types_map().map(|((id, p), types_map)| { - ctx.types_map = types_map; + defaults.extend(generic_params.iter_parents_with_store().map(|((id, p), store)| { + ctx.store = store; let result = handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params); idx += 1; result @@ -1432,16 +1267,21 @@ pub(crate) fn generic_defaults_with_diagnostics_recover( } fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { - let data = db.function_data(def); + let data = db.function_signature(def); let resolver = def.resolver(db.upcast()); - let mut ctx_params = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) - .with_impl_trait_mode(ImplTraitLoweringMode::Variable) + let mut ctx_params = TyLoweringContext::new(db, &resolver, &data.store, def.into()) .with_type_param_mode(ParamLoweringMode::Variable); let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr)); - let mut ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) - .with_type_param_mode(ParamLoweringMode::Variable); - let ret = ctx_ret.lower_ty(data.ret_type); + + let ret = match data.ret_type { + Some(ret_type) => { + let mut ctx_ret = TyLoweringContext::new(db, &resolver, &data.store, def.into()) + .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) + .with_type_param_mode(ParamLoweringMode::Variable); + ctx_ret.lower_ty(ret_type) + } + None => TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner), + }; let generics = generics(db.upcast(), def.into()); let sig = CallableSig::from_params_and_return( params, @@ -1467,10 +1307,10 @@ fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { /// Build the declared type of a const. fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> { - let data = db.const_data(def); + let data = db.const_signature(def); let generics = generics(db.upcast(), def.into()); let resolver = def.resolver(db.upcast()); - let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &data.store, def.into()) .with_type_param_mode(ParamLoweringMode::Variable); make_binders(db, &generics, ctx.lower_ty(data.type_ref)) @@ -1478,20 +1318,19 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> { /// Build the declared type of a static. fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders<Ty> { - let data = db.static_data(def); + let data = db.static_signature(def); let resolver = def.resolver(db.upcast()); - let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()); + let mut ctx = TyLoweringContext::new(db, &resolver, &data.store, def.into()); Binders::empty(Interner, ctx.lower_ty(data.type_ref)) } fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig { - let struct_data = db.variant_data(def.into()); + let struct_data = db.variant_fields(def.into()); let fields = struct_data.fields(); let resolver = def.resolver(db.upcast()); - let mut ctx = - TyLoweringContext::new(db, &resolver, struct_data.types_map(), AdtId::from(def).into()) - .with_type_param_mode(ParamLoweringMode::Variable); + let mut ctx = TyLoweringContext::new(db, &resolver, &struct_data.store, def.into()) + .with_type_param_mode(ParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(field.type_ref)); let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders(); Binders::new( @@ -1502,11 +1341,11 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS /// Build the type of a tuple struct constructor. fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option<Binders<Ty>> { - let struct_data = db.variant_data(def.into()); - match struct_data.kind() { - StructKind::Record => None, - StructKind::Unit => Some(type_for_adt(db, def.into())), - StructKind::Tuple => { + let struct_data = db.variant_fields(def.into()); + match struct_data.shape { + FieldsShape::Record => None, + FieldsShape::Unit => Some(type_for_adt(db, def.into())), + FieldsShape::Tuple => { let generics = generics(db.upcast(), AdtId::from(def).into()); let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); Some(make_binders( @@ -1519,19 +1358,14 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option<Bi } fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig { - let var_data = db.variant_data(def.into()); + let var_data = db.variant_fields(def.into()); let fields = var_data.fields(); let resolver = def.resolver(db.upcast()); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - var_data.types_map(), - DefWithBodyId::VariantId(def).into(), - ) - .with_type_param_mode(ParamLoweringMode::Variable); + let parent = def.lookup(db.upcast()).parent; + let mut ctx = TyLoweringContext::new(db, &resolver, &var_data.store, parent.into()) + .with_type_param_mode(ParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(field.type_ref)); - let (ret, binders) = - type_for_adt(db, def.lookup(db.upcast()).parent.into()).into_value_and_skipped_binders(); + let (ret, binders) = type_for_adt(db, parent.into()).into_value_and_skipped_binders(); Binders::new( binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall), @@ -1544,10 +1378,10 @@ fn type_for_enum_variant_constructor( def: EnumVariantId, ) -> Option<Binders<Ty>> { let e = def.lookup(db.upcast()).parent; - match db.variant_data(def.into()).kind() { - StructKind::Record => None, - StructKind::Unit => Some(type_for_adt(db, e.into())), - StructKind::Tuple => { + match db.variant_fields(def.into()).shape { + FieldsShape::Record => None, + FieldsShape::Unit => Some(type_for_adt(db, e.into())), + FieldsShape::Tuple => { let generics = generics(db.upcast(), e.into()); let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); Some(make_binders( @@ -1586,21 +1420,25 @@ pub(crate) fn type_for_type_alias_with_diagnostics_query( t: TypeAliasId, ) -> (Binders<Ty>, Diagnostics) { let generics = generics(db.upcast(), t.into()); - let resolver = t.resolver(db.upcast()); - let type_alias_data = db.type_alias_data(t); - let mut ctx = TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, t.into()) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) - .with_type_param_mode(ParamLoweringMode::Variable); - let inner = if type_alias_data.is_extern() { + let type_alias_data = db.type_alias_signature(t); + let mut diags = None; + let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) { TyKind::Foreign(crate::to_foreign_def_id(t)).intern(Interner) } else { - type_alias_data - .type_ref + let resolver = t.resolver(db.upcast()); + let alias = db.type_alias_signature(t); + let mut ctx = TyLoweringContext::new(db, &resolver, &alias.store, t.into()) + .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) + .with_type_param_mode(ParamLoweringMode::Variable); + let res = alias + .ty .map(|type_ref| ctx.lower_ty(type_ref)) - .unwrap_or_else(|| TyKind::Error.intern(Interner)) + .unwrap_or_else(|| TyKind::Error.intern(Interner)); + diags = create_diagnostics(ctx.diagnostics); + res }; - (make_binders(db, &generics, inner), create_diagnostics(ctx.diagnostics)) + (make_binders(db, &generics, inner), diags) } pub(crate) fn type_for_type_alias_with_diagnostics_query_recover( @@ -1675,10 +1513,10 @@ pub(crate) fn impl_self_ty_with_diagnostics_query( db: &dyn HirDatabase, impl_id: ImplId, ) -> (Binders<Ty>, Diagnostics) { - let impl_data = db.impl_data(impl_id); + let impl_data = db.impl_signature(impl_id); let resolver = impl_id.resolver(db.upcast()); let generics = generics(db.upcast(), impl_id.into()); - let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.store, impl_id.into()) .with_type_param_mode(ParamLoweringMode::Variable); ( make_binders(db, &generics, ctx.lower_ty(impl_data.self_ty)), @@ -1695,11 +1533,10 @@ pub(crate) fn const_param_ty_with_diagnostics_query( db: &dyn HirDatabase, def: ConstParamId, ) -> (Ty, Diagnostics) { - let parent_data = db.generic_params(def.parent()); + let (parent_data, store) = db.generic_params_and_store(def.parent()); let data = &parent_data[def.local_id()]; let resolver = def.parent().resolver(db.upcast()); - let mut ctx = - TyLoweringContext::new(db, &resolver, &parent_data.types_map, def.parent().into()); + let mut ctx = TyLoweringContext::new(db, &resolver, &store, def.parent()); let ty = match data { TypeOrConstParamData::TypeParamData(_) => { never!(); @@ -1727,9 +1564,9 @@ pub(crate) fn impl_trait_with_diagnostics_query( db: &dyn HirDatabase, impl_id: ImplId, ) -> Option<(Binders<TraitRef>, Diagnostics)> { - let impl_data = db.impl_data(impl_id); + let impl_data = db.impl_signature(impl_id); let resolver = impl_id.resolver(db.upcast()); - let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.store, impl_id.into()) .with_type_param_mode(ParamLoweringMode::Variable); let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders(); let target_trait = impl_data.target_trait.as_ref()?; @@ -1742,12 +1579,14 @@ pub(crate) fn return_type_impl_traits( def: hir_def::FunctionId, ) -> Option<Arc<Binders<ImplTraits>>> { // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe - let data = db.function_data(def); + let data = db.function_signature(def); let resolver = def.resolver(db.upcast()); - let mut ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) + let mut ctx_ret = TyLoweringContext::new(db, &resolver, &data.store, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); - let _ret = ctx_ret.lower_ty(data.ret_type); + if let Some(ret_type) = data.ret_type { + let _ret = ctx_ret.lower_ty(ret_type); + } let generics = generics(db.upcast(), def.into()); let return_type_impl_traits = ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data }; @@ -1762,12 +1601,12 @@ 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 data = db.type_alias_signature(def); let resolver = def.resolver(db.upcast()); - let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into()) + let mut ctx = TyLoweringContext::new(db, &resolver, &data.store, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); - if let Some(type_ref) = data.type_ref { + if let Some(type_ref) = data.ty { let _ty = ctx.lower_ty(type_ref); } let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data }; @@ -1794,9 +1633,10 @@ pub(crate) fn generic_arg_to_chalk<'a, T>( kind_id: GenericParamId, arg: &'a GenericArg, this: &mut T, - types_map: &TypesMap, + store: &ExpressionStore, for_type: impl FnOnce(&mut T, TypeRefId) -> Ty + 'a, for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a, + for_const_ty_path_fallback: impl FnOnce(&mut T, &Path, Ty) -> Const + 'a, for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a, ) -> crate::GenericArg { let kind = match kind_id { @@ -1815,79 +1655,16 @@ pub(crate) fn generic_arg_to_chalk<'a, T>( } (GenericArg::Const(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner), (GenericArg::Lifetime(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner), - (GenericArg::Type(t), ParamKind::Const(c_ty)) => { - // 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) = &types_map[*t] { - if let Some(p) = p.mod_path() { - if p.kind == PathKind::Plain { - if let [n] = p.segments() { - let c = ConstRef::Path(n.clone()); - return for_const(this, &c, c_ty).cast(Interner); - } - } - } - } - unknown_const_as_generic(c_ty) - } + (GenericArg::Type(t), ParamKind::Const(c_ty)) => match &store[*t] { + TypeRef::Path(p) => for_const_ty_path_fallback(this, p, c_ty).cast(Interner), + _ => unknown_const_as_generic(c_ty), + }, (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), } } -pub(crate) fn const_or_path_to_chalk<'g>( - db: &dyn HirDatabase, - resolver: &Resolver, - owner: TypeOwnerId, - expected_ty: Ty, - value: &ConstRef, - mode: ParamLoweringMode, - args: impl FnOnce() -> Option<&'g Generics>, - debruijn: DebruijnIndex, -) -> Const { - match value { - ConstRef::Scalar(s) => intern_const_ref(db, s, expected_ty, resolver.krate()), - ConstRef::Path(n) => { - let path = ModPath::from_segments(PathKind::Plain, Some(n.clone())); - path_to_const( - db, - resolver, - &Path::from_known_path_with_no_generic(path), - mode, - args, - debruijn, - expected_ty.clone(), - ) - .unwrap_or_else(|| unknown_const(expected_ty)) - } - &ConstRef::Complex(it) => { - let krate = resolver.krate(); - // Keep the `&&` this way, because it's better to access the crate data, as we access it for - // a bunch of other things nevertheless. - if krate.data(db).origin.is_local() - && krate.env(db).get("__ra_is_test_fixture").is_none() - { - // 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); - } - let c = db - .intern_in_type_const(InTypeConstLoc { - id: it, - owner, - expected_ty: Box::new(InTypeConstIdMetadata(expected_ty.clone())), - }) - .into(); - intern_const_scalar( - ConstScalar::UnevaluatedConst(c, Substitution::empty(Interner)), - expected_ty, - ) - } - } -} - /// 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`. |