mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Consider ADT generic parameter defaults for unsubstituted layout calculations
This commit is contained in:
parent
c3b8c2a254
commit
86967032f7
4 changed files with 61 additions and 10 deletions
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
fn test_hover_layout_of_enum() {
|
||||
check(
|
||||
|
@ -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>
|
||||
```
|
||||
"#]],
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue