diff --git a/crates/hir-ty/src/diagnostics.rs b/crates/hir-ty/src/diagnostics.rs index 30c02a2936..845d333335 100644 --- a/crates/hir-ty/src/diagnostics.rs +++ b/crates/hir-ty/src/diagnostics.rs @@ -9,5 +9,8 @@ pub use crate::diagnostics::{ expr::{ record_literal_missing_fields, record_pattern_missing_fields, BodyValidationDiagnostic, }, - unsafe_check::{missing_unsafe, unsafe_expressions, InsideUnsafeBlock, UnsafetyReason}, + unsafe_check::{ + missing_unsafe, unsafe_operations, unsafe_operations_for_body, InsideUnsafeBlock, + UnsafetyReason, + }, }; diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs index ac849b0762..d2b908839c 100644 --- a/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -95,7 +95,26 @@ enum UnsafeDiagnostic { DeprecatedSafe2024 { node: ExprId, inside_unsafe_block: InsideUnsafeBlock }, } -pub fn unsafe_expressions( +pub fn unsafe_operations_for_body( + db: &dyn HirDatabase, + infer: &InferenceResult, + def: DefWithBodyId, + body: &Body, + callback: &mut dyn FnMut(ExprOrPatId), +) { + let mut visitor_callback = |diag| { + if let UnsafeDiagnostic::UnsafeOperation { node, .. } = diag { + callback(node); + } + }; + let mut visitor = UnsafeVisitor::new(db, infer, body, def, &mut visitor_callback); + visitor.walk_expr(body.body_expr); + for ¶m in &body.params { + visitor.walk_pat(param); + } +} + +pub fn unsafe_operations( db: &dyn HirDatabase, infer: &InferenceResult, def: DefWithBodyId, @@ -281,13 +300,6 @@ impl<'a> UnsafeVisitor<'a> { self.on_unsafe_op(current.into(), UnsafetyReason::RawPtrDeref); } } - Expr::Unsafe { .. } => { - let old_inside_unsafe_block = - mem::replace(&mut self.inside_unsafe_block, InsideUnsafeBlock::Yes); - self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child)); - self.inside_unsafe_block = old_inside_unsafe_block; - return; - } &Expr::Assignment { target, value: _ } => { let old_inside_assignment = mem::replace(&mut self.inside_assignment, true); self.walk_pats_top(std::iter::once(target), current); @@ -306,6 +318,20 @@ impl<'a> UnsafeVisitor<'a> { } } } + Expr::Unsafe { statements, .. } => { + let old_inside_unsafe_block = + mem::replace(&mut self.inside_unsafe_block, InsideUnsafeBlock::Yes); + self.walk_pats_top( + statements.iter().filter_map(|statement| match statement { + &Statement::Let { pat, .. } => Some(pat), + _ => None, + }), + current, + ); + self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child)); + self.inside_unsafe_block = old_inside_unsafe_block; + return; + } Expr::Block { statements, .. } | Expr::Async { statements, .. } => { self.walk_pats_top( statements.iter().filter_map(|statement| match statement { diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index bb67fa63a1..1b8531209c 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -12,6 +12,7 @@ use std::{ use either::Either; use hir_def::{ + expr_store::ExprOrPatSource, hir::{Expr, ExprOrPatId}, lower::LowerCtx, nameres::{MacroSubNs, ModuleOrigin}, @@ -30,6 +31,7 @@ use hir_expand::{ name::AsName, ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, }; +use hir_ty::diagnostics::unsafe_operations_for_body; use intern::{sym, Symbol}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; @@ -48,8 +50,8 @@ use crate::{ db::HirDatabase, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{name_hygiene, resolve_hir_path, SourceAnalyzer}, - Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, - ConstParam, Crate, DeriveHelper, Enum, Field, Function, GenericSubstitution, HasSource, + Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, ConstParam, + Crate, DefWithBody, DeriveHelper, Enum, Field, Function, GenericSubstitution, HasSource, HirFileId, Impl, InFile, InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, @@ -1555,6 +1557,19 @@ impl<'db> SemanticsImpl<'db> { .matched_arm } + pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet { + let def = DefWithBodyId::from(def); + let (body, source_map) = self.db.body_with_source_map(def); + let infer = self.db.infer(def); + let mut res = FxHashSet::default(); + unsafe_operations_for_body(self.db, &infer, def, &body, &mut |node| { + if let Ok(node) = source_map.expr_or_pat_syntax(node) { + res.insert(node); + } + }); + res + } + pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool { let Some(mac) = self.resolve_macro_call(macro_call) else { return false }; if mac.is_asm_or_global_asm(self.db) { @@ -1682,6 +1697,15 @@ impl<'db> SemanticsImpl<'db> { Some(res) } + pub fn body_for(&self, node: InFile<&SyntaxNode>) -> Option { + let container = self.with_ctx(|ctx| ctx.find_container(node))?; + + match container { + ChildContainer::DefWithBodyId(def) => Some(def.into()), + _ => None, + } + } + /// Returns none if the file of the node is not part of a crate. fn analyze(&self, node: &SyntaxNode) -> Option { let node = self.find_file(node); @@ -1783,91 +1807,6 @@ impl<'db> SemanticsImpl<'db> { InFile::new(file_id, node) } - pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool { - method_call_expr - .receiver() - .and_then(|expr| { - let field_expr = match expr { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; - let ty = self.type_of_expr(&field_expr.expr()?)?.original; - if !ty.is_packed(self.db) { - return None; - } - - let func = self.resolve_method_call(method_call_expr)?; - let res = match func.self_param(self.db)?.access(self.db) { - Access::Shared | Access::Exclusive => true, - Access::Owned => false, - }; - Some(res) - }) - .unwrap_or(false) - } - - pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { - ref_expr - .expr() - .and_then(|expr| { - let field_expr = match expr { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; - let expr = field_expr.expr()?; - self.type_of_expr(&expr) - }) - // Binding a reference to a packed type is possibly unsafe. - .map(|ty| ty.original.is_packed(self.db)) - .unwrap_or(false) - - // FIXME This needs layout computation to be correct. It will highlight - // more than it should with the current implementation. - } - - pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool { - if ident_pat.ref_token().is_none() { - return false; - } - - ident_pat - .syntax() - .parent() - .and_then(|parent| { - // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or - // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`, - // so this tries to lookup the `IdentPat` anywhere along that structure to the - // `RecordPat` so we can get the containing type. - let record_pat = ast::RecordPatField::cast(parent.clone()) - .and_then(|record_pat| record_pat.syntax().parent()) - .or_else(|| Some(parent.clone())) - .and_then(|parent| { - ast::RecordPatFieldList::cast(parent)? - .syntax() - .parent() - .and_then(ast::RecordPat::cast) - }); - - // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if - // this is initialized from a `FieldExpr`. - if let Some(record_pat) = record_pat { - self.type_of_pat(&ast::Pat::RecordPat(record_pat)) - } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { - let field_expr = match let_stmt.initializer()? { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; - - self.type_of_expr(&field_expr.expr()?) - } else { - None - } - }) - // Binding a reference to a packed type is possibly unsafe. - .map(|ty| ty.original.is_packed(self.db)) - .unwrap_or(false) - } - /// Returns `true` if the `node` is inside an `unsafe` context. pub fn is_inside_unsafe(&self, expr: &ast::Expr) -> bool { let Some(enclosing_item) = diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 9019863f7f..d1245f5f7d 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -35,7 +35,7 @@ use hir_expand::{ }; use hir_ty::{ diagnostics::{ - record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions, + record_literal_missing_fields, record_pattern_missing_fields, unsafe_operations, InsideUnsafeBlock, }, from_assoc_type_id, @@ -1160,7 +1160,7 @@ impl SourceAnalyzer { if let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr) { let mut is_unsafe = false; let mut walk_expr = |expr_id| { - unsafe_expressions(db, infer, *def, body, expr_id, &mut |inside_unsafe_block| { + unsafe_operations(db, infer, *def, body, expr_id, &mut |inside_unsafe_block| { is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No }) }; diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index 751e4a5a57..330587e0db 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -750,7 +750,10 @@ impl FunctionBody { ast::Stmt::Item(_) => (), ast::Stmt::LetStmt(stmt) => { if let Some(pat) = stmt.pat() { - walk_pat(&pat, cb); + walk_pat(&pat, &mut |pat| { + cb(pat); + std::ops::ControlFlow::<(), ()>::Continue(()) + }); } if let Some(expr) = stmt.initializer() { walk_patterns_in_expr(&expr, cb); diff --git a/crates/ide-db/src/syntax_helpers/node_ext.rs b/crates/ide-db/src/syntax_helpers/node_ext.rs index 74c0b8e2ba..0b2e8aa683 100644 --- a/crates/ide-db/src/syntax_helpers/node_ext.rs +++ b/crates/ide-db/src/syntax_helpers/node_ext.rs @@ -1,4 +1,6 @@ //! Various helper functions to work with SyntaxNodes. +use std::ops::ControlFlow; + use itertools::Itertools; use parser::T; use span::Edition; @@ -119,7 +121,10 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { match ast::Stmt::cast(node.clone()) { Some(ast::Stmt::LetStmt(l)) => { if let Some(pat) = l.pat() { - walk_pat(&pat, cb); + walk_pat(&pat, &mut |pat| { + cb(pat); + ControlFlow::<(), ()>::Continue(()) + }); } if let Some(expr) = l.initializer() { walk_patterns_in_expr(&expr, cb); @@ -154,7 +159,10 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { } } else if let Some(pat) = ast::Pat::cast(node) { preorder.skip_subtree(); - walk_pat(&pat, cb); + walk_pat(&pat, &mut |pat| { + cb(pat); + ControlFlow::<(), ()>::Continue(()) + }); } } } @@ -162,7 +170,10 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { } /// Preorder walk all the pattern's sub patterns. -pub fn walk_pat(pat: &ast::Pat, cb: &mut dyn FnMut(ast::Pat)) { +pub fn walk_pat( + pat: &ast::Pat, + cb: &mut dyn FnMut(ast::Pat) -> ControlFlow, +) -> ControlFlow { let mut preorder = pat.syntax().preorder(); while let Some(event) = preorder.next() { let node = match event { @@ -173,10 +184,10 @@ pub fn walk_pat(pat: &ast::Pat, cb: &mut dyn FnMut(ast::Pat)) { match ast::Pat::cast(node) { Some(pat @ ast::Pat::ConstBlockPat(_)) => { preorder.skip_subtree(); - cb(pat); + cb(pat)?; } Some(pat) => { - cb(pat); + cb(pat)?; } // skip const args None if ast::GenericArg::can_cast(kind) => { @@ -185,6 +196,7 @@ pub fn walk_pat(pat: &ast::Pat, cb: &mut dyn FnMut(ast::Pat)) { None => (), } } + ControlFlow::Continue(()) } /// Preorder walk all the type's sub types. diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 519133e3ad..62dc92feb1 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -14,8 +14,11 @@ mod tests; use std::ops::ControlFlow; -use hir::{HirFileIdExt, InFile, InRealFile, MacroFileIdExt, MacroKind, Name, Semantics}; -use ide_db::{FxHashMap, Ranker, RootDatabase, SymbolKind}; +use either::Either; +use hir::{ + DefWithBody, HirFileIdExt, InFile, InRealFile, MacroFileIdExt, MacroKind, Name, Semantics, +}; +use ide_db::{FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind}; use span::EditionedFileId; use syntax::{ ast::{self, IsString}, @@ -232,7 +235,6 @@ fn traverse( range_to_highlight: TextRange, ) { let is_unlinked = sema.file_to_module_def(file_id).is_none(); - let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); enum AttrOrDerive { Attr(ast::Item), @@ -247,13 +249,22 @@ fn traverse( } } + let empty = FxHashSet::default(); + + // FIXME: accommodate range highlighting let mut tt_level = 0; + // FIXME: accommodate range highlighting let mut attr_or_derive_item = None; // FIXME: these are not perfectly accurate, we determine them by the real file's syntax tree // an attribute nested in a macro call will not emit `inside_attribute` let mut inside_attribute = false; + // FIXME: accommodate range highlighting + let mut body_stack: Vec> = vec![]; + let mut per_body_cache: FxHashMap, FxHashMap)> = + FxHashMap::default(); + // Walk all nodes, keeping track of whether we are inside a macro or not. // If in macro, expand it first and highlight the expanded code. let mut preorder = root.preorder_with_tokens(); @@ -282,48 +293,68 @@ fn traverse( Leave(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => { inside_attribute = false } - Enter(NodeOrToken::Node(node)) => { - if let Some(item) = ast::Item::cast(node.clone()) { + if let Some(item) = >::cast(node.clone()) { match item { - ast::Item::Fn(_) | ast::Item::Const(_) | ast::Item::Static(_) => { - bindings_shadow_count.clear() - } - _ => (), - } - - if attr_or_derive_item.is_none() { - if sema.is_attr_macro_call(InFile::new(file_id.into(), &item)) { - attr_or_derive_item = Some(AttrOrDerive::Attr(item)); - } else { - let adt = match item { - ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), - ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), - ast::Item::Union(it) => Some(ast::Adt::Union(it)), - _ => None, - }; - match adt { - Some(adt) - if sema - .is_derive_annotated(InFile::new(file_id.into(), &adt)) => - { - attr_or_derive_item = - Some(AttrOrDerive::Derive(ast::Item::from(adt))); + Either::Left(item) => { + match &item { + ast::Item::Fn(it) => { + body_stack.push(sema.to_def(it).map(Into::into)) + } + ast::Item::Const(it) => { + body_stack.push(sema.to_def(it).map(Into::into)) + } + ast::Item::Static(it) => { + body_stack.push(sema.to_def(it).map(Into::into)) } _ => (), } + + if attr_or_derive_item.is_none() { + if sema.is_attr_macro_call(InFile::new(file_id.into(), &item)) { + attr_or_derive_item = Some(AttrOrDerive::Attr(item)); + } else { + let adt = match item { + ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), + ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), + ast::Item::Union(it) => Some(ast::Adt::Union(it)), + _ => None, + }; + match adt { + Some(adt) + if sema.is_derive_annotated(InFile::new( + file_id.into(), + &adt, + )) => + { + attr_or_derive_item = + Some(AttrOrDerive::Derive(ast::Item::from(adt))); + } + _ => (), + } + } + } } + Either::Right(it) => body_stack.push(sema.to_def(&it).map(Into::into)), } } } - Leave(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => { + Leave(NodeOrToken::Node(node)) + if >::can_cast(node.kind()) => + { match ast::Item::cast(node.clone()) { - Some(item) - if attr_or_derive_item.as_ref().is_some_and(|it| *it.item() == item) => - { - attr_or_derive_item = None; + Some(item) => { + if attr_or_derive_item.as_ref().is_some_and(|it| *it.item() == item) { + attr_or_derive_item = None; + } + if matches!( + item, + ast::Item::Fn(_) | ast::Item::Const(_) | ast::Item::Static(_) + ) { + body_stack.pop(); + } } - _ => (), + None => _ = body_stack.pop(), } } _ => (), @@ -361,16 +392,22 @@ fn traverse( None => false, }; - let descended_element = if in_macro { + let (descended_element, current_body) = match element { // Attempt to descend tokens into macro-calls. - match element { - NodeOrToken::Token(token) => descend_token(sema, InRealFile::new(file_id, token)), - n => InFile::new(file_id.into(), n), + NodeOrToken::Token(token) if in_macro => { + let descended = descend_token(sema, InRealFile::new(file_id, token)); + let body = match &descended.value { + NodeOrToken::Node(n) => { + sema.body_for(InFile::new(descended.file_id, n.syntax())) + } + NodeOrToken::Token(t) => { + t.parent().and_then(|it| sema.body_for(InFile::new(descended.file_id, &it))) + } + }; + (descended, body) } - } else { - InFile::new(file_id.into(), element) + n => (InFile::new(file_id.into(), n), body_stack.last().copied().flatten()), }; - // string highlight injections if let (Some(original_token), Some(descended_token)) = (original_token, descended_element.value.as_token()) @@ -390,12 +427,24 @@ fn traverse( } let edition = descended_element.file_id.edition(sema.db); + let (unsafe_ops, bindings_shadow_count) = match current_body { + Some(current_body) => { + let (ops, bindings) = per_body_cache + .entry(current_body) + .or_insert_with(|| (sema.get_unsafe_ops(current_body), Default::default())); + (&*ops, Some(bindings)) + } + None => (&empty, None), + }; + let is_unsafe_node = + |node| unsafe_ops.contains(&InFile::new(descended_element.file_id, node)); let element = match descended_element.value { NodeOrToken::Node(name_like) => { let hl = highlight::name_like( sema, krate, - &mut bindings_shadow_count, + bindings_shadow_count, + &is_unsafe_node, config.syntactic_name_ref_highlighting, name_like, edition, @@ -408,7 +457,8 @@ fn traverse( hl } NodeOrToken::Token(token) => { - highlight::token(sema, token, edition, tt_level > 0).zip(Some(None)) + highlight::token(sema, token, edition, &is_unsafe_node, tt_level > 0) + .zip(Some(None)) } }; if let Some((mut highlight, binding_hash)) = element { diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs index c63043621c..cc02aff2ac 100644 --- a/crates/ide/src/syntax_highlighting/format.rs +++ b/crates/ide/src/syntax_highlighting/format.rs @@ -41,7 +41,7 @@ pub(super) fn highlight_format_string( if let Some(res) = res { stack.add(HlRange { range, - highlight: highlight_def(sema, krate, Definition::from(res), edition), + highlight: highlight_def(sema, krate, Definition::from(res), edition, true), binding_hash: None, }) } diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 127861a04b..282fbb4433 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -1,17 +1,20 @@ //! Computes color for a single element. +use std::ops::ControlFlow; + use either::Either; use hir::{AsAssocItem, HasVisibility, MacroFileIdExt, Semantics}; use ide_db::{ defs::{Definition, IdentClass, NameClass, NameRefClass}, + syntax_helpers::node_ext::walk_pat, FxHashMap, RootDatabase, SymbolKind, }; use span::Edition; use stdx::hash_once; use syntax::{ - ast, match_ast, AstNode, AstToken, NodeOrToken, + ast, match_ast, AstNode, AstPtr, AstToken, NodeOrToken, SyntaxKind::{self, *}, - SyntaxNode, SyntaxToken, T, + SyntaxNode, SyntaxNodePtr, SyntaxToken, T, }; use crate::{ @@ -23,6 +26,7 @@ pub(super) fn token( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, edition: Edition, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, in_tt: bool, ) -> Option { if let Some(comment) = ast::Comment::cast(token.clone()) { @@ -33,11 +37,8 @@ pub(super) fn token( }); } - let highlight: Highlight = match token.kind() { + let h = match token.kind() { STRING | BYTE_STRING | C_STRING => HlTag::StringLiteral.into(), - INT_NUMBER if token.parent_ancestors().nth(1).map(|it| it.kind()) == Some(FIELD_EXPR) => { - SymbolKind::Field.into() - } INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(), BYTE => HlTag::ByteLiteral.into(), CHAR => HlTag::CharLiteral.into(), @@ -46,24 +47,25 @@ pub(super) fn token( // that were not mapped down into macro invocations HlTag::None.into() } - p if p.is_punct() => punctuation(sema, token, p), + p if p.is_punct() => punctuation(sema, token, p, is_unsafe_node), k if k.is_keyword(edition) => { if in_tt && token.prev_token().is_some_and(|t| t.kind() == T![$]) { // we are likely within a macro definition where our keyword is a fragment name HlTag::None.into() } else { - keyword(sema, token, k)? + keyword(token, k) } } _ => return None, }; - Some(highlight) + Some(h) } pub(super) fn name_like( sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, - bindings_shadow_count: &mut FxHashMap, + bindings_shadow_count: Option<&mut FxHashMap>, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, syntactic_name_ref_highlighting: bool, name_like: ast::NameLike, edition: Edition, @@ -75,19 +77,26 @@ pub(super) fn name_like( krate, bindings_shadow_count, &mut binding_hash, + is_unsafe_node, syntactic_name_ref_highlighting, name_ref, edition, ), - ast::NameLike::Name(name) => { - highlight_name(sema, bindings_shadow_count, &mut binding_hash, krate, name, edition) - } + ast::NameLike::Name(name) => highlight_name( + sema, + bindings_shadow_count, + &mut binding_hash, + is_unsafe_node, + krate, + name, + edition, + ), ast::NameLike::Lifetime(lifetime) => match IdentClass::classify_lifetime(sema, &lifetime) { Some(IdentClass::NameClass(NameClass::Definition(def))) => { - highlight_def(sema, krate, def, edition) | HlMod::Definition + highlight_def(sema, krate, def, edition, false) | HlMod::Definition } Some(IdentClass::NameRefClass(NameRefClass::Definition(def, _))) => { - highlight_def(sema, krate, def, edition) + highlight_def(sema, krate, def, edition, true) } // FIXME: Fallback for '_, as we do not resolve these yet _ => SymbolKind::LifetimeParam.into(), @@ -100,44 +109,49 @@ fn punctuation( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, kind: SyntaxKind, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Highlight { - let parent = token.parent(); - let parent_kind = parent.as_ref().map_or(EOF, SyntaxNode::kind); - match (kind, parent_kind) { + let operator_parent = token.parent(); + let parent_kind = operator_parent.as_ref().map_or(EOF, SyntaxNode::kind); + let h = match (kind, parent_kind) { (T![?], TRY_EXPR) => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow, (T![&], BIN_EXPR) => HlOperator::Bitwise.into(), - (T![&], REF_EXPR) => { + (T![&], REF_EXPR | REF_PAT) => HlTag::Operator(HlOperator::Other).into(), + (T![..] | T![..=], _) => match token.parent().and_then(ast::Pat::cast) { + Some(pat) if is_unsafe_node(AstPtr::new(&pat).wrap_right()) => { + Highlight::from(HlOperator::Other) | HlMod::Unsafe + } + _ => HlOperator::Other.into(), + }, + (T![::] | T![->] | T![=>] | T![=] | T![@] | T![.], _) => HlOperator::Other.into(), + (T![!], MACRO_CALL) => { + if operator_parent + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)) + { + Highlight::from(HlPunct::MacroBang) | HlMod::Unsafe + } else { + HlPunct::MacroBang.into() + } + } + (T![!], MACRO_RULES) => HlPunct::MacroBang.into(), + (T![!], NEVER_TYPE) => HlTag::BuiltinType.into(), + (T![!], PREFIX_EXPR) => HlOperator::Logical.into(), + (T![*], PTR_TYPE) => HlTag::Keyword.into(), + (T![*], PREFIX_EXPR) => { let h = HlTag::Operator(HlOperator::Other).into(); - let is_unsafe = parent - .and_then(ast::RefExpr::cast) - .map(|ref_expr| sema.is_unsafe_ref_expr(&ref_expr)); - if let Some(true) = is_unsafe { + let ptr = operator_parent + .as_ref() + .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(it))); + if ptr.is_some_and(is_unsafe_node) { h | HlMod::Unsafe } else { h } } - (T![::] | T![->] | T![=>] | T![..] | T![..=] | T![=] | T![@] | T![.], _) => { - HlOperator::Other.into() - } - (T![!], MACRO_CALL | MACRO_RULES) => HlPunct::MacroBang.into(), - (T![!], NEVER_TYPE) => HlTag::BuiltinType.into(), - (T![!], PREFIX_EXPR) => HlOperator::Logical.into(), - (T![*], PTR_TYPE) => HlTag::Keyword.into(), - (T![*], PREFIX_EXPR) => { - let is_raw_ptr = (|| { - let prefix_expr = parent.and_then(ast::PrefixExpr::cast)?; - let expr = prefix_expr.expr()?; - sema.type_of_expr(&expr)?.original.is_raw_ptr().then_some(()) - })(); - if let Some(()) = is_raw_ptr { - HlTag::Operator(HlOperator::Other) | HlMod::Unsafe - } else { - HlOperator::Other.into() - } - } (T![-], PREFIX_EXPR) => { - let prefix_expr = parent.and_then(ast::PrefixExpr::cast).and_then(|e| e.expr()); + let prefix_expr = + operator_parent.and_then(ast::PrefixExpr::cast).and_then(|e| e.expr()); match prefix_expr { Some(ast::Expr::Literal(_)) => HlTag::NumericLiteral, _ => HlTag::Operator(HlOperator::Other), @@ -157,36 +171,90 @@ fn punctuation( HlOperator::Comparison.into() } (_, ATTR) => HlTag::AttributeBracket.into(), + (T![>], _) + if operator_parent + .as_ref() + .and_then(SyntaxNode::parent) + .is_some_and(|it| it.kind() == MACRO_RULES) => + { + HlOperator::Other.into() + } (kind, _) => match kind { - T!['['] | T![']'] => HlPunct::Bracket, - T!['{'] | T!['}'] => HlPunct::Brace, - T!['('] | T![')'] => HlPunct::Parenthesis, - T![>] - if parent + T!['['] | T![']'] => { + let is_unsafe_macro = operator_parent .as_ref() - .and_then(SyntaxNode::parent) - .is_some_and(|it| it.kind() == MACRO_RULES) => - { - return HlOperator::Other.into() + .and_then(|it| ast::TokenTree::cast(it.clone())?.syntax().parent()) + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)); + let is_unsafe = is_unsafe_macro + || operator_parent + .as_ref() + .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(it))) + .is_some_and(is_unsafe_node); + if is_unsafe { + return Highlight::from(HlPunct::Bracket) | HlMod::Unsafe; + } else { + HlPunct::Bracket + } + } + T!['{'] | T!['}'] => { + let is_unsafe_macro = operator_parent + .as_ref() + .and_then(|it| ast::TokenTree::cast(it.clone())?.syntax().parent()) + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)); + let is_unsafe = is_unsafe_macro + || operator_parent + .as_ref() + .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(it))) + .is_some_and(is_unsafe_node); + if is_unsafe { + return Highlight::from(HlPunct::Brace) | HlMod::Unsafe; + } else { + HlPunct::Brace + } + } + T!['('] | T![')'] => { + let is_unsafe_macro = operator_parent + .as_ref() + .and_then(|it| ast::TokenTree::cast(it.clone())?.syntax().parent()) + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)); + let is_unsafe = is_unsafe_macro + || operator_parent + .and_then(|it| { + if ast::ArgList::can_cast(it.kind()) { + it.parent() + } else { + Some(it) + } + }) + .and_then(|it| AstPtr::try_from_raw(SyntaxNodePtr::new(&it))) + .is_some_and(is_unsafe_node); + + if is_unsafe { + return Highlight::from(HlPunct::Parenthesis) | HlMod::Unsafe; + } else { + HlPunct::Parenthesis + } } T![<] | T![>] => HlPunct::Angle, - T![,] => HlPunct::Comma, + // Early return as otherwise we'd highlight these in + // asm expressions + T![,] => return HlPunct::Comma.into(), T![:] => HlPunct::Colon, T![;] => HlPunct::Semi, T![.] => HlPunct::Dot, _ => HlPunct::Other, } .into(), - } + }; + h } -fn keyword( - sema: &Semantics<'_, RootDatabase>, - token: SyntaxToken, - kind: SyntaxKind, -) -> Option { +fn keyword(token: SyntaxToken, kind: SyntaxKind) -> Highlight { let h = Highlight::new(HlTag::Keyword); - let h = match kind { + match kind { T![await] => h | HlMod::Async | HlMod::ControlFlow, T![async] => h | HlMod::Async, T![break] @@ -202,53 +270,33 @@ fn keyword( T![do] | T![yeet] if parent_matches::(&token) => h | HlMod::ControlFlow, T![for] if parent_matches::(&token) => h | HlMod::ControlFlow, T![unsafe] => h | HlMod::Unsafe, - T![const] - if token.parent().is_some_and(|it| { - matches!( - it.kind(), - SyntaxKind::CONST - | SyntaxKind::FN - | SyntaxKind::IMPL - | SyntaxKind::BLOCK_EXPR - | SyntaxKind::CLOSURE_EXPR - | SyntaxKind::FN_PTR_TYPE - | SyntaxKind::TYPE_BOUND - | SyntaxKind::CONST_BLOCK_PAT - ) - }) => - { - h | HlMod::Const - } + T![const] => h | HlMod::Const, T![true] | T![false] => HlTag::BoolLiteral.into(), // crate is handled just as a token if it's in an `extern crate` T![crate] if parent_matches::(&token) => h, - T![ref] => match token.parent().and_then(ast::IdentPat::cast) { - Some(ident) if sema.is_unsafe_ident_pat(&ident) => h | HlMod::Unsafe, - _ => h, - }, _ => h, - }; - Some(h) + } } fn highlight_name_ref( sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, - bindings_shadow_count: &mut FxHashMap, + bindings_shadow_count: Option<&mut FxHashMap>, binding_hash: &mut Option, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, syntactic_name_ref_highlighting: bool, name_ref: ast::NameRef, edition: Edition, ) -> Highlight { let db = sema.db; - if let Some(res) = highlight_method_call_by_name_ref(sema, krate, &name_ref, edition) { + if let Some(res) = highlight_method_call_by_name_ref(sema, krate, &name_ref, is_unsafe_node) { return res; } let name_class = match NameRefClass::classify(sema, &name_ref) { Some(name_kind) => name_kind, None if syntactic_name_ref_highlighting => { - return highlight_name_ref_by_syntax(name_ref, sema, krate, edition) + return highlight_name_ref_by_syntax(name_ref, sema, krate, is_unsafe_node) } // FIXME: This is required for helper attributes used by proc-macros, as those do not map down // to anything when used. @@ -267,17 +315,20 @@ fn highlight_name_ref( let mut h = match name_class { NameRefClass::Definition(def, _) => { if let Definition::Local(local) = &def { - let name = local.name(db); - let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); - *binding_hash = Some(calc_binding_hash(&name, *shadow_count)) + if let Some(bindings_shadow_count) = bindings_shadow_count { + let name = local.name(sema.db); + let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); + *binding_hash = Some(calc_binding_hash(&name, *shadow_count)) + } }; - let mut h = highlight_def(sema, krate, def, edition); + let mut h = highlight_def(sema, krate, def, edition, true); match def { Definition::Local(local) if is_consumed_lvalue(name_ref.syntax(), &local, db) => { h |= HlMod::Consuming; } + // highlight unsafe traits as unsafe only in their implementations Definition::Trait(trait_) if trait_.is_unsafe(db) => { if ast::Impl::for_trait_name_ref(&name_ref) .is_some_and(|impl_| impl_.unsafe_token().is_some()) @@ -285,23 +336,66 @@ fn highlight_name_ref( h |= HlMod::Unsafe; } } - Definition::Field(field) => { - if let Some(parent) = name_ref.syntax().parent() { - if matches!(parent.kind(), FIELD_EXPR | RECORD_PAT_FIELD) { - if let hir::VariantDef::Union(_) = field.parent_def(db) { - h |= HlMod::Unsafe; - } - } + Definition::Function(_) => { + let is_unsafe = name_ref + .syntax() + .parent() + .and_then(|it| ast::PathSegment::cast(it)?.parent_path().syntax().parent()) + .and_then(ast::PathExpr::cast) + .and_then(|it| it.syntax().parent()) + .and_then(ast::CallExpr::cast) + .is_some_and(|it| { + is_unsafe_node(AstPtr::new(&ast::Expr::CallExpr(it)).wrap_left()) + }); + if is_unsafe { + h |= HlMod::Unsafe; } } Definition::Macro(_) => { - if let Some(macro_call) = - ide_db::syntax_helpers::node_ext::full_path_of_name_ref(&name_ref) - .and_then(|it| it.syntax().parent().and_then(ast::MacroCall::cast)) - { - if sema.is_unsafe_macro_call(¯o_call) { - h |= HlMod::Unsafe; - } + let is_unsafe = name_ref + .syntax() + .parent() + .and_then(|it| ast::PathSegment::cast(it)?.parent_path().syntax().parent()) + .and_then(ast::MacroCall::cast) + .is_some_and(|macro_call| sema.is_unsafe_macro_call(¯o_call)); + if is_unsafe { + h |= HlMod::Unsafe; + } + } + Definition::Field(_) => { + let is_unsafe = name_ref + .syntax() + .parent() + .and_then(|it| { + match_ast! { match it { + ast::FieldExpr(expr) => Some(is_unsafe_node(AstPtr::new(&Either::Left(expr.into())))), + ast::RecordPatField(pat) => { + walk_pat(&pat.pat()?, &mut |pat| { + if is_unsafe_node(AstPtr::new(&Either::Right(pat))) { + ControlFlow::Break(true) + } + else {ControlFlow::Continue(())} + }).break_value() + }, + _ => None, + }} + }) + .unwrap_or(false); + if is_unsafe { + h |= HlMod::Unsafe; + } + } + Definition::Static(_) => { + let is_unsafe = name_ref + .syntax() + .parent() + .and_then(|it| ast::PathSegment::cast(it)?.parent_path().syntax().parent()) + .and_then(ast::PathExpr::cast) + .is_some_and(|it| { + is_unsafe_node(AstPtr::new(&ast::Expr::PathExpr(it)).wrap_left()) + }); + if is_unsafe { + h |= HlMod::Unsafe; } } _ => (), @@ -310,7 +404,7 @@ fn highlight_name_ref( h } NameRefClass::FieldShorthand { field_ref, .. } => { - highlight_def(sema, krate, field_ref.into(), edition) + highlight_def(sema, krate, field_ref.into(), edition, true) } NameRefClass::ExternCrateShorthand { decl, krate: resolved_krate } => { let mut h = HlTag::Symbol(SymbolKind::Module).into(); @@ -342,22 +436,25 @@ fn highlight_name_ref( fn highlight_name( sema: &Semantics<'_, RootDatabase>, - bindings_shadow_count: &mut FxHashMap, + bindings_shadow_count: Option<&mut FxHashMap>, binding_hash: &mut Option, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, krate: hir::Crate, name: ast::Name, edition: Edition, ) -> Highlight { let name_kind = NameClass::classify(sema, &name); if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind { - let name = local.name(sema.db); - let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); - *shadow_count += 1; - *binding_hash = Some(calc_binding_hash(&name, *shadow_count)) + if let Some(bindings_shadow_count) = bindings_shadow_count { + let name = local.name(sema.db); + let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); + *shadow_count += 1; + *binding_hash = Some(calc_binding_hash(&name, *shadow_count)) + } }; match name_kind { Some(NameClass::Definition(def)) => { - let mut h = highlight_def(sema, krate, def, edition) | HlMod::Definition; + let mut h = highlight_def(sema, krate, def, edition, false) | HlMod::Definition; if let Definition::Trait(trait_) = &def { if trait_.is_unsafe(sema.db) { h |= HlMod::Unsafe; @@ -365,10 +462,14 @@ fn highlight_name( } h } - Some(NameClass::ConstReference(def)) => highlight_def(sema, krate, def, edition), - Some(NameClass::PatFieldShorthand { field_ref, .. }) => { + Some(NameClass::ConstReference(def)) => highlight_def(sema, krate, def, edition, true), + Some(NameClass::PatFieldShorthand { .. }) => { let mut h = HlTag::Symbol(SymbolKind::Field).into(); - if let hir::VariantDef::Union(_) = field_ref.parent_def(sema.db) { + let is_unsafe = + name.syntax().parent().and_then(ast::IdentPat::cast).is_some_and(|it| { + is_unsafe_node(AstPtr::new(&ast::Pat::IdentPat(it)).wrap_right()) + }); + if is_unsafe { h |= HlMod::Unsafe; } h @@ -386,6 +487,7 @@ pub(super) fn highlight_def( krate: hir::Crate, def: Definition, edition: Edition, + is_ref: bool, ) -> Highlight { let db = sema.db; let mut h = match def { @@ -439,7 +541,7 @@ pub(super) fn highlight_def( // We probably should consider checking the current function, but I found no easy way to do // that (also I'm worried about perf). There's also an instance below. // FIXME: This should be the edition of the call. - if func.is_unsafe_to_call(db, None, edition) { + if !is_ref && func.is_unsafe_to_call(db, None, edition) { h |= HlMod::Unsafe; } if func.is_async(db) { @@ -509,7 +611,9 @@ pub(super) fn highlight_def( if s.is_mut(db) { h |= HlMod::Mutable; - h |= HlMod::Unsafe; + if !is_ref { + h |= HlMod::Unsafe; + } } h @@ -587,23 +691,24 @@ fn highlight_method_call_by_name_ref( sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, name_ref: &ast::NameRef, - edition: Edition, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Option { let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?; - highlight_method_call(sema, krate, &mc, edition) + highlight_method_call(sema, krate, &mc, is_unsafe_node) } fn highlight_method_call( sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, method_call: &ast::MethodCallExpr, - edition: Edition, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Option { let func = sema.resolve_method_call(method_call)?; let mut h = SymbolKind::Method.into(); - if func.is_unsafe_to_call(sema.db, None, edition) || sema.is_unsafe_method_call(method_call) { + let is_unsafe = is_unsafe_node(AstPtr::new(method_call).upcast::().wrap_left()); + if is_unsafe { h |= HlMod::Unsafe; } if func.is_async(sema.db) { @@ -695,7 +800,7 @@ fn highlight_name_ref_by_syntax( name: ast::NameRef, sema: &Semantics<'_, RootDatabase>, krate: hir::Crate, - edition: Edition, + is_unsafe_node: &impl Fn(AstPtr>) -> bool, ) -> Highlight { let default = HlTag::UnresolvedReference; @@ -707,19 +812,13 @@ fn highlight_name_ref_by_syntax( match parent.kind() { EXTERN_CRATE => HlTag::Symbol(SymbolKind::Module) | HlMod::CrateRoot, METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent) - .and_then(|it| highlight_method_call(sema, krate, &it, edition)) + .and_then(|it| highlight_method_call(sema, krate, &it, is_unsafe_node)) .unwrap_or_else(|| SymbolKind::Method.into()), FIELD_EXPR => { let h = HlTag::Symbol(SymbolKind::Field); - let is_union = ast::FieldExpr::cast(parent) - .and_then(|field_expr| sema.resolve_field(&field_expr)) - .is_some_and(|field| match field { - Either::Left(field) => { - matches!(field.parent_def(sema.db), hir::VariantDef::Union(_)) - } - Either::Right(_) => false, - }); - if is_union { + let is_unsafe = ast::Expr::cast(parent) + .is_some_and(|it| is_unsafe_node(AstPtr::new(&it).wrap_left())); + if is_unsafe { h | HlMod::Unsafe } else { h.into() diff --git a/crates/ide/src/syntax_highlighting/html.rs b/crates/ide/src/syntax_highlighting/html.rs index 47ad54759a..07d40bafeb 100644 --- a/crates/ide/src/syntax_highlighting/html.rs +++ b/crates/ide/src/syntax_highlighting/html.rs @@ -88,12 +88,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -115,6 +109,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html index 2bc22f960b..c8ffa9e855 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -49,26 +44,26 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd unsafe { let foo = 1; let mut o = 0; - core::arch::asm!( + core::arch::asm!( "%input = OpLoad _ {0}", concat!("%result = ", "bar", " _ %input"), "OpStore {1} %result", in(reg) &foo, in(reg) &mut o, - ); + ); let thread_id: usize; - core::arch::asm!(" + core::arch::asm!(" mov {0}, gs:[0x30] mov {0}, [{0}+0x48] - ", out(reg) thread_id, options(pure, readonly, nostack)); + ", out(reg) thread_id, options(pure, readonly, nostack)); static UNMAP_BASE: usize; const MEM_RELEASE: usize; static VirtualFree: usize; const OffPtr: usize; const OffFn: usize; - core::arch::asm!(" + core::arch::asm!(" push {free_type} push {free_size} push {base} @@ -82,26 +77,26 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd jmp {virtual_free} ", - off_ptr = const OffPtr, - off_fn = const OffFn, + off_ptr = const OffPtr, + off_fn = const OffFn, - free_size = const 0, - free_type = const MEM_RELEASE, + free_size = const 0, + free_type = const MEM_RELEASE, virtual_free = sym VirtualFree, base = sym UNMAP_BASE, options(noreturn), - ); + ); } } // taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274 #[inline] -pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { +pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { // Ensure thumb mode is set. let rv = (rv as u32) | 1; let msp = msp as u32; - core::arch::asm!( + core::arch::asm!( "mrs {tmp}, CONTROL", "bics {tmp}, {spsel}", "msr CONTROL, {tmp}", @@ -115,5 +110,5 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd msp = in(reg) msp, rv = in(reg) rv, options(noreturn, nomem, nostack), - ); + ); } \ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index 9c7f03fc15..faace6eaff 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html index e1d51dc0b7..d59f4caa97 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html b/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html index af29af3f03..3beda396da 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -58,7 +53,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd foo!(Bar); fn func(_: y::Bar) { mod inner { - struct Innerest<const C: usize> { field: [(); {C}] } + struct Innerest<const C: usize> { field: [(); {C}] } } } } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_const.html b/crates/ide/src/syntax_highlighting/test_data/highlight_const.html index 6d8f6b3c6e..9c7324eafa 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_const.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_const.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -50,21 +45,21 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd $($tt)* }; } -const CONST_ITEM: *const () = &raw const (); -const fn const_fn<const CONST_PARAM: ()>(const {}: const fn()) where (): const ConstTrait { +const CONST_ITEM: *const () = &raw const (); +const fn const_fn<const CONST_PARAM: ()>(const {}: const fn()) where (): const ConstTrait { CONST_ITEM; CONST_PARAM; const { - const || {} + const || {} } id!( CONST_ITEM; CONST_PARAM; const { - const || {} + const || {} }; - &raw const (); - const + &raw const (); + const ); ().assoc_const_method(); } @@ -80,6 +75,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd macro_rules! unsafe_deref { () => { - *(&() as *const ()) + *(&() as *const ()) }; } \ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html b/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html index 63e1560b92..4613c65ee6 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html b/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html index dfad3a6605..b1b2c659a2 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 263e4545fb..c8c8c5dba4 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -129,7 +124,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd /// /// ``` /// // functions - /// fn foo<T, const X: usize>(arg: i32) { + /// fn foo<T, const X: usize>(arg: i32) { /// let x: T = X; /// } /// ``` diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html index fe5f5ab6a9..5399f83085 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html index eb532a5639..00925bd81e 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -109,7 +104,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd loop {} } -fn const_param<const FOO: usize>() -> usize { +fn const_param<const FOO: usize>() -> usize { const_param::<{ FOO }>(); FOO } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html index 1f9422161d..3b468ab6db 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html b/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html index a846addba3..5ef64465c9 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html index c3377614d7..0407e6896e 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html index 9b22500396..f39d033c76 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html index 9b22500396..f39d033c76 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html index ac8353120e..721185a1a8 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html index 694e54d2fa..b2c82051eb 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html b/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html index 8428b81580..618ea2171b 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html index f224435e96..c3145941c3 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html b/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html index 947d1bf1e3..9996a87158 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html b/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html index 0fe2b6f274..dc9e1de4a4 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html b/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html index c60b6ab27b..9c42401ed0 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html b/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html index a4449b5d8d..7f6b4c2c88 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 539c74f6b5..f7d7982080 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -169,12 +164,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd toho!("{}fmt", 0); let i: u64 = 3; let o: u64; - core::arch::asm!( + core::arch::asm!( "mov {0}, {1}", "add {0}, 5", out(reg) o, in(reg) i, - ); + ); const CONSTANT: () = (): let mut m = (); diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index 9a46d9f402..44905831e3 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html @@ -14,12 +14,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string_literal { color: #CC9393; } .field { color: #94BFF3; } .function { color: #93E0E3; } -.function.unsafe { color: #BC8383; } -.trait.unsafe { color: #BC8383; } -.operator.unsafe { color: #BC8383; } -.mutable.unsafe { color: #BC8383; text-decoration: underline; } -.keyword.unsafe { color: #BC8383; font-weight: bold; } -.macro.unsafe { color: #BC8383; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } @@ -41,6 +35,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } .const { font-weight: bolder; } +.unsafe { color: #BC8383; } .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } @@ -52,78 +47,82 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd } macro_rules! unsafe_deref { () => { - *(&() as *const ()) + *(&() as *const ()) }; } -static mut MUT_GLOBAL: Struct = Struct { field: 0 }; -static GLOBAL: Struct = Struct { field: 0 }; -unsafe fn unsafe_fn() {} union Union { - a: u32, - b: f32, + field: u32, } struct Struct { field: i32 } + +static mut MUT_GLOBAL: Struct = Struct { field: 0 }; +unsafe fn unsafe_fn() {} + impl Struct { unsafe fn unsafe_method(&self) {} } -#[repr(packed)] -struct Packed { - a: u16, -} - unsafe trait UnsafeTrait {} -unsafe impl UnsafeTrait for Packed {} +unsafe impl UnsafeTrait for Union {} impl !UnsafeTrait for () {} fn unsafe_trait_bound<T: UnsafeTrait>(_: T) {} -trait DoTheAutoref { - fn calls_autoref(&self); -} - -impl DoTheAutoref for u16 { - fn calls_autoref(&self) {} +extern { + static EXTERN_STATIC: (); } fn main() { - let x = &5 as *const _ as *const usize; - let u = Union { b: 0 }; + let x: *const usize; + let u: Union; + // id should be safe here, but unsafe_deref should not id! { - unsafe { unsafe_deref!() } + unsafe { unsafe_deref!() } }; unsafe { - unsafe_deref!(); - id! { unsafe_deref!() }; + // unsafe macro calls + unsafe_deref!(); + id! { unsafe_deref!() }; // unsafe fn and method calls - unsafe_fn(); - let b = u.b; - match u { - Union { b: 0 } => (), - Union { a } => (), - } - Struct { field: 0 }.unsafe_method(); + unsafe_fn(); + self::unsafe_fn(); + (unsafe_fn as unsafe fn())(); + Struct { field: 0 }.unsafe_method(); + + u.field; + &u.field; + &raw const u.field; + // this should be safe! + let Union { field: _ }; + // but not these + let Union { field }; + let Union { field: true }; + let Union { field: field }; + let Union { field: ref field }; + let Union { field: (ref field | 0) }; // unsafe deref - *x; + *&raw const*&*x; // unsafe access to a static mut MUT_GLOBAL.field; - GLOBAL.field; + &MUT_GLOBAL.field; + &raw const MUT_GLOBAL.field; + MUT_GLOBAL; + &MUT_GLOBAL; + &raw const MUT_GLOBAL; + EXTERN_STATIC; + &EXTERN_STATIC; + &raw const EXTERN_STATIC; - // unsafe ref of packed fields - let packed = Packed { a: 0 }; - let a = &packed.a; - let ref a = packed.a; - let Packed { ref a } = packed; - let Packed { a: ref _a } = packed; - - // unsafe auto ref of packed field - packed.a.calls_autoref(); + core::arch::asm!( + "push {base}", + base = const 0 + ); } } \ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index e48ca86c46..504a1c970e 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -589,7 +589,7 @@ fn main() { fn test_unsafe_highlighting() { check_highlighting( r#" -//- minicore: sized +//- minicore: sized, asm macro_rules! id { ($($tt:tt)*) => { $($tt)* @@ -600,76 +600,80 @@ macro_rules! unsafe_deref { *(&() as *const ()) }; } -static mut MUT_GLOBAL: Struct = Struct { field: 0 }; -static GLOBAL: Struct = Struct { field: 0 }; -unsafe fn unsafe_fn() {} union Union { - a: u32, - b: f32, + field: u32, } struct Struct { field: i32 } + +static mut MUT_GLOBAL: Struct = Struct { field: 0 }; +unsafe fn unsafe_fn() {} + impl Struct { unsafe fn unsafe_method(&self) {} } -#[repr(packed)] -struct Packed { - a: u16, -} - unsafe trait UnsafeTrait {} -unsafe impl UnsafeTrait for Packed {} +unsafe impl UnsafeTrait for Union {} impl !UnsafeTrait for () {} fn unsafe_trait_bound(_: T) {} -trait DoTheAutoref { - fn calls_autoref(&self); -} - -impl DoTheAutoref for u16 { - fn calls_autoref(&self) {} +extern { + static EXTERN_STATIC: (); } fn main() { - let x = &5 as *const _ as *const usize; - let u = Union { b: 0 }; + let x: *const usize; + let u: Union; + // id should be safe here, but unsafe_deref should not id! { unsafe { unsafe_deref!() } }; unsafe { + // unsafe macro calls unsafe_deref!(); id! { unsafe_deref!() }; // unsafe fn and method calls unsafe_fn(); - let b = u.b; - match u { - Union { b: 0 } => (), - Union { a } => (), - } + self::unsafe_fn(); + (unsafe_fn as unsafe fn())(); Struct { field: 0 }.unsafe_method(); + u.field; + &u.field; + &raw const u.field; + // this should be safe! + let Union { field: _ }; + // but not these + let Union { field }; + let Union { field: true }; + let Union { field: field }; + let Union { field: ref field }; + let Union { field: (ref field | 0) }; + // unsafe deref - *x; + *&raw const*&*x; // unsafe access to a static mut MUT_GLOBAL.field; - GLOBAL.field; + &MUT_GLOBAL.field; + &raw const MUT_GLOBAL.field; + MUT_GLOBAL; + &MUT_GLOBAL; + &raw const MUT_GLOBAL; + EXTERN_STATIC; + &EXTERN_STATIC; + &raw const EXTERN_STATIC; - // unsafe ref of packed fields - let packed = Packed { a: 0 }; - let a = &packed.a; - let ref a = packed.a; - let Packed { ref a } = packed; - let Packed { a: ref _a } = packed; - - // unsafe auto ref of packed field - packed.a.calls_autoref(); + core::arch::asm!( + "push {base}", + base$0 = const 0 + ); } } "#, diff --git a/docs/book/src/assists_generated.md b/docs/book/src/assists_generated.md index 571113178d..918ae4a579 100644 --- a/docs/book/src/assists_generated.md +++ b/docs/book/src/assists_generated.md @@ -469,7 +469,7 @@ fn main() { ### `convert_closure_to_fn` -**Source:** [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L27) +**Source:** [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L25) This converts a closure to a freestanding function, changing all captures to parameters. @@ -1372,7 +1372,7 @@ fn main() { ### `flip_or_pattern` **Source:** [flip_or_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_or_pattern.rs#L9) -Flips two trait bounds. +Flips two patterns in an or-pattern. #### Before ```rust @@ -2302,7 +2302,7 @@ fn bar() { ### `inline_local_variable` -**Source:** [inline_local_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_local_variable.rs#L21) +**Source:** [inline_local_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_local_variable.rs#L17) Inlines a local variable.