Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
| -rw-r--r-- | crates/hir/src/lib.rs | 258 |
1 files changed, 243 insertions, 15 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c9498b3aea..83d72dfcf1 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -20,12 +20,11 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![recursion_limit = "512"] -mod semantics; -mod source_analyzer; - mod attrs; mod from_id; mod has_source; +mod semantics; +mod source_analyzer; pub mod db; pub mod diagnostics; @@ -43,7 +42,7 @@ use arrayvec::ArrayVec; use base_db::{CrateDisplayName, CrateId, CrateOrigin}; use either::Either; use hir_def::{ - body::{BodyDiagnostic, SyntheticSyntax}, + body::BodyDiagnostic, data::adt::VariantData, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat}, @@ -54,11 +53,12 @@ use hir_def::{ path::ImportAlias, per_ns::PerNs, resolver::{HasResolver, Resolver}, + type_ref::TypesSourceMap, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, - MacroExpander, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, - TypeOrConstParamId, TypeParamId, UnionId, + MacroExpander, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TraitId, TupleId, + TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{ attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError, @@ -76,8 +76,8 @@ use hir_ty::{ traits::FnTrait, AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, - TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId, - WhereClause, + TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic, + ValueTyDefId, WhereClause, }; use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; @@ -89,7 +89,7 @@ use syntax::{ ast::{self, HasAttrs as _, HasGenericParams, HasName}, format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T, }; -use triomphe::Arc; +use triomphe::{Arc, ThinArc}; use crate::db::{DefDatabase, HirDatabase}; @@ -147,6 +147,7 @@ pub use { }, hir_ty::{ consteval::ConstEvalError, + diagnostics::UnsafetyReason, display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode}, layout::LayoutError, @@ -410,6 +411,10 @@ impl ModuleDef { } } + if let Some(def) = self.as_self_generic_def() { + def.diagnostics(db, &mut acc); + } + acc } @@ -430,6 +435,23 @@ impl ModuleDef { } } + /// Returns only defs that have generics from themselves, not their parent. + pub fn as_self_generic_def(self) -> Option<GenericDef> { + match self { + ModuleDef::Function(it) => Some(it.into()), + ModuleDef::Adt(it) => Some(it.into()), + ModuleDef::Trait(it) => Some(it.into()), + ModuleDef::TraitAlias(it) => Some(it.into()), + ModuleDef::TypeAlias(it) => Some(it.into()), + ModuleDef::Module(_) + | ModuleDef::Variant(_) + | ModuleDef::Static(_) + | ModuleDef::Const(_) + | ModuleDef::BuiltinType(_) + | ModuleDef::Macro(_) => None, + } + } + pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> { Some(match self { ModuleDef::Module(it) => it.attrs(db), @@ -604,17 +626,42 @@ impl Module { ModuleDef::Adt(adt) => { match adt { Adt::Struct(s) => { + let tree_id = s.id.lookup(db.upcast()).id; + let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1; + push_ty_diagnostics( + db, + acc, + db.field_types_with_diagnostics(s.id.into()).1, + tree_source_maps.strukt(tree_id.value).item(), + ); for diag in db.struct_data_with_diagnostics(s.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } } Adt::Union(u) => { + let tree_id = u.id.lookup(db.upcast()).id; + let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1; + push_ty_diagnostics( + db, + acc, + db.field_types_with_diagnostics(u.id.into()).1, + tree_source_maps.union(tree_id.value).item(), + ); for diag in db.union_data_with_diagnostics(u.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } } Adt::Enum(e) => { for v in e.variants(db) { + let tree_id = v.id.lookup(db.upcast()).id; + let tree_source_maps = + tree_id.item_tree_with_source_map(db.upcast()).1; + push_ty_diagnostics( + db, + acc, + db.field_types_with_diagnostics(v.id.into()).1, + tree_source_maps.variant(tree_id.value), + ); acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints)); for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); @@ -625,6 +672,17 @@ impl Module { acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m), + ModuleDef::TypeAlias(type_alias) => { + let tree_id = type_alias.id.lookup(db.upcast()).id; + let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1; + push_ty_diagnostics( + db, + acc, + db.type_for_type_alias_with_diagnostics(type_alias.id).1, + tree_source_maps.type_alias(tree_id.value).item(), + ); + acc.extend(def.diagnostics(db, style_lints)); + } _ => acc.extend(def.diagnostics(db, style_lints)), } } @@ -634,8 +692,11 @@ impl Module { let mut impl_assoc_items_scratch = vec![]; for impl_def in self.impl_defs(db) { + GenericDef::Impl(impl_def).diagnostics(db, acc); + let loc = impl_def.id.lookup(db.upcast()); - let tree = loc.id.item_tree(db.upcast()); + let (tree, tree_source_maps) = loc.id.item_tree_with_source_map(db.upcast()); + let source_map = tree_source_maps.impl_(loc.id.value).item(); let node = &tree[loc.id.value]; let file_id = loc.id.file_id(); if file_id.macro_file().map_or(false, |it| it.is_builtin_derive(db.upcast())) { @@ -770,6 +831,19 @@ impl Module { impl_assoc_items_scratch.clear(); } + push_ty_diagnostics( + db, + acc, + db.impl_self_ty_with_diagnostics(impl_def.id).1, + source_map, + ); + push_ty_diagnostics( + db, + acc, + db.impl_trait_with_diagnostics(impl_def.id).and_then(|it| it.1), + source_map, + ); + for &item in db.impl_data(impl_def.id).items.iter() { AssocItem::from(item).diagnostics(db, acc, style_lints); } @@ -1801,6 +1875,25 @@ impl DefWithBody { let krate = self.module(db).id.krate(); let (body, source_map) = db.body_with_source_map(self.into()); + let item_tree_source_maps; + let outer_types_source_map = match self { + DefWithBody::Function(function) => { + let function = function.id.lookup(db.upcast()).id; + item_tree_source_maps = function.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.function(function.value).item() + } + DefWithBody::Static(statik) => { + let statik = statik.id.lookup(db.upcast()).id; + item_tree_source_maps = statik.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.statik(statik.value) + } + DefWithBody::Const(konst) => { + let konst = konst.id.lookup(db.upcast()).id; + item_tree_source_maps = konst.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.konst(konst.value) + } + DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => &TypesSourceMap::EMPTY, + }; for (_, def_map) in body.blocks(db.upcast()) { Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints); @@ -1860,7 +1953,13 @@ impl DefWithBody { let infer = db.infer(self.into()); for d in &infer.diagnostics { - acc.extend(AnyDiagnostic::inference_diagnostic(db, self.into(), d, &source_map)); + acc.extend(AnyDiagnostic::inference_diagnostic( + db, + self.into(), + d, + outer_types_source_map, + &source_map, + )); } for (pat_or_expr, mismatch) in infer.type_mismatches() { @@ -1890,10 +1989,10 @@ impl DefWithBody { ); } - let (unafe_exprs, only_lint) = hir_ty::diagnostics::missing_unsafe(db, self.into()); - for expr in unafe_exprs { - match source_map.expr_or_pat_syntax(expr) { - Ok(expr) => acc.push(MissingUnsafe { expr, only_lint }.into()), + let (unsafe_exprs, only_lint) = hir_ty::diagnostics::missing_unsafe(db, self.into()); + for (node, reason) in unsafe_exprs { + match source_map.expr_or_pat_syntax(node) { + Ok(node) => acc.push(MissingUnsafe { node, only_lint, reason }.into()), Err(SyntheticSyntax) => { // FIXME: Here and elsewhere in this file, the `expr` was // desugared, report or assert that this doesn't happen. @@ -3324,12 +3423,22 @@ impl AssocItem { ) { match self { AssocItem::Function(func) => { + GenericDef::Function(func).diagnostics(db, acc); DefWithBody::from(func).diagnostics(db, acc, style_lints); } AssocItem::Const(const_) => { DefWithBody::from(const_).diagnostics(db, acc, style_lints); } AssocItem::TypeAlias(type_alias) => { + GenericDef::TypeAlias(type_alias).diagnostics(db, acc); + let tree_id = type_alias.id.lookup(db.upcast()).id; + let tree_source_maps = tree_id.item_tree_with_source_map(db.upcast()).1; + push_ty_diagnostics( + db, + acc, + db.type_for_type_alias_with_diagnostics(type_alias.id).1, + tree_source_maps.type_alias(tree_id.value).item(), + ); for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) { acc.push(diag.into()); } @@ -3416,6 +3525,97 @@ impl GenericDef { }) .collect() } + + fn id(self) -> GenericDefId { + match self { + GenericDef::Function(it) => it.id.into(), + GenericDef::Adt(it) => it.into(), + GenericDef::Trait(it) => it.id.into(), + GenericDef::TraitAlias(it) => it.id.into(), + GenericDef::TypeAlias(it) => it.id.into(), + GenericDef::Impl(it) => it.id.into(), + GenericDef::Const(it) => it.id.into(), + } + } + + pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) { + let def = self.id(); + + let item_tree_source_maps; + let (generics, generics_source_map) = db.generic_params_with_source_map(def); + + if generics.is_empty() && generics.no_predicates() { + return; + } + + let source_map = match &generics_source_map { + Some(it) => it, + None => match def { + GenericDefId::FunctionId(it) => { + let id = it.lookup(db.upcast()).id; + item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.function(id.value).generics() + } + GenericDefId::AdtId(AdtId::EnumId(it)) => { + let id = it.lookup(db.upcast()).id; + item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.enum_generic(id.value) + } + GenericDefId::AdtId(AdtId::StructId(it)) => { + let id = it.lookup(db.upcast()).id; + item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.strukt(id.value).generics() + } + GenericDefId::AdtId(AdtId::UnionId(it)) => { + let id = it.lookup(db.upcast()).id; + item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.union(id.value).generics() + } + GenericDefId::TraitId(it) => { + let id = it.lookup(db.upcast()).id; + item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.trait_generic(id.value) + } + GenericDefId::TraitAliasId(it) => { + let id = it.lookup(db.upcast()).id; + item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.trait_alias_generic(id.value) + } + GenericDefId::TypeAliasId(it) => { + let id = it.lookup(db.upcast()).id; + item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.type_alias(id.value).generics() + } + GenericDefId::ImplId(it) => { + let id = it.lookup(db.upcast()).id; + item_tree_source_maps = id.item_tree_with_source_map(db.upcast()).1; + item_tree_source_maps.impl_(id.value).generics() + } + GenericDefId::ConstId(_) => return, + }, + }; + + push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, source_map); + push_ty_diagnostics( + db, + acc, + db.generic_predicates_without_parent_with_diagnostics(def).1, + source_map, + ); + for (param_id, param) in generics.iter_type_or_consts() { + if let TypeOrConstParamData::ConstParamData(_) = param { + push_ty_diagnostics( + db, + acc, + db.const_param_ty_with_diagnostics(ConstParamId::from_unchecked( + TypeOrConstParamId { parent: def, local_id: param_id }, + )) + .1, + source_map, + ); + } + } + } } /// A single local definition. @@ -3581,6 +3781,18 @@ impl Local { } } +impl PartialOrd for Local { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for Local { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.binding_id.cmp(&other.binding_id) + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct DeriveHelper { pub(crate) derive: MacroId, @@ -5799,3 +6011,19 @@ pub enum DocLinkDef { Field(Field), SelfType(Trait), } + +fn push_ty_diagnostics( + db: &dyn HirDatabase, + acc: &mut Vec<AnyDiagnostic>, + diagnostics: Option<ThinArc<(), TyLoweringDiagnostic>>, + source_map: &TypesSourceMap, +) { + if let Some(diagnostics) = diagnostics { + acc.extend( + diagnostics + .slice + .iter() + .filter_map(|diagnostic| AnyDiagnostic::ty_diagnostic(diagnostic, source_map, db)), + ); + } +} |