diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/hir/src/lib.rs')
-rw-r--r-- | src/tools/rust-analyzer/crates/hir/src/lib.rs | 158 |
1 files changed, 118 insertions, 40 deletions
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, } } |