mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-25 11:17:13 +00:00
Merge pull request #19274 from Veykril/push-pouwrwwrlrlt
Highlight unsafe operations as unsafe, not definitions
This commit is contained in:
commit
27dc614627
@ -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,
|
||||
},
|
||||
};
|
||||
|
@ -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 {
|
||||
|
@ -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<ExprOrPatSource> {
|
||||
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<DefWithBody> {
|
||||
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<SourceAnalyzer> {
|
||||
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) =
|
||||
|
@ -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
|
||||
})
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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<T>(
|
||||
pat: &ast::Pat,
|
||||
cb: &mut dyn FnMut(ast::Pat) -> ControlFlow<T>,
|
||||
) -> ControlFlow<T> {
|
||||
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.
|
||||
|
@ -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<Name, u32> = 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<Option<DefWithBody>> = vec![];
|
||||
let mut per_body_cache: FxHashMap<DefWithBody, (FxHashSet<_>, FxHashMap<Name, u32>)> =
|
||||
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) = <Either<ast::Item, ast::Variant>>::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 <Either<ast::Item, ast::Variant>>::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 {
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
@ -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<Either<ast::Expr, ast::Pat>>) -> bool,
|
||||
in_tt: bool,
|
||||
) -> Option<Highlight> {
|
||||
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<hir::Name, u32>,
|
||||
bindings_shadow_count: Option<&mut FxHashMap<hir::Name, u32>>,
|
||||
is_unsafe_node: &impl Fn(AstPtr<Either<ast::Expr, ast::Pat>>) -> 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<Either<ast::Expr, ast::Pat>>) -> 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<Highlight> {
|
||||
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::<ast::YeetExpr>(&token) => h | HlMod::ControlFlow,
|
||||
T![for] if parent_matches::<ast::ForExpr>(&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::<ast::ExternCrate>(&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<hir::Name, u32>,
|
||||
bindings_shadow_count: Option<&mut FxHashMap<hir::Name, u32>>,
|
||||
binding_hash: &mut Option<u64>,
|
||||
is_unsafe_node: &impl Fn(AstPtr<Either<ast::Expr, ast::Pat>>) -> 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<hir::Name, u32>,
|
||||
bindings_shadow_count: Option<&mut FxHashMap<hir::Name, u32>>,
|
||||
binding_hash: &mut Option<u64>,
|
||||
is_unsafe_node: &impl Fn(AstPtr<Either<ast::Expr, ast::Pat>>) -> 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<Either<ast::Expr, ast::Pat>>) -> bool,
|
||||
) -> Option<Highlight> {
|
||||
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<Either<ast::Expr, ast::Pat>>) -> bool,
|
||||
) -> Option<Highlight> {
|
||||
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::<ast::Expr>().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<Either<ast::Expr, ast::Pat>>) -> 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()
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
<span class="keyword unsafe">unsafe</span> <span class="brace">{</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">o</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang unsafe">!</span><span class="parenthesis unsafe">(</span>
|
||||
<span class="string_literal macro">"%input = OpLoad _ {</span><span class="variable">0</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||
<span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"%result = "</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="string_literal macro">" _ %input"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
|
||||
<span class="string_literal macro">"OpStore {</span><span class="variable">1</span><span class="string_literal macro">} %result"</span><span class="comma macro">,</span>
|
||||
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="variable macro">foo</span><span class="comma macro">,</span>
|
||||
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="keyword macro">mut</span> <span class="variable macro mutable">o</span><span class="comma macro">,</span>
|
||||
<span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="keyword">let</span> <span class="variable declaration">thread_id</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang unsafe">!</span><span class="parenthesis unsafe">(</span><span class="string_literal macro">"
|
||||
mov {</span><span class="variable">0</span><span class="string_literal macro">}, gs:[0x30]
|
||||
mov {</span><span class="variable">0</span><span class="string_literal macro">}, [{</span><span class="variable">0</span><span class="string_literal macro">}+0x48]
|
||||
"</span><span class="comma macro">,</span> <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">thread_id</span><span class="comma macro">,</span> <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">pure</span><span class="comma macro">,</span> <span class="keyword macro">readonly</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
"</span><span class="comma macro">,</span> <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">thread_id</span><span class="comma macro">,</span> <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">pure</span><span class="comma macro">,</span> <span class="keyword macro">readonly</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="keyword">static</span> <span class="static declaration">UNMAP_BASE</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||
<span class="keyword const">const</span> <span class="constant const declaration">MEM_RELEASE</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||
<span class="keyword">static</span> <span class="static declaration">VirtualFree</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||
<span class="keyword const">const</span> <span class="constant const declaration">OffPtr</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||
<span class="keyword const">const</span> <span class="constant const declaration">OffFn</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang unsafe">!</span><span class="parenthesis unsafe">(</span><span class="string_literal macro">"
|
||||
push {</span><span class="variable">free_type</span><span class="string_literal macro">}
|
||||
push {</span><span class="variable">free_size</span><span class="string_literal macro">}
|
||||
push {</span><span class="variable">base</span><span class="string_literal macro">}
|
||||
@ -82,26 +77,26 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
|
||||
jmp {</span><span class="variable">virtual_free</span><span class="string_literal macro">}
|
||||
"</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">off_ptr</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">OffPtr</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">off_fn</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">OffFn</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">off_ptr</span> <span class="operator macro">=</span> <span class="keyword const macro">const</span> <span class="constant const macro">OffPtr</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">off_fn</span> <span class="operator macro">=</span> <span class="keyword const macro">const</span> <span class="constant const macro">OffFn</span><span class="comma macro">,</span>
|
||||
|
||||
<span class="variable declaration macro">free_size</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="numeric_literal macro">0</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">free_type</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">MEM_RELEASE</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">free_size</span> <span class="operator macro">=</span> <span class="keyword const macro">const</span> <span class="numeric_literal macro">0</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">free_type</span> <span class="operator macro">=</span> <span class="keyword const macro">const</span> <span class="constant const macro">MEM_RELEASE</span><span class="comma macro">,</span>
|
||||
|
||||
<span class="variable declaration macro">virtual_free</span> <span class="operator macro">=</span> <span class="keyword macro">sym</span> <span class="static macro">VirtualFree</span><span class="comma macro">,</span>
|
||||
|
||||
<span class="variable declaration macro">base</span> <span class="operator macro">=</span> <span class="keyword macro">sym</span> <span class="static macro">UNMAP_BASE</span><span class="comma macro">,</span>
|
||||
<span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
|
||||
<span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="comment">// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274</span>
|
||||
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">inline</span><span class="attribute_bracket attribute">]</span>
|
||||
<span class="keyword">pub</span> <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration public unsafe">bootstrap</span><span class="parenthesis">(</span><span class="value_param declaration">msp</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">u32</span><span class="comma">,</span> <span class="value_param declaration">rv</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">u32</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">!</span> <span class="brace">{</span>
|
||||
<span class="keyword">pub</span> <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration public unsafe">bootstrap</span><span class="parenthesis">(</span><span class="value_param declaration">msp</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword const">const</span> <span class="builtin_type">u32</span><span class="comma">,</span> <span class="value_param declaration">rv</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword const">const</span> <span class="builtin_type">u32</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">!</span> <span class="brace">{</span>
|
||||
<span class="comment">// Ensure thumb mode is set.</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">rv</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="value_param">rv</span> <span class="keyword">as</span> <span class="builtin_type">u32</span><span class="parenthesis">)</span> <span class="bitwise">|</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">msp</span> <span class="operator">=</span> <span class="value_param">msp</span> <span class="keyword">as</span> <span class="builtin_type">u32</span><span class="semicolon">;</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang unsafe">!</span><span class="parenthesis unsafe">(</span>
|
||||
<span class="string_literal macro">"mrs {</span><span class="variable">tmp</span><span class="string_literal macro">}, CONTROL"</span><span class="comma macro">,</span>
|
||||
<span class="string_literal macro">"bics {</span><span class="variable">tmp</span><span class="string_literal macro">}, {</span><span class="variable">spsel</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||
<span class="string_literal macro">"msr CONTROL, {</span><span class="variable">tmp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||
@ -115,5 +110,5 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
<span class="variable declaration macro">msp</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">msp</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">rv</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">rv</span><span class="comma macro">,</span>
|
||||
<span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="comma macro">,</span> <span class="keyword macro">nomem</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
|
||||
<span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span></code></pre>
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
<span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="module">y</span><span class="operator">::</span><span class="struct public">Bar</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
||||
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span>
|
||||
<span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle"><</span><span class="keyword">const</span> <span class="const_param const declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">></span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span>
|
||||
<span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle"><</span><span class="keyword const">const</span> <span class="const_param const declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">></span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="brace">}</span>
|
||||
|
@ -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
|
||||
<span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span>
|
||||
<span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="keyword const">const</span> <span class="constant const declaration">CONST_ITEM</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="operator">&</span><span class="keyword">raw</span> <span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function const declaration">const_fn</span><span class="angle"><</span><span class="keyword">const</span> <span class="const_param const declaration">CONST_PARAM</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="angle">></span><span class="parenthesis">(</span><span class="keyword const">const</span> <span class="brace">{</span><span class="brace">}</span><span class="colon">:</span> <span class="keyword">const</span> <span class="keyword">fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span> <span class="keyword">where</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span> <span class="keyword const">const</span> <span class="trait">ConstTrait</span> <span class="brace">{</span>
|
||||
<span class="keyword const">const</span> <span class="constant const declaration">CONST_ITEM</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword const">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="operator">&</span><span class="keyword">raw</span> <span class="keyword const">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function const declaration">const_fn</span><span class="angle"><</span><span class="keyword const">const</span> <span class="const_param const declaration">CONST_PARAM</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="angle">></span><span class="parenthesis">(</span><span class="keyword const">const</span> <span class="brace">{</span><span class="brace">}</span><span class="colon">:</span> <span class="keyword const">const</span> <span class="keyword">fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span> <span class="keyword">where</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span> <span class="keyword const">const</span> <span class="trait">ConstTrait</span> <span class="brace">{</span>
|
||||
<span class="constant const">CONST_ITEM</span><span class="semicolon">;</span>
|
||||
<span class="const_param const">CONST_PARAM</span><span class="semicolon">;</span>
|
||||
<span class="keyword const">const</span> <span class="brace">{</span>
|
||||
<span class="keyword">const</span> <span class="punctuation">|</span><span class="punctuation">|</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
<span class="keyword const">const</span> <span class="punctuation">|</span><span class="punctuation">|</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="macro public">id</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
|
||||
<span class="constant const macro">CONST_ITEM</span><span class="semicolon macro">;</span>
|
||||
<span class="const_param const macro">CONST_PARAM</span><span class="semicolon macro">;</span>
|
||||
<span class="keyword const macro">const</span> <span class="brace macro">{</span>
|
||||
<span class="keyword macro">const</span> <span class="punctuation macro">|</span><span class="punctuation macro">|</span> <span class="brace macro">{</span><span class="brace macro">}</span>
|
||||
<span class="keyword const macro">const</span> <span class="punctuation macro">|</span><span class="punctuation macro">|</span> <span class="brace macro">{</span><span class="brace macro">}</span>
|
||||
<span class="brace macro">}</span><span class="semicolon macro">;</span>
|
||||
<span class="operator macro">&</span><span class="keyword macro">raw</span> <span class="keyword macro">const</span> <span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon macro">;</span>
|
||||
<span class="keyword macro">const</span>
|
||||
<span class="operator macro">&</span><span class="keyword macro">raw</span> <span class="keyword const macro">const</span> <span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon macro">;</span>
|
||||
<span class="keyword const macro">const</span>
|
||||
<span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="parenthesis">(</span><span class="parenthesis">)</span><span class="operator">.</span><span class="method const consuming trait">assoc_const_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span>
|
||||
@ -80,6 +75,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
|
||||
<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">unsafe_deref</span> <span class="brace">{</span>
|
||||
<span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span>
|
||||
<span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
|
||||
<span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword const">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
|
||||
<span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span></code></pre>
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
<span class="comment documentation">///</span>
|
||||
<span class="comment documentation">/// ```</span>
|
||||
<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="comment injected">// functions</span>
|
||||
<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function declaration injected">foo</span><span class="angle injected"><</span><span class="type_param declaration injected">T</span><span class="comma injected">,</span><span class="none injected"> </span><span class="keyword injected">const</span><span class="none injected"> </span><span class="const_param const declaration injected">X</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">usize</span><span class="angle injected">></span><span class="parenthesis injected">(</span><span class="value_param declaration injected">arg</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">i32</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span>
|
||||
<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function declaration injected">foo</span><span class="angle injected"><</span><span class="type_param declaration injected">T</span><span class="comma injected">,</span><span class="none injected"> </span><span class="keyword const injected">const</span><span class="none injected"> </span><span class="const_param const declaration injected">X</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">usize</span><span class="angle injected">></span><span class="parenthesis injected">(</span><span class="value_param declaration injected">arg</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">i32</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span>
|
||||
<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="none injected"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">x</span><span class="colon injected">:</span><span class="none injected"> </span><span class="type_param injected">T</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="const_param const injected">X</span><span class="semicolon injected">;</span>
|
||||
<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="brace injected">}</span>
|
||||
<span class="comment documentation">/// ```</span>
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
<span class="keyword control">loop</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
<span class="brace">}</span>
|
||||
|
||||
<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle"><</span><span class="keyword">const</span> <span class="const_param const declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">usize</span> <span class="brace">{</span>
|
||||
<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle"><</span><span class="keyword const">const</span> <span class="const_param const declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">usize</span> <span class="brace">{</span>
|
||||
<span class="function">const_param</span><span class="operator">::</span><span class="angle"><</span><span class="brace">{</span> <span class="const_param const">FOO</span> <span class="brace">}</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="const_param const">FOO</span>
|
||||
<span class="brace">}</span>
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
<span class="macro public">toho</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang unsafe">!</span><span class="parenthesis unsafe">(</span>
|
||||
<span class="string_literal macro">"mov {</span><span class="variable">0</span><span class="string_literal macro">}, {</span><span class="variable">1</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||
<span class="string_literal macro">"add {</span><span class="variable">0</span><span class="string_literal macro">}, 5"</span><span class="comma macro">,</span>
|
||||
<span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">o</span><span class="comma macro">,</span>
|
||||
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">i</span><span class="comma macro">,</span>
|
||||
<span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="keyword const">const</span> <span class="constant const declaration">CONSTANT</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span>
|
||||
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">m</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
|
@ -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
|
||||
<span class="brace">}</span>
|
||||
<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">unsafe_deref</span> <span class="brace">{</span>
|
||||
<span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span>
|
||||
<span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
|
||||
<span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword const">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
|
||||
<span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">MUT_GLOBAL</span><span class="colon">:</span> <span class="struct">Struct</span> <span class="operator">=</span> <span class="struct">Struct</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword">static</span> <span class="static declaration">GLOBAL</span><span class="colon">:</span> <span class="struct">Struct</span> <span class="operator">=</span> <span class="struct">Struct</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
|
||||
<span class="keyword">union</span> <span class="union declaration">Union</span> <span class="brace">{</span>
|
||||
<span class="field declaration">a</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
|
||||
<span class="field declaration">b</span><span class="colon">:</span> <span class="builtin_type">f32</span><span class="comma">,</span>
|
||||
<span class="field declaration">field</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
|
||||
<span class="brace">}</span>
|
||||
|
||||
<span class="keyword">struct</span> <span class="struct declaration">Struct</span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="builtin_type">i32</span> <span class="brace">}</span>
|
||||
|
||||
<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">MUT_GLOBAL</span><span class="colon">:</span> <span class="struct">Struct</span> <span class="operator">=</span> <span class="struct">Struct</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
|
||||
<span class="keyword">impl</span> <span class="struct">Struct</span> <span class="brace">{</span>
|
||||
<span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="method associated declaration reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
<span class="brace">}</span>
|
||||
|
||||
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">repr</span><span class="parenthesis attribute">(</span><span class="none attribute">packed</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
|
||||
<span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="brace">{</span>
|
||||
<span class="field declaration">a</span><span class="colon">:</span> <span class="builtin_type">u16</span><span class="comma">,</span>
|
||||
<span class="brace">}</span>
|
||||
|
||||
<span class="keyword unsafe">unsafe</span> <span class="keyword">trait</span> <span class="trait declaration unsafe">UnsafeTrait</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
<span class="keyword unsafe">unsafe</span> <span class="keyword">impl</span> <span class="trait unsafe">UnsafeTrait</span> <span class="keyword">for</span> <span class="struct">Packed</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
<span class="keyword unsafe">unsafe</span> <span class="keyword">impl</span> <span class="trait unsafe">UnsafeTrait</span> <span class="keyword">for</span> <span class="union">Union</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
<span class="keyword">impl</span> <span class="punctuation">!</span><span class="trait">UnsafeTrait</span> <span class="keyword">for</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
|
||||
<span class="keyword">fn</span> <span class="function declaration">unsafe_trait_bound</span><span class="angle"><</span><span class="type_param declaration">T</span><span class="colon">:</span> <span class="trait">UnsafeTrait</span><span class="angle">></span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="type_param">T</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
|
||||
<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span>
|
||||
<span class="keyword">fn</span> <span class="method associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span>
|
||||
|
||||
<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span>
|
||||
<span class="keyword">fn</span> <span class="method associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
|
||||
<span class="keyword">extern</span> <span class="brace">{</span>
|
||||
<span class="keyword">static</span> <span class="static declaration">EXTERN_STATIC</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span>
|
||||
|
||||
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field">b</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">x</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword const">const</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">u</span><span class="colon">:</span> <span class="union">Union</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="comment">// id should be safe here, but unsafe_deref should not</span>
|
||||
<span class="macro public">id</span><span class="macro_bang">!</span> <span class="brace">{</span>
|
||||
<span class="keyword macro unsafe">unsafe</span> <span class="brace macro">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span>
|
||||
<span class="keyword macro unsafe">unsafe</span> <span class="brace macro">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro unsafe">!</span><span class="parenthesis macro unsafe">(</span><span class="parenthesis macro unsafe">)</span> <span class="brace macro">}</span>
|
||||
<span class="brace">}</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="keyword unsafe">unsafe</span> <span class="brace">{</span>
|
||||
<span class="macro public unsafe">unsafe_deref</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="macro public unsafe">id</span><span class="macro_bang">!</span> <span class="brace">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="comment">// unsafe macro calls</span>
|
||||
<span class="macro public unsafe">unsafe_deref</span><span class="macro_bang unsafe">!</span><span class="parenthesis unsafe">(</span><span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
<span class="macro public unsafe">id</span><span class="macro_bang unsafe">!</span> <span class="brace unsafe">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro unsafe">!</span><span class="parenthesis macro unsafe">(</span><span class="parenthesis macro unsafe">)</span> <span class="brace unsafe">}</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="comment">// unsafe fn and method calls</span>
|
||||
<span class="function unsafe">unsafe_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="operator">.</span><span class="field unsafe">b</span><span class="semicolon">;</span>
|
||||
<span class="keyword control">match</span> <span class="variable">u</span> <span class="brace">{</span>
|
||||
<span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">b</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span> <span class="operator">=></span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
|
||||
<span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">a</span> <span class="brace">}</span> <span class="operator">=></span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="struct">Struct</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="operator">.</span><span class="method reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="function unsafe">unsafe_fn</span><span class="parenthesis unsafe">(</span><span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
<span class="self_keyword crate_root public">self</span><span class="operator">::</span><span class="function unsafe">unsafe_fn</span><span class="parenthesis unsafe">(</span><span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
<span class="parenthesis">(</span><span class="function">unsafe_fn</span> <span class="keyword">as</span> <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis unsafe">(</span><span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
<span class="struct">Struct</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="operator">.</span><span class="method reference unsafe">unsafe_method</span><span class="parenthesis unsafe">(</span><span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="variable">u</span><span class="operator">.</span><span class="field unsafe">field</span><span class="semicolon">;</span>
|
||||
<span class="operator">&</span><span class="variable">u</span><span class="operator">.</span><span class="field unsafe">field</span><span class="semicolon">;</span>
|
||||
<span class="operator">&</span><span class="keyword">raw</span> <span class="keyword const">const</span> <span class="variable">u</span><span class="operator">.</span><span class="field unsafe">field</span><span class="semicolon">;</span>
|
||||
<span class="comment">// this should be safe!</span>
|
||||
<span class="keyword">let</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="punctuation">_</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="comment">// but not these</span>
|
||||
<span class="keyword">let</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">field</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">field</span><span class="colon">:</span> <span class="bool_literal">true</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">field</span><span class="colon">:</span> <span class="variable declaration">field</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">field</span><span class="colon">:</span> <span class="keyword">ref</span> <span class="variable declaration reference">field</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">field</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="keyword">ref</span> <span class="variable declaration reference">field</span> <span class="punctuation">|</span> <span class="numeric_literal">0</span><span class="parenthesis">)</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="comment">// unsafe deref</span>
|
||||
<span class="operator unsafe">*</span><span class="variable">x</span><span class="semicolon">;</span>
|
||||
<span class="operator unsafe">*</span><span class="operator">&</span><span class="keyword">raw</span> <span class="keyword const">const</span><span class="operator">*</span><span class="operator">&</span><span class="operator unsafe">*</span><span class="variable">x</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="comment">// unsafe access to a static mut</span>
|
||||
<span class="static mutable unsafe">MUT_GLOBAL</span><span class="operator">.</span><span class="field">field</span><span class="semicolon">;</span>
|
||||
<span class="static">GLOBAL</span><span class="operator">.</span><span class="field">field</span><span class="semicolon">;</span>
|
||||
<span class="operator">&</span><span class="static mutable unsafe">MUT_GLOBAL</span><span class="operator">.</span><span class="field">field</span><span class="semicolon">;</span>
|
||||
<span class="operator">&</span><span class="keyword">raw</span> <span class="keyword const">const</span> <span class="static mutable unsafe">MUT_GLOBAL</span><span class="operator">.</span><span class="field">field</span><span class="semicolon">;</span>
|
||||
<span class="static mutable unsafe">MUT_GLOBAL</span><span class="semicolon">;</span>
|
||||
<span class="operator">&</span><span class="static mutable unsafe">MUT_GLOBAL</span><span class="semicolon">;</span>
|
||||
<span class="operator">&</span><span class="keyword">raw</span> <span class="keyword const">const</span> <span class="static mutable">MUT_GLOBAL</span><span class="semicolon">;</span>
|
||||
<span class="static unsafe">EXTERN_STATIC</span><span class="semicolon">;</span>
|
||||
<span class="operator">&</span><span class="static unsafe">EXTERN_STATIC</span><span class="semicolon">;</span>
|
||||
<span class="operator">&</span><span class="keyword">raw</span> <span class="keyword const">const</span> <span class="static">EXTERN_STATIC</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="comment">// unsafe ref of packed fields</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration">packed</span> <span class="operator">=</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="variable declaration reference">a</span> <span class="operator">=</span> <span class="operator unsafe">&</span><span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="keyword unsafe">ref</span> <span class="variable declaration reference">a</span> <span class="operator">=</span> <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="keyword unsafe">ref</span> <span class="field">a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span>
|
||||
<span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration reference">_a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="comment">// unsafe auto ref of packed field</span>
|
||||
<span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="method reference trait unsafe">calls_autoref</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang unsafe">!</span><span class="parenthesis unsafe">(</span>
|
||||
<span class="string_literal macro">"push {</span><span class="variable">base</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||
<span class="variable declaration macro">base</span> <span class="operator macro">=</span> <span class="keyword const macro">const</span> <span class="numeric_literal macro">0</span>
|
||||
<span class="parenthesis unsafe">)</span><span class="semicolon">;</span>
|
||||
<span class="brace">}</span>
|
||||
<span class="brace">}</span></code></pre>
|
@ -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: 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 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
|
||||
);
|
||||
}
|
||||
}
|
||||
"#,
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user