diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index 27eb05cd4d..6ea1e676a1 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -285,6 +285,7 @@ pub struct CrateData { /// For purposes of analysis, crates are anonymous (only names in /// `Dependency` matters), this name should only be used for UI. pub display_name: Option, + // FIXME: Arc this pub cfg_options: CfgOptions, /// The cfg options that could be used by the crate pub potential_cfg_options: Option, diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index da790f1151..b5317be288 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -737,7 +737,7 @@ impl<'a> AssocItemCollector<'a> { &AstIdWithPath::new(file_id, ast_id, Clone::clone(path)), ctxt, expand_to, - self.expander.module.krate(), + self.expander.krate(), resolver, ) { Ok(Some(call_id)) => { diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs index b0872fcdc0..3084e06c1b 100644 --- a/crates/hir-def/src/expander.rs +++ b/crates/hir-def/src/expander.rs @@ -21,7 +21,6 @@ use crate::{ pub struct Expander { cfg_options: CfgOptions, span_map: OnceCell, - krate: CrateId, current_file_id: HirFileId, pub(crate) module: ModuleId, /// `recursion_depth == usize::MAX` indicates that the recursion limit has been reached. @@ -45,10 +44,13 @@ impl Expander { recursion_limit, cfg_options: db.crate_graph()[module.krate].cfg_options.clone(), span_map: OnceCell::new(), - krate: module.krate, } } + pub fn krate(&self) -> CrateId { + self.module.krate + } + pub fn enter_expand( &mut self, db: &dyn DefDatabase, @@ -112,7 +114,7 @@ impl Expander { pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs { Attrs::filter( db, - self.krate, + self.krate(), RawAttrs::new( db.upcast(), owner, diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index 705609ba68..eb5c2c5504 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -77,30 +77,32 @@ pub(crate) fn path_to_const( resolver: &Resolver, path: &Path, mode: ParamLoweringMode, - args_lazy: impl FnOnce() -> Generics, + args: impl FnOnce() -> Option, debruijn: DebruijnIndex, expected_ty: Ty, ) -> Option { match resolver.resolve_path_in_value_ns_fully(db.upcast(), path) { Some(ValueNs::GenericParam(p)) => { let ty = db.const_param_ty(p); - let args = args_lazy(); let value = match mode { ParamLoweringMode::Placeholder => { ConstValue::Placeholder(to_placeholder_idx(db, p.into())) } - ParamLoweringMode::Variable => match args.param_idx(p.into()) { - Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), - None => { - never!( - "Generic list doesn't contain this param: {:?}, {:?}, {:?}", - args, - path, - p - ); - return None; + ParamLoweringMode::Variable => { + let args = args(); + match args.as_ref().and_then(|args| args.param_idx(p.into())) { + Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), + None => { + never!( + "Generic list doesn't contain this param: {:?}, {:?}, {:?}", + args, + path, + p + ); + return None; + } } - }, + } }; Some(ConstData { ty, value }.intern(Interner)) } @@ -285,7 +287,6 @@ pub(crate) fn eval_to_const( expr: ExprId, mode: ParamLoweringMode, ctx: &mut InferenceContext<'_>, - args: impl FnOnce() -> Generics, debruijn: DebruijnIndex, ) -> Const { let db = ctx.db; @@ -304,7 +305,9 @@ pub(crate) fn eval_to_const( } if let Expr::Path(p) = &ctx.body.exprs[expr] { let resolver = &ctx.resolver; - if let Some(c) = path_to_const(db, resolver, p, mode, args, debruijn, infer[expr].clone()) { + if let Some(c) = + path_to_const(db, resolver, p, mode, || ctx.generics(), debruijn, infer[expr].clone()) + { return c; } } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 3b644379fa..3aacf7d07f 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -60,7 +60,7 @@ use crate::{ lower::ImplTraitLoweringMode, to_assoc_type_id, traits::FnTrait, - utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder}, + utils::{Generics, InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder}, AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId, ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, @@ -630,6 +630,10 @@ impl<'a> InferenceContext<'a> { } } + pub(crate) fn generics(&self) -> Option { + Some(crate::utils::generics(self.db.upcast(), self.resolver.generic_def()?)) + } + // FIXME: This function should be private in module. It is currently only used in the consteval, since we need // `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you // used this function for another workaround, mention it here. If you really need this function and believe that diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs index f8c03ee288..060b5f36f2 100644 --- a/crates/hir-ty/src/infer/cast.rs +++ b/crates/hir-ty/src/infer/cast.rs @@ -19,10 +19,6 @@ impl CastCheck { let expr_ty = table.resolve_ty_shallow(&self.expr_ty); let cast_ty = table.resolve_ty_shallow(&self.cast_ty); - if expr_ty.contains_unknown() || cast_ty.contains_unknown() { - return; - } - if table.coerce(&expr_ty, &cast_ty).is_ok() { return; } diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 20d24e6fe2..f08c0b6871 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -26,7 +26,7 @@ use crate::{ mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, to_chalk_trait_id, traits::FnTrait, - utils::{self, elaborate_clause_supertraits, generics, Generics}, + utils::{self, elaborate_clause_supertraits, Generics}, Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty, TyExt, WhereClause, @@ -331,14 +331,10 @@ impl CapturedItemWithoutTy { place: self.place, kind: self.kind, span: self.span, - ty: replace_placeholder_with_binder(ctx.db, ctx.owner, ty), + ty: replace_placeholder_with_binder(ctx, ty), }; - fn replace_placeholder_with_binder( - db: &dyn HirDatabase, - owner: DefWithBodyId, - ty: Ty, - ) -> Binders { + fn replace_placeholder_with_binder(ctx: &mut InferenceContext<'_>, ty: Ty) -> Binders { struct Filler<'a> { db: &'a dyn HirDatabase, generics: Generics, @@ -379,12 +375,12 @@ impl CapturedItemWithoutTy { Ok(BoundVar::new(outer_binder, idx).to_ty(Interner)) } } - let Some(generic_def) = owner.as_generic_def_id() else { + let Some(generics) = ctx.generics() else { return Binders::empty(Interner, ty); }; - let filler = &mut Filler { db, generics: generics(db.upcast(), generic_def) }; + let filler = &mut Filler { db: ctx.db, generics }; let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty); - make_binders(db, &filler.generics, result) + make_binders(ctx.db, &filler.generics, result) } } } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 4d3d7376c4..d011a62e77 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1040,18 +1040,12 @@ impl InferenceContext<'_> { ( elem_ty, - if let Some(g_def) = self.owner.as_generic_def_id() { - let generics = generics(self.db.upcast(), g_def); - consteval::eval_to_const( - repeat, - ParamLoweringMode::Placeholder, - self, - || generics, - DebruijnIndex::INNERMOST, - ) - } else { - consteval::usize_const(self.db, None, krate) - }, + consteval::eval_to_const( + repeat, + ParamLoweringMode::Placeholder, + self, + DebruijnIndex::INNERMOST, + ), ) } }; @@ -1852,7 +1846,7 @@ impl InferenceContext<'_> { ty, c, ParamLoweringMode::Placeholder, - || generics(this.db.upcast(), this.resolver.generic_def().unwrap()), + || this.generics(), DebruijnIndex::INNERMOST, ) }, diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index 440ffa3357..1b354935a5 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -2,13 +2,13 @@ use std::iter::repeat_with; -use chalk_ir::Mutability; use hir_def::{ body::Body, hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, Literal, Pat, PatId}, path::Path, }; use hir_expand::name::Name; +use stdx::TupleExt; use crate::{ consteval::{try_const_usize, usize_const}, @@ -16,8 +16,8 @@ use crate::{ infer::{BindingMode, Expectation, InferenceContext, TypeMismatch}, lower::lower_to_chalk_mutability, primitive::UintTy, - static_lifetime, InferenceDiagnostic, Interner, Scalar, Substitution, Ty, TyBuilder, TyExt, - TyKind, + static_lifetime, InferenceDiagnostic, Interner, Mutability, Scalar, Substitution, Ty, + TyBuilder, TyExt, TyKind, }; /// Used to generalize patterns and assignee expressions. @@ -90,9 +90,6 @@ impl InferenceContext<'_> { self.unify(&ty, expected); - let substs = - ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(Interner)); - match def { _ if subs.is_empty() => {} Some(def) => { @@ -109,8 +106,10 @@ impl InferenceContext<'_> { let pre_iter = pre.iter().enumerate(); let post_iter = (post_idx_offset..).zip(post.iter()); + let substs = ty.as_adt().map(TupleExt::tail); + for (i, &subpat) in pre_iter.chain(post_iter) { - let field_def = { + let expected_ty = { match variant_data.field(&Name::new_tuple_field(i)) { Some(local_id) => { if !visibilities[local_id] @@ -118,17 +117,17 @@ impl InferenceContext<'_> { { // FIXME(DIAGNOSE): private tuple field } - Some(local_id) + let f = field_types[local_id].clone(); + let expected_ty = match substs { + Some(substs) => f.substitute(Interner, substs), + None => f.substitute(Interner, &Substitution::empty(Interner)), + }; + self.normalize_associated_types_in(expected_ty) } - None => None, + None => self.err_ty(), } }; - let expected_ty = field_def.map_or(self.err_ty(), |f| { - field_types[f].clone().substitute(Interner, &substs) - }); - let expected_ty = self.normalize_associated_types_in(expected_ty); - T::infer(self, subpat, &expected_ty, default_bm); } } @@ -159,9 +158,6 @@ impl InferenceContext<'_> { self.unify(&ty, expected); - let substs = - ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(Interner)); - match def { _ if subs.len() == 0 => {} Some(def) => { @@ -169,8 +165,10 @@ impl InferenceContext<'_> { let variant_data = def.variant_data(self.db.upcast()); let visibilities = self.db.field_visibilities(def); + let substs = ty.as_adt().map(TupleExt::tail); + for (name, inner) in subs { - let field_def = { + let expected_ty = { match variant_data.field(&name) { Some(local_id) => { if !visibilities[local_id] @@ -181,23 +179,23 @@ impl InferenceContext<'_> { private: true, }); } - Some(local_id) + let f = field_types[local_id].clone(); + let expected_ty = match substs { + Some(substs) => f.substitute(Interner, substs), + None => f.substitute(Interner, &Substitution::empty(Interner)), + }; + self.normalize_associated_types_in(expected_ty) } None => { self.push_diagnostic(InferenceDiagnostic::NoSuchField { field: inner.into(), private: false, }); - None + self.err_ty() } } }; - let expected_ty = field_def.map_or(self.err_ty(), |f| { - field_types[f].clone().substitute(Interner, &substs) - }); - let expected_ty = self.normalize_associated_types_in(expected_ty); - T::infer(self, inner, &expected_ty, default_bm); } } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 9a468e2a23..a4ab1ebb8b 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -62,8 +62,8 @@ use crate::{ mapping::{from_chalk_trait_id, lt_to_placeholder_idx, 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, - InTypeConstIdMetadata, + self, all_super_trait_refs, associated_type_by_name_including_super_traits, generics, + Generics, InTypeConstIdMetadata, }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, @@ -245,13 +245,8 @@ impl<'a> TyLoweringContext<'a> { ) } - fn generics(&self) -> Generics { - generics( - self.db.upcast(), - self.resolver - .generic_def() - .expect("there should be generics if there's a generic param"), - ) + fn generics(&self) -> Option { + Some(generics(self.db.upcast(), self.resolver.generic_def()?)) } pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option) { @@ -352,8 +347,7 @@ impl<'a> TyLoweringContext<'a> { let idx = counter.get(); // FIXME we're probably doing something wrong here counter.set(idx + count_impl_traits(type_ref) as u16); - if let Some(def) = self.resolver.generic_def() { - let generics = generics(self.db.upcast(), def); + if let Some(generics) = self.generics() { let param = generics .iter() .filter(|(_, data)| { @@ -388,8 +382,7 @@ impl<'a> TyLoweringContext<'a> { const_params, _impl_trait_params, _lifetime_params, - ) = if let Some(def) = self.resolver.generic_def() { - let generics = generics(self.db.upcast(), def); + ) = if let Some(generics) = self.generics() { generics.provenance_split() } else { (0, 0, 0, 0, 0, 0) @@ -577,44 +570,40 @@ impl<'a> TyLoweringContext<'a> { // FIXME(trait_alias): Implement trait alias. return (TyKind::Error.intern(Interner), None); } - TypeNs::GenericParam(param_id) => { - let generics = generics( - self.db.upcast(), - self.resolver.generic_def().expect("generics in scope"), - ); - match self.type_param_mode { - ParamLoweringMode::Placeholder => { - TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into())) - } - ParamLoweringMode::Variable => { - let idx = match generics.param_idx(param_id.into()) { - None => { - never!("no matching generics"); - return (TyKind::Error.intern(Interner), None); - } - Some(idx) => idx, - }; - - TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) - } + TypeNs::GenericParam(param_id) => match self.type_param_mode { + ParamLoweringMode::Placeholder => { + TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into())) + } + ParamLoweringMode::Variable => { + let idx = match self + .generics() + .expect("generics in scope") + .param_idx(param_id.into()) + { + None => { + never!("no matching generics"); + return (TyKind::Error.intern(Interner), None); + } + Some(idx) => idx, + }; + + TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) } - .intern(Interner) } + .intern(Interner), TypeNs::SelfType(impl_id) => { - let def = - self.resolver.generic_def().expect("impl should have generic param scope"); - let generics = generics(self.db.upcast(), def); + let generics = self.generics().expect("impl should have generic param scope"); 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 generics = generics.parent_or_self(); let subst = generics.placeholder_subst(self.db); self.db.impl_self_ty(impl_id).substitute(Interner, &subst) } ParamLoweringMode::Variable => { - let starting_from = match def { + let starting_from = match generics.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 @@ -682,12 +671,12 @@ impl<'a> TyLoweringContext<'a> { } fn select_associated_type(&self, res: Option, segment: PathSegment<'_>) -> Ty { - let Some((def, res)) = self.resolver.generic_def().zip(res) else { + let Some((generics, res)) = self.generics().zip(res) else { return TyKind::Error.intern(Interner); }; let ty = named_associated_type_shorthand_candidates( self.db, - def, + generics.def(), res, Some(segment.name.clone()), move |name, t, associated_ty| { @@ -699,7 +688,6 @@ impl<'a> TyLoweringContext<'a> { 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) } @@ -721,7 +709,7 @@ impl<'a> TyLoweringContext<'a> { None, ); - let len_self = generics(self.db.upcast(), associated_ty.into()).len_self(); + let len_self = utils::generics(self.db.upcast(), associated_ty.into()).len_self(); let substs = Substitution::from_iter( Interner, @@ -1029,18 +1017,17 @@ impl<'a> TyLoweringContext<'a> { | WherePredicate::TypeBound { target, bound } => { let self_ty = match target { WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref), - WherePredicateTypeTarget::TypeOrConstParam(param_id) => { - let generic_def = self.resolver.generic_def().expect("generics in scope"); - let generics = generics(self.db.upcast(), generic_def); - let param_id = hir_def::TypeOrConstParamId { - parent: generic_def, - local_id: *param_id, - }; - let placeholder = to_placeholder_idx(self.db, param_id); + &WherePredicateTypeTarget::TypeOrConstParam(local_id) => { + let def = self.resolver.generic_def().expect("generics in scope"); + let param_id = hir_def::TypeOrConstParamId { parent: def, local_id }; match self.type_param_mode { - ParamLoweringMode::Placeholder => TyKind::Placeholder(placeholder), + ParamLoweringMode::Placeholder => { + TyKind::Placeholder(to_placeholder_idx(self.db, param_id)) + } ParamLoweringMode::Variable => { - let idx = generics.param_idx(param_id).expect("matching generics"); + let idx = generics(self.db.upcast(), def) + .param_idx(param_id) + .expect("matching generics"); TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx)) } } @@ -1218,8 +1205,8 @@ impl<'a> TyLoweringContext<'a> { }); if let Some(target_param_idx) = target_param_idx { let mut counter = 0; - for (idx, data) in self.generics().params.type_or_consts.iter() - { + let generics = self.generics().expect("generics in scope"); + for (idx, data) in 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 @@ -1409,10 +1396,7 @@ impl<'a> TyLoweringContext<'a> { 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 generics = self.generics().expect("generics in scope"); let idx = match generics.lifetime_idx(id) { None => return error_lifetime(), Some(idx) => idx, @@ -2258,7 +2242,7 @@ pub(crate) fn const_or_path_to_chalk( expected_ty: Ty, value: &ConstRef, mode: ParamLoweringMode, - args: impl FnOnce() -> Generics, + args: impl FnOnce() -> Option, debruijn: DebruijnIndex, ) -> Const { match value { @@ -2277,7 +2261,7 @@ pub(crate) fn const_or_path_to_chalk( .unwrap_or_else(|| unknown_const(expected_ty)) } &ConstRef::Complex(it) => { - let crate_data = &db.crate_graph()[owner.module(db.upcast()).krate()]; + let crate_data = &db.crate_graph()[resolver.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 diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index afd4d1f271..77c5fd054d 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -262,7 +262,7 @@ impl<'a> ClosureSubst<'a> { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub(crate) struct Generics { def: GenericDefId, pub(crate) params: Interned, @@ -274,6 +274,10 @@ impl Generics { self.iter().map(|(id, _)| id) } + pub(crate) fn def(&self) -> GenericDefId { + self.def + } + /// Iterator over types and const params of self, then parent. pub(crate) fn iter<'a>( &'a self, @@ -450,6 +454,10 @@ impl Generics { self.parent_generics.as_deref() } + pub(crate) fn parent_or_self(&self) -> &Generics { + self.parent_generics.as_deref().unwrap_or(self) + } + /// Returns a Substitution that replaces each parameter by a bound variable. pub(crate) fn bound_vars_subst( &self, diff --git a/crates/limit/Cargo.toml b/crates/limit/Cargo.toml index c89722cc40..c1a768833b 100644 --- a/crates/limit/Cargo.toml +++ b/crates/limit/Cargo.toml @@ -10,7 +10,6 @@ rust-version.workspace = true [features] tracking = [] -default = ["tracking"] [lints] -workspace = true \ No newline at end of file +workspace = true