diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/hir')
9 files changed, 185 insertions, 67 deletions
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml index 8e6a2441b..e1418de3c 100644 --- a/src/tools/rust-analyzer/crates/hir/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml @@ -13,9 +13,9 @@ doctest = false rustc-hash = "1.1.0" either = "1.7.0" arrayvec = "0.7.2" -itertools = "0.10.3" -smallvec = "1.9.0" -once_cell = "1.12.0" +itertools = "0.10.5" +smallvec = "1.10.0" +once_cell = "1.15.0" stdx = { path = "../stdx", version = "0.0.0" } syntax = { path = "../syntax", version = "0.0.0" } diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 5edc16d8b..c5dc60f1e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -1,7 +1,7 @@ //! Re-export diagnostics such that clients of `hir` don't have to depend on //! low-level crates. //! -//! This probably isn't the best way to do this -- ideally, diagnistics should +//! This probably isn't the best way to do this -- ideally, diagnostics should //! be expressed in terms of hir types themselves. use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index 0e29c52ad..27b2f445d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -492,6 +492,9 @@ impl HirDisplay for TypeAlias { write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; let data = f.db.type_alias_data(self.id); write!(f, "type {}", data.name)?; + let def_id = GenericDefId::TypeAliasId(self.id); + write_generic_params(def_id, f)?; + write_where_clause(def_id, f)?; if !data.bounds.is_empty() { f.write_str(": ")?; f.write_joined(&data.bounds, " + ")?; diff --git a/src/tools/rust-analyzer/crates/hir/src/from_id.rs b/src/tools/rust-analyzer/crates/hir/src/from_id.rs index 9c7558d19..f825a72c0 100644 --- a/src/tools/rust-analyzer/crates/hir/src/from_id.rs +++ b/src/tools/rust-analyzer/crates/hir/src/from_id.rs @@ -140,6 +140,7 @@ impl From<DefWithBody> for DefWithBodyId { DefWithBody::Function(it) => DefWithBodyId::FunctionId(it.id), DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id), DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id), + DefWithBody::Variant(it) => DefWithBodyId::VariantId(it.into()), } } } @@ -150,6 +151,7 @@ impl From<DefWithBodyId> for DefWithBody { DefWithBodyId::FunctionId(it) => DefWithBody::Function(it.into()), DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()), DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()), + DefWithBodyId::VariantId(it) => DefWithBody::Variant(it.into()), } } } @@ -172,9 +174,7 @@ impl From<GenericDef> for GenericDefId { GenericDef::Trait(it) => GenericDefId::TraitId(it.id), GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id), GenericDef::Impl(it) => GenericDefId::ImplId(it.id), - GenericDef::Variant(it) => { - GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id }) - } + GenericDef::Variant(it) => GenericDefId::EnumVariantId(it.into()), GenericDef::Const(it) => GenericDefId::ConstId(it.id), } } @@ -188,9 +188,7 @@ impl From<GenericDefId> for GenericDef { GenericDefId::TraitId(it) => GenericDef::Trait(it.into()), GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), GenericDefId::ImplId(it) => GenericDef::Impl(it.into()), - GenericDefId::EnumVariantId(it) => { - GenericDef::Variant(Variant { parent: it.parent.into(), id: it.local_id }) - } + GenericDefId::EnumVariantId(it) => GenericDef::Variant(it.into()), GenericDefId::ConstId(it) => GenericDef::Const(it.into()), } } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index e4bb63a86..f5324208c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -39,7 +39,7 @@ use arrayvec::ArrayVec; use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind}; use either::Either; use hir_def::{ - adt::{ReprKind, VariantData}, + adt::{ReprData, VariantData}, body::{BodyDiagnostic, SyntheticSyntax}, expr::{BindingAnnotation, LabelId, Pat, PatId}, generics::{TypeOrConstParamData, TypeParamProvenance}, @@ -50,7 +50,7 @@ use hir_def::{ resolver::{HasResolver, Resolver}, src::HasSource as _, AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, - FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId, + EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; @@ -61,12 +61,10 @@ use hir_ty::{ diagnostics::BodyValidationDiagnostic, method_resolution::{self, TyFingerprint}, primitive::UintTy, - subst_prefix, traits::FnTrait, - AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, - ClosureId, DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind, - QuantifiedWhereClause, Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty, - TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause, + AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, + GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, + TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, WhereClause, }; use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; @@ -74,7 +72,7 @@ use once_cell::unsync::Lazy; use rustc_hash::FxHashSet; use stdx::{impl_from, never}; use syntax::{ - ast::{self, HasAttrs as _, HasDocComments, HasName}, + ast::{self, Expr, HasAttrs as _, HasDocComments, HasName}, AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T, }; @@ -349,7 +347,10 @@ impl ModuleDef { ModuleDef::Module(it) => it.id.into(), ModuleDef::Const(it) => it.id.into(), ModuleDef::Static(it) => it.id.into(), - _ => return Vec::new(), + ModuleDef::Variant(it) => { + EnumVariantId { parent: it.parent.into(), local_id: it.id }.into() + } + ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(), }; let module = match self.module(db) { @@ -378,10 +379,10 @@ impl ModuleDef { ModuleDef::Function(it) => Some(it.into()), ModuleDef::Const(it) => Some(it.into()), ModuleDef::Static(it) => Some(it.into()), + ModuleDef::Variant(it) => Some(it.into()), ModuleDef::Module(_) | ModuleDef::Adt(_) - | ModuleDef::Variant(_) | ModuleDef::Trait(_) | ModuleDef::TypeAlias(_) | ModuleDef::Macro(_) @@ -538,6 +539,30 @@ impl Module { } acc.extend(decl.diagnostics(db)) } + ModuleDef::Adt(adt) => { + match adt { + Adt::Struct(s) => { + for diag in db.struct_data_with_diagnostics(s.id).1.iter() { + emit_def_diagnostic(db, acc, diag); + } + } + Adt::Union(u) => { + for diag in db.union_data_with_diagnostics(u.id).1.iter() { + emit_def_diagnostic(db, acc, diag); + } + } + Adt::Enum(e) => { + for v in e.variants(db) { + acc.extend(ModuleDef::Variant(v).diagnostics(db)); + } + + for diag in db.enum_data_with_diagnostics(e.id).1.iter() { + emit_def_diagnostic(db, acc, diag); + } + } + } + acc.extend(decl.diagnostics(db)) + } _ => acc.extend(decl.diagnostics(db)), } } @@ -582,8 +607,13 @@ impl Module { /// Finds a path that can be used to refer to the given item from within /// this module, if possible. - pub fn find_use_path(self, db: &dyn DefDatabase, item: impl Into<ItemInNs>) -> Option<ModPath> { - hir_def::find_path::find_path(db, item.into().into(), self.into()) + pub fn find_use_path( + self, + db: &dyn DefDatabase, + item: impl Into<ItemInNs>, + prefer_no_std: bool, + ) -> Option<ModPath> { + hir_def::find_path::find_path(db, item.into().into(), self.into(), prefer_no_std) } /// Finds a path that can be used to refer to the given item from within @@ -593,8 +623,15 @@ impl Module { db: &dyn DefDatabase, item: impl Into<ItemInNs>, prefix_kind: PrefixKind, + prefer_no_std: bool, ) -> Option<ModPath> { - hir_def::find_path::find_path_prefixed(db, item.into().into(), self.into(), prefix_kind) + hir_def::find_path::find_path_prefixed( + db, + item.into().into(), + self.into(), + prefix_kind, + prefer_no_std, + ) } } @@ -863,7 +900,7 @@ impl Struct { Type::from_def(db, self.id) } - pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> { + pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprData> { db.struct_data(self.id).repr.clone() } @@ -941,6 +978,21 @@ impl Enum { pub fn ty(self, db: &dyn HirDatabase) -> Type { Type::from_def(db, self.id) } + + /// The type of the enum variant bodies. + pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type { + Type::new_for_crate( + self.id.lookup(db.upcast()).container.krate(), + TyBuilder::builtin(match db.enum_data(self.id).variant_body_type() { + Either::Left(builtin) => hir_def::builtin_type::BuiltinType::Int(builtin), + Either::Right(builtin) => hir_def::builtin_type::BuiltinType::Uint(builtin), + }), + ) + } + + pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool { + self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit)) + } } impl HasVisibility for Enum { @@ -949,6 +1001,12 @@ impl HasVisibility for Enum { } } +impl From<&Variant> for DefWithBodyId { + fn from(&v: &Variant) -> Self { + DefWithBodyId::VariantId(v.into()) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Variant { pub(crate) parent: Enum, @@ -983,6 +1041,14 @@ impl Variant { pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { db.enum_data(self.parent.id).variants[self.id].variant_data.clone() } + + pub fn value(self, db: &dyn HirDatabase) -> Option<Expr> { + self.source(db)?.value.expr() + } + + pub fn eval(self, db: &dyn HirDatabase) -> Result<ComputedExpr, ConstEvalError> { + db.const_eval_variant(self.into()) + } } /// Variants inherit visibility from the parent enum. @@ -1023,7 +1089,7 @@ impl Adt { pub fn ty_with_args(self, db: &dyn HirDatabase, args: &[Type]) -> Type { let id = AdtId::from(self); let mut it = args.iter().map(|t| t.ty.clone()); - let ty = TyBuilder::def_ty(db, id.into()) + let ty = TyBuilder::def_ty(db, id.into(), None) .fill(|x| { let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); match x { @@ -1118,8 +1184,9 @@ pub enum DefWithBody { Function(Function), Static(Static), Const(Const), + Variant(Variant), } -impl_from!(Function, Const, Static for DefWithBody); +impl_from!(Function, Const, Static, Variant for DefWithBody); impl DefWithBody { pub fn module(self, db: &dyn HirDatabase) -> Module { @@ -1127,6 +1194,7 @@ impl DefWithBody { DefWithBody::Const(c) => c.module(db), DefWithBody::Function(f) => f.module(db), DefWithBody::Static(s) => s.module(db), + DefWithBody::Variant(v) => v.module(db), } } @@ -1135,6 +1203,7 @@ impl DefWithBody { DefWithBody::Function(f) => Some(f.name(db)), DefWithBody::Static(s) => Some(s.name(db)), DefWithBody::Const(c) => c.name(db), + DefWithBody::Variant(v) => Some(v.name(db)), } } @@ -1144,6 +1213,7 @@ impl DefWithBody { DefWithBody::Function(it) => it.ret_type(db), DefWithBody::Static(it) => it.ty(db), DefWithBody::Const(it) => it.ty(db), + DefWithBody::Variant(it) => it.parent.variant_body_ty(db), } } @@ -1152,6 +1222,7 @@ impl DefWithBody { DefWithBody::Function(it) => it.id.into(), DefWithBody::Static(it) => it.id.into(), DefWithBody::Const(it) => it.id.into(), + DefWithBody::Variant(it) => it.into(), } } @@ -1368,6 +1439,7 @@ impl DefWithBody { DefWithBody::Function(it) => it.into(), DefWithBody::Static(it) => it.into(), DefWithBody::Const(it) => it.into(), + DefWithBody::Variant(it) => it.into(), }; for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) { acc.push(diag.into()) @@ -2474,7 +2546,7 @@ impl TypeParam { let resolver = self.id.parent().resolver(db.upcast()); let ty = params.get(local_idx)?.clone(); let subst = TyBuilder::placeholder_subst(db, self.id.parent()); - let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx)); + let ty = ty.substitute(Interner, &subst); match ty.data(Interner) { GenericArgData::Ty(x) => Some(Type::new_with_resolver_inner(db, &resolver, x.clone())), _ => None, @@ -2728,7 +2800,22 @@ impl Type { } fn from_def(db: &dyn HirDatabase, def: impl HasResolver + Into<TyDefId>) -> Type { - let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build(); + let ty_def = def.into(); + let parent_subst = match ty_def { + TyDefId::TypeAliasId(id) => match id.lookup(db.upcast()).container { + ItemContainerId::TraitId(id) => { + let subst = TyBuilder::subst_for_def(db, id, None).fill_with_unknown().build(); + Some(subst) + } + ItemContainerId::ImplId(id) => { + let subst = TyBuilder::subst_for_def(db, id, None).fill_with_unknown().build(); + Some(subst) + } + _ => None, + }, + _ => None, + }; + let ty = TyBuilder::def_ty(db, ty_def, parent_subst).fill_with_unknown().build(); Type::new(db, def, ty) } @@ -2868,7 +2955,11 @@ impl Type { alias: TypeAlias, ) -> Option<Type> { let mut args = args.iter(); - let projection = TyBuilder::assoc_type_projection(db, alias.id) + let trait_id = match alias.id.lookup(db.upcast()).container { + ItemContainerId::TraitId(id) => id, + _ => unreachable!("non assoc type alias reached in normalize_trait_assoc_type()"), + }; + let parent_subst = TyBuilder::subst_for_def(db, trait_id, None) .push(self.ty.clone()) .fill(|x| { // FIXME: this code is not covered in tests. @@ -2880,27 +2971,14 @@ impl Type { } }) .build(); - let goal = hir_ty::make_canonical( - InEnvironment::new( - &self.env.env, - AliasEq { - alias: AliasTy::Projection(projection), - ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) - .intern(Interner), - } - .cast(Interner), - ), - [TyVariableKind::General].into_iter(), - ); + // FIXME: We don't handle GATs yet. + let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build(); - match db.trait_solve(self.env.krate, goal)? { - Solution::Unique(s) => s - .value - .subst - .as_slice(Interner) - .first() - .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone())), - Solution::Ambig(_) => None, + let ty = db.normalize_projection(projection, self.env.clone()); + if ty.is_unknown() { + None + } else { + Some(self.derived(ty)) } } @@ -2944,7 +3022,7 @@ impl Type { let adt = adt_id.into(); match adt { - Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)), + Adt::Struct(s) => matches!(s.repr(db), Some(ReprData { packed: true, .. })), _ => false, } } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 416b6f580..119ec3210 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -257,6 +257,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { pub fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> { self.imp.original_ast_node(node) } + /// Attempts to map the node out of macro expanded files. + /// This only work for attribute expansions, as other ones do not have nodes as input. + pub fn original_syntax_node(&self, node: &SyntaxNode) -> Option<SyntaxNode> { + self.imp.original_syntax_node(node) + } pub fn diagnostics_display_range(&self, diagnostics: InFile<SyntaxNodePtr>) -> FileRange { self.imp.diagnostics_display_range(diagnostics) @@ -956,6 +961,16 @@ impl<'db> SemanticsImpl<'db> { ) } + fn original_syntax_node(&self, node: &SyntaxNode) -> Option<SyntaxNode> { + let InFile { file_id, .. } = self.find_file(node); + InFile::new(file_id, node).original_syntax_node(self.db.upcast()).map( + |InFile { file_id, value }| { + self.cache(find_root(&value), file_id); + value + }, + ) + } + fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange { let root = self.parse_or_expand(src.file_id).unwrap(); let node = src.map(|it| it.to_node(&root)); diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index ba9a1cfb6..fa45e3c12 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -115,7 +115,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> { } impl SourceToDefCtx<'_, '_> { - pub(super) fn file_to_def(&mut self, file: FileId) -> SmallVec<[ModuleId; 1]> { + pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> { let _p = profile::span("SourceBinder::to_module_def"); let mut mods = SmallVec::new(); for &crate_id in self.db.relevant_crates(file).iter() { @@ -130,7 +130,7 @@ impl SourceToDefCtx<'_, '_> { mods } - pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> { + pub(super) fn module_to_def(&self, src: InFile<ast::Module>) -> Option<ModuleId> { let _p = profile::span("module_to_def"); let parent_declaration = src .syntax() @@ -151,7 +151,7 @@ impl SourceToDefCtx<'_, '_> { Some(def_map.module_id(child_id)) } - pub(super) fn source_file_to_def(&mut self, src: InFile<ast::SourceFile>) -> Option<ModuleId> { + pub(super) fn source_file_to_def(&self, src: InFile<ast::SourceFile>) -> Option<ModuleId> { let _p = profile::span("source_file_to_def"); let file_id = src.file_id.original_file(self.db.upcast()); self.file_to_def(file_id).get(0).copied() @@ -384,7 +384,7 @@ impl SourceToDefCtx<'_, '_> { } else { let it = ast::Variant::cast(container.value)?; let def = self.enum_variant_to_def(InFile::new(container.file_id, it))?; - VariantId::from(def).into() + DefWithBodyId::from(def).into() }; Some(cont) } diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 342912b67..07bae2b38 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -22,7 +22,7 @@ use hir_def::{ resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, type_ref::Mutability, AsMacroCall, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, LocalFieldId, - Lookup, ModuleDefId, VariantId, + Lookup, ModuleDefId, TraitId, VariantId, }; use hir_expand::{ builtin_fn_macro::BuiltinFnLikeExpander, @@ -302,10 +302,15 @@ impl SourceAnalyzer { } } + let future_trait = db + .lang_item(self.resolver.krate(), hir_expand::name![future_trait].to_smol_str())? + .as_trait()?; let poll_fn = db .lang_item(self.resolver.krate(), hir_expand::name![poll].to_smol_str())? .as_function()?; - let substs = hir_ty::TyBuilder::subst_for_def(db, poll_fn).push(ty.clone()).build(); + // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself + // doesn't have any generic parameters, so we skip building another subst for `poll()`. + let substs = hir_ty::TyBuilder::subst_for_def(db, future_trait, None).push(ty).build(); Some(self.resolve_impl_method_or_trait_def(db, poll_fn, &substs)) } @@ -321,8 +326,10 @@ impl SourceAnalyzer { }; let ty = self.ty_of_expr(db, &prefix_expr.expr()?.into())?; - let op_fn = self.lang_trait_fn(db, &lang_item_name, &lang_item_name)?; - let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build(); + let (op_trait, op_fn) = self.lang_trait_fn(db, &lang_item_name, &lang_item_name)?; + // HACK: subst for all methods coincides with that for their trait because the methods + // don't have any generic parameters, so we skip building another subst for the methods. + let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build(); Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs)) } @@ -337,8 +344,10 @@ impl SourceAnalyzer { let lang_item_name = name![index]; - let op_fn = self.lang_trait_fn(db, &lang_item_name, &lang_item_name)?; - let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn) + let (op_trait, op_fn) = self.lang_trait_fn(db, &lang_item_name, &lang_item_name)?; + // HACK: subst for all methods coincides with that for their trait because the methods + // don't have any generic parameters, so we skip building another subst for the methods. + let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None) .push(base_ty.clone()) .push(index_ty.clone()) .build(); @@ -354,10 +363,14 @@ impl SourceAnalyzer { let lhs = self.ty_of_expr(db, &binop_expr.lhs()?.into())?; let rhs = self.ty_of_expr(db, &binop_expr.rhs()?.into())?; - let op_fn = lang_names_for_bin_op(op) + let (op_trait, op_fn) = lang_names_for_bin_op(op) .and_then(|(name, lang_item)| self.lang_trait_fn(db, &lang_item, &name))?; - let substs = - hir_ty::TyBuilder::subst_for_def(db, op_fn).push(lhs.clone()).push(rhs.clone()).build(); + // HACK: subst for `index()` coincides with that for `Index` because `index()` itself + // doesn't have any generic parameters, so we skip building another subst for `index()`. + let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None) + .push(lhs.clone()) + .push(rhs.clone()) + .build(); Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs)) } @@ -371,7 +384,13 @@ impl SourceAnalyzer { let op_fn = db.lang_item(self.resolver.krate(), name![branch].to_smol_str())?.as_function()?; - let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build(); + let op_trait = match op_fn.lookup(db.upcast()).container { + ItemContainerId::TraitId(id) => id, + _ => return None, + }; + // HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself + // doesn't have any generic parameters, so we skip building another subst for `branch()`. + let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build(); Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs)) } @@ -799,9 +818,10 @@ impl SourceAnalyzer { db: &dyn HirDatabase, lang_trait: &Name, method_name: &Name, - ) -> Option<FunctionId> { - db.trait_data(db.lang_item(self.resolver.krate(), lang_trait.to_smol_str())?.as_trait()?) - .method_by_name(method_name) + ) -> Option<(TraitId, FunctionId)> { + let trait_id = db.lang_item(self.resolver.krate(), lang_trait.to_smol_str())?.as_trait()?; + let fn_id = db.trait_data(trait_id).method_by_name(method_name)?; + Some((trait_id, fn_id)) } fn ty_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<&Ty> { diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 616a406c7..fd78decda 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -244,6 +244,10 @@ impl<'a> SymbolCollector<'a> { DefWithBodyId::ConstId(id) => Some( id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(), ), + DefWithBodyId::VariantId(id) => Some({ + let db = self.db.upcast(); + id.parent.lookup(db).source(db).value.name()?.text().into() + }), } } |