Skip to content

Commit ddb971a

Browse files
committed
Handle return types for in type const bodies
1 parent f6b57e1 commit ddb971a

File tree

6 files changed

+125
-16
lines changed

6 files changed

+125
-16
lines changed

crates/hir-def/src/db.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ use crate::{
2525
AnonymousConstId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId,
2626
EnumLoc, ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc,
2727
InTypeConstId, LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId,
28-
MacroRulesLoc, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc,
29-
TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, TypeOwnerId,
30-
UnionId, UnionLoc, VariantId,
28+
MacroRulesLoc, OpaqueInternableThing, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId,
29+
StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc,
30+
TypeOwnerId, UnionId, UnionLoc, VariantId,
3131
};
3232

3333
#[salsa::query_group(InternDatabaseStorage)]
@@ -65,7 +65,10 @@ pub trait InternDatabase: SourceDatabase {
6565
#[salsa::interned]
6666
fn intern_anonymous_const(&self, id: (DefWithBodyId, ExprId)) -> AnonymousConstId;
6767
#[salsa::interned]
68-
fn intern_in_type_const(&self, id: (AstId<ast::Expr>, TypeOwnerId)) -> InTypeConstId;
68+
fn intern_in_type_const(
69+
&self,
70+
id: (AstId<ast::Expr>, TypeOwnerId, Box<dyn OpaqueInternableThing>),
71+
) -> InTypeConstId;
6972
}
7073

7174
#[salsa::query_group(DefDatabaseStorage)]

crates/hir-def/src/lib.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ mod test_db;
5757
mod macro_expansion_tests;
5858
mod pretty;
5959

60-
use std::hash::{Hash, Hasher};
60+
use std::{
61+
hash::{Hash, Hasher},
62+
panic::{RefUnwindSafe, UnwindSafe},
63+
};
6164

6265
use base_db::{
6366
impl_intern_key,
@@ -501,9 +504,40 @@ impl TypeOwnerId {
501504

502505
impl_from!(ModuleId, DefWithBodyId(FunctionId, ConstId, StaticId), GenericDefId(AdtId, TypeAliasId, ImplId) for TypeOwnerId);
503506

507+
/// A thing that we want to store in interned ids, but we don't know its type in `hir-def`
508+
pub trait OpaqueInternableThing:
509+
std::any::Any + std::fmt::Debug + Sync + Send + UnwindSafe + RefUnwindSafe
510+
{
511+
fn as_any(&self) -> &dyn std::any::Any;
512+
fn box_any(&self) -> Box<dyn std::any::Any>;
513+
fn dyn_hash(&self, state: &mut dyn Hasher);
514+
fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool;
515+
fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing>;
516+
}
517+
518+
impl Hash for dyn OpaqueInternableThing {
519+
fn hash<H: Hasher>(&self, state: &mut H) {
520+
self.dyn_hash(state);
521+
}
522+
}
523+
524+
impl PartialEq for dyn OpaqueInternableThing {
525+
fn eq(&self, other: &Self) -> bool {
526+
self.dyn_eq(other)
527+
}
528+
}
529+
530+
impl Eq for dyn OpaqueInternableThing {}
531+
532+
impl Clone for Box<dyn OpaqueInternableThing> {
533+
fn clone(&self) -> Self {
534+
self.dyn_clone()
535+
}
536+
}
537+
504538
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
505539
pub struct InTypeConstId(InternId);
506-
type InTypeConstLoc = (AstId<ast::Expr>, TypeOwnerId);
540+
type InTypeConstLoc = (AstId<ast::Expr>, TypeOwnerId, Box<dyn OpaqueInternableThing>);
507541
impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const);
508542

509543
impl InTypeConstId {
@@ -535,7 +569,7 @@ impl GeneralConstId {
535569
parent.as_generic_def_id()
536570
}
537571
GeneralConstId::InTypeConstId(x) => {
538-
let (_, parent) = x.lookup(db);
572+
let (_, parent, _) = x.lookup(db);
539573
parent.as_generic_def_id()
540574
}
541575
}

crates/hir-ty/src/infer.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,13 @@ use stdx::{always, never};
4141
use triomphe::Arc;
4242

4343
use crate::{
44-
db::HirDatabase, fold_tys, infer::coerce::CoerceMany, lower::ImplTraitLoweringMode,
45-
static_lifetime, to_assoc_type_id, traits::FnTrait, utils::UnevaluatedConstEvaluatorFolder,
44+
db::HirDatabase,
45+
fold_tys,
46+
infer::coerce::CoerceMany,
47+
lower::ImplTraitLoweringMode,
48+
static_lifetime, to_assoc_type_id,
49+
traits::FnTrait,
50+
utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
4651
AliasEq, AliasTy, ClosureId, DomainGoal, GenericArg, Goal, ImplTraitId, InEnvironment,
4752
Interner, ProjectionTy, RpitId, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt,
4853
};
@@ -102,9 +107,9 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
102107
},
103108
});
104109
}
105-
DefWithBodyId::InTypeConstId(_) => {
106-
// FIXME: We should know the expected type here.
107-
ctx.return_ty = ctx.table.new_type_var();
110+
DefWithBodyId::InTypeConstId(c) => {
111+
ctx.return_ty =
112+
c.lookup(db.upcast()).2.box_any().downcast::<InTypeConstIdMetadata>().unwrap().0;
108113
}
109114
}
110115

