mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
parent
b3ef934ccb
commit
25242fe93f
395 changed files with 14569 additions and 5755 deletions
|
@ -148,7 +148,7 @@ fn resolve_doc_path(
|
|||
|
||||
let modpath = {
|
||||
// FIXME: this is not how we should get a mod path here
|
||||
let ast_path = ast::SourceFile::parse(&format!("type T = {};", link))
|
||||
let ast_path = ast::SourceFile::parse(&format!("type T = {link};"))
|
||||
.syntax_node()
|
||||
.descendants()
|
||||
.find_map(ast::Path::cast)?;
|
||||
|
|
|
@ -10,7 +10,7 @@ use hir_def::path::ModPath;
|
|||
use hir_expand::{name::Name, HirFileId, InFile};
|
||||
use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
|
||||
|
||||
use crate::{MacroKind, Type};
|
||||
use crate::{AssocItem, Field, MacroKind, Type};
|
||||
|
||||
macro_rules! diagnostics {
|
||||
($($diag:ident,)*) => {
|
||||
|
@ -41,6 +41,8 @@ diagnostics![
|
|||
MissingMatchArms,
|
||||
MissingUnsafe,
|
||||
NoSuchField,
|
||||
PrivateAssocItem,
|
||||
PrivateField,
|
||||
ReplaceFilterMapNextWithFindMap,
|
||||
TypeMismatch,
|
||||
UnimplementedBuiltinMacro,
|
||||
|
@ -121,6 +123,19 @@ pub struct NoSuchField {
|
|||
pub field: InFile<AstPtr<ast::RecordExprField>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PrivateAssocItem {
|
||||
pub expr_or_pat:
|
||||
InFile<Either<AstPtr<ast::Expr>, Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>>>,
|
||||
pub item: AssocItem,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PrivateField {
|
||||
pub expr: InFile<AstPtr<ast::Expr>>,
|
||||
pub field: Field,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BreakOutsideOfLoop {
|
||||
pub expr: InFile<AstPtr<ast::Expr>>,
|
||||
|
|
|
@ -79,7 +79,7 @@ impl HirDisplay for Function {
|
|||
}
|
||||
}
|
||||
match name {
|
||||
Some(name) => write!(f, "{}: ", name)?,
|
||||
Some(name) => write!(f, "{name}: ")?,
|
||||
None => f.write_str("_: ")?,
|
||||
}
|
||||
// FIXME: Use resolved `param.ty` or raw `type_ref`?
|
||||
|
@ -327,7 +327,7 @@ fn write_generic_params(
|
|||
continue;
|
||||
}
|
||||
delim(f)?;
|
||||
write!(f, "{}", name)?;
|
||||
write!(f, "{name}")?;
|
||||
if let Some(default) = &ty.default {
|
||||
f.write_str(" = ")?;
|
||||
default.hir_fmt(f)?;
|
||||
|
@ -335,7 +335,7 @@ fn write_generic_params(
|
|||
}
|
||||
TypeOrConstParamData::ConstParamData(c) => {
|
||||
delim(f)?;
|
||||
write!(f, "const {}: ", name)?;
|
||||
write!(f, "const {name}: ")?;
|
||||
c.ty.hir_fmt(f)?;
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(),
|
|||
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
|
||||
WherePredicateTypeTarget::TypeOrConstParam(id) => {
|
||||
match ¶ms.type_or_consts[*id].name() {
|
||||
Some(name) => write!(f, "{}", name),
|
||||
Some(name) => write!(f, "{name}"),
|
||||
None => f.write_str("{unnamed}"),
|
||||
}
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(),
|
|||
if idx != 0 {
|
||||
f.write_str(", ")?;
|
||||
}
|
||||
write!(f, "{}", lifetime)?;
|
||||
write!(f, "{lifetime}")?;
|
||||
}
|
||||
f.write_str("> ")?;
|
||||
write_target(target, f)?;
|
||||
|
@ -447,7 +447,7 @@ impl HirDisplay for Const {
|
|||
let data = f.db.const_data(self.id);
|
||||
f.write_str("const ")?;
|
||||
match &data.name {
|
||||
Some(name) => write!(f, "{}: ", name)?,
|
||||
Some(name) => write!(f, "{name}: ")?,
|
||||
None => f.write_str("_: ")?,
|
||||
}
|
||||
data.type_ref.hir_fmt(f)?;
|
||||
|
@ -511,9 +511,9 @@ impl HirDisplay for Module {
|
|||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
// FIXME: Module doesn't have visibility saved in data.
|
||||
match self.name(f.db) {
|
||||
Some(name) => write!(f, "mod {}", name),
|
||||
Some(name) => write!(f, "mod {name}"),
|
||||
None if self.is_crate_root(f.db) => match self.krate(f.db).display_name(f.db) {
|
||||
Some(name) => write!(f, "extern crate {}", name),
|
||||
Some(name) => write!(f, "extern crate {name}"),
|
||||
None => f.write_str("extern crate {unknown}"),
|
||||
},
|
||||
None => f.write_str("mod {unnamed}"),
|
||||
|
|
|
@ -39,12 +39,13 @@ use arrayvec::ArrayVec;
|
|||
use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
adt::{ReprData, VariantData},
|
||||
adt::VariantData,
|
||||
body::{BodyDiagnostic, SyntheticSyntax},
|
||||
expr::{BindingAnnotation, LabelId, Pat, PatId},
|
||||
expr::{BindingAnnotation, ExprOrPatId, LabelId, Pat, PatId},
|
||||
generics::{TypeOrConstParamData, TypeParamProvenance},
|
||||
item_tree::ItemTreeNode,
|
||||
lang_item::LangItemTarget,
|
||||
layout::{Layout, LayoutError, ReprOptions},
|
||||
nameres::{self, diagnostics::DefDiagnostic},
|
||||
per_ns::PerNs,
|
||||
resolver::{HasResolver, Resolver},
|
||||
|
@ -59,6 +60,7 @@ use hir_ty::{
|
|||
all_super_traits, autoderef,
|
||||
consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt},
|
||||
diagnostics::BodyValidationDiagnostic,
|
||||
layout::layout_of_ty,
|
||||
method_resolution::{self, TyFingerprint},
|
||||
primitive::UintTy,
|
||||
traits::FnTrait,
|
||||
|
@ -72,7 +74,7 @@ use once_cell::unsync::Lazy;
|
|||
use rustc_hash::FxHashSet;
|
||||
use stdx::{impl_from, never};
|
||||
use syntax::{
|
||||
ast::{self, Expr, HasAttrs as _, HasDocComments, HasName},
|
||||
ast::{self, HasAttrs as _, HasDocComments, HasName},
|
||||
AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
|
||||
};
|
||||
|
||||
|
@ -83,9 +85,10 @@ pub use crate::{
|
|||
diagnostics::{
|
||||
AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, InvalidDeriveTarget,
|
||||
MacroError, MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms,
|
||||
MissingUnsafe, NoSuchField, ReplaceFilterMapNextWithFindMap, TypeMismatch,
|
||||
UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
|
||||
UnresolvedModule, UnresolvedProcMacro,
|
||||
MissingUnsafe, NoSuchField, PrivateAssocItem, PrivateField,
|
||||
ReplaceFilterMapNextWithFindMap, TypeMismatch, UnimplementedBuiltinMacro,
|
||||
UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule,
|
||||
UnresolvedProcMacro,
|
||||
},
|
||||
has_source::HasSource,
|
||||
semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
|
||||
|
@ -112,12 +115,20 @@ pub use {
|
|||
path::{ModPath, PathKind},
|
||||
type_ref::{Mutability, TypeRef},
|
||||
visibility::Visibility,
|
||||
// FIXME: This is here since it is input of a method in `HirWrite`
|
||||
// and things outside of hir need to implement that trait. We probably
|
||||
// should move whole `hir_ty::display` to this crate so we will become
|
||||
// able to use `ModuleDef` or `Definition` instead of `ModuleDefId`.
|
||||
ModuleDefId,
|
||||
},
|
||||
hir_expand::{
|
||||
name::{known, Name},
|
||||
ExpandResult, HirFileId, InFile, MacroFile, Origin,
|
||||
},
|
||||
hir_ty::{display::HirDisplay, PointerCast, Safety},
|
||||
hir_ty::{
|
||||
display::{HirDisplay, HirWrite},
|
||||
PointerCast, Safety,
|
||||
},
|
||||
};
|
||||
|
||||
// These are negative re-exports: pub using these names is forbidden, they
|
||||
|
@ -597,7 +608,7 @@ impl Module {
|
|||
pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
|
||||
let def_map = self.id.def_map(db.upcast());
|
||||
let scope = &def_map[self.id.local_id].scope;
|
||||
scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| MacroId::from(it).into()).collect()
|
||||
scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| it.into()).collect()
|
||||
}
|
||||
|
||||
pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
|
||||
|
@ -803,7 +814,7 @@ fn precise_macro_call_location(
|
|||
.doc_comments_and_attrs()
|
||||
.nth((*invoc_attr_index) as usize)
|
||||
.and_then(Either::left)
|
||||
.unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
|
||||
.unwrap_or_else(|| panic!("cannot find attribute #{invoc_attr_index}"));
|
||||
|
||||
(
|
||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
|
||||
|
@ -844,6 +855,10 @@ impl Field {
|
|||
self.parent.variant_data(db).fields()[self.id].name.clone()
|
||||
}
|
||||
|
||||
pub fn index(&self) -> usize {
|
||||
u32::from(self.id.into_raw()) as usize
|
||||
}
|
||||
|
||||
/// Returns the type as in the signature of the struct (i.e., with
|
||||
/// placeholder types for type parameters). Only use this in the context of
|
||||
/// the field definition.
|
||||
|
@ -859,6 +874,10 @@ impl Field {
|
|||
Type::new(db, var_id, ty)
|
||||
}
|
||||
|
||||
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||
layout_of_ty(db, &self.ty(db).ty, self.parent.module(db).krate().into())
|
||||
}
|
||||
|
||||
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
|
||||
self.parent
|
||||
}
|
||||
|
@ -900,7 +919,7 @@ impl Struct {
|
|||
Type::from_def(db, self.id)
|
||||
}
|
||||
|
||||
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprData> {
|
||||
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
|
||||
db.struct_data(self.id).repr.clone()
|
||||
}
|
||||
|
||||
|
@ -984,8 +1003,30 @@ impl Enum {
|
|||
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),
|
||||
hir_def::layout::IntegerType::Pointer(sign) => match sign {
|
||||
true => hir_def::builtin_type::BuiltinType::Int(
|
||||
hir_def::builtin_type::BuiltinInt::Isize,
|
||||
),
|
||||
false => hir_def::builtin_type::BuiltinType::Uint(
|
||||
hir_def::builtin_type::BuiltinUint::Usize,
|
||||
),
|
||||
},
|
||||
hir_def::layout::IntegerType::Fixed(i, sign) => match sign {
|
||||
true => hir_def::builtin_type::BuiltinType::Int(match i {
|
||||
hir_def::layout::Integer::I8 => hir_def::builtin_type::BuiltinInt::I8,
|
||||
hir_def::layout::Integer::I16 => hir_def::builtin_type::BuiltinInt::I16,
|
||||
hir_def::layout::Integer::I32 => hir_def::builtin_type::BuiltinInt::I32,
|
||||
hir_def::layout::Integer::I64 => hir_def::builtin_type::BuiltinInt::I64,
|
||||
hir_def::layout::Integer::I128 => hir_def::builtin_type::BuiltinInt::I128,
|
||||
}),
|
||||
false => hir_def::builtin_type::BuiltinType::Uint(match i {
|
||||
hir_def::layout::Integer::I8 => hir_def::builtin_type::BuiltinUint::U8,
|
||||
hir_def::layout::Integer::I16 => hir_def::builtin_type::BuiltinUint::U16,
|
||||
hir_def::layout::Integer::I32 => hir_def::builtin_type::BuiltinUint::U32,
|
||||
hir_def::layout::Integer::I64 => hir_def::builtin_type::BuiltinUint::U64,
|
||||
hir_def::layout::Integer::I128 => hir_def::builtin_type::BuiltinUint::U128,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
@ -1042,7 +1083,7 @@ impl Variant {
|
|||
db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
|
||||
}
|
||||
|
||||
pub fn value(self, db: &dyn HirDatabase) -> Option<Expr> {
|
||||
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
|
||||
self.source(db)?.value.expr()
|
||||
}
|
||||
|
||||
|
@ -1076,6 +1117,13 @@ impl Adt {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
||||
if db.generic_params(self.into()).iter().count() != 0 {
|
||||
return Err(LayoutError::HasPlaceholder);
|
||||
}
|
||||
db.layout_of_adt(self.into(), Substitution::empty(Interner))
|
||||
}
|
||||
|
||||
/// Turns this ADT into a type. Any type parameters of the ADT will be
|
||||
/// turned into unknown types, which is good for e.g. finding the most
|
||||
/// general set of completions, but will not look very nice when printed.
|
||||
|
@ -1306,6 +1354,25 @@ impl DefWithBody {
|
|||
Err(SyntheticSyntax) => (),
|
||||
}
|
||||
}
|
||||
&hir_ty::InferenceDiagnostic::PrivateField { expr, field } => {
|
||||
let expr = source_map.expr_syntax(expr).expect("unexpected synthetic");
|
||||
let field = field.into();
|
||||
acc.push(PrivateField { expr, field }.into())
|
||||
}
|
||||
&hir_ty::InferenceDiagnostic::PrivateAssocItem { id, item } => {
|
||||
let expr_or_pat = match id {
|
||||
ExprOrPatId::ExprId(expr) => source_map
|
||||
.expr_syntax(expr)
|
||||
.expect("unexpected synthetic")
|
||||
.map(Either::Left),
|
||||
ExprOrPatId::PatId(pat) => source_map
|
||||
.pat_syntax(pat)
|
||||
.expect("unexpected synthetic")
|
||||
.map(Either::Right),
|
||||
};
|
||||
let item = item.into();
|
||||
acc.push(PrivateAssocItem { expr_or_pat, item }.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
for (expr, mismatch) in infer.expr_type_mismatches() {
|
||||
|
@ -1492,7 +1559,7 @@ impl Function {
|
|||
}
|
||||
|
||||
pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
|
||||
self.has_self_param(db).then(|| SelfParam { func: self.id })
|
||||
self.has_self_param(db).then_some(SelfParam { func: self.id })
|
||||
}
|
||||
|
||||
pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
|
||||
|
@ -2344,17 +2411,19 @@ pub struct DeriveHelper {
|
|||
|
||||
impl DeriveHelper {
|
||||
pub fn derive(&self) -> Macro {
|
||||
Macro { id: self.derive.into() }
|
||||
Macro { id: self.derive }
|
||||
}
|
||||
|
||||
pub fn name(&self, db: &dyn HirDatabase) -> Name {
|
||||
match self.derive {
|
||||
MacroId::Macro2Id(_) => None,
|
||||
MacroId::Macro2Id(it) => {
|
||||
db.macro2_data(it).helpers.as_deref().and_then(|it| it.get(self.idx)).cloned()
|
||||
}
|
||||
MacroId::MacroRulesId(_) => None,
|
||||
MacroId::ProcMacroId(proc_macro) => db
|
||||
.proc_macro_data(proc_macro)
|
||||
.helpers
|
||||
.as_ref()
|
||||
.as_deref()
|
||||
.and_then(|it| it.get(self.idx))
|
||||
.cloned(),
|
||||
}
|
||||
|
@ -2712,7 +2781,7 @@ impl Impl {
|
|||
pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
|
||||
let krate = trait_.module(db).krate();
|
||||
let mut all = Vec::new();
|
||||
for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter() {
|
||||
for Crate { id } in krate.transitive_reverse_dependencies(db) {
|
||||
let impls = db.trait_impls_in_crate(id);
|
||||
all.extend(impls.for_trait(trait_.id).map(Self::from))
|
||||
}
|
||||
|
@ -2857,6 +2926,13 @@ impl Type {
|
|||
matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
|
||||
}
|
||||
|
||||
pub fn is_int_or_uint(&self) -> bool {
|
||||
match self.ty.kind(Interner) {
|
||||
TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_ref(&self) -> Option<Type> {
|
||||
match &self.ty.kind(Interner) {
|
||||
TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
|
||||
|
@ -3031,7 +3107,7 @@ impl Type {
|
|||
|
||||
let adt = adt_id.into();
|
||||
match adt {
|
||||
Adt::Struct(s) => matches!(s.repr(db), Some(ReprData { packed: true, .. })),
|
||||
Adt::Struct(s) => s.repr(db).unwrap_or_default().pack.is_some(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -3225,7 +3301,7 @@ impl Type {
|
|||
with_local_impls.and_then(|b| b.id.containing_block()).into(),
|
||||
name,
|
||||
method_resolution::LookupMode::MethodCall,
|
||||
&mut |_adj, id| callback(id),
|
||||
&mut |_adj, id, _| callback(id),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3650,6 +3726,13 @@ impl From<ItemInNs> for ScopeDef {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Adjustment {
|
||||
pub source: Type,
|
||||
pub target: Type,
|
||||
pub kind: Adjust,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Adjust {
|
||||
/// Go from ! to any type.
|
||||
|
|
|
@ -2,14 +2,17 @@
|
|||
|
||||
mod source_to_def;
|
||||
|
||||
use std::{cell::RefCell, fmt, iter, ops};
|
||||
use std::{cell::RefCell, fmt, iter, mem, ops};
|
||||
|
||||
use base_db::{FileId, FileRange};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
body, macro_id_to_def_id,
|
||||
body,
|
||||
expr::Expr,
|
||||
macro_id_to_def_id,
|
||||
resolver::{self, HasResolver, Resolver, TypeNs},
|
||||
type_ref::Mutability,
|
||||
AsMacroCall, FunctionId, MacroId, TraitId, VariantId,
|
||||
AsMacroCall, DefWithBodyId, FunctionId, MacroId, TraitId, VariantId,
|
||||
};
|
||||
use hir_expand::{
|
||||
db::AstDatabase,
|
||||
|
@ -29,7 +32,7 @@ use crate::{
|
|||
db::HirDatabase,
|
||||
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
|
||||
source_analyzer::{resolve_hir_path, SourceAnalyzer},
|
||||
Access, Adjust, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate,
|
||||
Access, Adjust, Adjustment, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate,
|
||||
DeriveHelper, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local,
|
||||
Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, ToolModule, Trait, Type,
|
||||
TypeAlias, TypeParam, VariantDef,
|
||||
|
@ -334,7 +337,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
self.imp.resolve_trait(trait_)
|
||||
}
|
||||
|
||||
pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjust>> {
|
||||
pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjustment>> {
|
||||
self.imp.expr_adjustments(expr)
|
||||
}
|
||||
|
||||
|
@ -438,8 +441,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
}
|
||||
|
||||
pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
|
||||
let src = self.imp.find_file(src.syntax()).with_value(src).cloned();
|
||||
T::to_def(&self.imp, src)
|
||||
self.imp.to_def(src)
|
||||
}
|
||||
|
||||
pub fn to_module_def(&self, file: FileId) -> Option<Module> {
|
||||
|
@ -481,6 +483,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
|
||||
self.imp.is_unsafe_ident_pat(ident_pat)
|
||||
}
|
||||
|
||||
/// Returns `true` if the `node` is inside an `unsafe` context.
|
||||
pub fn is_inside_unsafe(&self, expr: &ast::Expr) -> bool {
|
||||
self.imp.is_inside_unsafe(expr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> SemanticsImpl<'db> {
|
||||
|
@ -788,7 +795,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
// requeue the tokens we got from mapping our current token down
|
||||
stack.extend(mapped_tokens);
|
||||
// if the length changed we have found a mapping for the token
|
||||
(stack.len() != len).then(|| ())
|
||||
(stack.len() != len).then_some(())
|
||||
};
|
||||
|
||||
// Remap the next token in the queue into a macro call its in, if it is not being remapped
|
||||
|
@ -840,7 +847,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
}
|
||||
};
|
||||
process_expansion_for_token(&mut stack, file_id, None, token.as_ref())
|
||||
} else if let Some(meta) = ast::Meta::cast(parent.clone()) {
|
||||
} else if let Some(meta) = ast::Meta::cast(parent) {
|
||||
// attribute we failed expansion for earlier, this might be a derive invocation
|
||||
// or derive helper attribute
|
||||
let attr = meta.parent_attr()?;
|
||||
|
@ -1067,26 +1074,42 @@ impl<'db> SemanticsImpl<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjust>> {
|
||||
fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjustment>> {
|
||||
let mutability = |m| match m {
|
||||
hir_ty::Mutability::Not => Mutability::Shared,
|
||||
hir_ty::Mutability::Mut => Mutability::Mut,
|
||||
};
|
||||
self.analyze(expr.syntax())?.expr_adjustments(self.db, expr).map(|it| {
|
||||
|
||||
let analyzer = self.analyze(expr.syntax())?;
|
||||
|
||||
let (mut source_ty, _) = analyzer.type_of_expr(self.db, expr)?;
|
||||
|
||||
analyzer.expr_adjustments(self.db, expr).map(|it| {
|
||||
it.iter()
|
||||
.map(|adjust| match adjust.kind {
|
||||
hir_ty::Adjust::NeverToAny => Adjust::NeverToAny,
|
||||
hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => {
|
||||
Adjust::Deref(Some(OverloadedDeref(mutability(m))))
|
||||
}
|
||||
hir_ty::Adjust::Deref(None) => Adjust::Deref(None),
|
||||
hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::RawPtr(m)) => {
|
||||
Adjust::Borrow(AutoBorrow::RawPtr(mutability(m)))
|
||||
}
|
||||
hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::Ref(m)) => {
|
||||
Adjust::Borrow(AutoBorrow::Ref(mutability(m)))
|
||||
}
|
||||
hir_ty::Adjust::Pointer(pc) => Adjust::Pointer(pc),
|
||||
.map(|adjust| {
|
||||
let target =
|
||||
Type::new_with_resolver(self.db, &analyzer.resolver, adjust.target.clone());
|
||||
let kind = match adjust.kind {
|
||||
hir_ty::Adjust::NeverToAny => Adjust::NeverToAny,
|
||||
hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => {
|
||||
Adjust::Deref(Some(OverloadedDeref(mutability(m))))
|
||||
}
|
||||
hir_ty::Adjust::Deref(None) => Adjust::Deref(None),
|
||||
hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::RawPtr(m)) => {
|
||||
Adjust::Borrow(AutoBorrow::RawPtr(mutability(m)))
|
||||
}
|
||||
hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::Ref(m)) => {
|
||||
Adjust::Borrow(AutoBorrow::Ref(mutability(m)))
|
||||
}
|
||||
hir_ty::Adjust::Pointer(pc) => Adjust::Pointer(pc),
|
||||
};
|
||||
|
||||
// Update `source_ty` for the next adjustment
|
||||
let source = mem::replace(&mut source_ty, target.clone());
|
||||
|
||||
let adjustment = Adjustment { source, target, kind };
|
||||
|
||||
adjustment
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
|
@ -1198,7 +1221,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
krate
|
||||
.dependencies(self.db)
|
||||
.into_iter()
|
||||
.find_map(|dep| (dep.name == name).then(|| dep.krate))
|
||||
.find_map(|dep| (dep.name == name).then_some(dep.krate))
|
||||
}
|
||||
|
||||
fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
|
||||
|
@ -1223,10 +1246,15 @@ impl<'db> SemanticsImpl<'db> {
|
|||
|
||||
fn with_ctx<F: FnOnce(&mut SourceToDefCtx<'_, '_>) -> T, T>(&self, f: F) -> T {
|
||||
let mut cache = self.s2d_cache.borrow_mut();
|
||||
let mut ctx = SourceToDefCtx { db: self.db, cache: &mut *cache };
|
||||
let mut ctx = SourceToDefCtx { db: self.db, cache: &mut cache };
|
||||
f(&mut ctx)
|
||||
}
|
||||
|
||||
fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
|
||||
let src = self.find_file(src.syntax()).with_value(src).cloned();
|
||||
T::to_def(self, src)
|
||||
}
|
||||
|
||||
fn to_module_def(&self, file: FileId) -> impl Iterator<Item = Module> {
|
||||
self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from)
|
||||
}
|
||||
|
@ -1350,7 +1378,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
self.cache
|
||||
.borrow()
|
||||
.keys()
|
||||
.map(|it| format!("{:?}", it))
|
||||
.map(|it| format!("{it:?}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
|
@ -1442,6 +1470,56 @@ impl<'db> SemanticsImpl<'db> {
|
|||
.map(|ty| ty.original.is_packed(self.db))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn is_inside_unsafe(&self, expr: &ast::Expr) -> bool {
|
||||
let item_or_variant = |ancestor: SyntaxNode| {
|
||||
if ast::Item::can_cast(ancestor.kind()) {
|
||||
ast::Item::cast(ancestor).map(Either::Left)
|
||||
} else {
|
||||
ast::Variant::cast(ancestor).map(Either::Right)
|
||||
}
|
||||
};
|
||||
let Some(enclosing_item) = expr.syntax().ancestors().find_map(item_or_variant) else { return false };
|
||||
|
||||
let def = match &enclosing_item {
|
||||
Either::Left(ast::Item::Fn(it)) if it.unsafe_token().is_some() => return true,
|
||||
Either::Left(ast::Item::Fn(it)) => {
|
||||
self.to_def(it).map(<_>::into).map(DefWithBodyId::FunctionId)
|
||||
}
|
||||
Either::Left(ast::Item::Const(it)) => {
|
||||
self.to_def(it).map(<_>::into).map(DefWithBodyId::ConstId)
|
||||
}
|
||||
Either::Left(ast::Item::Static(it)) => {
|
||||
self.to_def(it).map(<_>::into).map(DefWithBodyId::StaticId)
|
||||
}
|
||||
Either::Left(_) => None,
|
||||
Either::Right(it) => self.to_def(it).map(<_>::into).map(DefWithBodyId::VariantId),
|
||||
};
|
||||
let Some(def) = def else { return false };
|
||||
let enclosing_node = enclosing_item.as_ref().either(|i| i.syntax(), |v| v.syntax());
|
||||
|
||||
let (body, source_map) = self.db.body_with_source_map(def);
|
||||
|
||||
let file_id = self.find_file(expr.syntax()).file_id;
|
||||
|
||||
let Some(mut parent) = expr.syntax().parent() else { return false };
|
||||
loop {
|
||||
if &parent == enclosing_node {
|
||||
break false;
|
||||
}
|
||||
|
||||
if let Some(parent) = ast::Expr::cast(parent.clone()) {
|
||||
if let Some(expr_id) = source_map.node_expr(InFile { file_id, value: &parent }) {
|
||||
if let Expr::Unsafe { .. } = body[expr_id] {
|
||||
break true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(parent_) = parent.parent() else { break false };
|
||||
parent = parent_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn macro_call_to_macro_id(
|
||||
|
@ -1600,7 +1678,7 @@ impl<'a> SemanticsScope<'a> {
|
|||
self.db,
|
||||
def,
|
||||
resolution.in_type_ns()?,
|
||||
|name, _, id| cb(name, id.into()),
|
||||
|name, id| cb(name, id.into()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ use hir_def::{
|
|||
path::{ModPath, Path, PathKind},
|
||||
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
|
||||
type_ref::Mutability,
|
||||
AsMacroCall, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, LocalFieldId,
|
||||
Lookup, ModuleDefId, TraitId, VariantId,
|
||||
AsMacroCall, AssocItemId, ConstId, DefWithBodyId, FieldId, FunctionId, ItemContainerId,
|
||||
LocalFieldId, Lookup, ModuleDefId, TraitId, VariantId,
|
||||
};
|
||||
use hir_expand::{
|
||||
builtin_fn_macro::BuiltinFnLikeExpander,
|
||||
|
@ -118,7 +118,7 @@ impl SourceAnalyzer {
|
|||
fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
|
||||
let src = match expr {
|
||||
ast::Expr::MacroExpr(expr) => {
|
||||
self.expand_expr(db, InFile::new(self.file_id, expr.macro_call()?.clone()))?
|
||||
self.expand_expr(db, InFile::new(self.file_id, expr.macro_call()?))?
|
||||
}
|
||||
_ => InFile::new(self.file_id, expr.clone()),
|
||||
};
|
||||
|
@ -228,7 +228,7 @@ impl SourceAnalyzer {
|
|||
db: &dyn HirDatabase,
|
||||
pat: &ast::Pat,
|
||||
) -> Option<SmallVec<[Type; 1]>> {
|
||||
let pat_id = self.pat_id(&pat)?;
|
||||
let pat_id = self.pat_id(pat)?;
|
||||
let infer = self.infer.as_ref()?;
|
||||
Some(
|
||||
infer
|
||||
|
@ -270,7 +270,7 @@ impl SourceAnalyzer {
|
|||
db: &dyn HirDatabase,
|
||||
await_expr: &ast::AwaitExpr,
|
||||
) -> Option<FunctionId> {
|
||||
let mut ty = self.ty_of_expr(db, &await_expr.expr()?.into())?.clone();
|
||||
let mut ty = self.ty_of_expr(db, &await_expr.expr()?)?.clone();
|
||||
|
||||
let into_future_trait = self
|
||||
.resolver
|
||||
|
@ -316,7 +316,7 @@ impl SourceAnalyzer {
|
|||
ast::UnaryOp::Not => name![not],
|
||||
ast::UnaryOp::Neg => name![neg],
|
||||
};
|
||||
let ty = self.ty_of_expr(db, &prefix_expr.expr()?.into())?;
|
||||
let ty = self.ty_of_expr(db, &prefix_expr.expr()?)?;
|
||||
|
||||
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
|
||||
|
@ -331,8 +331,8 @@ impl SourceAnalyzer {
|
|||
db: &dyn HirDatabase,
|
||||
index_expr: &ast::IndexExpr,
|
||||
) -> Option<FunctionId> {
|
||||
let base_ty = self.ty_of_expr(db, &index_expr.base()?.into())?;
|
||||
let index_ty = self.ty_of_expr(db, &index_expr.index()?.into())?;
|
||||
let base_ty = self.ty_of_expr(db, &index_expr.base()?)?;
|
||||
let index_ty = self.ty_of_expr(db, &index_expr.index()?)?;
|
||||
|
||||
let lang_item_name = name![index];
|
||||
|
||||
|
@ -352,8 +352,8 @@ impl SourceAnalyzer {
|
|||
binop_expr: &ast::BinExpr,
|
||||
) -> Option<FunctionId> {
|
||||
let op = binop_expr.op_kind()?;
|
||||
let lhs = self.ty_of_expr(db, &binop_expr.lhs()?.into())?;
|
||||
let rhs = self.ty_of_expr(db, &binop_expr.rhs()?.into())?;
|
||||
let lhs = self.ty_of_expr(db, &binop_expr.lhs()?)?;
|
||||
let rhs = self.ty_of_expr(db, &binop_expr.rhs()?)?;
|
||||
|
||||
let (op_trait, op_fn) = lang_names_for_bin_op(op)
|
||||
.and_then(|(name, lang_item)| self.lang_trait_fn(db, &lang_item, &name))?;
|
||||
|
@ -372,7 +372,7 @@ impl SourceAnalyzer {
|
|||
db: &dyn HirDatabase,
|
||||
try_expr: &ast::TryExpr,
|
||||
) -> Option<FunctionId> {
|
||||
let ty = self.ty_of_expr(db, &try_expr.expr()?.into())?;
|
||||
let ty = self.ty_of_expr(db, &try_expr.expr()?)?;
|
||||
|
||||
let op_fn =
|
||||
db.lang_item(self.resolver.krate(), name![branch].to_smol_str())?.as_function()?;
|
||||
|
@ -482,7 +482,7 @@ impl SourceAnalyzer {
|
|||
let infer = self.infer.as_deref()?;
|
||||
if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
|
||||
let expr_id = self.expr_id(db, &path_expr.into())?;
|
||||
if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
|
||||
if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr(expr_id) {
|
||||
let assoc = match assoc {
|
||||
AssocItemId::FunctionId(f_in_trait) => {
|
||||
match infer.type_of_expr.get(expr_id) {
|
||||
|
@ -501,7 +501,9 @@ impl SourceAnalyzer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
AssocItemId::ConstId(const_id) => {
|
||||
self.resolve_impl_const_or_trait_def(db, const_id, subs).into()
|
||||
}
|
||||
_ => assoc,
|
||||
};
|
||||
|
||||
|
@ -515,7 +517,7 @@ impl SourceAnalyzer {
|
|||
prefer_value_ns = true;
|
||||
} else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
|
||||
let pat_id = self.pat_id(&path_pat.into())?;
|
||||
if let Some(assoc) = infer.assoc_resolutions_for_pat(pat_id) {
|
||||
if let Some((assoc, _)) = infer.assoc_resolutions_for_pat(pat_id) {
|
||||
return Some(PathResolution::Def(AssocItem::from(assoc).into()));
|
||||
}
|
||||
if let Some(VariantId::EnumVariantId(variant)) =
|
||||
|
@ -792,6 +794,24 @@ impl SourceAnalyzer {
|
|||
method_resolution::lookup_impl_method(db, env, func, substs)
|
||||
}
|
||||
|
||||
fn resolve_impl_const_or_trait_def(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
const_id: ConstId,
|
||||
subs: Substitution,
|
||||
) -> ConstId {
|
||||
let krate = self.resolver.krate();
|
||||
let owner = match self.resolver.body_owner() {
|
||||
Some(it) => it,
|
||||
None => return const_id,
|
||||
};
|
||||
let env = owner.as_generic_def_id().map_or_else(
|
||||
|| Arc::new(hir_ty::TraitEnvironment::empty(krate)),
|
||||
|d| db.trait_environment(d),
|
||||
);
|
||||
method_resolution::lookup_impl_const(db, env, const_id, subs)
|
||||
}
|
||||
|
||||
fn lang_trait_fn(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
|
@ -804,7 +824,7 @@ impl SourceAnalyzer {
|
|||
}
|
||||
|
||||
fn ty_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<&Ty> {
|
||||
self.infer.as_ref()?.type_of_expr.get(self.expr_id(db, &expr)?)
|
||||
self.infer.as_ref()?.type_of_expr.get(self.expr_id(db, expr)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -967,7 +987,7 @@ fn resolve_hir_path_(
|
|||
db,
|
||||
def,
|
||||
res.in_type_ns()?,
|
||||
|name, _, id| (name == unresolved.name).then(|| id),
|
||||
|name, id| (name == unresolved.name).then_some(id),
|
||||
)
|
||||
})
|
||||
.map(TypeAlias::from)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue