-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Closed
Labels
Broken WindowBugs / technical debt to be addressed immediatelyBugs / technical debt to be addressed immediately
Description
Panic context:
>
version: ce4670f29 2021-08-25 dev
request: textDocument/codeAction CodeActionParams {
text_document: TextDocumentIdentifier {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "/home/matklad/projects/tracing-span-tree/src/lib.rs",
query: None,
fragment: None,
},
},
range: Range {
start: Position {
line: 147,
character: 0,
},
end: Position {
line: 154,
character: 0,
},
},
context: CodeActionContext {
diagnostics: [],
only: None,
},
work_done_progress_params: WorkDoneProgressParams {
work_done_token: None,
},
partial_result_params: PartialResultParams {
partial_result_token: None,
},
}
thread '<unnamed>' panicked at 'body references two different self params', crates/ide_assists/src/handlers/extract_function.rs:604:33
stack backtrace:
0: std::panicking::begin_panic
1: ide_assists::handlers::extract_function::FunctionBody::analyze::{{closure}}
2: syntax::ast::expr_ext::<impl syntax::ast::generated::nodes::Expr>::walk::{{closure}}
3: syntax::ast::expr_ext::<impl syntax::ast::generated::nodes::Expr>::preorder
4: syntax::ast::expr_ext::<impl syntax::ast::generated::nodes::Expr>::walk
5: ide_assists::handlers::extract_function::extract_function
6: ide_assists::assists
7: ide::Analysis::assists_with_fixes::{{closure}}
8: std::panicking::try
9: ide::Analysis::assists_with_fixes
10: rust_analyzer::handlers::handle_code_action
11: rust_analyzer::dispatch::RequestDispatcher::on::{{closure}}::{{closure}}
12: <F as threadpool::FnBox>::call_box
Code:
//! Consumer of `tracing` data, which prints a hierarchical profile.
//!
//! Based on https://github.com/davidbarsky/tracing-tree, but does less, while
//! actually printing timings for spans.
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::time::{Duration, Instant};
use std::{fmt, mem};
use tracing::debug;
use tracing::field::{Field, Visit};
use tracing::span::Attributes;
use tracing::{Event, Id, Subscriber};
use tracing_subscriber::layer::Context;
use tracing_subscriber::prelude::*;
use tracing_subscriber::registry::LookupSpan;
use tracing_subscriber::reload::Handle;
use tracing_subscriber::Layer;
pub fn enable() {
let subscriber = tracing_subscriber::Registry::default().with(SpanTree);
tracing::subscriber::set_global_default(subscriber)
.unwrap_or_else(|_| debug!("Global subscriber is already set"));
}
#[derive(Default)]
pub struct SpanTree {
aggregate: bool,
}
impl SpanTree {
pub fn aggregate(self, yes: bool) -> SpanTree {
SpanTree {
aggregate: yes,
..self
}
}
}
struct Data {
start: Instant,
children: Vec<Node>,
}
impl Data {
fn new(attrs: &Attributes<'_>) -> Self {
let mut span = Self {
start: Instant::now(),
children: Vec::new(),
};
attrs.record(&mut span);
span
}
fn into_node(self, name: &'static str) -> Node {
Node {
name,
count: 1,
duration: self.start.elapsed(),
children: self.children,
}
}
}
impl Visit for Data {
fn record_debug(&mut self, _field: &Field, _value: &dyn fmt::Debug) {}
}
impl<S> Layer<S> for SpanTree
where
S: Subscriber + for<'span> LookupSpan<'span> + fmt::Debug,
{
fn new_span(&self, attrs: &Attributes, id: &Id, ctx: Context<S>) {
let span = ctx.span(id).unwrap();
let data = Data::new(attrs);
span.extensions_mut().insert(data);
}
fn on_event(&self, _event: &Event<'_>, _ctx: Context<S>) {}
fn on_close(&self, id: Id, ctx: Context<S>) {
let span = ctx.span(&id).unwrap();
let data: Data = span.extensions_mut().remove().unwrap();
let node = data.into_node(span.name());
let ext = span.extensions();
let data = ext.get::<Data>().unwrap();
let duration = data.start.elapsed();
match span.parent_id() {
Some(parent_id) => {
let parent_span = ctx.span(parent_id).unwrap();
let mut parent_data: Data = parent_span.extensions_mut().get_mut().unwrap();
parent_data.children.push(Node);
}
None => print(&node),
}
let level = ctx.scope().count();
}
}
struct Node {
name: &'static str,
count: u32,
duration: Duration,
children: Vec<Node>,
}
impl Node {
fn print(&self) {
self.go(0)
}
fn go(&self, level: u32) {
let bold = "\u{001b}[1m";
let reset = "\u{001b}[0m";
eprintln!(
"{:width$} {:3.2?} {bold}{}{reset}",
"",
self.duration,
self.name,
bold = bold,
reset = reset,
width = level * 2
);
for child in &self.children {
self.go(child, level + 1)
}
if level == 0 {
eprintln!()
}
}
fn aggregate(&mut self) {
self.children.sort_by_key(|it| it.name);
let mut idx = 0;
for i in 1..self.children.len() {
if self.children[idx].name == self.children[i].name {
let child = mem::take(&mut self.children[i]);
self.children[idx].merge(child)
} else {
idx += 1;
assert!(idx <= i);
self.children.swap(idx, i);
}
self.children[i].aggregate();
match visited.entry(&self.children[i].name as *const str) {
Entry::Occupied(entry) => {}
Entry::Vacant(entry) => {
entry.insert(idx);
self.children.swap(i, idx);
idx += 1
}
}
}
}
fn merge(&mut self, other: Node) {
debug_assert!(self.name == other.name);
self.duration += other.duration;
self.count += other.count;
}
}Selection on failure:
Metadata
Metadata
Assignees
Labels
Broken WindowBugs / technical debt to be addressed immediatelyBugs / technical debt to be addressed immediately
