mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 05:38:46 +00:00
Resolve tuple variants in value namespace
This commit is contained in:
parent
0bee7cb716
commit
b596c32a41
4 changed files with 55 additions and 7 deletions
|
@ -23,7 +23,7 @@ use hir_def::{
|
|||
expr::{ArithOp, BinaryOp, BindingAnnotation, ExprId, PatId},
|
||||
lang_item::LangItemTarget,
|
||||
path::{path, Path},
|
||||
resolver::{HasResolver, Resolver, TypeNs},
|
||||
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||
type_ref::TypeRef,
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule, Lookup,
|
||||
TraitId, TypeAliasId, VariantId,
|
||||
|
@ -548,7 +548,7 @@ impl<'a> InferenceContext<'a> {
|
|||
self.table.normalize_associated_types_in(ty)
|
||||
}
|
||||
|
||||
fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
|
||||
fn resolve_variant(&mut self, path: Option<&Path>, value_ns: bool) -> (Ty, Option<VariantId>) {
|
||||
let path = match path {
|
||||
Some(path) => path,
|
||||
None => return (self.err_ty(), None),
|
||||
|
@ -557,11 +557,32 @@ impl<'a> InferenceContext<'a> {
|
|||
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
|
||||
// FIXME: this should resolve assoc items as well, see this example:
|
||||
// https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
|
||||
let (resolution, unresolved) =
|
||||
let (resolution, unresolved) = if value_ns {
|
||||
match resolver.resolve_path_in_value_ns(self.db.upcast(), path.mod_path()) {
|
||||
Some(ResolveValueResult::ValueNs(value)) => match value {
|
||||
ValueNs::EnumVariantId(var) => {
|
||||
let substs = ctx.substs_from_path(path, var.into(), true);
|
||||
let ty = self.db.ty(var.parent.into());
|
||||
let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
|
||||
return (ty, Some(var.into()));
|
||||
}
|
||||
ValueNs::StructId(strukt) => {
|
||||
let substs = ctx.substs_from_path(path, strukt.into(), true);
|
||||
let ty = self.db.ty(strukt.into());
|
||||
let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
|
||||
return (ty, Some(strukt.into()));
|
||||
}
|
||||
_ => return (self.err_ty(), None),
|
||||
},
|
||||
Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)),
|
||||
None => return (self.err_ty(), None),
|
||||
}
|
||||
} else {
|
||||
match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
|
||||
Some(it) => it,
|
||||
None => return (self.err_ty(), None),
|
||||
};
|
||||
}
|
||||
};
|
||||
return match resolution {
|
||||
TypeNs::AdtId(AdtId::StructId(strukt)) => {
|
||||
let substs = ctx.substs_from_path(path, strukt.into(), true);
|
||||
|
|
|
@ -437,7 +437,7 @@ impl<'a> InferenceContext<'a> {
|
|||
TyKind::Never.intern(&Interner)
|
||||
}
|
||||
Expr::RecordLit { path, fields, spread } => {
|
||||
let (ty, def_id) = self.resolve_variant(path.as_deref());
|
||||
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
|
||||
if let Some(variant) = def_id {
|
||||
self.write_variant_resolution(tgt_expr.into(), variant);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ impl<'a> InferenceContext<'a> {
|
|||
id: PatId,
|
||||
ellipsis: Option<usize>,
|
||||
) -> Ty {
|
||||
let (ty, def) = self.resolve_variant(path);
|
||||
let (ty, def) = self.resolve_variant(path, true);
|
||||
let var_data = def.map(|it| it.variant_data(self.db.upcast()));
|
||||
if let Some(variant) = def {
|
||||
self.write_variant_resolution(id.into(), variant);
|
||||
|
@ -68,7 +68,7 @@ impl<'a> InferenceContext<'a> {
|
|||
default_bm: BindingMode,
|
||||
id: PatId,
|
||||
) -> Ty {
|
||||
let (ty, def) = self.resolve_variant(path);
|
||||
let (ty, def) = self.resolve_variant(path, false);
|
||||
let var_data = def.map(|it| it.variant_data(self.db.upcast()));
|
||||
if let Some(variant) = def {
|
||||
self.write_variant_resolution(id.into(), variant);
|
||||
|
|
|
@ -889,3 +889,30 @@ fn main() {
|
|||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_lookup_in_value_ns() {
|
||||
check_types(
|
||||
r#"
|
||||
use self::Constructor::*;
|
||||
struct IntRange {
|
||||
range: (),
|
||||
}
|
||||
enum Constructor {
|
||||
IntRange(IntRange),
|
||||
}
|
||||
fn main() {
|
||||
match Constructor::IntRange(IntRange { range: () }) {
|
||||
IntRange(x) => {
|
||||
x;
|
||||
//^ IntRange
|
||||
}
|
||||
Constructor::IntRange(x) => {
|
||||
x;
|
||||
//^ IntRange
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue