Unnamed repository; edit this file 'description' to name the repository.
Merge remote-tracking branch 'origin/master' into sync-from-rust-2
Amos Wenger 2022-07-25
parent dfe8449 · parent ac86b8e · commit 0d04e63
-rw-r--r--crates/hir-def/src/body/lower.rs40
-rw-r--r--crates/hir-def/src/expr.rs12
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs5
-rw-r--r--crates/hir-ty/src/infer/expr.rs18
-rw-r--r--crates/ide-assists/src/handlers/add_missing_impl_members.rs17
-rw-r--r--crates/ide-assists/src/utils/gen_trait_fn_body.rs11
-rw-r--r--crates/ide-completion/src/render.rs40
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs31
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs6
-rw-r--r--crates/rust-analyzer/src/global_state.rs4
-rw-r--r--crates/rust-analyzer/src/handlers.rs2
-rw-r--r--crates/rust-analyzer/src/reload.rs47
12 files changed, 169 insertions, 64 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index c3f2611227..66f9c24e87 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -96,6 +96,7 @@ pub(super) fn lower(
expander,
name_to_pat_grouping: Default::default(),
is_lowering_inside_or_pat: false,
+ is_lowering_assignee_expr: false,
}
.collect(params, body)
}
@@ -109,6 +110,7 @@ struct ExprCollector<'a> {
// a poor-mans union-find?
name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
is_lowering_inside_or_pat: bool,
+ is_lowering_assignee_expr: bool,
}
impl ExprCollector<'_> {
@@ -283,7 +285,10 @@ impl ExprCollector<'_> {
} else {
Box::default()
};
- self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
+ self.alloc_expr(
+ Expr::Call { callee, args, is_assignee_expr: self.is_lowering_assignee_expr },
+ syntax_ptr,
+ )
}
ast::Expr::MethodCallExpr(e) => {
let receiver = self.collect_expr_opt(e.receiver());
@@ -359,6 +364,7 @@ impl ExprCollector<'_> {
ast::Expr::RecordExpr(e) => {
let path =
e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
+ let is_assignee_expr = self.is_lowering_assignee_expr;
let record_lit = if let Some(nfl) = e.record_expr_field_list() {
let fields = nfl
.fields()
@@ -378,9 +384,16 @@ impl ExprCollector<'_> {
})
.collect();
let spread = nfl.spread().map(|s| self.collect_expr(s));
- Expr::RecordLit { path, fields, spread }
+ let ellipsis = nfl.dotdot_token().is_some();
+ Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr }
} else {
- Expr::RecordLit { path, fields: Box::default(), spread: None }
+ Expr::RecordLit {
+ path,
+ fields: Box::default(),
+ spread: None,
+ ellipsis: false,
+ is_assignee_expr,
+ }
};
self.alloc_expr(record_lit, syntax_ptr)
@@ -458,14 +471,21 @@ impl ExprCollector<'_> {
)
}
ast::Expr::BinExpr(e) => {
+ let op = e.op_kind();
+ if let Some(ast::BinaryOp::Assignment { op: None }) = op {
+ self.is_lowering_assignee_expr = true;
+ }
let lhs = self.collect_expr_opt(e.lhs());
+ self.is_lowering_assignee_expr = false;
let rhs = self.collect_expr_opt(e.rhs());
- let op = e.op_kind();
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
}
ast::Expr::TupleExpr(e) => {
let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
- self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
+ self.alloc_expr(
+ Expr::Tuple { exprs, is_assignee_expr: self.is_lowering_assignee_expr },
+ syntax_ptr,
+ )
}
ast::Expr::BoxExpr(e) => {
let expr = self.collect_expr_opt(e.expr());
@@ -477,8 +497,14 @@ impl ExprCollector<'_> {
match kind {
ArrayExprKind::ElementList(e) => {
- let exprs = e.map(|expr| self.collect_expr(expr)).collect();
- self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
+ let elements = e.map(|expr| self.collect_expr(expr)).collect();
+ self.alloc_expr(
+ Expr::Array(Array::ElementList {
+ elements,
+ is_assignee_expr: self.is_lowering_assignee_expr,
+ }),
+ syntax_ptr,
+ )
}
ArrayExprKind::Repeat { initializer, repeat } => {
let initializer = self.collect_expr_opt(initializer);
diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs
index a991365d6b..c1b3788acb 100644
--- a/crates/hir-def/src/expr.rs
+++ b/crates/hir-def/src/expr.rs
@@ -110,6 +110,7 @@ pub enum Expr {
Call {
callee: ExprId,
args: Box<[ExprId]>,
+ is_assignee_expr: bool,
},
MethodCall {
receiver: ExprId,
@@ -138,6 +139,8 @@ pub enum Expr {
path: Option<Box<Path>>,
fields: Box<[RecordLitField]>,
spread: Option<ExprId>,
+ ellipsis: bool,
+ is_assignee_expr: bool,
},
Field {
expr: ExprId,
@@ -196,6 +199,7 @@ pub enum Expr {
},
Tuple {
exprs: Box<[ExprId]>,
+ is_assignee_expr: bool,
},
Unsafe {
body: ExprId,
@@ -211,7 +215,7 @@ pub enum Expr {
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Array {
- ElementList(Box<[ExprId]>),
+ ElementList { elements: Box<[ExprId]>, is_assignee_expr: bool },
Repeat { initializer: ExprId, repeat: ExprId },
}
@@ -285,7 +289,7 @@ impl Expr {
f(*iterable);
f(*body);
}
- Expr::Call { callee, args } => {
+ Expr::Call { callee, args, .. } => {
f(*callee);
args.iter().copied().for_each(f);
}
@@ -339,9 +343,9 @@ impl Expr {
| Expr::Box { expr } => {
f(*expr);
}
- Expr::Tuple { exprs } => exprs.iter().copied().for_each(f),
+ Expr::Tuple { exprs, .. } => exprs.iter().copied().for_each(f),
Expr::Array(a) => match a {
- Array::ElementList(exprs) => exprs.iter().copied().for_each(f),
+ Array::ElementList { elements, .. } => elements.iter().copied().for_each(f),
Array::Repeat { initializer, repeat } => {
f(*initializer);
f(*repeat)
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 8cca522aef..642e03edd2 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -305,7 +305,10 @@ pub fn record_literal_missing_fields(
expr: &Expr,
) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> {
let (fields, exhaustive) = match expr {
- Expr::RecordLit { path: _, fields, spread } => (fields, spread.is_none()),
+ Expr::RecordLit { fields, spread, ellipsis, is_assignee_expr, .. } => {
+ let exhaustive = if *is_assignee_expr { !*ellipsis } else { spread.is_none() };
+ (fields, exhaustive)
+ }
_ => return None,
};
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 2f33467072..d164e64a8b 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -276,7 +276,7 @@ impl<'a> InferenceContext<'a> {
closure_ty
}
- Expr::Call { callee, args } => {
+ Expr::Call { callee, args, .. } => {
let callee_ty = self.infer_expr(*callee, &Expectation::none());
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
let mut res = None;
@@ -421,7 +421,7 @@ impl<'a> InferenceContext<'a> {
}
TyKind::Never.intern(Interner)
}
- Expr::RecordLit { path, fields, spread } => {
+ Expr::RecordLit { path, fields, spread, .. } => {
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
if let Some(variant) = def_id {
self.write_variant_resolution(tgt_expr.into(), variant);
@@ -693,7 +693,7 @@ impl<'a> InferenceContext<'a> {
self.err_ty()
}
}
- Expr::Tuple { exprs } => {
+ Expr::Tuple { exprs, .. } => {
let mut tys = match expected
.only_has_type(&mut self.table)
.as_ref()
@@ -724,12 +724,12 @@ impl<'a> InferenceContext<'a> {
let expected = Expectation::has_type(elem_ty.clone());
let len = match array {
- Array::ElementList(items) => {
- for &expr in items.iter() {
+ Array::ElementList { elements, .. } => {
+ for &expr in elements.iter() {
let cur_elem_ty = self.infer_expr_inner(expr, &expected);
coerce.coerce(self, Some(expr), &cur_elem_ty);
}
- consteval::usize_const(Some(items.len() as u128))
+ consteval::usize_const(Some(elements.len() as u128))
}
&Array::Repeat { initializer, repeat } => {
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
@@ -850,7 +850,7 @@ impl<'a> InferenceContext<'a> {
let rhs_ty = self.resolve_ty_shallow(rhs_ty);
let ty = match &self.body[lhs] {
- Expr::Tuple { exprs } => {
+ Expr::Tuple { exprs, .. } => {
// We don't consider multiple ellipses. This is analogous to
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
let ellipsis = exprs.iter().position(|e| is_rest_expr(*e));
@@ -858,7 +858,7 @@ impl<'a> InferenceContext<'a> {
self.infer_tuple_pat_like(&rhs_ty, (), ellipsis, &exprs)
}
- Expr::Call { callee, args } => {
+ Expr::Call { callee, args, .. } => {
// Tuple structs
let path = match &self.body[*callee] {
Expr::Path(path) => Some(path),
@@ -872,7 +872,7 @@ impl<'a> InferenceContext<'a> {
self.infer_tuple_struct_pat_like(path, &rhs_ty, (), lhs, ellipsis, &args)
}
- Expr::Array(Array::ElementList(elements)) => {
+ Expr::Array(Array::ElementList { elements, .. }) => {
let elem_ty = match rhs_ty.kind(Interner) {
TyKind::Array(st, _) => st.clone(),
_ => self.err_ty(),
diff --git a/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 7f2a26ad06..c808c010c6 100644
--- a/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -145,13 +145,16 @@ fn add_missing_impl_members_inner(
Some(cap) => {
let mut cursor = Cursor::Before(first_new_item.syntax());
let placeholder;
- if let ast::AssocItem::Fn(func) = &first_new_item {
- if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
- if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
- {
- if m.syntax().text() == "todo!()" {
- placeholder = m;
- cursor = Cursor::Replace(placeholder.syntax());
+ if let DefaultMethods::No = mode {
+ if let ast::AssocItem::Fn(func) = &first_new_item {
+ if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
+ if let Some(m) =
+ func.syntax().descendants().find_map(ast::MacroCall::cast)
+ {
+ if m.syntax().text() == "todo!()" {
+ placeholder = m;
+ cursor = Cursor::Replace(placeholder.syntax());
+ }
}
}
}
diff --git a/crates/ide-assists/src/utils/gen_trait_fn_body.rs b/crates/ide-assists/src/utils/gen_trait_fn_body.rs
index ec4835969f..7a0c912959 100644
--- a/crates/ide-assists/src/utils/gen_trait_fn_body.rs
+++ b/crates/ide-assists/src/utils/gen_trait_fn_body.rs
@@ -5,7 +5,7 @@ use syntax::{
ted,
};
-/// Generate custom trait bodies where possible.
+/// Generate custom trait bodies without default implementation where possible.
///
/// Returns `Option` so that we can use `?` rather than `if let Some`. Returning
/// `None` means that generating a custom trait body failed, and the body will remain
@@ -28,6 +28,7 @@ pub(crate) fn gen_trait_fn_body(
/// Generate a `Clone` impl based on the fields and members of the target type.
fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
+ stdx::always!(func.name().map_or(false, |name| name.text() == "clone"));
fn gen_clone_call(target: ast::Expr) -> ast::Expr {
let method = make::name_ref("clone");
make::expr_method_call(target, method, make::arg_list(None))
@@ -339,6 +340,7 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
/// Generate a `Hash` impl based on the fields and members of the target type.
fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
+ stdx::always!(func.name().map_or(false, |name| name.text() == "hash"));
fn gen_hash_call(target: ast::Expr) -> ast::Stmt {
let method = make::name_ref("hash");
let arg = make::expr_path(make::ext::ident_path("state"));
@@ -394,9 +396,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
/// Generate a `PartialEq` impl based on the fields and members of the target type.
fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
- if func.name().map_or(false, |name| name.text() == "ne") {
- return None;
- }
+ stdx::always!(func.name().map_or(false, |name| name.text() == "eq"));
fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> {
match expr {
Some(expr) => Some(make::expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)),
@@ -573,6 +573,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
}
fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
+ stdx::always!(func.name().map_or(false, |name| name.text() == "partial_cmp"));
fn gen_partial_eq_match(match_target: ast::Expr) -> Option<ast::Stmt> {
let mut arms = vec![];
@@ -643,7 +644,7 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
make::block_expr(stmts.into_iter(), tail).indent(ast::edit::IndentLevel(1))
}
- // No fields in the body means there's nothing to hash.
+ // No fields in the body means there's nothing to compare.
None => {
let expr = make::expr_literal("true").into();
make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1))
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 3f25b294e0..9b25964a60 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -121,7 +121,7 @@ pub(crate) fn render_field(
let mut item = CompletionItem::new(
SymbolKind::Field,
ctx.source_range(),
- receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name).into()),
+ field_with_receiver(receiver.as_ref(), &name),
);
item.set_relevance(CompletionRelevance {
type_match: compute_type_match(ctx.completion, ty),
@@ -132,7 +132,7 @@ pub(crate) fn render_field(
.set_documentation(field.docs(ctx.db()))
.set_deprecated(is_deprecated)
.lookup_by(name.clone());
- item.insert_text(escaped_name);
+ item.insert_text(field_with_receiver(receiver.as_ref(), &escaped_name));
if let Some(receiver) = &dot_access.receiver {
if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) {
if let Some(ref_match) = compute_ref_match(ctx.completion, ty) {
@@ -143,6 +143,11 @@ pub(crate) fn render_field(
item.build()
}
+fn field_with_receiver(receiver: Option<&hir::Name>, field_name: &str) -> SmolStr {
+ receiver
+ .map_or_else(|| field_name.into(), |receiver| format!("{}.{}", receiver, field_name).into())
+}
+
pub(crate) fn render_tuple_field(
ctx: RenderContext<'_>,
receiver: Option<hir::Name>,
@@ -152,7 +157,7 @@ pub(crate) fn render_tuple_field(
let mut item = CompletionItem::new(
SymbolKind::Field,
ctx.source_range(),
- receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)),
+ field_with_receiver(receiver.as_ref(), &field.to_string()),
);
item.detail(ty.display(ctx.db()).to_string()).lookup_by(field.to_string());
item.build()
@@ -1876,4 +1881,33 @@ impl r#trait for r#struct { type r#type = $0; }
"#,
)
}
+
+ #[test]
+ fn field_access_includes_self() {
+ check_edit(
+ "length",
+ r#"
+struct S {
+ length: i32
+}
+
+impl S {
+ fn some_fn(&self) {
+ let l = len$0
+ }
+}
+"#,
+ r#"
+struct S {
+ length: i32
+}
+
+impl S {
+ fn some_fn(&self) {
+ let l = self.length
+ }
+}
+"#,
+ )
+ }
}
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index 30f903af50..edb1fc0919 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -293,6 +293,37 @@ fn x(a: S) {
}
#[test]
+ fn missing_record_expr_in_assignee_expr() {
+ check_diagnostics(
+ r"
+struct S { s: usize, t: usize }
+struct S2 { s: S, t: () }
+struct T(S);
+fn regular(a: S) {
+ let s;
+ S { s, .. } = a;
+}
+fn nested(a: S2) {
+ let s;
+ S2 { s: S { s, .. }, .. } = a;
+}
+fn in_tuple(a: (S,)) {
+ let s;
+ (S { s, .. },) = a;
+}
+fn in_array(a: [S;1]) {
+ let s;
+ [S { s, .. },] = a;
+}
+fn in_tuple_struct(a: T) {
+ let s;
+ T(S { s, .. }) = a;
+}
+ ",
+ );
+ }
+
+ #[test]
fn range_mapping_out_of_macros() {
check_fix(
r#"
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 4243af25ff..0ada4b73e8 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -60,9 +60,9 @@ pub fn load_workspace(
let proc_macro_client = if load_config.with_proc_macro {
let path = AbsPathBuf::assert(std::env::current_exe()?);
- Some(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap())
+ Ok(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap())
} else {
- None
+ Err("proc macro server not started".to_owned())
};
let crate_graph = ws.to_crate_graph(
@@ -89,7 +89,7 @@ pub fn load_workspace(
if load_config.prefill_caches {
host.analysis().parallel_prime_caches(1, |_| {})?;
}
- Ok((host, vfs, proc_macro_client))
+ Ok((host, vfs, proc_macro_client.ok()))
}
fn load_crate_graph(
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 4af60035a2..8f881cba4d 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -61,7 +61,7 @@ pub(crate) struct GlobalState {
pub(crate) proc_macro_changed: bool,
pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
pub(crate) source_root_config: SourceRootConfig,
- pub(crate) proc_macro_client: Option<ProcMacroServer>,
+ pub(crate) proc_macro_clients: Vec<Result<ProcMacroServer, String>>,
pub(crate) flycheck: Vec<FlycheckHandle>,
pub(crate) flycheck_sender: Sender<flycheck::Message>,
@@ -151,7 +151,7 @@ impl GlobalState {
proc_macro_changed: false,
last_reported_status: None,
source_root_config: SourceRootConfig::default(),
- proc_macro_client: None,
+ proc_macro_clients: vec![],
flycheck: Vec::new(),
flycheck_sender,
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 520aa7d1dd..deb777c952 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -44,7 +44,7 @@ use crate::{
};
pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> Result<()> {
- state.proc_macro_client = None;
+ state.proc_macro_clients.clear();
state.proc_macro_changed = false;
state.fetch_workspaces_queue.request_op("reload workspace request".to_string());
state.fetch_build_data_queue.request_op("reload workspace request".to_string());
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 77125f88f4..e5802773e7 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -303,18 +303,21 @@ impl GlobalState {
let files_config = self.config.files();
let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
- if self.proc_macro_client.is_none() {
+ if self.proc_macro_clients.is_empty() {
if let Some((path, args)) = self.config.proc_macro_srv() {
- match ProcMacroServer::spawn(path.clone(), args) {
- Ok(it) => self.proc_macro_client = Some(it),
- Err(err) => {
- tracing::error!(
- "Failed to run proc_macro_srv from path {}, error: {:?}",
- path.display(),
- err
- );
- }
- }
+ self.proc_macro_clients = (0..self.workspaces.len())
+ .map(|_| {
+ ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
+ let error = format!(
+ "Failed to run proc_macro_srv from path {}, error: {:?}",
+ path.display(),
+ err
+ );
+ tracing::error!(error);
+ error
+ })
+ })
+ .collect();
}
}
@@ -331,15 +334,7 @@ impl GlobalState {
// Create crate graph from all the workspaces
let crate_graph = {
- let proc_macro_client = self.proc_macro_client.as_ref();
let dummy_replacements = self.config.dummy_replacements();
- let mut load_proc_macro = move |crate_name: &str, path: &AbsPath| {
- load_proc_macro(
- proc_macro_client,
- path,
- dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
- )
- };
let vfs = &mut self.vfs.write().0;
let loader = &mut self.loader;
@@ -359,7 +354,15 @@ impl GlobalState {
};
let mut crate_graph = CrateGraph::default();
- for ws in self.workspaces.iter() {
+ for (idx, ws) in self.workspaces.iter().enumerate() {
+ let proc_macro_client = self.proc_macro_clients[idx].as_ref();
+ let mut load_proc_macro = move |crate_name: &str, path: &AbsPath| {
+ load_proc_macro(
+ proc_macro_client,
+ path,
+ dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
+ )
+ };
crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
}
crate_graph
@@ -536,14 +539,14 @@ impl SourceRootConfig {
/// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace`
/// with an identity dummy expander.
pub(crate) fn load_proc_macro(
- server: Option<&ProcMacroServer>,
+ server: Result<&ProcMacroServer, &String>,
path: &AbsPath,
dummy_replace: &[Box<str>],
) -> ProcMacroLoadResult {
let res: Result<Vec<_>, String> = (|| {
let dylib = MacroDylib::new(path.to_path_buf())
.map_err(|io| format!("Proc-macro dylib loading failed: {io}"))?;
- let server = server.ok_or_else(|| format!("Proc-macro server not started"))?;
+ let server = server.map_err(ToOwned::to_owned)?;
let vec = server.load_dylib(dylib).map_err(|e| format!("{e}"))?;
if vec.is_empty() {
return Err("proc macro library returned no proc macros".to_string());