Consider ADT generic parameter defaults for unsubstituted layout calculations

This commit is contained in:
Lukas Wirth 2024-04-03 08:57:48 +02:00
parent c3b8c2a254
commit 86967032f7
4 changed files with 61 additions and 10 deletions

View File

@ -74,6 +74,10 @@ fn build_internal(self) -> (D, Substitution) {
(self.data, subst) (self.data, subst)
} }
pub fn build_into_subst(self) -> Substitution {
self.build_internal().1
}
pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self { pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
assert!(self.remaining() > 0); assert!(self.remaining() > 0);
let arg = arg.cast(Interner); let arg = arg.cast(Interner);
@ -291,7 +295,6 @@ pub fn fill_with_defaults(
) -> Self { ) -> Self {
// Note that we're building ADT, so we never have parent generic parameters. // Note that we're building ADT, so we never have parent generic parameters.
let defaults = db.generic_defaults(self.data.into()); let defaults = db.generic_defaults(self.data.into());
let dummy_ty = TyKind::Error.intern(Interner).cast(Interner);
for default_ty in defaults.iter().skip(self.vec.len()) { for default_ty in defaults.iter().skip(self.vec.len()) {
// NOTE(skip_binders): we only check if the arg type is error type. // NOTE(skip_binders): we only check if the arg type is error type.
if let Some(x) = default_ty.skip_binders().ty(Interner) { if let Some(x) = default_ty.skip_binders().ty(Interner) {
@ -301,13 +304,16 @@ pub fn fill_with_defaults(
} }
} }
// Each default can only depend on the previous parameters. // Each default can only depend on the previous parameters.
// FIXME: we don't handle const generics here.
let subst_so_far = Substitution::from_iter( let subst_so_far = Substitution::from_iter(
Interner, Interner,
self.vec self.vec
.iter() .iter()
.cloned() .cloned()
.chain(iter::repeat(dummy_ty.clone())) .chain(self.param_kinds[self.vec.len()..].iter().map(|it| match it {
ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
ParamKind::Lifetime => error_lifetime().cast(Interner),
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
}))
.take(self.param_kinds.len()), .take(self.param_kinds.len()),
); );
self.vec.push(default_ty.clone().substitute(Interner, &subst_so_far).cast(Interner)); self.vec.push(default_ty.clone().substitute(Interner, &subst_so_far).cast(Interner));

View File

@ -1418,16 +1418,14 @@ pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
} }
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
if !db.generic_params(self.into()).is_empty() {
return Err(LayoutError::HasPlaceholder);
}
let krate = self.krate(db).id;
db.layout_of_adt( db.layout_of_adt(
self.into(), self.into(),
Substitution::empty(Interner), TyBuilder::adt(db, self.into())
.fill_with_defaults(db, || TyKind::Error.intern(Interner))
.build_into_subst(),
db.trait_environment(self.into()), db.trait_environment(self.into()),
) )
.map(|layout| Layout(layout, db.target_data_layout(krate).unwrap())) .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap()))
} }
/// Turns this ADT into a type. Any type parameters of the ADT will be /// Turns this ADT into a type. Any type parameters of the ADT will be

View File

@ -2322,6 +2322,49 @@ fn test_hover_layout_of_variant() {
); );
} }
#[test]
fn test_hover_layout_of_variant_generic() {
check(
r#"enum Option<T> {
Some(T),
None$0
}"#,
expect![[r#"
*None*
```rust
test::Option
```
```rust
None
```
"#]],
);
}
#[test]
fn test_hover_layout_generic_unused() {
check(
r#"
//- minicore: phantom_data
struct S$0<T>(core::marker::PhantomData<T>);
"#,
expect![[r#"
*S*
```rust
test
```
```rust
// size = 0, align = 1
struct S<T>(PhantomData<T>)
```
"#]],
);
}
#[test] #[test]
fn test_hover_layout_of_enum() { fn test_hover_layout_of_enum() {
check( check(
@ -3673,6 +3716,7 @@ fn const_generic_order() {
``` ```
```rust ```rust
// size = 0, align = 1
struct ST<const C: usize = 1, T = Foo>(T) struct ST<const C: usize = 1, T = Foo>(T)
``` ```
"#]], "#]],
@ -3694,6 +3738,7 @@ fn const_generic_default_value() {
``` ```
```rust ```rust
// size = 0, align = 1
struct ST<const C: usize = {const}, T = Foo>(T) struct ST<const C: usize = {const}, T = Foo>(T)
``` ```
"#]], "#]],
@ -3716,6 +3761,7 @@ fn const_generic_default_value_2() {
``` ```
```rust ```rust
// size = 0, align = 1
struct ST<const C: usize = VAL, T = Foo>(T) struct ST<const C: usize = VAL, T = Foo>(T)
``` ```
"#]], "#]],
@ -7872,6 +7918,7 @@ struct Pedro$0<'a> {
``` ```
```rust ```rust
// size = 16 (0x10), align = 8, niches = 1
struct Pedro<'a> struct Pedro<'a>
``` ```
"#]], "#]],

View File

@ -37,7 +37,7 @@ pub enum ProcMacroKind {
CustomDerive, CustomDerive,
Attr, Attr,
// This used to be called FuncLike, so that's what the server expects currently. // This used to be called FuncLike, so that's what the server expects currently.
#[serde(alias = "bang")] #[serde(alias = "Bang")]
#[serde(rename(serialize = "FuncLike", deserialize = "FuncLike"))] #[serde(rename(serialize = "FuncLike", deserialize = "FuncLike"))]
Bang, Bang,
} }