Unnamed repository; edit this file 'description' to name the repository.
Handle return types for in type const bodies
| -rw-r--r-- | crates/hir-def/src/db.rs | 11 | ||||
| -rw-r--r-- | crates/hir-def/src/lib.rs | 40 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 15 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 13 | ||||
| -rw-r--r-- | crates/hir-ty/src/tests/simple.rs | 32 | ||||
| -rw-r--r-- | crates/hir-ty/src/utils.rs | 30 |
6 files changed, 125 insertions, 16 deletions
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 3257667780..28e76fb5a8 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -25,9 +25,9 @@ use crate::{ AnonymousConstId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, - MacroRulesLoc, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, - TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, TypeOwnerId, - UnionId, UnionLoc, VariantId, + MacroRulesLoc, OpaqueInternableThing, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, + StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, + TypeOwnerId, UnionId, UnionLoc, VariantId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -65,7 +65,10 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_anonymous_const(&self, id: (DefWithBodyId, ExprId)) -> AnonymousConstId; #[salsa::interned] - fn intern_in_type_const(&self, id: (AstId<ast::Expr>, TypeOwnerId)) -> InTypeConstId; + fn intern_in_type_const( + &self, + id: (AstId<ast::Expr>, TypeOwnerId, Box<dyn OpaqueInternableThing>), + ) -> InTypeConstId; } #[salsa::query_group(DefDatabaseStorage)] diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 44dd0a7b38..e90572ec97 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -57,7 +57,10 @@ mod test_db; mod macro_expansion_tests; mod pretty; -use std::hash::{Hash, Hasher}; +use std::{ + hash::{Hash, Hasher}, + panic::{RefUnwindSafe, UnwindSafe}, +}; use base_db::{ impl_intern_key, @@ -501,9 +504,40 @@ impl TypeOwnerId { impl_from!(ModuleId, DefWithBodyId(FunctionId, ConstId, StaticId), GenericDefId(AdtId, TypeAliasId, ImplId) for TypeOwnerId); +/// A thing that we want to store in interned ids, but we don't know its type in `hir-def` +pub trait OpaqueInternableThing: + std::any::Any + std::fmt::Debug + Sync + Send + UnwindSafe + RefUnwindSafe +{ + fn as_any(&self) -> &dyn std::any::Any; + fn box_any(&self) -> Box<dyn std::any::Any>; + fn dyn_hash(&self, state: &mut dyn Hasher); + fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool; + fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing>; +} + +impl Hash for dyn OpaqueInternableThing { + fn hash<H: Hasher>(&self, state: &mut H) { + self.dyn_hash(state); + } +} + +impl PartialEq for dyn OpaqueInternableThing { + fn eq(&self, other: &Self) -> bool { + self.dyn_eq(other) + } +} + +impl Eq for dyn OpaqueInternableThing {} + +impl Clone for Box<dyn OpaqueInternableThing> { + fn clone(&self) -> Self { + self.dyn_clone() + } +} + #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub struct InTypeConstId(InternId); -type InTypeConstLoc = (AstId<ast::Expr>, TypeOwnerId); +type InTypeConstLoc = (AstId<ast::Expr>, TypeOwnerId, Box<dyn OpaqueInternableThing>); impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const); impl InTypeConstId { @@ -535,7 +569,7 @@ impl GeneralConstId { parent.as_generic_def_id() } GeneralConstId::InTypeConstId(x) => { - let (_, parent) = x.lookup(db); + let (_, parent, _) = x.lookup(db); parent.as_generic_def_id() } } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index ef1fd6d458..6399fa052b 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -41,8 +41,13 @@ use stdx::{always, never}; use triomphe::Arc; use crate::{ - db::HirDatabase, fold_tys, infer::coerce::CoerceMany, lower::ImplTraitLoweringMode, - static_lifetime, to_assoc_type_id, traits::FnTrait, utils::UnevaluatedConstEvaluatorFolder, + db::HirDatabase, + fold_tys, + infer::coerce::CoerceMany, + lower::ImplTraitLoweringMode, + static_lifetime, to_assoc_type_id, + traits::FnTrait, + utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder}, AliasEq, AliasTy, ClosureId, DomainGoal, GenericArg, Goal, ImplTraitId, InEnvironment, Interner, ProjectionTy, RpitId, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, }; @@ -102,9 +107,9 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer }, }); } - DefWithBodyId::InTypeConstId(_) => { - // FIXME: We should know the expected type here. - ctx.return_ty = ctx.table.new_type_var(); + DefWithBodyId::InTypeConstId(c) => { + ctx.return_ty = + c.lookup(db.upcast()).2.box_any().downcast::<InTypeConstIdMetadata>().unwrap().0; } } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 65884b28ff..c0bcf790b1 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -53,7 +53,10 @@ use crate::{ mapping::{from_chalk_trait_id, ToChalk}, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, utils::Generics, - utils::{all_super_trait_refs, associated_type_by_name_including_super_traits, generics}, + utils::{ + all_super_trait_refs, associated_type_by_name_including_super_traits, generics, + InTypeConstIdMetadata, + }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, FnPointer, FnSig, FnSubst, GenericArgData, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, @@ -2052,7 +2055,13 @@ pub(crate) fn const_or_path_to_chalk( // that are unlikely to be edited. return unknown_const(expected_ty); } - let c = db.intern_in_type_const((x, owner)).into(); + let c = db + .intern_in_type_const(( + x, + owner, + Box::new(InTypeConstIdMetadata(expected_ty.clone())), + )) + .into(); intern_const_scalar( ConstScalar::UnevaluatedConst(c, Substitution::empty(Interner)), expected_ty, diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index 3ece40486d..fb0aa2faf1 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -1829,6 +1829,38 @@ impl Foo for u8 { } #[test] +fn const_eval_in_function_signature() { + check_types( + r#" +const fn foo() -> usize { + 5 +} + +fn f() -> [u8; foo()] { + loop {} +} + +fn main() { + let t = f(); + //^ [u8; 5] +}"#, + ); + check_types( + r#" +//- minicore: default, builtin_impls +fn f() -> [u8; Default::default()] { + loop {} +} + +fn main() { + let t = f(); + //^ [u8; 0] +} + "#, + ); +} + +#[test] fn shadowing_primitive_with_inner_items() { check_types( r#" diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 681d087ede..3636580630 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -1,7 +1,7 @@ //! Helper functions for working with def, which don't need to be a separate //! query, but can't be computed directly from `*Data` (ie, which need a `db`). -use std::iter; +use std::{hash::Hash, iter}; use base_db::CrateId; use chalk_ir::{ @@ -20,7 +20,8 @@ use hir_def::{ resolver::{HasResolver, TypeNs}, type_ref::{TraitBoundModifier, TypeRef}, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, - LocalEnumVariantId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, + LocalEnumVariantId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, + TypeParamId, }; use hir_expand::name::Name; use intern::Interned; @@ -464,3 +465,28 @@ pub(crate) fn detect_variant_from_bytes<'a>( }; Some((var_id, var_layout)) } + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub(crate) struct InTypeConstIdMetadata(pub(crate) Ty); + +impl OpaqueInternableThing for InTypeConstIdMetadata { + fn dyn_hash(&self, mut state: &mut dyn std::hash::Hasher) { + self.hash(&mut state); + } + + fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool { + other.as_any().downcast_ref::<Self>().map_or(false, |x| self == x) + } + + fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing> { + Box::new(self.clone()) + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn box_any(&self) -> Box<dyn std::any::Any> { + Box::new(self.clone()) + } +} |