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 | 89 |
1 files changed, 81 insertions, 8 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 58340c74fe..8f5db32f95 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -43,7 +43,7 @@ use hir_def::{ body::{BodyDiagnostic, SyntheticSyntax}, data::adt::VariantData, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, - hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat}, + hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat}, item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode}, lang_item::LangItemTarget, layout::{self, ReprOptions, TargetDataLayout}, @@ -66,7 +66,7 @@ use hir_ty::{ diagnostics::BodyValidationDiagnostic, error_lifetime, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, - method_resolution::{self}, + method_resolution, mir::{interpret_mir, MutBorrowKind}, primitive::UintTy, traits::FnTrait, @@ -80,7 +80,7 @@ use nameres::diagnostics::DefDiagnosticKind; use rustc_hash::FxHashSet; use smallvec::SmallVec; use span::{Edition, EditionedFileId, FileId, MacroCallId, SyntaxContextId}; -use stdx::{impl_from, never}; +use stdx::{format_to, impl_from, never}; use syntax::{ ast::{self, HasAttrs as _, HasGenericParams, HasName}, format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T, @@ -137,6 +137,7 @@ pub use { hygiene::{marks_rev, SyntaxContextExt}, inert_attr_macro::AttributeTemplate, name::Name, + prettify_macro_expansion, proc_macro::{ProcMacros, ProcMacrosBuilder}, tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt, }, @@ -145,7 +146,8 @@ pub use { display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, layout::LayoutError, mir::{MirEvalError, MirLowerError}, - FnAbi, PointerCast, Safety, + object_safety::{MethodViolationCode, ObjectSafetyViolation}, + CastError, FnAbi, PointerCast, Safety, }, // FIXME: Properly encapsulate mir hir_ty::{mir, Interner as ChalkTyInterner}, @@ -1882,9 +1884,10 @@ impl DefWithBody { ); } - for expr in hir_ty::diagnostics::missing_unsafe(db, self.into()) { + let (unafe_exprs, only_lint) = hir_ty::diagnostics::missing_unsafe(db, self.into()); + for expr in unafe_exprs { match source_map.expr_syntax(expr) { - Ok(expr) => acc.push(MissingUnsafe { expr }.into()), + Ok(expr) => acc.push(MissingUnsafe { expr, only_lint }.into()), Err(SyntheticSyntax) => { // FIXME: Here and elsewhere in this file, the `expr` was // desugared, report or assert that this doesn't happen. @@ -2206,6 +2209,35 @@ impl Function { db.function_data(self.id).is_async() } + pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool { + if self.is_async(db) { + return true; + } + + let Some(impl_traits) = self.ret_type(db).as_impl_traits(db) else { return false }; + let Some(future_trait_id) = + db.lang_item(self.ty(db).env.krate, LangItem::Future).and_then(|t| t.as_trait()) + else { + return false; + }; + let Some(sized_trait_id) = + db.lang_item(self.ty(db).env.krate, LangItem::Sized).and_then(|t| t.as_trait()) + else { + return false; + }; + + let mut has_impl_future = false; + impl_traits + .filter(|t| { + let fut = t.id == future_trait_id; + has_impl_future |= fut; + !fut && t.id != sized_trait_id + }) + // all traits but the future trait must be auto traits + .all(|t| t.is_auto(db)) + && has_impl_future + } + /// Does this function have `#[test]` attribute? pub fn is_test(self, db: &dyn HirDatabase) -> bool { db.function_data(self.id).attrs.is_test() @@ -2522,6 +2554,17 @@ impl Const { Type::from_value_def(db, self.id) } + /// Evaluate the constant and return the result as a string. + /// + /// This function is intended for IDE assistance, different from [`Const::render_eval`]. + pub fn eval(self, db: &dyn HirDatabase, edition: Edition) -> Result<String, ConstEvalError> { + let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?; + Ok(format!("{}", c.display(db, edition))) + } + + /// Evaluate the constant and return the result as a string, with more detailed information. + /// + /// This function is intended for user-facing display. pub fn render_eval( self, db: &dyn HirDatabase, @@ -2536,10 +2579,16 @@ impl Const { let value = u128::from_le_bytes(mir::pad16(b, false)); let value_signed = i128::from_le_bytes(mir::pad16(b, matches!(s, Scalar::Int(_)))); + let mut result = if let Scalar::Int(_) = s { + value_signed.to_string() + } else { + value.to_string() + }; if value >= 10 { - return Ok(format!("{value_signed} ({value:#X})")); + format_to!(result, " ({value:#X})"); + return Ok(result); } else { - return Ok(format!("{value_signed}")); + return Ok(result); } } } @@ -2641,6 +2690,10 @@ impl Trait { .count() } + pub fn object_safety(&self, db: &dyn HirDatabase) -> Option<ObjectSafetyViolation> { + hir_ty::object_safety::object_safety(db, self.id) + } + fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> { db.trait_data(self.id) .macro_calls @@ -5211,6 +5264,26 @@ impl Type { } } +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub struct InlineAsmOperand { + owner: DefWithBodyId, + expr: ExprId, + index: usize, +} + +impl InlineAsmOperand { + pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody { + self.owner.into() + } + + pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> { + match &db.body(self.owner)[self.expr] { + hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(), + _ => None, + } + } +} + // FIXME: Document this #[derive(Debug)] pub struct Callable { |