Unnamed repository; edit this file 'description' to name the repository.
Consider ADT generic parameter defaults for unsubstituted layout calculations
Lukas Wirth 2024-04-03
parent c3b8c2a · commit 8696703
-rw-r--r--crates/hir-ty/src/builder.rs12
-rw-r--r--crates/hir/src/lib.rs10
-rw-r--r--crates/ide/src/hover/tests.rs47
-rw-r--r--crates/proc-macro-api/src/lib.rs2
4 files changed, 61 insertions, 10 deletions
diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs
index cb118a3684..41acd3555e 100644
--- a/crates/hir-ty/src/builder.rs
+++ b/crates/hir-ty/src/builder.rs
@@ -74,6 +74,10 @@ impl<D> TyBuilder<D> {
(self.data, subst)
}
+ pub fn build_into_subst(self) -> Substitution {
+ self.build_internal().1
+ }
+
pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
assert!(self.remaining() > 0);
let arg = arg.cast(Interner);
@@ -291,7 +295,6 @@ impl TyBuilder<hir_def::AdtId> {
) -> Self {
// Note that we're building ADT, so we never have parent generic parameters.
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()) {
// NOTE(skip_binders): we only check if the arg type is error type.
if let Some(x) = default_ty.skip_binders().ty(Interner) {
@@ -301,13 +304,16 @@ impl TyBuilder<hir_def::AdtId> {
}
}
// Each default can only depend on the previous parameters.
- // FIXME: we don't handle const generics here.
let subst_so_far = Substitution::from_iter(
Interner,
self.vec
.iter()
.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()),
);
self.vec.push(default_ty.clone().substitute(Interner, &subst_so_far).cast(Interner));
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index d1735e9f1d..503c549327 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1418,16 +1418,14 @@ impl Adt {
}
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(
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()),
)
- .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
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index d1721f1191..754fb2eccd 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -2323,6 +2323,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]
fn test_hover_layout_of_enum() {
check(
r#"enum $0Foo {
@@ -3673,6 +3716,7 @@ struct S$0T<const C: usize = 1, T = Foo>(T);
```
```rust
+ // size = 0, align = 1
struct ST<const C: usize = 1, T = Foo>(T)
```
"#]],
@@ -3694,6 +3738,7 @@ struct S$0T<const C: usize = {40 + 2}, T = Foo>(T);
```
```rust
+ // size = 0, align = 1
struct ST<const C: usize = {const}, T = Foo>(T)
```
"#]],
@@ -3716,6 +3761,7 @@ struct S$0T<const C: usize = VAL, T = Foo>(T);
```
```rust
+ // size = 0, align = 1
struct ST<const C: usize = VAL, T = Foo>(T)
```
"#]],
@@ -7872,6 +7918,7 @@ struct Pedro$0<'a> {
```
```rust
+ // size = 16 (0x10), align = 8, niches = 1
struct Pedro<'a>
```
"#]],
diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs
index fd49164464..3c0c904bab 100644
--- a/crates/proc-macro-api/src/lib.rs
+++ b/crates/proc-macro-api/src/lib.rs
@@ -37,7 +37,7 @@ pub enum ProcMacroKind {
CustomDerive,
Attr,
// 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"))]
Bang,
}