mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
Merge commit '37f84c101b
' into sync-from-ra
This commit is contained in:
parent
6502421771
commit
4704881b64
311 changed files with 13700 additions and 9110 deletions
|
@ -47,7 +47,7 @@ use hir_def::{
|
|||
lang_item::LangItemTarget,
|
||||
layout::{self, ReprOptions, TargetDataLayout},
|
||||
macro_id_to_def_id,
|
||||
nameres::{self, diagnostics::DefDiagnostic, ModuleOrigin},
|
||||
nameres::{self, diagnostics::DefDiagnostic},
|
||||
per_ns::PerNs,
|
||||
resolver::{HasResolver, Resolver},
|
||||
src::HasSource as _,
|
||||
|
@ -62,7 +62,6 @@ use hir_ty::{
|
|||
all_super_traits, autoderef,
|
||||
consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt},
|
||||
diagnostics::BodyValidationDiagnostic,
|
||||
display::HexifiedConst,
|
||||
layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding},
|
||||
method_resolution::{self, TyFingerprint},
|
||||
mir::{self, interpret_mir},
|
||||
|
@ -89,11 +88,11 @@ use crate::db::{DefDatabase, HirDatabase};
|
|||
pub use crate::{
|
||||
attrs::{HasAttrs, Namespace},
|
||||
diagnostics::{
|
||||
AnyDiagnostic, BreakOutsideOfLoop, ExpectedFunction, InactiveCode, IncoherentImpl,
|
||||
IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError, MacroExpansionParseError,
|
||||
MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms, MissingUnsafe,
|
||||
MovedOutOfRef, NeedMut, NoSuchField, PrivateAssocItem, PrivateField,
|
||||
ReplaceFilterMapNextWithFindMap, TypeMismatch, TypedHole, UndeclaredLabel,
|
||||
AnyDiagnostic, BreakOutsideOfLoop, CaseType, ExpectedFunction, InactiveCode,
|
||||
IncoherentImpl, IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError,
|
||||
MacroExpansionParseError, MalformedDerive, MismatchedArgCount, MissingFields,
|
||||
MissingMatchArms, MissingUnsafe, MovedOutOfRef, NeedMut, NoSuchField, PrivateAssocItem,
|
||||
PrivateField, ReplaceFilterMapNextWithFindMap, TypeMismatch, TypedHole, UndeclaredLabel,
|
||||
UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate, UnresolvedField,
|
||||
UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule,
|
||||
UnresolvedProcMacro, UnusedMut,
|
||||
|
@ -505,15 +504,10 @@ impl Module {
|
|||
/// Finds nearest non-block ancestor `Module` (`self` included).
|
||||
pub fn nearest_non_block_module(self, db: &dyn HirDatabase) -> Module {
|
||||
let mut id = self.id;
|
||||
loop {
|
||||
let def_map = id.def_map(db.upcast());
|
||||
let origin = def_map[id.local_id].origin;
|
||||
if matches!(origin, ModuleOrigin::BlockExpr { .. }) {
|
||||
id = id.containing_module(db.upcast()).expect("block without parent module")
|
||||
} else {
|
||||
return Module { id };
|
||||
}
|
||||
while id.is_block_module() {
|
||||
id = id.containing_module(db.upcast()).expect("block without parent module");
|
||||
}
|
||||
Module { id }
|
||||
}
|
||||
|
||||
pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
|
||||
|
@ -619,15 +613,21 @@ impl Module {
|
|||
let inherent_impls = db.inherent_impls_in_crate(self.id.krate());
|
||||
|
||||
for impl_def in self.impl_defs(db) {
|
||||
let loc = impl_def.id.lookup(db.upcast());
|
||||
let tree = loc.id.item_tree(db.upcast());
|
||||
let node = &tree[loc.id.value];
|
||||
let file_id = loc.id.file_id();
|
||||
if file_id.is_builtin_derive(db.upcast()) {
|
||||
// these expansion come from us, diagnosing them is a waste of resources
|
||||
// FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
|
||||
continue;
|
||||
}
|
||||
|
||||
for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
|
||||
emit_def_diagnostic(db, acc, diag);
|
||||
}
|
||||
|
||||
if inherent_impls.invalid_impls().contains(&impl_def.id) {
|
||||
let loc = impl_def.id.lookup(db.upcast());
|
||||
let tree = loc.id.item_tree(db.upcast());
|
||||
let node = &tree[loc.id.value];
|
||||
let file_id = loc.id.file_id();
|
||||
let ast_id_map = db.ast_id_map(file_id);
|
||||
|
||||
acc.push(IncoherentImpl { impl_: ast_id_map.get(node.ast_id()), file_id }.into())
|
||||
|
@ -698,16 +698,18 @@ impl Module {
|
|||
|
||||
fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
|
||||
let id = macro_id_to_def_id(db.upcast(), m.id);
|
||||
if let Err(e) = db.macro_def(id) {
|
||||
let Some(ast) = id.ast_id().left() else {
|
||||
never!("MacroDefError for proc-macro: {:?}", e);
|
||||
if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) {
|
||||
if let Some(e) = expander.mac.err() {
|
||||
let Some(ast) = id.ast_id().left() else {
|
||||
never!("declarative expander for non decl-macro: {:?}", e);
|
||||
return;
|
||||
};
|
||||
emit_def_diagnostic_(
|
||||
db,
|
||||
acc,
|
||||
&DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
|
||||
);
|
||||
emit_def_diagnostic_(
|
||||
db,
|
||||
acc,
|
||||
&DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -753,7 +755,7 @@ fn emit_def_diagnostic_(
|
|||
let item = ast.to_node(db.upcast());
|
||||
acc.push(
|
||||
InactiveCode {
|
||||
node: ast.with_value(AstPtr::new(&item).into()),
|
||||
node: ast.with_value(SyntaxNodePtr::new(&item).into()),
|
||||
cfg: cfg.clone(),
|
||||
opts: opts.clone(),
|
||||
}
|
||||
|
@ -1234,7 +1236,7 @@ impl Adt {
|
|||
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
|
||||
let subst = db.generic_defaults(self.into());
|
||||
subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
|
||||
GenericArgData::Ty(x) => x.is_unknown(),
|
||||
GenericArgData::Ty(it) => it.is_unknown(),
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
@ -1635,11 +1637,11 @@ impl DefWithBody {
|
|||
for moof in &borrowck_result.moved_out_of_ref {
|
||||
let span: InFile<SyntaxNodePtr> = match moof.span {
|
||||
mir::MirSpan::ExprId(e) => match source_map.expr_syntax(e) {
|
||||
Ok(s) => s.map(|x| x.into()),
|
||||
Ok(s) => s.map(|it| it.into()),
|
||||
Err(_) => continue,
|
||||
},
|
||||
mir::MirSpan::PatId(p) => match source_map.pat_syntax(p) {
|
||||
Ok(s) => s.map(|x| match x {
|
||||
Ok(s) => s.map(|it| match it {
|
||||
Either::Left(e) => e.into(),
|
||||
Either::Right(e) => e.into(),
|
||||
}),
|
||||
|
@ -1661,6 +1663,14 @@ impl DefWithBody {
|
|||
let Some(&local) = mir_body.binding_locals.get(binding_id) else {
|
||||
continue;
|
||||
};
|
||||
if body[binding_id]
|
||||
.definitions
|
||||
.iter()
|
||||
.any(|&pat| source_map.pat_syntax(pat).is_err())
|
||||
{
|
||||
// Skip synthetic bindings
|
||||
continue;
|
||||
}
|
||||
let need_mut = &mol[local];
|
||||
let local = Local { parent: self.into(), binding_id };
|
||||
match (need_mut, local.is_mut(db)) {
|
||||
|
@ -1670,11 +1680,11 @@ impl DefWithBody {
|
|||
for span in spans {
|
||||
let span: InFile<SyntaxNodePtr> = match span {
|
||||
mir::MirSpan::ExprId(e) => match source_map.expr_syntax(*e) {
|
||||
Ok(s) => s.map(|x| x.into()),
|
||||
Ok(s) => s.map(|it| it.into()),
|
||||
Err(_) => continue,
|
||||
},
|
||||
mir::MirSpan::PatId(p) => match source_map.pat_syntax(*p) {
|
||||
Ok(s) => s.map(|x| match x {
|
||||
Ok(s) => s.map(|it| match it {
|
||||
Either::Left(e) => e.into(),
|
||||
Either::Right(e) => e.into(),
|
||||
}),
|
||||
|
@ -1687,7 +1697,7 @@ impl DefWithBody {
|
|||
}
|
||||
(mir::MutabilityReason::Not, true) => {
|
||||
if !infer.mutated_bindings_in_closure.contains(&binding_id) {
|
||||
let should_ignore = matches!(body[binding_id].name.as_str(), Some(x) if x.starts_with("_"));
|
||||
let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with("_"));
|
||||
if !should_ignore {
|
||||
acc.push(UnusedMut { local }.into())
|
||||
}
|
||||
|
@ -1919,6 +1929,21 @@ impl Function {
|
|||
db.function_data(self.id).has_async_kw()
|
||||
}
|
||||
|
||||
/// Does this function have `#[test]` attribute?
|
||||
pub fn is_test(self, db: &dyn HirDatabase) -> bool {
|
||||
db.function_data(self.id).attrs.is_test()
|
||||
}
|
||||
|
||||
/// Does this function have the ignore attribute?
|
||||
pub fn is_ignore(self, db: &dyn HirDatabase) -> bool {
|
||||
db.function_data(self.id).attrs.is_ignore()
|
||||
}
|
||||
|
||||
/// Does this function have `#[bench]` attribute?
|
||||
pub fn is_bench(self, db: &dyn HirDatabase) -> bool {
|
||||
db.function_data(self.id).attrs.is_bench()
|
||||
}
|
||||
|
||||
pub fn is_unsafe_to_call(self, db: &dyn HirDatabase) -> bool {
|
||||
hir_ty::is_fn_unsafe_to_call(db, self.id)
|
||||
}
|
||||
|
@ -1962,7 +1987,7 @@ impl Function {
|
|||
return r;
|
||||
}
|
||||
};
|
||||
let (result, stdout, stderr) = interpret_mir(db, &body, false);
|
||||
let (result, stdout, stderr) = interpret_mir(db, body, false);
|
||||
let mut text = match result {
|
||||
Ok(_) => "pass".to_string(),
|
||||
Err(e) => {
|
||||
|
@ -2132,7 +2157,27 @@ impl Const {
|
|||
|
||||
pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
|
||||
let c = db.const_eval(self.id.into(), Substitution::empty(Interner))?;
|
||||
let r = format!("{}", HexifiedConst(c).display(db));
|
||||
let data = &c.data(Interner);
|
||||
if let TyKind::Scalar(s) = data.ty.kind(Interner) {
|
||||
if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
|
||||
if let hir_ty::ConstValue::Concrete(c) = &data.value {
|
||||
if let hir_ty::ConstScalar::Bytes(b, _) = &c.interned {
|
||||
let value = u128::from_le_bytes(mir::pad16(b, false));
|
||||
let value_signed =
|
||||
i128::from_le_bytes(mir::pad16(b, matches!(s, Scalar::Int(_))));
|
||||
if value >= 10 {
|
||||
return Ok(format!("{} ({:#X})", value_signed, value));
|
||||
} else {
|
||||
return Ok(format!("{}", value_signed));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Ok(s) = mir::render_const_using_debug_impl(db, self.id, &c) {
|
||||
return Ok(s);
|
||||
}
|
||||
let r = format!("{}", c.display(db));
|
||||
return Ok(r);
|
||||
}
|
||||
}
|
||||
|
@ -2270,7 +2315,7 @@ impl TypeAlias {
|
|||
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
|
||||
let subst = db.generic_defaults(self.id.into());
|
||||
subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
|
||||
GenericArgData::Ty(x) => x.is_unknown(),
|
||||
GenericArgData::Ty(it) => it.is_unknown(),
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
@ -2660,8 +2705,8 @@ impl GenericDef {
|
|||
let ty_params = generics.type_or_consts.iter().map(|(local_id, _)| {
|
||||
let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
|
||||
match toc.split(db) {
|
||||
Either::Left(x) => GenericParam::ConstParam(x),
|
||||
Either::Right(x) => GenericParam::TypeParam(x),
|
||||
Either::Left(it) => GenericParam::ConstParam(it),
|
||||
Either::Right(it) => GenericParam::TypeParam(it),
|
||||
}
|
||||
});
|
||||
self.lifetime_params(db)
|
||||
|
@ -2709,14 +2754,14 @@ pub struct LocalSource {
|
|||
impl LocalSource {
|
||||
pub fn as_ident_pat(&self) -> Option<&ast::IdentPat> {
|
||||
match &self.source.value {
|
||||
Either::Left(x) => Some(x),
|
||||
Either::Left(it) => Some(it),
|
||||
Either::Right(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_ident_pat(self) -> Option<ast::IdentPat> {
|
||||
match self.source.value {
|
||||
Either::Left(x) => Some(x),
|
||||
Either::Left(it) => Some(it),
|
||||
Either::Right(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -2738,7 +2783,7 @@ impl LocalSource {
|
|||
}
|
||||
|
||||
pub fn syntax_ptr(self) -> InFile<SyntaxNodePtr> {
|
||||
self.source.map(|x| SyntaxNodePtr::new(x.syntax()))
|
||||
self.source.map(|it| SyntaxNodePtr::new(it.syntax()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2797,13 +2842,13 @@ impl Local {
|
|||
Type::new(db, def, ty)
|
||||
}
|
||||
|
||||
/// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = x;`
|
||||
/// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;`
|
||||
pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
|
||||
let (body, source_map) = db.body_with_source_map(self.parent);
|
||||
self.sources_(db, &body, &source_map).collect()
|
||||
}
|
||||
|
||||
/// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = x;`
|
||||
/// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = it;`
|
||||
pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
|
||||
let (body, source_map) = db.body_with_source_map(self.parent);
|
||||
let src = self.sources_(db, &body, &source_map).next().unwrap();
|
||||
|
@ -3057,7 +3102,9 @@ impl TypeParam {
|
|||
let subst = TyBuilder::placeholder_subst(db, self.id.parent());
|
||||
let ty = ty.substitute(Interner, &subst);
|
||||
match ty.data(Interner) {
|
||||
GenericArgData::Ty(x) => Some(Type::new_with_resolver_inner(db, &resolver, x.clone())),
|
||||
GenericArgData::Ty(it) => {
|
||||
Some(Type::new_with_resolver_inner(db, &resolver, it.clone()))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -3096,7 +3143,7 @@ impl ConstParam {
|
|||
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
||||
let params = db.generic_params(self.id.parent());
|
||||
match params.type_or_consts[self.id.local_id()].name() {
|
||||
Some(x) => x.clone(),
|
||||
Some(it) => it.clone(),
|
||||
None => {
|
||||
never!();
|
||||
Name::missing()
|
||||
|
@ -3153,8 +3200,8 @@ impl TypeOrConstParam {
|
|||
|
||||
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
||||
match self.split(db) {
|
||||
Either::Left(x) => x.ty(db),
|
||||
Either::Right(x) => x.ty(db),
|
||||
Either::Left(it) => it.ty(db),
|
||||
Either::Right(it) => it.ty(db),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3260,9 +3307,9 @@ impl Impl {
|
|||
self.id.lookup(db.upcast()).container.into()
|
||||
}
|
||||
|
||||
pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
|
||||
pub fn as_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
|
||||
let src = self.source(db)?;
|
||||
src.file_id.is_builtin_derive(db.upcast())
|
||||
src.file_id.as_builtin_derive_attr_node(db.upcast())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3652,9 +3699,9 @@ impl Type {
|
|||
};
|
||||
let parent_subst = TyBuilder::subst_for_def(db, trait_id, None)
|
||||
.push(self.ty.clone())
|
||||
.fill(|x| {
|
||||
.fill(|it| {
|
||||
// FIXME: this code is not covered in tests.
|
||||
match x {
|
||||
match it {
|
||||
ParamKind::Type => {
|
||||
GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner)
|
||||
}
|
||||
|
@ -3821,7 +3868,7 @@ impl Type {
|
|||
|
||||
pub fn as_array(&self, db: &dyn HirDatabase) -> Option<(Type, usize)> {
|
||||
if let TyKind::Array(ty, len) = &self.ty.kind(Interner) {
|
||||
try_const_usize(db, len).map(|x| (self.derived(ty.clone()), x as usize))
|
||||
try_const_usize(db, len).map(|it| (self.derived(ty.clone()), it as usize))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue