From 86967032f75bc0d3a1f09a6520a9f78d2f433118 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 3 Apr 2024 08:57:48 +0200 Subject: [PATCH] Consider ADT generic parameter defaults for unsubstituted layout calculations --- crates/hir-ty/src/builder.rs | 12 ++++++-- crates/hir/src/lib.rs | 10 +++---- crates/ide/src/hover/tests.rs | 47 ++++++++++++++++++++++++++++++++ crates/proc-macro-api/src/lib.rs | 2 +- 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs index cb118a36848..41acd3555eb 100644 --- a/crates/hir-ty/src/builder.rs +++ b/crates/hir-ty/src/builder.rs @@ -74,6 +74,10 @@ fn build_internal(self) -> (D, Substitution) { (self.data, subst) } + pub fn build_into_subst(self) -> Substitution { + self.build_internal().1 + } + pub fn push(mut self, arg: impl CastTo) -> Self { assert!(self.remaining() > 0); let arg = arg.cast(Interner); @@ -291,7 +295,6 @@ pub fn fill_with_defaults( ) -> 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 @@ pub fn fill_with_defaults( } } // 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 d1735e9f1d3..503c5493274 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1418,16 +1418,14 @@ pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { } pub fn layout(self, db: &dyn HirDatabase) -> Result { - 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 d1721f1191a..754fb2eccdb 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -2322,6 +2322,49 @@ fn test_hover_layout_of_variant() { ); } +#[test] +fn test_hover_layout_of_variant_generic() { + check( + r#"enum Option { + 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(core::marker::PhantomData); +"#, + expect![[r#" + *S* + + ```rust + test + ``` + + ```rust + // size = 0, align = 1 + struct S(PhantomData) + ``` + "#]], + ); +} + #[test] fn test_hover_layout_of_enum() { check( @@ -3673,6 +3716,7 @@ fn const_generic_order() { ``` ```rust + // size = 0, align = 1 struct ST(T) ``` "#]], @@ -3694,6 +3738,7 @@ fn const_generic_default_value() { ``` ```rust + // size = 0, align = 1 struct ST(T) ``` "#]], @@ -3716,6 +3761,7 @@ fn const_generic_default_value_2() { ``` ```rust + // size = 0, align = 1 struct ST(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 fd491644648..3c0c904babe 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, }