Merge #3490
3490: Support aliases and Self in struct literals r=matklad a=flodiebold Fixes #3306. Co-authored-by: Florian Diebold <florian.diebold@freiheit.com>
This commit is contained in:
commit
995a92814f
@ -425,7 +425,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
|
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
|
||||||
// FIXME: this should resolve assoc items as well, see this example:
|
// FIXME: this should resolve assoc items as well, see this example:
|
||||||
// https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
|
// https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
|
||||||
match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) {
|
return match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) {
|
||||||
Some(TypeNs::AdtId(AdtId::StructId(strukt))) => {
|
Some(TypeNs::AdtId(AdtId::StructId(strukt))) => {
|
||||||
let substs = Ty::substs_from_path(&ctx, path, strukt.into());
|
let substs = Ty::substs_from_path(&ctx, path, strukt.into());
|
||||||
let ty = self.db.ty(strukt.into());
|
let ty = self.db.ty(strukt.into());
|
||||||
@ -438,7 +438,33 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
let ty = self.insert_type_vars(ty.subst(&substs));
|
let ty = self.insert_type_vars(ty.subst(&substs));
|
||||||
(ty, Some(var.into()))
|
(ty, Some(var.into()))
|
||||||
}
|
}
|
||||||
|
Some(TypeNs::SelfType(impl_id)) => {
|
||||||
|
let generics = crate::utils::generics(self.db, impl_id.into());
|
||||||
|
let substs = Substs::type_params_for_generics(&generics);
|
||||||
|
let ty = self.db.impl_self_ty(impl_id).subst(&substs);
|
||||||
|
let variant = ty_variant(&ty);
|
||||||
|
(ty, variant)
|
||||||
|
}
|
||||||
|
Some(TypeNs::TypeAliasId(it)) => {
|
||||||
|
let substs = Substs::build_for_def(self.db, it)
|
||||||
|
.fill(std::iter::repeat_with(|| self.table.new_type_var()))
|
||||||
|
.build();
|
||||||
|
let ty = self.db.ty(it.into()).subst(&substs);
|
||||||
|
let variant = ty_variant(&ty);
|
||||||
|
(ty, variant)
|
||||||
|
}
|
||||||
Some(_) | None => (Ty::Unknown, None),
|
Some(_) | None => (Ty::Unknown, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
fn ty_variant(ty: &Ty) -> Option<VariantId> {
|
||||||
|
ty.as_adt().and_then(|(adt_id, _)| match adt_id {
|
||||||
|
AdtId::StructId(s) => Some(VariantId::StructId(s)),
|
||||||
|
AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
|
||||||
|
AdtId::EnumId(_) => {
|
||||||
|
// Error E0071, expected struct, variant or union type, found enum `Foo`
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,47 @@ fn test() {
|
|||||||
assert_eq!("Nat", type_at_pos(&db, pos));
|
assert_eq!("Nat", type_at_pos(&db, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn self_in_struct_lit() {
|
||||||
|
assert_snapshot!(infer(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
struct S<T> { x: T }
|
||||||
|
|
||||||
|
impl S<u32> {
|
||||||
|
fn foo() {
|
||||||
|
Self { x: 1 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
), @r###"
|
||||||
|
[63; 93) '{ ... }': ()
|
||||||
|
[73; 86) 'Self { x: 1 }': S<u32>
|
||||||
|
[83; 84) '1': u32
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_alias_in_struct_lit() {
|
||||||
|
assert_snapshot!(infer(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
struct S<T> { x: T }
|
||||||
|
|
||||||
|
type SS = S<u32>;
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
SS { x: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
"#,
|
||||||
|
), @r###"
|
||||||
|
[64; 84) '{ ...1 }; }': ()
|
||||||
|
[70; 81) 'SS { x: 1 }': S<u32>
|
||||||
|
[78; 79) '1': u32
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_ranges() {
|
fn infer_ranges() {
|
||||||
let (db, pos) = TestDB::with_position(
|
let (db, pos) = TestDB::with_position(
|
||||||
|
@ -472,6 +472,33 @@ mod tests {
|
|||||||
check_apply_diagnostic_fix(before, after);
|
check_apply_diagnostic_fix(before, after);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fill_struct_fields_self() {
|
||||||
|
let before = r"
|
||||||
|
struct TestStruct {
|
||||||
|
one: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestStruct {
|
||||||
|
fn test_fn() {
|
||||||
|
let s = Self {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
let after = r"
|
||||||
|
struct TestStruct {
|
||||||
|
one: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestStruct {
|
||||||
|
fn test_fn() {
|
||||||
|
let s = Self { one: ()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
";
|
||||||
|
check_apply_diagnostic_fix(before, after);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fill_struct_fields_enum() {
|
fn test_fill_struct_fields_enum() {
|
||||||
let before = r"
|
let before = r"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user