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.rs258
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)),
+ );
+ }
+}