crates/hir-ty/src/lower.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ use crate::{
5353
mapping::{from_chalk_trait_id, ToChalk},
5454
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
5555
utils::Generics,
56-
utils::{all_super_trait_refs, associated_type_by_name_including_super_traits, generics},
56+
utils::{
57+
all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
58+
InTypeConstIdMetadata,
59+
},
5760
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
5861
FnPointer, FnSig, FnSubst, GenericArgData, ImplTraitId, Interner, ParamKind, PolyFnSig,
5962
ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait,
@@ -2052,7 +2055,13 @@ pub(crate) fn const_or_path_to_chalk(
20522055
// that are unlikely to be edited.
20532056
return unknown_const(expected_ty);
20542057
}
2055-
let c = db.intern_in_type_const((x, owner)).into();
2058+
let c = db
2059+
.intern_in_type_const((
2060+
x,
2061+
owner,
2062+
Box::new(InTypeConstIdMetadata(expected_ty.clone())),
2063+
))
2064+
.into();
20562065
intern_const_scalar(
20572066
ConstScalar::UnevaluatedConst(c, Substitution::empty(Interner)),
20582067
expected_ty,

crates/hir-ty/src/tests/simple.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,6 +1828,38 @@ impl Foo for u8 {
18281828
);
18291829
}
18301830

1831+
#[test]
1832+
fn const_eval_in_function_signature() {
1833+
check_types(
1834+
r#"
1835+
const fn foo() -> usize {
1836+
5
1837+
}
1838+
1839+
fn f() -> [u8; foo()] {
1840+
loop {}
1841+
}
1842+
1843+
fn main() {
1844+
let t = f();
1845+
//^ [u8; 5]
1846+
}"#,
1847+
);
1848+
check_types(
1849+
r#"
1850+
//- minicore: default, builtin_impls
1851+
fn f() -> [u8; Default::default()] {
1852+
loop {}
1853+
}
1854+
1855+
fn main() {
1856+
let t = f();
1857+
//^ [u8; 0]
1858+
}
1859+
"#,
1860+
);
1861+
}
1862+
18311863
#[test]
18321864
fn shadowing_primitive_with_inner_items() {
18331865
check_types(

crates/hir-ty/src/utils.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Helper functions for working with def, which don't need to be a separate
22
//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
33
4-
use std::iter;
4+
use std::{hash::Hash, iter};
55

66
use base_db::CrateId;
77
use chalk_ir::{
@@ -20,7 +20,8 @@ use hir_def::{
2020
resolver::{HasResolver, TypeNs},
2121
type_ref::{TraitBoundModifier, TypeRef},
2222
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId,
23-
LocalEnumVariantId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
23+
LocalEnumVariantId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
24+
TypeParamId,
2425
};
2526
use hir_expand::name::Name;
2627
use intern::Interned;
@@ -464,3 +465,28 @@ pub(crate) fn detect_variant_from_bytes<'a>(
464465
};
465466
Some((var_id, var_layout))
466467
}
468+
469+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
470+
pub(crate) struct InTypeConstIdMetadata(pub(crate) Ty);
471+
472+
impl OpaqueInternableThing for InTypeConstIdMetadata {
473+
fn dyn_hash(&self, mut state: &mut dyn std::hash::Hasher) {
474+
self.hash(&mut state);
475+
}
476+
477+
fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool {
478+
other.as_any().downcast_ref::<Self>().map_or(false, |x| self == x)
479+
}
480+
481+
fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing> {
482+
Box::new(self.clone())
483+
}
484+
485+
fn as_any(&self) -> &dyn std::any::Any {
486+
self
487+
}
488+
489+
fn box_any(&self) -> Box<dyn std::any::Any> {
490+
Box::new(self.clone())
491+
}
492+
}

0 commit comments

Comments
 (0)