From 3f42b2e837c4672a0fbe953e14ae2fd3fe6fc3b6 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 15 May 2020 17:15:40 +0200 Subject: Handle `Self` in values and patterns I.e. - `Self(x)` or `Self` in tuple/unit struct impls - `Self::Variant(x)` or `Self::Variant` in enum impls - the same in patterns Fixes #4454. --- crates/ra_hir_ty/src/infer/path.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir_ty/src/infer') diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 2b6bc0f79..1c2e56fb0 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -5,7 +5,7 @@ use std::iter; use hir_def::{ path::{Path, PathSegment}, resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, - AssocContainerId, AssocItemId, Lookup, + AdtId, AssocContainerId, AssocItemId, EnumVariantId, Lookup, }; use hir_expand::name::Name; @@ -77,6 +77,18 @@ impl<'a> InferenceContext<'a> { it.into() } + ValueNs::ImplSelf(impl_id) => { + let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); + let substs = Substs::type_params_for_generics(&generics); + let ty = self.db.impl_self_ty(impl_id).subst(&substs); + if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() { + let ty = self.db.value_ty(struct_id.into()).subst(&substs); + return Some(ty); + } else { + // FIXME: diagnostic, invalid Self reference + return None; + } + } }; let ty = self.db.value_ty(typable); @@ -199,6 +211,10 @@ impl<'a> InferenceContext<'a> { return None; } + if let Some(result) = self.resolve_enum_variant_on_ty(&ty, name, id) { + return Some(result); + } + let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); let krate = self.resolver.krate()?; let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast()); @@ -250,4 +266,21 @@ impl<'a> InferenceContext<'a> { }, ) } + + fn resolve_enum_variant_on_ty( + &mut self, + ty: &Ty, + name: &Name, + id: ExprOrPatId, + ) -> Option<(ValueNs, Option)> { + let (enum_id, subst) = match ty.as_adt() { + Some((AdtId::EnumId(e), subst)) => (e, subst), + _ => return None, + }; + let enum_data = self.db.enum_data(enum_id); + let local_id = enum_data.variant(name)?; + let variant = EnumVariantId { parent: enum_id, local_id }; + self.write_variant_resolution(id, variant.into()); + Some((ValueNs::EnumVariantId(variant), Some(subst.clone()))) + } } -- cgit v1.2.3