mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Fix some typos
This commit is contained in:
parent
a36e310229
commit
4fd3613434
26 changed files with 69 additions and 65 deletions
|
@ -1,4 +1,4 @@
|
|||
//! `ra_assits` crate provides a bunch of code assists, aslo known as code
|
||||
//! `ra_assits` crate provides a bunch of code assists, also known as code
|
||||
//! actions (in LSP) or intentions (in IntelliJ).
|
||||
//!
|
||||
//! An assist is a micro-refactoring, which is automatically activated in
|
||||
|
|
|
@ -17,9 +17,9 @@ pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
|
|||
|
||||
let macro_range = macro_call.syntax().range();
|
||||
|
||||
// If the cursor is inside the macrocall, we'll try to maintain
|
||||
// the cursor position by subtracting the length of dbg!( from the start
|
||||
// of the filerange, otherwise we'll default to using the start of the macrocall
|
||||
// If the cursor is inside the macro call, we'll try to maintain the cursor
|
||||
// position by subtracting the length of dbg!( from the start of the file
|
||||
// range, otherwise we'll default to using the start of the macro call
|
||||
let cursor_pos = {
|
||||
let file_range = ctx.frange.range;
|
||||
|
||||
|
@ -61,7 +61,7 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b
|
|||
let path = macro_call.path()?;
|
||||
let name_ref = path.segment()?.name_ref()?;
|
||||
|
||||
// Make sure it is actually a dbg-macrocall, dbg followed by !
|
||||
// Make sure it is actually a dbg-macro call, dbg followed by !
|
||||
let excl = path.syntax().next_sibling()?;
|
||||
|
||||
if name_ref.text() != macro_name || excl.kind() != EXCL {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
//! any background processing (this bit is handled by salsa, see the
|
||||
//! `BaseDatabase::check_canceled` method).
|
||||
|
||||
/// An "error" signifing that the operation was canceled.
|
||||
/// An "error" signifying that the operation was canceled.
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Canceled {
|
||||
_private: (),
|
||||
|
|
|
@ -134,7 +134,7 @@ impl Module {
|
|||
|
||||
/// Topmost parent of this module. Every module has a `crate_root`, but some
|
||||
/// might be missing `krate`. This can happen if a module's file is not included
|
||||
/// in the module tree of any target in Cargo.toml.
|
||||
/// in the module tree of any target in `Cargo.toml`.
|
||||
pub fn crate_root(&self, db: &impl PersistentHirDatabase) -> Module {
|
||||
self.crate_root_impl(db)
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ impl Enum {
|
|||
db.type_for_def((*self).into())
|
||||
}
|
||||
|
||||
// TODO move to a more general type
|
||||
// TODO: move to a more general type
|
||||
/// Builds a resolver for type references inside this struct.
|
||||
pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
|
||||
// take the outer scope...
|
||||
|
@ -495,7 +495,7 @@ impl Function {
|
|||
db.generic_params((*self).into())
|
||||
}
|
||||
|
||||
// TODO move to a more general type for 'body-having' items
|
||||
// TODO: move to a more general type for 'body-having' items
|
||||
/// Builds a resolver for code inside this item.
|
||||
pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
|
||||
// take the outer scope...
|
||||
|
|
|
@ -84,7 +84,7 @@ impl ExprScopes {
|
|||
fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
|
||||
match &body[pat] {
|
||||
Pat::Bind { name, .. } => {
|
||||
// bind can have a subpattern, but it's actually not allowed
|
||||
// bind can have a sub pattern, but it's actually not allowed
|
||||
// to bind to things in there
|
||||
let entry = ScopeEntry { name: name.clone(), pat };
|
||||
self.scopes[scope].entries.push(entry)
|
||||
|
|
|
@ -46,24 +46,24 @@ impl HirInterner {
|
|||
/// This module defines a bunch of ids we are using. The most important ones are
|
||||
/// probably `HirFileId` and `DefId`.
|
||||
|
||||
/// Input to the analyzer is a set of files, where each file is indentified by
|
||||
/// Input to the analyzer is a set of files, where each file is identified by
|
||||
/// `FileId` and contains source code. However, another source of source code in
|
||||
/// Rust are macros: each macro can be thought of as producing a "temporary
|
||||
/// file". To assign an id to such a file, we use the id of the macro call that
|
||||
/// produced the file. So, a `HirFileId` is either a `FileId` (source code
|
||||
/// written by user), or a `MacroCallId` (source code produced by macro).
|
||||
///
|
||||
/// What is a `MacroCallId`? Simplifying, it's a `HirFileId` of a file containin
|
||||
/// the call plus the offset of the macro call in the file. Note that this is a
|
||||
/// recursive definition! However, the size_of of `HirFileId` is finite
|
||||
/// (because everything bottoms out at the real `FileId`) and small
|
||||
/// What is a `MacroCallId`? Simplifying, it's a `HirFileId` of a file
|
||||
/// containing the call plus the offset of the macro call in the file. Note that
|
||||
/// this is a recursive definition! However, the size_of of `HirFileId` is
|
||||
/// finite (because everything bottoms out at the real `FileId`) and small
|
||||
/// (`MacroCallId` uses the location interner).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct HirFileId(HirFileIdRepr);
|
||||
|
||||
impl HirFileId {
|
||||
/// For macro-expansion files, returns the file original source file the
|
||||
/// expansionoriginated from.
|
||||
/// expansion originated from.
|
||||
pub fn original_file(self, db: &impl PersistentHirDatabase) -> FileId {
|
||||
match self.0 {
|
||||
HirFileIdRepr::File(file_id) => file_id,
|
||||
|
@ -324,9 +324,9 @@ impl SourceFileItems {
|
|||
|
||||
fn init(&mut self, source_file: &SourceFile) {
|
||||
// By walking the tree in bread-first order we make sure that parents
|
||||
// get lower ids then children. That is, addding a new child does not
|
||||
// get lower ids then children. That is, adding a new child does not
|
||||
// change parent's id. This means that, say, adding a new function to a
|
||||
// trait does not chage ids of top-level items, which helps caching.
|
||||
// trait does not change ids of top-level items, which helps caching.
|
||||
bfs(source_file.syntax(), |it| {
|
||||
if let Some(module_item) = ast::ModuleItem::cast(it) {
|
||||
self.alloc(module_item.syntax());
|
||||
|
|
|
@ -490,7 +490,7 @@ impl ItemMap {
|
|||
None => {
|
||||
// we still have path segments left, but the path so far
|
||||
// didn't resolve in the types namespace => no resolution
|
||||
// (don't break here because curr_per_ns might contain
|
||||
// (don't break here because `curr_per_ns` might contain
|
||||
// something in the value namespace, and it would be wrong
|
||||
// to return that)
|
||||
return (PerNs::none(), ReachedFixedPoint::No);
|
||||
|
|
|
@ -208,7 +208,7 @@ impl LoweredModule {
|
|||
}
|
||||
}
|
||||
ast::ModuleItemKind::Module(_) => {
|
||||
// modules are handled separately direclty by nameres
|
||||
// modules are handled separately directly by name res
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ impl Path {
|
|||
return Some(q);
|
||||
}
|
||||
// TODO: this bottom up traversal is not too precise.
|
||||
// Should we handle do a top-down analysiss, recording results?
|
||||
// Should we handle do a top-down analysis, recording results?
|
||||
let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
|
||||
let use_tree = use_tree_list.parent_use_tree();
|
||||
use_tree.path()
|
||||
|
|
|
@ -30,7 +30,7 @@ pub use crate::completion::completion_item::{CompletionItem, CompletionItemKind,
|
|||
/// incomplete and can look really weird.
|
||||
///
|
||||
/// Once the context is collected, we run a series of completion routines which
|
||||
/// look at the context and produce completion items. One subtelty about this
|
||||
/// look at the context and produce completion items. One subtlety about this
|
||||
/// phase is that completion engine should not filter by the substring which is
|
||||
/// already present, it should give all possible variants for the identifier at
|
||||
/// the caret. In other words, for
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_hash::FxHashMap;
|
|||
|
||||
use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem};
|
||||
|
||||
/// Complete repeated parametes, both name and type. For example, if all
|
||||
/// Complete repeated parameters, both name and type. For example, if all
|
||||
/// functions in a file have a `spam: &mut Spam` parameter, a completion with
|
||||
/// `spam: &mut Spam` insert text/label and `spam` lookup string will be
|
||||
/// suggested.
|
||||
|
|
|
@ -93,10 +93,10 @@ pub(crate) fn reference_definition(
|
|||
return Exact(nav);
|
||||
}
|
||||
Some(Resolution::GenericParam(..)) => {
|
||||
// TODO go to the generic param def
|
||||
// TODO: go to the generic param def
|
||||
}
|
||||
Some(Resolution::SelfType(_impl_block)) => {
|
||||
// TODO go to the implemented type
|
||||
// TODO: go to the implemented type
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
@ -133,8 +133,8 @@ mod tests {
|
|||
|
||||
use crate::mock_analysis::analysis_and_position;
|
||||
|
||||
fn check_goto(fixuture: &str, expected: &str) {
|
||||
let (analysis, pos) = analysis_and_position(fixuture);
|
||||
fn check_goto(fixture: &str, expected: &str) {
|
||||
let (analysis, pos) = analysis_and_position(fixture);
|
||||
|
||||
let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info;
|
||||
assert_eq!(navs.len(), 1);
|
||||
|
|
|
@ -71,8 +71,8 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: this should not really use navigation target. Rather, approximatelly
|
||||
// resovled symbol should return a `DefId`.
|
||||
// FIXME: this should not really use navigation target. Rather, approximately
|
||||
// resolved symbol should return a `DefId`.
|
||||
fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Option<String> {
|
||||
match (nav.description(db), nav.docs(db)) {
|
||||
(Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs),
|
||||
|
|
|
@ -78,8 +78,8 @@ fn impls_for_trait(
|
|||
mod tests {
|
||||
use crate::mock_analysis::analysis_and_position;
|
||||
|
||||
fn check_goto(fixuture: &str, expected: &[&str]) {
|
||||
let (analysis, pos) = analysis_and_position(fixuture);
|
||||
fn check_goto(fixture: &str, expected: &[&str]) {
|
||||
let (analysis, pos) = analysis_and_position(fixture);
|
||||
|
||||
let navs = analysis.goto_implementation(pos).unwrap().unwrap().info;
|
||||
assert_eq!(navs.len(), expected.len());
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//! However, IDE specific bits of the analysis (most notably completion) happen
|
||||
//! in this crate.
|
||||
//!
|
||||
//! The sibling `ra_ide_api_light` handles thouse bits of IDE functionality
|
||||
//! The sibling `ra_ide_api_light` handles those bits of IDE functionality
|
||||
//! which are restricted to a single file and need only syntax.
|
||||
|
||||
// For proving that RootDatabase is RefUnwindSafe.
|
||||
|
@ -67,7 +67,7 @@ pub use ra_db::{
|
|||
pub use hir::Documentation;
|
||||
|
||||
// We use jemalloc mainly to get heap usage statistics, actual performance
|
||||
// differnece is not measures.
|
||||
// difference is not measures.
|
||||
#[cfg(feature = "jemalloc")]
|
||||
#[global_allocator]
|
||||
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
|
||||
|
@ -221,12 +221,12 @@ impl Analysis {
|
|||
self.db.line_index(file_id)
|
||||
}
|
||||
|
||||
/// Selects the next syntactic nodes encopasing the range.
|
||||
/// Selects the next syntactic nodes encompassing the range.
|
||||
pub fn extend_selection(&self, frange: FileRange) -> Cancelable<TextRange> {
|
||||
self.with_db(|db| extend_selection::extend_selection(db, frange))
|
||||
}
|
||||
|
||||
/// Returns position of the mathcing brace (all types of braces are
|
||||
/// Returns position of the matching brace (all types of braces are
|
||||
/// supported).
|
||||
pub fn matching_brace(&self, position: FilePosition) -> Option<TextUnit> {
|
||||
let file = self.db.parse(position.file_id);
|
||||
|
@ -316,7 +316,7 @@ impl Analysis {
|
|||
self.with_db(|db| references::find_all_refs(db, position))
|
||||
}
|
||||
|
||||
/// Returns a short text descrbing element at position.
|
||||
/// Returns a short text describing element at position.
|
||||
pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> {
|
||||
self.with_db(|db| hover::hover(db, position))
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ impl MockAnalysis {
|
|||
}
|
||||
/// Creates `MockAnalysis` using a fixture data in the following format:
|
||||
///
|
||||
/// ```notrust
|
||||
/// ```rust,ignore
|
||||
/// //- /main.rs
|
||||
/// mod foo;
|
||||
/// fn main() {}
|
||||
|
|
|
@ -295,17 +295,17 @@ mod tests {
|
|||
fn test_rename(text: &str, new_name: &str, expected: &str) {
|
||||
let (analysis, position) = single_file_with_position(text);
|
||||
let source_change = analysis.rename(position, new_name).unwrap();
|
||||
let mut text_edit_bulder = ra_text_edit::TextEditBuilder::default();
|
||||
let mut text_edit_builder = ra_text_edit::TextEditBuilder::default();
|
||||
let mut file_id: Option<FileId> = None;
|
||||
if let Some(change) = source_change {
|
||||
for edit in change.source_file_edits {
|
||||
file_id = Some(edit.file_id);
|
||||
for atom in edit.edit.as_atoms() {
|
||||
text_edit_bulder.replace(atom.delete, atom.insert.clone());
|
||||
text_edit_builder.replace(atom.delete, atom.insert.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
let result = text_edit_bulder.finish().apply(&*analysis.file_text(file_id.unwrap()));
|
||||
let result = text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap()));
|
||||
assert_eq_text!(expected, &*result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,20 +5,20 @@
|
|||
//! symbols. The backbone of the index is the **awesome** `fst` crate by
|
||||
//! @BurntSushi.
|
||||
//!
|
||||
//! In a nutshell, you give a set of strings to the `fst`, and it builds a
|
||||
//! In a nutshell, you give a set of strings to `fst`, and it builds a
|
||||
//! finite state machine describing this set of strings. The strings which
|
||||
//! could fuzzy-match a pattern can also be described by a finite state machine.
|
||||
//! What is freakingly cool is that you can now traverse both state machines in
|
||||
//! What is freaking cool is that you can now traverse both state machines in
|
||||
//! lock-step to enumerate the strings which are both in the input set and
|
||||
//! fuzz-match the query. Or, more formally, given two languages described by
|
||||
//! fsts, one can build an product fst which describes the intersection of the
|
||||
//! FSTs, one can build a product FST which describes the intersection of the
|
||||
//! languages.
|
||||
//!
|
||||
//! `fst` does not support cheap updating of the index, but it supports unioning
|
||||
//! of state machines. So, to account for changing source code, we build an fst
|
||||
//! for each library (which is assumed to never change) and an fst for each rust
|
||||
//! of state machines. So, to account for changing source code, we build an FST
|
||||
//! for each library (which is assumed to never change) and an FST for each Rust
|
||||
//! file in the current workspace, and run a query against the union of all
|
||||
//! those fsts.
|
||||
//! those FSTs.
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
hash::{Hash, Hasher},
|
||||
|
|
|
@ -109,7 +109,7 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
|
||||
// Good first issue (although a slightly chellegning one):
|
||||
// Good first issue (although a slightly challenging one):
|
||||
//
|
||||
// * Pick a random test from here
|
||||
// https://github.com/intellij-rust/intellij-rust/blob/c4e9feee4ad46e7953b1948c112533360b6087bb/src/test/kotlin/org/rust/lang/core/macros/RsMacroExpansionTest.kt
|
||||
|
@ -171,8 +171,8 @@ impl_froms!(TokenTree: Leaf, Subtree);
|
|||
|
||||
let (invocation_tt, _) = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
|
||||
|
||||
let expaned = rules.expand(&invocation_tt).unwrap();
|
||||
assert_eq!(expaned.to_string(), expansion);
|
||||
let expanded = rules.expand(&invocation_tt).unwrap();
|
||||
assert_eq!(expanded.to_string(), expansion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -58,7 +58,7 @@ fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Option<tt::Subtree> {
|
|||
///
|
||||
/// The other side of the puzzle is `expand_subtree`, where we use the bindings
|
||||
/// to substitute meta variables in the output template. When expanding, we
|
||||
/// maintain a `nesteing` stack of indicies whihc tells us which occurence from
|
||||
/// maintain a `nesting` stack of indices which tells us which occurrence from
|
||||
/// the `Bindings` we should take. We push to the stack when we enter a
|
||||
/// repetition.
|
||||
///
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::Result;
|
|||
///
|
||||
/// Note that internally, rust analyzer uses a different structure:
|
||||
/// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates,
|
||||
/// while this knows about `Pacakges` & `Targets`: purely cargo-related
|
||||
/// while this knows about `Packages` & `Targets`: purely cargo-related
|
||||
/// concepts.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CargoWorkspace {
|
||||
|
|
|
@ -169,7 +169,7 @@ fn convert_notify_event(event: DebouncedEvent, sender: &Sender<(PathBuf, ChangeK
|
|||
// ignore
|
||||
}
|
||||
DebouncedEvent::Rescan => {
|
||||
// TODO rescan all roots
|
||||
// TODO: rescan all roots
|
||||
}
|
||||
DebouncedEvent::Create(path) => {
|
||||
sender.send((path, ChangeKind::Create)).unwrap();
|
||||
|
@ -185,7 +185,7 @@ fn convert_notify_event(event: DebouncedEvent, sender: &Sender<(PathBuf, ChangeK
|
|||
sender.send((dst, ChangeKind::Create)).unwrap();
|
||||
}
|
||||
DebouncedEvent::Error(err, path) => {
|
||||
// TODO should we reload the file contents?
|
||||
// TODO: should we reload the file contents?
|
||||
log::warn!("watcher error \"{}\", {:?}", err, path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
//!
|
||||
//! It is also responsible for watching the disk for changes, and for merging
|
||||
//! editor state (modified, unsaved files) with disk state.
|
||||
//! TODO: Some LSP clients support watching the disk, so this crate should
|
||||
//! to support custom watcher events (related to https://github.com/rust-analyzer/rust-analyzer/issues/131)
|
||||
//!
|
||||
//! TODO: Some LSP clients support watching the disk, so this crate should to
|
||||
//! support custom watcher events (related to
|
||||
//! <https://github.com/rust-analyzer/rust-analyzer/issues/131>)
|
||||
//!
|
||||
//! VFS is based on a concept of roots: a set of directories on the file system
|
||||
//! which are watched for changes. Typically, there will be a root for each
|
||||
|
@ -212,12 +214,12 @@ impl Vfs {
|
|||
let mut cur_files = Vec::new();
|
||||
// While we were scanning the root in the background, a file might have
|
||||
// been open in the editor, so we need to account for that.
|
||||
let exising = self.root2files[root]
|
||||
let existing = self.root2files[root]
|
||||
.iter()
|
||||
.map(|&file| (self.files[file].path.clone(), file))
|
||||
.collect::<FxHashMap<_, _>>();
|
||||
for (path, text) in files {
|
||||
if let Some(&file) = exising.get(&path) {
|
||||
if let Some(&file) = existing.get(&path) {
|
||||
let text = Arc::clone(&self.files[file].text);
|
||||
cur_files.push((file, path, text));
|
||||
continue;
|
||||
|
@ -322,7 +324,7 @@ impl Vfs {
|
|||
mem::replace(&mut self.pending_changes, Vec::new())
|
||||
}
|
||||
|
||||
/// Sutdown the VFS and terminate the background watching thread.
|
||||
/// Shutdown the VFS and terminate the background watching thread.
|
||||
pub fn shutdown(self) -> thread::Result<()> {
|
||||
self.worker.shutdown()
|
||||
}
|
||||
|
@ -347,7 +349,7 @@ impl Vfs {
|
|||
}
|
||||
|
||||
fn remove_file(&mut self, file: VfsFile) {
|
||||
//FIXME: use arena with removal
|
||||
// FIXME: use arena with removal
|
||||
self.files[file].text = Default::default();
|
||||
self.files[file].path = Default::default();
|
||||
let root = self.files[file].root;
|
||||
|
|
|
@ -113,9 +113,9 @@ pub struct FixtureEntry {
|
|||
pub text: String,
|
||||
}
|
||||
|
||||
/// Parses text wich looks like this:
|
||||
/// Parses text which looks like this:
|
||||
///
|
||||
/// ```notrust
|
||||
/// ```rust,ignore
|
||||
/// //- some meta
|
||||
/// line 1
|
||||
/// line 2
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//! This module implements manually tracked test coverage, which useful for
|
||||
//! quickly finding a test responsible for testing a particular bit of code.
|
||||
//!
|
||||
//! See https://matklad.github.io/2018/06/18/a-trick-for-test-maintenance.html
|
||||
//! See <https://matklad.github.io/2018/06/18/a-trick-for-test-maintenance.html>
|
||||
//! for details, but the TL;DR is that you write your test as
|
||||
//!
|
||||
//! ```no-run
|
||||
//! ```rust,no_run
|
||||
//! #[test]
|
||||
//! fn test_foo() {
|
||||
//! covers!(test_foo);
|
||||
|
@ -13,7 +13,9 @@
|
|||
//!
|
||||
//! and in the code under test you write
|
||||
//!
|
||||
//! ```no-run
|
||||
//! ```rust,no_run
|
||||
//! # use test_utils::tested_by;
|
||||
//! # fn some_condition() -> bool { true }
|
||||
//! fn foo() {
|
||||
//! if some_condition() {
|
||||
//! tested_by!(test_foo);
|
||||
|
|
|
@ -65,7 +65,7 @@ impl WorkerHandle {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets up worker channels in a deadlock-avoind way.
|
||||
/// Sets up worker channels in a deadlock-avoiding way.
|
||||
/// If one sets both input and output buffers to a fixed size,
|
||||
/// a worker might get stuck.
|
||||
fn worker_chan<I, O>(buf: usize) -> (Worker<I, O>, Receiver<I>, Sender<O>) {
|
||||
|
|
Loading…
Reference in a new issue