From 70dd70b1fcbbbe2e60849412412ef05e7d31eb0a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 13 Nov 2019 09:56:33 +0300 Subject: [PATCH 01/25] Reduce duplication between uncertain floats & ints --- crates/ra_hir/src/lib.rs | 4 +-- crates/ra_hir/src/ty.rs | 6 ++--- crates/ra_hir/src/ty/infer.rs | 28 ++++++++------------ crates/ra_hir/src/ty/infer/expr.rs | 30 ++++++++++----------- crates/ra_hir/src/ty/lower.rs | 14 +++++----- crates/ra_hir/src/ty/method_resolution.rs | 11 ++++---- crates/ra_hir/src/ty/primitive.rs | 32 +++++++++-------------- 7 files changed, 55 insertions(+), 70 deletions(-) diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 92d71b9e88f..5ba847d3515 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -77,9 +77,7 @@ pub use crate::{ source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, ty::{ display::HirDisplay, - primitive::{ - FloatBitness, FloatTy, IntBitness, IntTy, Signedness, UncertainFloatTy, UncertainIntTy, - }, + primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }, }; diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 6f24cfad602..ff6030ac426 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -21,7 +21,7 @@ use crate::{ expr::ExprId, generics::{GenericParams, HasGenericParams}, util::make_mut_slice, - Adt, Crate, DefWithBody, Mutability, Name, Trait, TypeAlias, + Adt, Crate, DefWithBody, FloatTy, IntTy, Mutability, Name, Trait, TypeAlias, Uncertain, }; use display::{HirDisplay, HirFormatter}; @@ -47,10 +47,10 @@ pub enum TypeCtor { Char, /// A primitive integer type. For example, `i32`. - Int(primitive::UncertainIntTy), + Int(Uncertain), /// A primitive floating-point type. For example, `f64`. - Float(primitive::UncertainFloatTy), + Float(Uncertain), /// Structures, enumerations and unions. Adt(Adt), diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index f17c6c61433..c092608642d 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -31,10 +31,10 @@ use ra_prof::profile; use test_utils::tested_by; use super::{ - lower, primitive, + lower, traits::{Guidance, Obligation, ProjectionPredicate, Solution}, ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, - TypeCtor, TypeWalk, + TypeCtor, TypeWalk, Uncertain, }; use crate::{ adt::VariantDef, @@ -43,7 +43,7 @@ use crate::{ expr::{BindingAnnotation, Body, ExprId, PatId}, resolve::{Resolver, TypeNs}, ty::infer::diagnostics::InferenceDiagnostic, - Adt, AssocItem, ConstData, DefWithBody, FnData, Function, Path, StructField, + Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, IntTy, Path, StructField, }; macro_rules! ty_app { @@ -358,14 +358,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { match ty { Ty::Unknown => self.new_type_var(), - Ty::Apply(ApplicationTy { - ctor: TypeCtor::Int(primitive::UncertainIntTy::Unknown), - .. - }) => self.new_integer_var(), - Ty::Apply(ApplicationTy { - ctor: TypeCtor::Float(primitive::UncertainFloatTy::Unknown), - .. - }) => self.new_float_var(), + Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(Uncertain::Unknown), .. }) => { + self.new_integer_var() + } + Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(Uncertain::Unknown), .. }) => { + self.new_float_var() + } _ => ty, } } @@ -684,12 +682,8 @@ impl InferTy { fn fallback_value(self) -> Ty { match self { InferTy::TypeVar(..) => Ty::Unknown, - InferTy::IntVar(..) => { - Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Known(primitive::IntTy::i32()))) - } - InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float( - primitive::UncertainFloatTy::Known(primitive::FloatTy::f64()), - )), + InferTy::IntVar(..) => Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::i32()))), + InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(Uncertain::Known(FloatTy::f64()))), InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never), } } diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index c6802487a0c..5e68a1678f4 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs @@ -3,7 +3,10 @@ use std::iter::{repeat, repeat_with}; use std::sync::Arc; -use hir_def::path::{GenericArg, GenericArgs}; +use hir_def::{ + builtin_type::Signedness, + path::{GenericArg, GenericArgs}, +}; use hir_expand::name; use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; @@ -12,8 +15,9 @@ use crate::{ expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, generics::{GenericParams, HasGenericParams}, ty::{ - autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Namespace, + autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, + Uncertain, }, Adt, Name, }; @@ -337,13 +341,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { UnaryOp::Neg => { match &inner_ty { Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::Int(primitive::UncertainIntTy::Unknown) - | TypeCtor::Int(primitive::UncertainIntTy::Known( - primitive::IntTy { - signedness: primitive::Signedness::Signed, - .. - }, - )) + TypeCtor::Int(Uncertain::Unknown) + | TypeCtor::Int(Uncertain::Known(IntTy { + signedness: Signedness::Signed, + .. + })) | TypeCtor::Float(..) => inner_ty, _ => Ty::Unknown, }, @@ -428,9 +430,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ); self.infer_expr( *repeat, - &Expectation::has_type(Ty::simple(TypeCtor::Int( - primitive::UncertainIntTy::Known(primitive::IntTy::usize()), - ))), + &Expectation::has_type(Ty::simple(TypeCtor::Int(Uncertain::Known( + IntTy::usize(), + )))), ); } } @@ -443,9 +445,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str)) } Literal::ByteString(..) => { - let byte_type = Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Known( - primitive::IntTy::u8(), - ))); + let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8()))); let slice_type = Ty::apply_one(TypeCtor::Slice, byte_type); Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type) } diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 1832fcf5042..de3c56097bd 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -25,7 +25,7 @@ use crate::{ generics::{GenericDef, WherePredicate}, resolve::{Resolver, TypeNs}, ty::{ - primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, + primitive::{FloatTy, IntTy, Uncertain}, Adt, }, util::make_mut_slice, @@ -674,20 +674,20 @@ impl From for FloatTy { } } -impl From> for UncertainIntTy { +impl From> for Uncertain { fn from(t: Option) -> Self { match t { - None => UncertainIntTy::Unknown, - Some(t) => UncertainIntTy::Known(t.into()), + None => Uncertain::Unknown, + Some(t) => Uncertain::Known(t.into()), } } } -impl From> for UncertainFloatTy { +impl From> for Uncertain { fn from(t: Option) -> Self { match t { - None => UncertainFloatTy::Unknown, - Some(t) => UncertainFloatTy::Known(t.into()), + None => Uncertain::Unknown, + Some(t) => Uncertain::Known(t.into()), } } } diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 8c3d32d09dc..eb5ca6769a1 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -8,16 +8,17 @@ use arrayvec::ArrayVec; use hir_def::CrateModuleId; use rustc_hash::FxHashMap; -use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; use crate::{ db::HirDatabase, impl_block::{ImplBlock, ImplId}, resolve::Resolver, - ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, + ty::primitive::{FloatBitness, Uncertain}, ty::{Ty, TypeCtor}, AssocItem, Crate, Function, Module, Mutability, Name, Trait, }; +use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; + /// This is used as a key for indexing impls. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TyFingerprint { @@ -140,14 +141,12 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option Some(std::iter::once(def_id.krate(db)?).collect()), TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"), TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"), - TypeCtor::Float(UncertainFloatTy::Known(f)) => match f.bitness { + TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"), FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"), }, - TypeCtor::Int(UncertainIntTy::Known(i)) => { - lang_item_crate!(db, cur_crate, i.ty_to_string()) - } + TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(db, cur_crate, i.ty_to_string()), TypeCtor::Str => lang_item_crate!(db, cur_crate, "str_alloc", "str"), TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!(db, cur_crate, "const_ptr"), diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs index 7362de4c3f7..47789db8775 100644 --- a/crates/ra_hir/src/ty/primitive.rs +++ b/crates/ra_hir/src/ty/primitive.rs @@ -4,44 +4,38 @@ use std::fmt; pub use hir_def::builtin_type::{FloatBitness, IntBitness, Signedness}; -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum UncertainIntTy { +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum Uncertain { Unknown, - Known(IntTy), + Known(T), } -impl From for UncertainIntTy { +impl From for Uncertain { fn from(ty: IntTy) -> Self { - UncertainIntTy::Known(ty) + Uncertain::Known(ty) } } -impl fmt::Display for UncertainIntTy { +impl fmt::Display for Uncertain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - UncertainIntTy::Unknown => write!(f, "{{integer}}"), - UncertainIntTy::Known(ty) => write!(f, "{}", ty), + Uncertain::Unknown => write!(f, "{{integer}}"), + Uncertain::Known(ty) => write!(f, "{}", ty), } } } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum UncertainFloatTy { - Unknown, - Known(FloatTy), -} - -impl From for UncertainFloatTy { +impl From for Uncertain { fn from(ty: FloatTy) -> Self { - UncertainFloatTy::Known(ty) + Uncertain::Known(ty) } } -impl fmt::Display for UncertainFloatTy { +impl fmt::Display for Uncertain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - UncertainFloatTy::Unknown => write!(f, "{{float}}"), - UncertainFloatTy::Known(ty) => write!(f, "{}", ty), + Uncertain::Unknown => write!(f, "{{float}}"), + Uncertain::Known(ty) => write!(f, "{}", ty), } } } From 018255efe3e456aa8d712f68a714d5c6e010d03f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 13 Nov 2019 10:27:21 +0300 Subject: [PATCH 02/25] Minor cleanup --- crates/ra_assists/src/assists/early_return.rs | 39 ++++++++++--------- xtask/src/main.rs | 2 +- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs index 570a07a20c5..f4461000198 100644 --- a/crates/ra_assists/src/assists/early_return.rs +++ b/crates/ra_assists/src/assists/early_return.rs @@ -38,27 +38,27 @@ use crate::{ // ``` pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option { let if_expr: ast::IfExpr = ctx.find_node_at_offset()?; + if if_expr.else_branch().is_some() { + return None; + } + let cond = if_expr.condition()?; - let mut if_let_ident: Option = None; // Check if there is an IfLet that we can handle. - match cond.pat() { - None => {} // No IfLet, supported. - Some(TupleStructPat(ref pat)) if pat.args().count() == 1usize => match &pat.path() { - Some(p) => match p.qualifier() { - None => if_let_ident = Some(p.syntax().text().to_string()), - _ => return None, - }, - _ => return None, - }, - _ => return None, // Unsupported IfLet. + let if_let_ident = match cond.pat() { + None => None, // No IfLet, supported. + Some(TupleStructPat(pat)) if pat.args().count() == 1 => { + let path = pat.path()?; + match path.qualifier() { + None => Some(path.syntax().to_string()), + Some(_) => return None, + } + } + Some(_) => return None, // Unsupported IfLet. }; let expr = cond.expr()?; let then_block = if_expr.then_branch()?.block()?; - if if_expr.else_branch().is_some() { - return None; - } let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::Block::cast)?; @@ -100,7 +100,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt let early_expression = &(early_expression.to_owned() + ";"); let new_expr = if_indent_level.increase_indent(make::if_expression(&expr, early_expression)); - replace(new_expr, &then_block, &parent_block, &if_expr) + replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) } Some(if_let_ident) => { // If-let. @@ -109,7 +109,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt &if_let_ident, early_expression, )); - replace(new_expr, &then_block, &parent_block, &if_expr) + replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) } }; edit.target(if_expr.syntax().text_range()); @@ -117,7 +117,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt edit.set_cursor(cursor_position); fn replace( - new_expr: impl AstNode, + new_expr: &SyntaxNode, then_block: &Block, parent_block: &Block, if_expr: &ast::IfExpr, @@ -130,7 +130,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt } else { end_of_then }; - let mut then_statements = new_expr.syntax().children_with_tokens().chain( + let mut then_statements = new_expr.children_with_tokens().chain( then_block_items .syntax() .children_with_tokens() @@ -151,9 +151,10 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt #[cfg(test)] mod tests { - use super::*; use crate::helpers::{check_assist, check_assist_not_applicable}; + use super::*; + #[test] fn convert_inside_fn() { check_assist( diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 16bddfb281f..c46eaa407ab 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -19,7 +19,7 @@ use xtask::{ }; // Latest stable, feel free to send a PR if this lags behind. -const REQUIRED_RUST_VERSION: u32 = 38; +const REQUIRED_RUST_VERSION: u32 = 39; struct InstallOpt { client: Option, From 2a69d584d6afc842d6dc8503f3fd3a0a691ea385 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 13 Nov 2019 10:54:50 +0300 Subject: [PATCH 03/25] Add a bit of types --- crates/ra_assists/src/assists/early_return.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs index f4461000198..8507a60fb9a 100644 --- a/crates/ra_assists/src/assists/early_return.rs +++ b/crates/ra_assists/src/assists/early_return.rs @@ -45,12 +45,12 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt let cond = if_expr.condition()?; // Check if there is an IfLet that we can handle. - let if_let_ident = match cond.pat() { + let bound_ident = match cond.pat() { None => None, // No IfLet, supported. Some(TupleStructPat(pat)) if pat.args().count() == 1 => { let path = pat.path()?; match path.qualifier() { - None => Some(path.syntax().to_string()), + None => Some(path.segment()?.name_ref()?), Some(_) => return None, } } @@ -94,7 +94,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt ctx.add_assist(AssistId("convert_to_guarded_return"), "convert to guarded return", |edit| { let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); - let new_block = match if_let_ident { + let new_block = match bound_ident { None => { // If. let early_expression = &(early_expression.to_owned() + ";"); @@ -102,11 +102,11 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt if_indent_level.increase_indent(make::if_expression(&expr, early_expression)); replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) } - Some(if_let_ident) => { + Some(bound_ident) => { // If-let. let new_expr = if_indent_level.increase_indent(make::let_match_early( expr, - &if_let_ident, + &bound_ident.syntax().to_string(), early_expression, )); replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) From e177c65e36f432821087b215b83c2dad1c97f478 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 13 Nov 2019 11:40:51 +0300 Subject: [PATCH 04/25] Use strongly-typed ast building for early-return assist --- crates/ra_assists/src/assists/early_return.rs | 95 ++++++++++++++----- crates/ra_syntax/src/ast/make.rs | 52 ++++++---- 2 files changed, 102 insertions(+), 45 deletions(-) diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs index 8507a60fb9a..26441252662 100644 --- a/crates/ra_assists/src/assists/early_return.rs +++ b/crates/ra_assists/src/assists/early_return.rs @@ -1,4 +1,4 @@ -use std::ops::RangeInclusive; +use std::{iter::once, ops::RangeInclusive}; use hir::db::HirDatabase; use ra_syntax::{ @@ -45,19 +45,22 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt let cond = if_expr.condition()?; // Check if there is an IfLet that we can handle. - let bound_ident = match cond.pat() { + let if_let_pat = match cond.pat() { None => None, // No IfLet, supported. Some(TupleStructPat(pat)) if pat.args().count() == 1 => { let path = pat.path()?; match path.qualifier() { - None => Some(path.segment()?.name_ref()?), + None => { + let bound_ident = pat.args().next().unwrap(); + Some((path, bound_ident)) + } Some(_) => return None, } } Some(_) => return None, // Unsupported IfLet. }; - let expr = cond.expr()?; + let cond_expr = cond.expr()?; let then_block = if_expr.then_branch()?.block()?; let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::Block::cast)?; @@ -79,11 +82,11 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt let parent_container = parent_block.syntax().parent()?.parent()?; - let early_expression = match parent_container.kind() { - WHILE_EXPR | LOOP_EXPR => Some("continue"), - FN_DEF => Some("return"), - _ => None, - }?; + let early_expression: ast::Expr = match parent_container.kind() { + WHILE_EXPR | LOOP_EXPR => make::expr_continue().into(), + FN_DEF => make::expr_return().into(), + _ => return None, + }; if then_block.syntax().first_child_or_token().map(|t| t.kind() == L_CURLY).is_none() { return None; @@ -94,22 +97,43 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt ctx.add_assist(AssistId("convert_to_guarded_return"), "convert to guarded return", |edit| { let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); - let new_block = match bound_ident { + let new_block = match if_let_pat { None => { // If. - let early_expression = &(early_expression.to_owned() + ";"); - let new_expr = - if_indent_level.increase_indent(make::if_expression(&expr, early_expression)); + let early_expression = &(early_expression.syntax().to_string() + ";"); + let new_expr = if_indent_level + .increase_indent(make::if_expression(&cond_expr, early_expression)); replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) } - Some(bound_ident) => { + Some((path, bound_ident)) => { // If-let. - let new_expr = if_indent_level.increase_indent(make::let_match_early( - expr, - &bound_ident.syntax().to_string(), - early_expression, - )); - replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) + let match_expr = { + let happy_arm = make::match_arm( + once( + make::tuple_struct_pat( + path, + once(make::bind_pat(make::name("it")).into()), + ) + .into(), + ), + make::expr_path(make::path_from_name_ref(make::name_ref("it"))).into(), + ); + + let sad_arm = make::match_arm( + // FIXME: would be cool to use `None` or `Err(_)` if appropriate + once(make::placeholder_pat().into()), + early_expression.into(), + ); + + make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) + }; + + let let_stmt = make::let_stmt( + make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), + Some(match_expr.into()), + ); + let let_stmt = if_indent_level.increase_indent(let_stmt); + replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) } }; edit.target(if_expr.syntax().text_range()); @@ -205,7 +229,7 @@ mod tests { bar(); le<|>t n = match n { Some(it) => it, - None => return, + _ => return, }; foo(n); @@ -216,6 +240,29 @@ mod tests { ); } + #[test] + fn convert_if_let_result() { + check_assist( + convert_to_guarded_return, + r#" + fn main() { + if<|> let Ok(x) = Err(92) { + foo(x); + } + } + "#, + r#" + fn main() { + le<|>t x = match Err(92) { + Ok(it) => it, + _ => return, + }; + foo(x); + } + "#, + ); + } + #[test] fn convert_let_ok_inside_fn() { check_assist( @@ -236,7 +283,7 @@ mod tests { bar(); le<|>t n = match n { Ok(it) => it, - None => return, + _ => return, }; foo(n); @@ -294,7 +341,7 @@ mod tests { while true { le<|>t n = match n { Some(it) => it, - None => continue, + _ => continue, }; foo(n); bar(); @@ -351,7 +398,7 @@ mod tests { loop { le<|>t n = match n { Some(it) => it, - None => continue, + _ => continue, }; foo(n); bar(); diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 95062ef6c46..6c903ca641f 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs @@ -4,6 +4,10 @@ use itertools::Itertools; use crate::{ast, AstNode, SourceFile}; +pub fn name(text: &str) -> ast::Name { + ast_from_text(&format!("mod {};", text)) +} + pub fn name_ref(text: &str) -> ast::NameRef { ast_from_text(&format!("fn f() {{ {}; }}", text)) } @@ -43,6 +47,21 @@ pub fn expr_unit() -> ast::Expr { pub fn expr_unimplemented() -> ast::Expr { expr_from_text("unimplemented!()") } +pub fn expr_path(path: ast::Path) -> ast::Expr { + expr_from_text(&path.syntax().to_string()) +} +pub fn expr_continue() -> ast::Expr { + expr_from_text("continue") +} +pub fn expr_break() -> ast::Expr { + expr_from_text("break") +} +pub fn expr_return() -> ast::Expr { + expr_from_text("return") +} +pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr { + expr_from_text(&format!("match {} {}", expr.syntax(), match_arm_list.syntax())) +} fn expr_from_text(text: &str) -> ast::Expr { ast_from_text(&format!("const C: () = {};", text)) } @@ -92,8 +111,8 @@ pub fn path_pat(path: ast::Path) -> ast::PathPat { } } -pub fn match_arm(pats: impl Iterator, expr: ast::Expr) -> ast::MatchArm { - let pats_str = pats.map(|p| p.syntax().to_string()).join(" | "); +pub fn match_arm(pats: impl IntoIterator, expr: ast::Expr) -> ast::MatchArm { + let pats_str = pats.into_iter().map(|p| p.syntax().to_string()).join(" | "); return from_text(&format!("{} => {}", pats_str, expr.syntax())); fn from_text(text: &str) -> ast::MatchArm { @@ -101,8 +120,8 @@ pub fn match_arm(pats: impl Iterator, expr: ast::Expr) -> ast:: } } -pub fn match_arm_list(arms: impl Iterator) -> ast::MatchArmList { - let arms_str = arms.map(|arm| format!("\n {}", arm.syntax())).join(","); +pub fn match_arm_list(arms: impl IntoIterator) -> ast::MatchArmList { + let arms_str = arms.into_iter().map(|arm| format!("\n {}", arm.syntax())).join(","); return from_text(&format!("{},\n", arms_str)); fn from_text(text: &str) -> ast::MatchArmList { @@ -110,23 +129,6 @@ pub fn match_arm_list(arms: impl Iterator) -> ast::MatchAr } } -pub fn let_match_early(expr: ast::Expr, path: &str, early_expression: &str) -> ast::LetStmt { - return from_text(&format!( - r#"let {} = match {} {{ - {}(it) => it, - None => {}, -}};"#, - expr.syntax().text(), - expr.syntax().text(), - path, - early_expression - )); - - fn from_text(text: &str) -> ast::LetStmt { - ast_from_text(&format!("fn f() {{ {} }}", text)) - } -} - pub fn where_pred(path: ast::Path, bounds: impl Iterator) -> ast::WherePred { let bounds = bounds.map(|b| b.syntax().to_string()).join(" + "); return from_text(&format!("{}: {}", path.syntax(), bounds)); @@ -153,6 +155,14 @@ pub fn if_expression(condition: &ast::Expr, statement: &str) -> ast::IfExpr { )) } +pub fn let_stmt(pattern: ast::Pat, initializer: Option) -> ast::LetStmt { + let text = match initializer { + Some(it) => format!("let {} = {};", pattern.syntax(), it.syntax()), + None => format!("let {};", pattern.syntax()), + }; + ast_from_text(&format!("fn f() {{ {} }}", text)) +} + fn ast_from_text(text: &str) -> N { let parse = SourceFile::parse(text); let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); From 4cea6bb6f11e28a2d1d2e023d46caa82b0f38796 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 13 Nov 2019 11:55:43 +0300 Subject: [PATCH 05/25] Make make:: builders slightly more convenient --- crates/ra_syntax/src/ast/edit.rs | 2 +- crates/ra_syntax/src/ast/make.rs | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 47bdbb81a1a..6f005a2d88c 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs @@ -358,7 +358,7 @@ fn replace_children( fn test_increase_indent() { let arm_list = { let arm = make::match_arm(iter::once(make::placeholder_pat().into()), make::expr_unit()); - make::match_arm_list(vec![arm.clone(), arm].into_iter()) + make::match_arm_list(vec![arm.clone(), arm]) }; assert_eq!( arm_list.syntax().to_string(), diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 6c903ca641f..9749327fa45 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs @@ -84,9 +84,9 @@ pub fn placeholder_pat() -> ast::PlaceholderPat { pub fn tuple_struct_pat( path: ast::Path, - pats: impl Iterator, + pats: impl IntoIterator, ) -> ast::TupleStructPat { - let pats_str = pats.map(|p| p.syntax().to_string()).join(", "); + let pats_str = pats.into_iter().map(|p| p.syntax().to_string()).join(", "); return from_text(&format!("{}({})", path.syntax(), pats_str)); fn from_text(text: &str) -> ast::TupleStructPat { @@ -94,8 +94,8 @@ pub fn tuple_struct_pat( } } -pub fn record_pat(path: ast::Path, pats: impl Iterator) -> ast::RecordPat { - let pats_str = pats.map(|p| p.syntax().to_string()).join(", "); +pub fn record_pat(path: ast::Path, pats: impl IntoIterator) -> ast::RecordPat { + let pats_str = pats.into_iter().map(|p| p.syntax().to_string()).join(", "); return from_text(&format!("{} {{ {} }}", path.syntax(), pats_str)); fn from_text(text: &str) -> ast::RecordPat { @@ -129,8 +129,11 @@ pub fn match_arm_list(arms: impl IntoIterator) -> ast::Mat } } -pub fn where_pred(path: ast::Path, bounds: impl Iterator) -> ast::WherePred { - let bounds = bounds.map(|b| b.syntax().to_string()).join(" + "); +pub fn where_pred( + path: ast::Path, + bounds: impl IntoIterator, +) -> ast::WherePred { + let bounds = bounds.into_iter().map(|b| b.syntax().to_string()).join(" + "); return from_text(&format!("{}: {}", path.syntax(), bounds)); fn from_text(text: &str) -> ast::WherePred { @@ -138,8 +141,8 @@ pub fn where_pred(path: ast::Path, bounds: impl Iterator) } } -pub fn where_clause(preds: impl Iterator) -> ast::WhereClause { - let preds = preds.map(|p| p.syntax().to_string()).join(", "); +pub fn where_clause(preds: impl IntoIterator) -> ast::WhereClause { + let preds = preds.into_iter().map(|p| p.syntax().to_string()).join(", "); return from_text(preds.as_str()); fn from_text(text: &str) -> ast::WhereClause { From 1e40b395edea2f6998d36d2d66d791a9109db2a8 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Wed, 13 Nov 2019 08:25:37 -0500 Subject: [PATCH 06/25] Update Crates --- Cargo.lock | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37ff1ce7631..3fa6e931ccf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -122,7 +122,7 @@ source = "git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b95 dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -187,7 +187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -310,7 +310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -348,7 +348,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "filetime" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -465,7 +465,7 @@ name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-segmentation 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -748,7 +748,7 @@ version = "4.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -766,12 +766,12 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -779,7 +779,7 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -842,7 +842,7 @@ dependencies = [ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -876,7 +876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -896,7 +896,7 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1091,7 +1091,7 @@ dependencies = [ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1383,7 +1383,7 @@ dependencies = [ "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1506,7 +1506,7 @@ dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1551,7 +1551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1571,7 +1571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1625,7 +1625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1681,7 +1681,7 @@ name = "threadpool" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1696,10 +1696,10 @@ dependencies = [ [[package]] name = "unicase" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1720,7 +1720,7 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1755,7 +1755,7 @@ dependencies = [ [[package]] name = "version_check" -version = "0.1.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1886,7 +1886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" +"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flexi_logger 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a13ea6b8a4debecf47bf3966d56db0e21366bc3a3649ba159e1a9e6fdd36a4f4" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" @@ -1937,8 +1937,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155394f924cdddf08149da25bfb932d226b4a593ca7468b08191ff6335941af5" +"checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6" +"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum number_prefix 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a" "checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" @@ -2003,22 +2003,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" "checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" -"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" +"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" "checksum text_unit 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e08bbcb7a3adbda0eb23431206b653bdad3d8dea311e72d36bf2215e27a42579" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" +"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf" -"checksum unicode-segmentation 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49f5526225fd8b77342d5986ab5f6055552e9c0776193b5b63fd53b46debfad7" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" "checksum uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" From 06754b78ac462d7b9fe8bd176ff7831772c0b1c8 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Wed, 13 Nov 2019 11:19:07 -0500 Subject: [PATCH 07/25] Use autocfg to determine rust version --- Cargo.lock | 1 + xtask/Cargo.toml | 1 + xtask/src/main.rs | 35 ++++++++++------------------------- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3fa6e931ccf..97452951cfc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1823,6 +1823,7 @@ dependencies = [ name = "xtask" version = "0.1.0" dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 023f6a859fd..72b39c3b48f 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -6,6 +6,7 @@ authors = ["rust-analyzer developers"] publish = false [dependencies] +autocfg = "0.1" walkdir = "2.1.3" pico-args = "0.3.0" quote = "1.0.2" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index c46eaa407ab..576ba003a7b 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -9,17 +9,18 @@ //! `.cargo/config`. mod help; +use autocfg; use core::fmt::Write; use core::str; use pico_args::Arguments; use std::{env, path::PathBuf}; use xtask::{ codegen::{self, Mode}, - install_format_hook, run, run_clippy, run_fuzzer, run_rustfmt, run_with_output, Cmd, Result, + install_format_hook, run, run_clippy, run_fuzzer, run_rustfmt, Cmd, Result, }; // Latest stable, feel free to send a PR if this lags behind. -const REQUIRED_RUST_VERSION: u32 = 39; +const REQUIRED_RUST_VERSION: (usize, usize) = (1, 39); struct InstallOpt { client: Option, @@ -226,20 +227,14 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { } fn install_server(opts: ServerOpt) -> Result<()> { - let mut old_rust = false; - if let Ok(output) = run_with_output("cargo --version", ".") { - if let Ok(stdout) = String::from_utf8(output.stdout) { - println!("{}", stdout); - if !check_version(&stdout, REQUIRED_RUST_VERSION) { - old_rust = true; - } - } - } + let ac = autocfg::AutoCfg::with_dir("target")?; + + let old_rust = !ac.probe_rustc_version(REQUIRED_RUST_VERSION.0, REQUIRED_RUST_VERSION.1); if old_rust { eprintln!( - "\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n", - REQUIRED_RUST_VERSION + "\nWARNING: at least rust {}.{}.0 is required to compile rust-analyzer\n", + REQUIRED_RUST_VERSION.0, REQUIRED_RUST_VERSION.1 ) } @@ -251,20 +246,10 @@ fn install_server(opts: ServerOpt) -> Result<()> { if res.is_err() && old_rust { eprintln!( - "\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n", - REQUIRED_RUST_VERSION + "\nWARNING: at least rust {}.{}.0 is required to compile rust-analyzer\n", + REQUIRED_RUST_VERSION.0, REQUIRED_RUST_VERSION.1 ) } res } - -fn check_version(version_output: &str, min_minor_version: u32) -> bool { - // Parse second the number out of - // cargo 1.39.0-beta (1c6ec66d5 2019-09-30) - let minor: Option = version_output.split('.').nth(1).and_then(|it| it.parse().ok()); - match minor { - None => true, - Some(minor) => minor >= min_minor_version, - } -} From 5e3c1c2b5f63e57f98a7d02f75a559d225341b1c Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Wed, 13 Nov 2019 20:44:39 +0100 Subject: [PATCH 08/25] Allow usage of CARGO_TARGET_DIR env var --- xtask/src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 576ba003a7b..84842b4283d 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -227,7 +227,8 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { } fn install_server(opts: ServerOpt) -> Result<()> { - let ac = autocfg::AutoCfg::with_dir("target")?; + let target_dir = env::var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into()); + let ac = autocfg::AutoCfg::with_dir(target_dir)?; let old_rust = !ac.probe_rustc_version(REQUIRED_RUST_VERSION.0, REQUIRED_RUST_VERSION.1); From 5075c77957e127be51e1b5271567f906abeb50c6 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Wed, 13 Nov 2019 20:51:57 +0100 Subject: [PATCH 09/25] Use anyhow::Result in xtask, add contexts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This builds on #2231 but was actually done before that. You see, the cause for #2231 was that I got this error message: Error: Error { kind: Io(Os { code: 2, kind: NotFound, message: "No such file or directory" }) } Just switching to `anyhow::Result` got me stack traces (when setting `RUST_LIB_BACKTRACE=1`) that at least showed stack backtrace: 0: std::backtrace::Backtrace::create 1: std::backtrace::Backtrace::capture 2: anyhow::error:: for anyhow::Error>::from 3: xtask::install_server 4: xtask::install 5: xtask::main 6: std::rt::lang_start::{{closure}} 7: std::panicking::try::do_call 8: __rust_maybe_catch_panic 9: std::rt::lang_start_internal 10: std::rt::lang_start 11: main With the added contexts (not at all exhaustive), the error became Error: install server Caused by: 0: build AutoCfg with target directory 1: No such file or directory (os error 2) Since anyhow is such a small thing (no new transitive dependencies!), and in general gives you `Result>` on steroids, I think this a nice small change. The only slightly annoying thing was to replace all the `Err(format!(…))?` calls (haven't even looked at whether we can make it support wrapping strings though), but the `bail!` macro is shorter anyway :) --- Cargo.lock | 7 +++++++ xtask/Cargo.toml | 1 + xtask/src/bin/pre-commit.rs | 4 ++-- xtask/src/codegen.rs | 8 +++----- xtask/src/codegen/gen_parser_tests.rs | 4 ++-- xtask/src/lib.rs | 16 +++++++--------- xtask/src/main.rs | 25 ++++++++++++++----------- 7 files changed, 36 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97452951cfc..c9ab3ef1081 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,11 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "anyhow" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.5.1" @@ -1823,6 +1828,7 @@ dependencies = [ name = "xtask" version = "0.1.0" dependencies = [ + "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1847,6 +1853,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "57114fc2a6cc374bce195d3482057c846e706d252ff3604363449695684d7a0d" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 72b39c3b48f..bba4be19278 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -13,3 +13,4 @@ quote = "1.0.2" proc-macro2 = "1.0.1" ron = "0.5.1" serde = { version = "1.0.0", features = ["derive"] } +anyhow = "1.0.19" diff --git a/xtask/src/bin/pre-commit.rs b/xtask/src/bin/pre-commit.rs index cc6ccb25eea..44507fb7487 100644 --- a/xtask/src/bin/pre-commit.rs +++ b/xtask/src/bin/pre-commit.rs @@ -19,10 +19,10 @@ fn update_staged() -> Result<()> { .current_dir(&root) .output()?; if !output.status.success() { - Err(format!( + anyhow::bail!( "`git diff --diff-filter=MAR --name-only --cached` exited with {}", output.status - ))?; + ); } for line in String::from_utf8(output.stdout)?.lines() { run(&format!("git update-index --add {}", root.join(line).to_string_lossy()), ".")?; diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 770b55a9ac8..53f524f42df 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -52,7 +52,7 @@ fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> { _ => (), } if mode == Mode::Verify { - Err(format!("`{}` is not up-to-date", path.display()))?; + anyhow::bail!("`{}` is not up-to-date", path.display()); } eprintln!("updating {}", path.display()); fs::write(path, contents)?; @@ -101,10 +101,8 @@ fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lins: bool) -> let is_comment = line.starts_with(prefix); if is_comment { block.push(line[prefix.len()..].to_string()); - } else { - if !block.is_empty() { - res.push(mem::replace(&mut block, Vec::new())) - } + } else if !block.is_empty() { + res.push(mem::replace(&mut block, Vec::new())); } } if !block.is_empty() { diff --git a/xtask/src/codegen/gen_parser_tests.rs b/xtask/src/codegen/gen_parser_tests.rs index d0f0f683b81..2977da2fae2 100644 --- a/xtask/src/codegen/gen_parser_tests.rs +++ b/xtask/src/codegen/gen_parser_tests.rs @@ -102,10 +102,10 @@ fn tests_from_dir(dir: &Path) -> Result { for test in collect_tests(&text) { if test.ok { if let Some(old_test) = res.ok.insert(test.name.clone(), test) { - return Err(format!("Duplicate test: {}", old_test.name).into()); + anyhow::bail!("Duplicate test: {}", old_test.name); } } else if let Some(old_test) = res.err.insert(test.name.clone(), test) { - return Err(format!("Duplicate test: {}", old_test.name).into()); + anyhow::bail!("Duplicate test: {}", old_test.name); } } Ok(()) diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index bae4c4650c0..bfee2f9c8e7 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -2,10 +2,10 @@ pub mod codegen; +use anyhow::Context; +pub use anyhow::Result; use std::{ - env, - error::Error, - fs, + env, fs, io::{Error as IoError, ErrorKind}, path::{Path, PathBuf}, process::{Command, Output, Stdio}, @@ -13,8 +13,6 @@ use std::{ use crate::codegen::Mode; -pub type Result = std::result::Result>; - const TOOLCHAIN: &str = "stable"; pub fn project_root() -> PathBuf { @@ -69,7 +67,7 @@ pub fn run_rustfmt(mode: Mode) -> Result<()> { .status() { Ok(status) if status.success() => (), - _ => install_rustfmt()?, + _ => install_rustfmt().context("install rustfmt")?, }; if mode == Mode::Verify { @@ -112,7 +110,7 @@ pub fn run_clippy() -> Result<()> { .status() { Ok(status) if status.success() => (), - _ => install_clippy()?, + _ => install_clippy().context("install clippy")?, }; let allowed_lints = [ @@ -162,9 +160,9 @@ where let exec = args.next().unwrap(); let mut cmd = Command::new(exec); f(cmd.args(args).current_dir(proj_dir).stderr(Stdio::inherit())); - let output = cmd.output()?; + let output = cmd.output().with_context(|| format!("running `{}`", cmdline))?; if !output.status.success() { - Err(format!("`{}` exited with {}", cmdline, output.status))?; + anyhow::bail!("`{}` exited with {}", cmdline, output.status); } Ok(output) } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 84842b4283d..7eab1c949db 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -9,6 +9,7 @@ //! `.cargo/config`. mod help; +use anyhow::Context; use autocfg; use core::fmt::Write; use core::str; @@ -114,21 +115,21 @@ fn handle_extra_flags(e: pico_args::Error) -> Result<()> { write!(&mut invalid_flags, "{}, ", flag)?; } let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2); - Err(format!("Invalid flags: {}", invalid_flags).into()) + anyhow::bail!("Invalid flags: {}", invalid_flags) } else { - Err(e.to_string().into()) + anyhow::bail!(e.to_string()) } } fn install(opts: InstallOpt) -> Result<()> { if cfg!(target_os = "macos") { - fix_path_for_mac()? + fix_path_for_mac().context("Fix path for mac")? } if let Some(server) = opts.server { - install_server(server)?; + install_server(server).context("install server")?; } if let Some(client) = opts.client { - install_client(client)?; + install_client(client).context("install client")?; } Ok(()) } @@ -140,7 +141,7 @@ fn fix_path_for_mac() -> Result<()> { const ROOT_DIR: &str = ""; let home_dir = match env::var("HOME") { Ok(home) => home, - Err(e) => Err(format!("Failed getting HOME from environment with error: {}.", e))?, + Err(e) => anyhow::bail!("Failed getting HOME from environment with error: {}.", e), }; [ROOT_DIR, &home_dir] @@ -154,12 +155,12 @@ fn fix_path_for_mac() -> Result<()> { if !vscode_path.is_empty() { let vars = match env::var_os("PATH") { Some(path) => path, - None => Err("Could not get PATH variable from env.")?, + None => anyhow::bail!("Could not get PATH variable from env."), }; let mut paths = env::split_paths(&vars).collect::>(); paths.append(&mut vscode_path); - let new_paths = env::join_paths(paths)?; + let new_paths = env::join_paths(paths).context("build env PATH")?; env::set_var("PATH", &new_paths); } @@ -198,7 +199,7 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { let code_binary = match code_binary { Some(it) => it, - None => Err("Can't execute `code --version`. Perhaps it is not in $PATH?")?, + None => anyhow::bail!("Can't execute `code --version`. Perhaps it is not in $PATH?"), }; Cmd { @@ -219,8 +220,10 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { .run_with_output()?; if !str::from_utf8(&output.stdout)?.contains("ra-lsp") { - Err("Could not install the Visual Studio Code extension. \ - Please make sure you have at least NodeJS 10.x installed and try again.")?; + anyhow::bail!( + "Could not install the Visual Studio Code extension. \ + Please make sure you have at least NodeJS 10.x installed and try again." + ); } Ok(()) From b8f62095d6cf07ba521cdb3f7bac147496b313c9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 09:09:42 +0300 Subject: [PATCH 10/25] Normalize data No need to store derivable info --- crates/ra_hir/src/expr/scope.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 0e49a28d6c3..fe5e836f219 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -17,7 +17,6 @@ impl_arena_id!(ScopeId); #[derive(Debug, PartialEq, Eq)] pub struct ExprScopes { - pub(crate) body: Arc, scopes: Arena, scope_by_expr: FxHashMap, } @@ -47,19 +46,16 @@ pub(crate) struct ScopeData { impl ExprScopes { pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { let body = db.body(def); - let res = ExprScopes::new(body); + let res = ExprScopes::new(&*body); Arc::new(res) } - fn new(body: Arc) -> ExprScopes { - let mut scopes = ExprScopes { - body: body.clone(), - scopes: Arena::default(), - scope_by_expr: FxHashMap::default(), - }; + fn new(body: &Body) -> ExprScopes { + let mut scopes = + ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; let root = scopes.root_scope(); - scopes.add_params_bindings(root, body.params()); - compute_expr_scopes(body.body_expr(), &body, &mut scopes, root); + scopes.add_params_bindings(body, root, body.params()); + compute_expr_scopes(body.body_expr(), body, &mut scopes, root); scopes } @@ -99,9 +95,8 @@ impl ExprScopes { } } - fn add_params_bindings(&mut self, scope: ScopeId, params: &[PatId]) { - let body = Arc::clone(&self.body); - params.iter().for_each(|pat| self.add_bindings(&body, scope, *pat)); + fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) { + params.iter().for_each(|pat| self.add_bindings(body, scope, *pat)); } fn set_scope(&mut self, node: ExprId, scope: ScopeId) { @@ -151,7 +146,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope } Expr::Lambda { args, body: body_expr, .. } => { let scope = scopes.new_scope(scope); - scopes.add_params_bindings(scope, &args); + scopes.add_params_bindings(body, scope, &args); compute_expr_scopes(*body_expr, body, scopes, scope); } Expr::Match { expr, arms } => { From debf95eb1b79a54ed482ea01f1716e5ff1faf0b6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 09:24:39 +0300 Subject: [PATCH 11/25] Reduce visibility --- crates/ra_hir_def/src/body.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index ac8f8261b8f..269501221d8 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -26,11 +26,7 @@ impl MacroResolver { MacroResolver { crate_def_map: db.crate_def_map(module.krate), module } } - pub(crate) fn resolve_path_as_macro( - &self, - db: &impl DefDatabase2, - path: &Path, - ) -> Option { + fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option { self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros() } } From b3175b7077129ca4b6c52e05f0491e65617ae423 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 09:37:33 +0300 Subject: [PATCH 12/25] Move current file to MacroResolver --- crates/ra_hir/src/expr.rs | 4 ++-- crates/ra_hir_def/src/body.rs | 13 ++++++++---- crates/ra_hir_def/src/body/lower.rs | 31 +++++++++++++++-------------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 82955fa5586..d1af8ee3990 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -40,8 +40,8 @@ pub(crate) fn body_with_source_map_query( (src.file_id, src.ast.body()) } }; - let resolver = hir_def::body::MacroResolver::new(db, def.module(db).id); - let (body, source_map) = Body::new(db, resolver, file_id, params, body); + let resolver = hir_def::body::MacroResolver::new(db, file_id, def.module(db).id); + let (body, source_map) = Body::new(db, resolver, params, body); (Arc::new(body), Arc::new(source_map)) } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 269501221d8..7e84e91135d 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -18,12 +18,18 @@ use crate::{ pub struct MacroResolver { crate_def_map: Arc, + current_file_id: HirFileId, module: ModuleId, } impl MacroResolver { - pub fn new(db: &impl DefDatabase2, module: ModuleId) -> MacroResolver { - MacroResolver { crate_def_map: db.crate_def_map(module.krate), module } + pub fn new( + db: &impl DefDatabase2, + current_file_id: HirFileId, + module: ModuleId, + ) -> MacroResolver { + let crate_def_map = db.crate_def_map(module.krate); + MacroResolver { crate_def_map, current_file_id, module } } fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option { @@ -77,11 +83,10 @@ impl Body { pub fn new( db: &impl DefDatabase2, resolver: MacroResolver, - file_id: HirFileId, params: Option, body: Option, ) -> (Body, BodySourceMap) { - lower::lower(db, resolver, file_id, params, body) + lower::lower(db, resolver, params, body) } pub fn params(&self) -> &[PatId] { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 2aa863c9ecd..1a990101ff3 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -31,15 +31,15 @@ use crate::{ pub(super) fn lower( db: &impl DefDatabase2, resolver: MacroResolver, - file_id: HirFileId, params: Option, body: Option, ) -> (Body, BodySourceMap) { + let original_file_id = resolver.current_file_id; + ExprCollector { resolver, db, - original_file_id: file_id, - current_file_id: file_id, + original_file_id, source_map: BodySourceMap::default(), body: Body { exprs: Arena::default(), @@ -55,7 +55,6 @@ struct ExprCollector { db: DB, resolver: MacroResolver, original_file_id: HirFileId, - current_file_id: HirFileId, body: Body, source_map: BodySourceMap, @@ -101,12 +100,12 @@ where fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { let ptr = Either::A(ptr); let id = self.body.exprs.alloc(expr); - if self.current_file_id == self.original_file_id { + if self.resolver.current_file_id == self.original_file_id { self.source_map.expr_map.insert(ptr, id); } self.source_map .expr_map_back - .insert(id, Source { file_id: self.current_file_id, ast: ptr }); + .insert(id, Source { file_id: self.resolver.current_file_id, ast: ptr }); id } // desugared exprs don't have ptr, that's wrong and should be fixed @@ -117,20 +116,22 @@ where fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { let ptr = Either::B(ptr); let id = self.body.exprs.alloc(expr); - if self.current_file_id == self.original_file_id { + if self.resolver.current_file_id == self.original_file_id { self.source_map.expr_map.insert(ptr, id); } self.source_map .expr_map_back - .insert(id, Source { file_id: self.current_file_id, ast: ptr }); + .insert(id, Source { file_id: self.resolver.current_file_id, ast: ptr }); id } fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { let id = self.body.pats.alloc(pat); - if self.current_file_id == self.original_file_id { + if self.resolver.current_file_id == self.original_file_id { self.source_map.pat_map.insert(ptr, id); } - self.source_map.pat_map_back.insert(id, Source { file_id: self.current_file_id, ast: ptr }); + self.source_map + .pat_map_back + .insert(id, Source { file_id: self.resolver.current_file_id, ast: ptr }); id } @@ -445,8 +446,8 @@ where ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), ast::Expr::MacroCall(e) => { let ast_id = AstId::new( - self.current_file_id, - self.db.ast_id_map(self.current_file_id).ast_id(&e), + self.resolver.current_file_id, + self.db.ast_id_map(self.resolver.current_file_id).ast_id(&e), ); if let Some(path) = e.path().and_then(|path| self.parse_path(path)) { @@ -457,9 +458,9 @@ where if let Some(expr) = ast::Expr::cast(node) { log::debug!("macro expansion {:#?}", expr.syntax()); let old_file_id = - std::mem::replace(&mut self.current_file_id, file_id); + std::mem::replace(&mut self.resolver.current_file_id, file_id); let id = self.collect_expr(expr); - self.current_file_id = old_file_id; + self.resolver.current_file_id = old_file_id; return id; } } @@ -581,7 +582,7 @@ where } fn parse_path(&mut self, path: ast::Path) -> Option { - let hygiene = Hygiene::new(self.db, self.current_file_id); + let hygiene = Hygiene::new(self.db, self.resolver.current_file_id); Path::from_src(path, &hygiene) } } From 8c8ef1432e1891809f48ff691f949047d6527c07 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 09:38:25 +0300 Subject: [PATCH 13/25] Rename MacroResolver -> Expander --- crates/ra_hir/src/expr.rs | 4 ++-- crates/ra_hir_def/src/body.rs | 16 +++++--------- crates/ra_hir_def/src/body/lower.rs | 34 ++++++++++++++--------------- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index d1af8ee3990..d19f5d14cea 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -40,8 +40,8 @@ pub(crate) fn body_with_source_map_query( (src.file_id, src.ast.body()) } }; - let resolver = hir_def::body::MacroResolver::new(db, file_id, def.module(db).id); - let (body, source_map) = Body::new(db, resolver, params, body); + let expander = hir_def::body::Expander::new(db, file_id, def.module(db).id); + let (body, source_map) = Body::new(db, expander, params, body); (Arc::new(body), Arc::new(source_map)) } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 7e84e91135d..5d8c299ba5f 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -16,20 +16,16 @@ use crate::{ ModuleId, }; -pub struct MacroResolver { +pub struct Expander { crate_def_map: Arc, current_file_id: HirFileId, module: ModuleId, } -impl MacroResolver { - pub fn new( - db: &impl DefDatabase2, - current_file_id: HirFileId, - module: ModuleId, - ) -> MacroResolver { +impl Expander { + pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander { let crate_def_map = db.crate_def_map(module.krate); - MacroResolver { crate_def_map, current_file_id, module } + Expander { crate_def_map, current_file_id, module } } fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option { @@ -82,11 +78,11 @@ pub struct BodySourceMap { impl Body { pub fn new( db: &impl DefDatabase2, - resolver: MacroResolver, + expander: Expander, params: Option, body: Option, ) -> (Body, BodySourceMap) { - lower::lower(db, resolver, params, body) + lower::lower(db, expander, params, body) } pub fn params(&self) -> &[PatId] { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 1a990101ff3..cc4bbe11acc 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -16,7 +16,7 @@ use ra_syntax::{ }; use crate::{ - body::{Body, BodySourceMap, MacroResolver, PatPtr}, + body::{Body, BodySourceMap, Expander, PatPtr}, builtin_type::{BuiltinFloat, BuiltinInt}, db::DefDatabase2, expr::{ @@ -30,14 +30,14 @@ use crate::{ pub(super) fn lower( db: &impl DefDatabase2, - resolver: MacroResolver, + expander: Expander, params: Option, body: Option, ) -> (Body, BodySourceMap) { - let original_file_id = resolver.current_file_id; + let original_file_id = expander.current_file_id; ExprCollector { - resolver, + expander, db, original_file_id, source_map: BodySourceMap::default(), @@ -53,7 +53,7 @@ pub(super) fn lower( struct ExprCollector { db: DB, - resolver: MacroResolver, + expander: Expander, original_file_id: HirFileId, body: Body, @@ -100,12 +100,12 @@ where fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { let ptr = Either::A(ptr); let id = self.body.exprs.alloc(expr); - if self.resolver.current_file_id == self.original_file_id { + if self.expander.current_file_id == self.original_file_id { self.source_map.expr_map.insert(ptr, id); } self.source_map .expr_map_back - .insert(id, Source { file_id: self.resolver.current_file_id, ast: ptr }); + .insert(id, Source { file_id: self.expander.current_file_id, ast: ptr }); id } // desugared exprs don't have ptr, that's wrong and should be fixed @@ -116,22 +116,22 @@ where fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { let ptr = Either::B(ptr); let id = self.body.exprs.alloc(expr); - if self.resolver.current_file_id == self.original_file_id { + if self.expander.current_file_id == self.original_file_id { self.source_map.expr_map.insert(ptr, id); } self.source_map .expr_map_back - .insert(id, Source { file_id: self.resolver.current_file_id, ast: ptr }); + .insert(id, Source { file_id: self.expander.current_file_id, ast: ptr }); id } fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { let id = self.body.pats.alloc(pat); - if self.resolver.current_file_id == self.original_file_id { + if self.expander.current_file_id == self.original_file_id { self.source_map.pat_map.insert(ptr, id); } self.source_map .pat_map_back - .insert(id, Source { file_id: self.resolver.current_file_id, ast: ptr }); + .insert(id, Source { file_id: self.expander.current_file_id, ast: ptr }); id } @@ -446,21 +446,21 @@ where ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), ast::Expr::MacroCall(e) => { let ast_id = AstId::new( - self.resolver.current_file_id, - self.db.ast_id_map(self.resolver.current_file_id).ast_id(&e), + self.expander.current_file_id, + self.db.ast_id_map(self.expander.current_file_id).ast_id(&e), ); if let Some(path) = e.path().and_then(|path| self.parse_path(path)) { - if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) { + if let Some(def) = self.expander.resolve_path_as_macro(self.db, &path) { let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id }); let file_id = call_id.as_file(MacroFileKind::Expr); if let Some(node) = self.db.parse_or_expand(file_id) { if let Some(expr) = ast::Expr::cast(node) { log::debug!("macro expansion {:#?}", expr.syntax()); let old_file_id = - std::mem::replace(&mut self.resolver.current_file_id, file_id); + std::mem::replace(&mut self.expander.current_file_id, file_id); let id = self.collect_expr(expr); - self.resolver.current_file_id = old_file_id; + self.expander.current_file_id = old_file_id; return id; } } @@ -582,7 +582,7 @@ where } fn parse_path(&mut self, path: ast::Path) -> Option { - let hygiene = Hygiene::new(self.db, self.resolver.current_file_id); + let hygiene = Hygiene::new(self.db, self.expander.current_file_id); Path::from_src(path, &hygiene) } } From e7e85c60d2c225eacc80184a7918ecf6c8ab0563 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 09:41:46 +0300 Subject: [PATCH 14/25] Move original_file to Expander --- crates/ra_hir_def/src/body.rs | 8 +++++++- crates/ra_hir_def/src/body/lower.rs | 12 ++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 5d8c299ba5f..1c9c864490f 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -18,6 +18,7 @@ use crate::{ pub struct Expander { crate_def_map: Arc, + original_file_id: HirFileId, current_file_id: HirFileId, module: ModuleId, } @@ -25,7 +26,12 @@ pub struct Expander { impl Expander { pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander { let crate_def_map = db.crate_def_map(module.krate); - Expander { crate_def_map, current_file_id, module } + Expander { crate_def_map, original_file_id: current_file_id, current_file_id, module } + } + + // FIXME: remove this. + fn is_in_expansion(&self) -> bool { + self.original_file_id != self.current_file_id } fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index cc4bbe11acc..602bcb220bd 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -4,7 +4,7 @@ use hir_expand::{ either::Either, hygiene::Hygiene, name::{self, AsName, Name}, - AstId, HirFileId, MacroCallLoc, MacroFileKind, Source, + AstId, MacroCallLoc, MacroFileKind, Source, }; use ra_arena::Arena; use ra_syntax::{ @@ -34,12 +34,9 @@ pub(super) fn lower( params: Option, body: Option, ) -> (Body, BodySourceMap) { - let original_file_id = expander.current_file_id; - ExprCollector { expander, db, - original_file_id, source_map: BodySourceMap::default(), body: Body { exprs: Arena::default(), @@ -54,7 +51,6 @@ pub(super) fn lower( struct ExprCollector { db: DB, expander: Expander, - original_file_id: HirFileId, body: Body, source_map: BodySourceMap, @@ -100,7 +96,7 @@ where fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { let ptr = Either::A(ptr); let id = self.body.exprs.alloc(expr); - if self.expander.current_file_id == self.original_file_id { + if !self.expander.is_in_expansion() { self.source_map.expr_map.insert(ptr, id); } self.source_map @@ -116,7 +112,7 @@ where fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { let ptr = Either::B(ptr); let id = self.body.exprs.alloc(expr); - if self.expander.current_file_id == self.original_file_id { + if !self.expander.is_in_expansion() { self.source_map.expr_map.insert(ptr, id); } self.source_map @@ -126,7 +122,7 @@ where } fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { let id = self.body.pats.alloc(pat); - if self.expander.current_file_id == self.original_file_id { + if !self.expander.is_in_expansion() { self.source_map.pat_map.insert(ptr, id); } self.source_map From c89010df2d586eec33b50f3afcc4b2226da32672 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 09:43:59 +0300 Subject: [PATCH 15/25] Add Expader::to_source --- crates/ra_hir_def/src/body.rs | 4 ++++ crates/ra_hir_def/src/body/lower.rs | 14 ++++---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 1c9c864490f..622c836d120 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -34,6 +34,10 @@ impl Expander { self.original_file_id != self.current_file_id } + fn to_source(&self, ast: T) -> Source { + Source { file_id: self.current_file_id, ast } + } + fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option { self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros() } diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 602bcb220bd..1ea8ce249ca 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -4,7 +4,7 @@ use hir_expand::{ either::Either, hygiene::Hygiene, name::{self, AsName, Name}, - AstId, MacroCallLoc, MacroFileKind, Source, + AstId, MacroCallLoc, MacroFileKind, }; use ra_arena::Arena; use ra_syntax::{ @@ -99,9 +99,7 @@ where if !self.expander.is_in_expansion() { self.source_map.expr_map.insert(ptr, id); } - self.source_map - .expr_map_back - .insert(id, Source { file_id: self.expander.current_file_id, ast: ptr }); + self.source_map.expr_map_back.insert(id, self.expander.to_source(ptr)); id } // desugared exprs don't have ptr, that's wrong and should be fixed @@ -115,9 +113,7 @@ where if !self.expander.is_in_expansion() { self.source_map.expr_map.insert(ptr, id); } - self.source_map - .expr_map_back - .insert(id, Source { file_id: self.expander.current_file_id, ast: ptr }); + self.source_map.expr_map_back.insert(id, self.expander.to_source(ptr)); id } fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { @@ -125,9 +121,7 @@ where if !self.expander.is_in_expansion() { self.source_map.pat_map.insert(ptr, id); } - self.source_map - .pat_map_back - .insert(id, Source { file_id: self.expander.current_file_id, ast: ptr }); + self.source_map.pat_map_back.insert(id, self.expander.to_source(ptr)); id } From e7880db1d0f75c639ee561b586219648bd05c21c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 09:52:03 +0300 Subject: [PATCH 16/25] Expansion stack scaffold --- crates/ra_hir_def/src/body.rs | 37 +++++++++++++++++++++++++++-- crates/ra_hir_def/src/body/lower.rs | 9 +++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 622c836d120..3b262e3bd8e 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -3,7 +3,7 @@ mod lower; use std::{ops::Index, sync::Arc}; -use hir_expand::{either::Either, HirFileId, MacroDefId, Source}; +use hir_expand::{either::Either, hygiene::Hygiene, HirFileId, MacroDefId, Source}; use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::{ast, AstPtr}; use rustc_hash::FxHashMap; @@ -20,13 +20,34 @@ pub struct Expander { crate_def_map: Arc, original_file_id: HirFileId, current_file_id: HirFileId, + hygiene: Hygiene, module: ModuleId, } impl Expander { pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander { let crate_def_map = db.crate_def_map(module.krate); - Expander { crate_def_map, original_file_id: current_file_id, current_file_id, module } + let hygiene = Hygiene::new(db, current_file_id); + Expander { + crate_def_map, + original_file_id: current_file_id, + current_file_id, + hygiene, + module, + } + } + + fn enter(&mut self, db: &impl DefDatabase2, file_id: HirFileId) -> Mark { + let mark = Mark { file_id: self.current_file_id }; + self.hygiene = Hygiene::new(db, file_id); + self.current_file_id = file_id; + mark + } + + fn exit(&mut self, db: &impl DefDatabase2, mark: Mark) { + self.hygiene = Hygiene::new(db, mark.file_id); + self.current_file_id = mark.file_id; + std::mem::forget(mark); } // FIXME: remove this. @@ -43,6 +64,18 @@ impl Expander { } } +struct Mark { + file_id: HirFileId, +} + +impl Drop for Mark { + fn drop(&mut self) { + if !std::thread::panicking() { + panic!("dropped mark") + } + } +} + /// The body of an item (function, const etc.). #[derive(Debug, Eq, PartialEq)] pub struct Body { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 1ea8ce249ca..5c291421a13 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -2,7 +2,6 @@ use hir_expand::{ either::Either, - hygiene::Hygiene, name::{self, AsName, Name}, AstId, MacroCallLoc, MacroFileKind, }; @@ -447,10 +446,9 @@ where if let Some(node) = self.db.parse_or_expand(file_id) { if let Some(expr) = ast::Expr::cast(node) { log::debug!("macro expansion {:#?}", expr.syntax()); - let old_file_id = - std::mem::replace(&mut self.expander.current_file_id, file_id); + let mark = self.expander.enter(self.db, file_id); let id = self.collect_expr(expr); - self.expander.current_file_id = old_file_id; + self.expander.exit(self.db, mark); return id; } } @@ -572,8 +570,7 @@ where } fn parse_path(&mut self, path: ast::Path) -> Option { - let hygiene = Hygiene::new(self.db, self.expander.current_file_id); - Path::from_src(path, &hygiene) + Path::from_src(path, &self.expander.hygiene) } } From 5c720b256f5d73434250072cc65fead746250d87 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 09:58:39 +0300 Subject: [PATCH 17/25] Move parse_path to Expander --- crates/ra_hir_def/src/body.rs | 4 ++++ crates/ra_hir_def/src/body/lower.rs | 16 ++++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 3b262e3bd8e..afceeb8dee8 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -59,6 +59,10 @@ impl Expander { Source { file_id: self.current_file_id, ast } } + fn parse_path(&mut self, path: ast::Path) -> Option { + Path::from_src(path, &self.hygiene) + } + fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option { self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros() } diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 5c291421a13..29c1ec2a19d 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -262,7 +262,7 @@ where ast::Expr::PathExpr(e) => { let path = e .path() - .and_then(|path| self.parse_path(path)) + .and_then(|path| self.expander.parse_path(path)) .map(Expr::Path) .unwrap_or(Expr::Missing); self.alloc_expr(path, syntax_ptr) @@ -286,7 +286,7 @@ where self.alloc_expr(Expr::Return { expr }, syntax_ptr) } ast::Expr::RecordLit(e) => { - let path = e.path().and_then(|path| self.parse_path(path)); + let path = e.path().and_then(|path| self.expander.parse_path(path)); let mut field_ptrs = Vec::new(); let record_lit = if let Some(nfl) = e.record_field_list() { let fields = nfl @@ -439,7 +439,7 @@ where self.db.ast_id_map(self.expander.current_file_id).ast_id(&e), ); - if let Some(path) = e.path().and_then(|path| self.parse_path(path)) { + if let Some(path) = e.path().and_then(|path| self.expander.parse_path(path)) { if let Some(def) = self.expander.resolve_path_as_macro(self.db, &path) { let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id }); let file_id = call_id.as_file(MacroFileKind::Expr); @@ -508,7 +508,7 @@ where Pat::Bind { name, mode: annotation, subpat } } ast::Pat::TupleStructPat(p) => { - let path = p.path().and_then(|path| self.parse_path(path)); + let path = p.path().and_then(|path| self.expander.parse_path(path)); let args = p.args().map(|p| self.collect_pat(p)).collect(); Pat::TupleStruct { path, args } } @@ -518,7 +518,7 @@ where Pat::Ref { pat, mutability } } ast::Pat::PathPat(p) => { - let path = p.path().and_then(|path| self.parse_path(path)); + let path = p.path().and_then(|path| self.expander.parse_path(path)); path.map(Pat::Path).unwrap_or(Pat::Missing) } ast::Pat::TuplePat(p) => { @@ -527,7 +527,7 @@ where } ast::Pat::PlaceholderPat(_) => Pat::Wild, ast::Pat::RecordPat(p) => { - let path = p.path().and_then(|path| self.parse_path(path)); + let path = p.path().and_then(|path| self.expander.parse_path(path)); let record_field_pat_list = p.record_field_pat_list().expect("every struct should have a field list"); let mut fields: Vec<_> = record_field_pat_list @@ -568,10 +568,6 @@ where self.missing_pat() } } - - fn parse_path(&mut self, path: ast::Path) -> Option { - Path::from_src(path, &self.expander.hygiene) - } } impl From for BinaryOp { From a73b7bb3f6af134c781cba1126350749c5a91144 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 10:04:39 +0300 Subject: [PATCH 18/25] Move expansion to Expander --- crates/ra_hir_def/src/body.rs | 36 +++++++++++++++++++++++++++-- crates/ra_hir_def/src/body/lower.rs | 32 ++++++------------------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index afceeb8dee8..65fefd912e0 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -3,9 +3,12 @@ mod lower; use std::{ops::Index, sync::Arc}; -use hir_expand::{either::Either, hygiene::Hygiene, HirFileId, MacroDefId, Source}; +use hir_expand::{ + either::Either, hygiene::Hygiene, AstId, HirFileId, MacroCallLoc, MacroDefId, MacroFileKind, + Source, +}; use ra_arena::{map::ArenaMap, Arena}; -use ra_syntax::{ast, AstPtr}; +use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; use crate::{ @@ -37,6 +40,35 @@ impl Expander { } } + fn expand( + &mut self, + db: &impl DefDatabase2, + macro_call: ast::MacroCall, + ) -> Option<(Mark, ast::Expr)> { + let ast_id = AstId::new( + self.current_file_id, + db.ast_id_map(self.current_file_id).ast_id(¯o_call), + ); + + if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { + if let Some(def) = self.resolve_path_as_macro(db, &path) { + let call_id = db.intern_macro(MacroCallLoc { def, ast_id }); + let file_id = call_id.as_file(MacroFileKind::Expr); + if let Some(node) = db.parse_or_expand(file_id) { + if let Some(expr) = ast::Expr::cast(node) { + log::debug!("macro expansion {:#?}", expr.syntax()); + let mark = self.enter(db, file_id); + return Some((mark, expr)); + } + } + } + } + + // FIXME: Instead of just dropping the error from expansion + // report it + None + } + fn enter(&mut self, db: &impl DefDatabase2, file_id: HirFileId) -> Mark { let mark = Mark { file_id: self.current_file_id }; self.hygiene = Hygiene::new(db, file_id); diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 29c1ec2a19d..c4550019576 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -3,7 +3,6 @@ use hir_expand::{ either::Either, name::{self, AsName, Name}, - AstId, MacroCallLoc, MacroFileKind, }; use ra_arena::Arena; use ra_syntax::{ @@ -433,31 +432,14 @@ where // FIXME implement HIR for these: ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), - ast::Expr::MacroCall(e) => { - let ast_id = AstId::new( - self.expander.current_file_id, - self.db.ast_id_map(self.expander.current_file_id).ast_id(&e), - ); - - if let Some(path) = e.path().and_then(|path| self.expander.parse_path(path)) { - if let Some(def) = self.expander.resolve_path_as_macro(self.db, &path) { - let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id }); - let file_id = call_id.as_file(MacroFileKind::Expr); - if let Some(node) = self.db.parse_or_expand(file_id) { - if let Some(expr) = ast::Expr::cast(node) { - log::debug!("macro expansion {:#?}", expr.syntax()); - let mark = self.expander.enter(self.db, file_id); - let id = self.collect_expr(expr); - self.expander.exit(self.db, mark); - return id; - } - } - } + ast::Expr::MacroCall(e) => match self.expander.expand(self.db, e) { + Some((mark, expansion)) => { + let id = self.collect_expr(expansion); + self.expander.exit(self.db, mark); + id } - // FIXME: Instead of just dropping the error from expansion - // report it - self.alloc_expr(Expr::Missing, syntax_ptr) - } + None => self.alloc_expr(Expr::Missing, syntax_ptr), + }, } } From da2ca01ebaaaaa47aa09c5848c53b145a68af8fa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 10:30:30 +0300 Subject: [PATCH 19/25] Handle macro-generated expressions slightly less wrong --- crates/ra_hir/src/expr/scope.rs | 6 +++- crates/ra_hir/src/from_source.rs | 3 +- crates/ra_hir/src/source_binder.rs | 44 ++++++++++++++++++++--------- crates/ra_hir_def/src/body.rs | 28 ++++++------------ crates/ra_hir_def/src/body/lower.rs | 24 ++++++++-------- crates/ra_hir_expand/src/lib.rs | 5 +++- 6 files changed, 62 insertions(+), 48 deletions(-) diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index fe5e836f219..afba6606986 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -166,6 +166,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope #[cfg(test)] mod tests { + use hir_expand::Source; use ra_db::{fixture::WithFixture, SourceDatabase}; use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; use test_utils::{assert_eq_text, extract_offset}; @@ -189,7 +190,10 @@ mod tests { let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); let scopes = analyzer.scopes(); - let expr_id = analyzer.body_source_map().node_expr(&marker.into()).unwrap(); + let expr_id = analyzer + .body_source_map() + .node_expr(Source { file_id: file_id.into(), ast: &marker.into() }) + .unwrap(); let scope = scopes.scope_for(expr_id); let actual = scopes diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 2c441b0f4d5..4b561c63dea 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -145,7 +145,8 @@ impl Local { Some(res) })?; let (_body, source_map) = db.body_with_source_map(parent); - let pat_id = source_map.node_pat(&src.ast.into())?; + let src = src.map(ast::Pat::from); + let pat_id = source_map.node_pat(src.as_ref())?; Some(Local { parent, pat_id }) } } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index f28e9c931ab..88eed1137f7 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -7,8 +7,11 @@ //! purely for "IDE needs". use std::sync::Arc; -use hir_def::path::known; -use hir_expand::name::AsName; +use hir_def::{ + expr::{ExprId, PatId}, + path::known, +}; +use hir_expand::{name::AsName, Source}; use ra_db::FileId; use ra_syntax::{ ast::{self, AstNode}, @@ -93,6 +96,8 @@ fn def_with_body_from_child_node( /// original source files. It should not be used inside the HIR itself. #[derive(Debug)] pub struct SourceAnalyzer { + // FIXME: this doesn't handle macros at all + file_id: FileId, resolver: Resolver, body_owner: Option, body_source_map: Option>, @@ -147,7 +152,7 @@ impl SourceAnalyzer { let source_map = def.body_source_map(db); let scopes = db.expr_scopes(def); let scope = match offset { - None => scope_for(&scopes, &source_map, &node), + None => scope_for(&scopes, &source_map, file_id.into(), &node), Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), }; let resolver = expr::resolver_for_scope(db, def, scope); @@ -157,6 +162,7 @@ impl SourceAnalyzer { body_source_map: Some(source_map), infer: Some(def.infer(db)), scopes: Some(scopes), + file_id, } } else { SourceAnalyzer { @@ -168,17 +174,28 @@ impl SourceAnalyzer { body_source_map: None, infer: None, scopes: None, + file_id, } } } + fn expr_id(&self, expr: &ast::Expr) -> Option { + let src = Source { file_id: self.file_id.into(), ast: expr }; + self.body_source_map.as_ref()?.node_expr(src) + } + + fn pat_id(&self, pat: &ast::Pat) -> Option { + let src = Source { file_id: self.file_id.into(), ast: pat }; + self.body_source_map.as_ref()?.node_pat(src) + } + pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option { - let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?; + let expr_id = self.expr_id(expr)?; Some(self.infer.as_ref()?[expr_id].clone()) } pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option { - let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?; + let pat_id = self.pat_id(pat)?; Some(self.infer.as_ref()?[pat_id].clone()) } @@ -191,22 +208,22 @@ impl SourceAnalyzer { } pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { - let expr_id = self.body_source_map.as_ref()?.node_expr(&call.clone().into())?; + let expr_id = self.expr_id(&call.clone().into())?; self.infer.as_ref()?.method_resolution(expr_id) } pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option { - let expr_id = self.body_source_map.as_ref()?.node_expr(&field.clone().into())?; + let expr_id = self.expr_id(&field.clone().into())?; self.infer.as_ref()?.field_resolution(expr_id) } pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option { - let expr_id = self.body_source_map.as_ref()?.node_expr(&record_lit.clone().into())?; + let expr_id = self.expr_id(&record_lit.clone().into())?; self.infer.as_ref()?.variant_resolution_for_expr(expr_id) } pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option { - let pat_id = self.body_source_map.as_ref()?.node_pat(&record_pat.clone().into())?; + let pat_id = self.pat_id(&record_pat.clone().into())?; self.infer.as_ref()?.variant_resolution_for_pat(pat_id) } @@ -264,13 +281,13 @@ impl SourceAnalyzer { pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option { if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { - let expr_id = self.body_source_map.as_ref()?.node_expr(&path_expr.into())?; + let expr_id = self.expr_id(&path_expr.into())?; if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { return Some(PathResolution::AssocItem(assoc)); } } if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { - let pat_id = self.body_source_map.as_ref()?.node_pat(&path_pat.into())?; + let pat_id = self.pat_id(&path_pat.into())?; if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { return Some(PathResolution::AssocItem(assoc)); } @@ -285,7 +302,7 @@ impl SourceAnalyzer { let name = name_ref.as_name(); let source_map = self.body_source_map.as_ref()?; let scopes = self.scopes.as_ref()?; - let scope = scope_for(scopes, source_map, name_ref.syntax()); + let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax()); let ret = scopes .scope_chain(scope) .flat_map(|scope| scopes.entries(scope).iter()) @@ -418,11 +435,12 @@ impl SourceAnalyzer { fn scope_for( scopes: &ExprScopes, source_map: &BodySourceMap, + file_id: HirFileId, node: &SyntaxNode, ) -> Option { node.ancestors() .filter_map(ast::Expr::cast) - .filter_map(|it| source_map.node_expr(&it)) + .filter_map(|it| source_map.node_expr(Source { file_id, ast: &it })) .find_map(|it| scopes.scope_for(it)) } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 65fefd912e0..75bba31c219 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -21,7 +21,6 @@ use crate::{ pub struct Expander { crate_def_map: Arc, - original_file_id: HirFileId, current_file_id: HirFileId, hygiene: Hygiene, module: ModuleId, @@ -31,13 +30,7 @@ impl Expander { pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander { let crate_def_map = db.crate_def_map(module.krate); let hygiene = Hygiene::new(db, current_file_id); - Expander { - crate_def_map, - original_file_id: current_file_id, - current_file_id, - hygiene, - module, - } + Expander { crate_def_map, current_file_id, hygiene, module } } fn expand( @@ -82,11 +75,6 @@ impl Expander { std::mem::forget(mark); } - // FIXME: remove this. - fn is_in_expansion(&self) -> bool { - self.original_file_id != self.current_file_id - } - fn to_source(&self, ast: T) -> Source { Source { file_id: self.current_file_id, ast } } @@ -147,9 +135,9 @@ pub type PatSource = Source; /// this properly for macros. #[derive(Default, Debug, Eq, PartialEq)] pub struct BodySourceMap { - expr_map: FxHashMap, + expr_map: FxHashMap, expr_map_back: ArenaMap, - pat_map: FxHashMap, + pat_map: FxHashMap, pat_map_back: ArenaMap, field_map: FxHashMap<(ExprId, usize), AstPtr>, } @@ -202,16 +190,18 @@ impl BodySourceMap { self.expr_map_back.get(expr).copied() } - pub fn node_expr(&self, node: &ast::Expr) -> Option { - self.expr_map.get(&Either::A(AstPtr::new(node))).cloned() + pub fn node_expr(&self, node: Source<&ast::Expr>) -> Option { + let src = node.map(|it| Either::A(AstPtr::new(it))); + self.expr_map.get(&src).cloned() } pub fn pat_syntax(&self, pat: PatId) -> Option { self.pat_map_back.get(pat).copied() } - pub fn node_pat(&self, node: &ast::Pat) -> Option { - self.pat_map.get(&Either::A(AstPtr::new(node))).cloned() + pub fn node_pat(&self, node: Source<&ast::Pat>) -> Option { + let src = node.map(|it| Either::A(AstPtr::new(it))); + self.pat_map.get(&src).cloned() } pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index c4550019576..f6d79ddf058 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -94,10 +94,9 @@ where fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { let ptr = Either::A(ptr); let id = self.body.exprs.alloc(expr); - if !self.expander.is_in_expansion() { - self.source_map.expr_map.insert(ptr, id); - } - self.source_map.expr_map_back.insert(id, self.expander.to_source(ptr)); + let src = self.expander.to_source(ptr); + self.source_map.expr_map.insert(src, id); + self.source_map.expr_map_back.insert(id, src); id } // desugared exprs don't have ptr, that's wrong and should be fixed @@ -108,18 +107,16 @@ where fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { let ptr = Either::B(ptr); let id = self.body.exprs.alloc(expr); - if !self.expander.is_in_expansion() { - self.source_map.expr_map.insert(ptr, id); - } - self.source_map.expr_map_back.insert(id, self.expander.to_source(ptr)); + let src = self.expander.to_source(ptr); + self.source_map.expr_map.insert(src, id); + self.source_map.expr_map_back.insert(id, src); id } fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { let id = self.body.pats.alloc(pat); - if !self.expander.is_in_expansion() { - self.source_map.pat_map.insert(ptr, id); - } - self.source_map.pat_map_back.insert(id, self.expander.to_source(ptr)); + let src = self.expander.to_source(ptr); + self.source_map.pat_map.insert(src, id); + self.source_map.pat_map_back.insert(id, src); id } @@ -277,7 +274,8 @@ where ast::Expr::ParenExpr(e) => { let inner = self.collect_expr_opt(e.expr()); // make the paren expr point to the inner expression as well - self.source_map.expr_map.insert(Either::A(syntax_ptr), inner); + let src = self.expander.to_source(Either::A(syntax_ptr)); + self.source_map.expr_map.insert(src, inner); inner } ast::Expr::ReturnExpr(e) => { diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index c6ffa2c6f2f..930789b0fe2 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -223,7 +223,7 @@ impl AstId { } } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct Source { pub file_id: HirFileId, pub ast: T, @@ -233,6 +233,9 @@ impl Source { pub fn map U, U>(self, f: F) -> Source { Source { file_id: self.file_id, ast: f(self.ast) } } + pub fn as_ref(&self) -> Source<&T> { + Source { file_id: self.file_id, ast: &self.ast } + } pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode { db.parse_or_expand(self.file_id).expect("source created from invalid file") } From c65f42325fa9213ad79fcf12115213a923b651df Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 11:11:32 +0300 Subject: [PATCH 20/25] Revert #2230 Looks like autocfg tries to do slightly more than we need (see #2231), so let's stick with minimal home-grown solution. --- Cargo.lock | 1 - xtask/Cargo.toml | 1 - xtask/src/main.rs | 36 +++++++++++++++++++++++++----------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c9ab3ef1081..1dedf977210 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1829,7 +1829,6 @@ name = "xtask" version = "0.1.0" dependencies = [ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index bba4be19278..77b9ae2b467 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -6,7 +6,6 @@ authors = ["rust-analyzer developers"] publish = false [dependencies] -autocfg = "0.1" walkdir = "2.1.3" pico-args = "0.3.0" quote = "1.0.2" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 7eab1c949db..f14e6c8ae7e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -10,18 +10,17 @@ mod help; use anyhow::Context; -use autocfg; use core::fmt::Write; use core::str; use pico_args::Arguments; use std::{env, path::PathBuf}; use xtask::{ codegen::{self, Mode}, - install_format_hook, run, run_clippy, run_fuzzer, run_rustfmt, Cmd, Result, + install_format_hook, run, run_clippy, run_fuzzer, run_rustfmt, run_with_output, Cmd, Result, }; // Latest stable, feel free to send a PR if this lags behind. -const REQUIRED_RUST_VERSION: (usize, usize) = (1, 39); +const REQUIRED_RUST_VERSION: u32 = 39; struct InstallOpt { client: Option, @@ -230,15 +229,20 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { } fn install_server(opts: ServerOpt) -> Result<()> { - let target_dir = env::var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into()); - let ac = autocfg::AutoCfg::with_dir(target_dir)?; - - let old_rust = !ac.probe_rustc_version(REQUIRED_RUST_VERSION.0, REQUIRED_RUST_VERSION.1); + let mut old_rust = false; + if let Ok(output) = run_with_output("cargo --version", ".") { + if let Ok(stdout) = String::from_utf8(output.stdout) { + println!("{}", stdout); + if !check_version(&stdout, REQUIRED_RUST_VERSION) { + old_rust = true; + } + } + } if old_rust { eprintln!( - "\nWARNING: at least rust {}.{}.0 is required to compile rust-analyzer\n", - REQUIRED_RUST_VERSION.0, REQUIRED_RUST_VERSION.1 + "\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n", + REQUIRED_RUST_VERSION, ) } @@ -250,10 +254,20 @@ fn install_server(opts: ServerOpt) -> Result<()> { if res.is_err() && old_rust { eprintln!( - "\nWARNING: at least rust {}.{}.0 is required to compile rust-analyzer\n", - REQUIRED_RUST_VERSION.0, REQUIRED_RUST_VERSION.1 + "\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n", + REQUIRED_RUST_VERSION, ) } res } + +fn check_version(version_output: &str, min_minor_version: u32) -> bool { + // Parse second the number out of + // cargo 1.39.0-beta (1c6ec66d5 2019-09-30) + let minor: Option = version_output.split('.').nth(1).and_then(|it| it.parse().ok()); + match minor { + None => true, + Some(minor) => minor >= min_minor_version, + } +} From 4efd345b09ca6e06fc0580d91a6c13f30b6b7f23 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 11:33:18 +0300 Subject: [PATCH 21/25] Slightly better naming --- crates/ra_hir_def/src/body.rs | 15 ++++++--------- crates/ra_hir_def/src/body/lower.rs | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 75bba31c219..bff17fd62a2 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -33,7 +33,7 @@ impl Expander { Expander { crate_def_map, current_file_id, hygiene, module } } - fn expand( + fn enter_expand( &mut self, db: &impl DefDatabase2, macro_call: ast::MacroCall, @@ -50,7 +50,11 @@ impl Expander { if let Some(node) = db.parse_or_expand(file_id) { if let Some(expr) = ast::Expr::cast(node) { log::debug!("macro expansion {:#?}", expr.syntax()); - let mark = self.enter(db, file_id); + + let mark = Mark { file_id: self.current_file_id }; + self.hygiene = Hygiene::new(db, file_id); + self.current_file_id = file_id; + return Some((mark, expr)); } } @@ -62,13 +66,6 @@ impl Expander { None } - fn enter(&mut self, db: &impl DefDatabase2, file_id: HirFileId) -> Mark { - let mark = Mark { file_id: self.current_file_id }; - self.hygiene = Hygiene::new(db, file_id); - self.current_file_id = file_id; - mark - } - fn exit(&mut self, db: &impl DefDatabase2, mark: Mark) { self.hygiene = Hygiene::new(db, mark.file_id); self.current_file_id = mark.file_id; diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index f6d79ddf058..a5bb60e8576 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -430,7 +430,7 @@ where // FIXME implement HIR for these: ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), - ast::Expr::MacroCall(e) => match self.expander.expand(self.db, e) { + ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) { Some((mark, expansion)) => { let id = self.collect_expr(expansion); self.expander.exit(self.db, mark); From f924ae3b86dc5e978071b6f8308b9f357415780b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 11:56:13 +0300 Subject: [PATCH 22/25] Move scopes to hir_def --- crates/ra_hir/src/db.rs | 2 +- crates/ra_hir/src/expr.rs | 204 +++++++++++++++- crates/ra_hir/src/expr/scope.rs | 353 ---------------------------- crates/ra_hir/src/resolve.rs | 5 +- crates/ra_hir/src/source_binder.rs | 6 +- crates/ra_hir_def/src/body.rs | 1 + crates/ra_hir_def/src/body/scope.rs | 157 +++++++++++++ 7 files changed, 360 insertions(+), 368 deletions(-) delete mode 100644 crates/ra_hir/src/expr/scope.rs create mode 100644 crates/ra_hir_def/src/body/scope.rs diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 9ac811232fc..14f6b5df416 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -85,7 +85,7 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { #[salsa::query_group(HirDatabaseStorage)] #[salsa::requires(salsa::Database)] pub trait HirDatabase: DefDatabase + AstDatabase { - #[salsa::invoke(ExprScopes::expr_scopes_query)] + #[salsa::invoke(crate::expr::expr_scopes_query)] fn expr_scopes(&self, def: DefWithBody) -> Arc; #[salsa::invoke(crate::ty::infer_query)] diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index d19f5d14cea..f02104b2d7b 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -1,6 +1,5 @@ //! FIXME: write short doc here -pub(crate) mod scope; pub(crate) mod validation; use std::sync::Arc; @@ -9,10 +8,11 @@ use ra_syntax::{ast, AstPtr}; use crate::{db::HirDatabase, DefWithBody, HasSource, Resolver}; -pub use self::scope::ExprScopes; - pub use hir_def::{ - body::{Body, BodySourceMap, ExprPtr, ExprSource, PatPtr, PatSource}, + body::{ + scope::{ExprScopes, ScopeEntry, ScopeId}, + Body, BodySourceMap, ExprPtr, ExprSource, PatPtr, PatSource, + }, expr::{ ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp, @@ -49,6 +49,11 @@ pub(crate) fn body_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { db.body_with_source_map(def).0 } +pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { + let body = db.body(def); + Arc::new(ExprScopes::new(&*body)) +} + // needs arbitrary_self_types to be a method... or maybe move to the def? pub(crate) fn resolver_for_expr( db: &impl HirDatabase, @@ -62,7 +67,7 @@ pub(crate) fn resolver_for_expr( pub(crate) fn resolver_for_scope( db: &impl HirDatabase, owner: DefWithBody, - scope_id: Option, + scope_id: Option, ) -> Resolver { let mut r = owner.resolver(db); let scopes = db.expr_scopes(owner); @@ -72,3 +77,192 @@ pub(crate) fn resolver_for_scope( } r } + +#[cfg(test)] +mod tests { + use hir_expand::Source; + use ra_db::{fixture::WithFixture, SourceDatabase}; + use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; + use test_utils::{assert_eq_text, extract_offset}; + + use crate::{source_binder::SourceAnalyzer, test_db::TestDB}; + + fn do_check(code: &str, expected: &[&str]) { + let (off, code) = extract_offset(code); + let code = { + let mut buf = String::new(); + let off = u32::from(off) as usize; + buf.push_str(&code[..off]); + buf.push_str("marker"); + buf.push_str(&code[off..]); + buf + }; + + let (db, file_id) = TestDB::with_single_file(&code); + + let file = db.parse(file_id).ok().unwrap(); + let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); + let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); + + let scopes = analyzer.scopes(); + let expr_id = analyzer + .body_source_map() + .node_expr(Source { file_id: file_id.into(), ast: &marker.into() }) + .unwrap(); + let scope = scopes.scope_for(expr_id); + + let actual = scopes + .scope_chain(scope) + .flat_map(|scope| scopes.entries(scope)) + .map(|it| it.name().to_string()) + .collect::>() + .join("\n"); + let expected = expected.join("\n"); + assert_eq_text!(&expected, &actual); + } + + #[test] + fn test_lambda_scope() { + do_check( + r" + fn quux(foo: i32) { + let f = |bar, baz: i32| { + <|> + }; + }", + &["bar", "baz", "foo"], + ); + } + + #[test] + fn test_call_scope() { + do_check( + r" + fn quux() { + f(|x| <|> ); + }", + &["x"], + ); + } + + #[test] + fn test_method_call_scope() { + do_check( + r" + fn quux() { + z.f(|x| <|> ); + }", + &["x"], + ); + } + + #[test] + fn test_loop_scope() { + do_check( + r" + fn quux() { + loop { + let x = (); + <|> + }; + }", + &["x"], + ); + } + + #[test] + fn test_match() { + do_check( + r" + fn quux() { + match () { + Some(x) => { + <|> + } + }; + }", + &["x"], + ); + } + + #[test] + fn test_shadow_variable() { + do_check( + r" + fn foo(x: String) { + let x : &str = &x<|>; + }", + &["x"], + ); + } + + fn do_check_local_name(code: &str, expected_offset: u32) { + let (off, code) = extract_offset(code); + + let (db, file_id) = TestDB::with_single_file(&code); + let file = db.parse(file_id).ok().unwrap(); + let expected_name = find_node_at_offset::(file.syntax(), expected_offset.into()) + .expect("failed to find a name at the target offset"); + let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); + let analyzer = SourceAnalyzer::new(&db, file_id, name_ref.syntax(), None); + + let local_name_entry = analyzer.resolve_local_name(&name_ref).unwrap(); + let local_name = + local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); + assert_eq!(local_name.range(), expected_name.syntax().text_range()); + } + + #[test] + fn test_resolve_local_name() { + do_check_local_name( + r#" + fn foo(x: i32, y: u32) { + { + let z = x * 2; + } + { + let t = x<|> * 3; + } + }"#, + 21, + ); + } + + #[test] + fn test_resolve_local_name_declaration() { + do_check_local_name( + r#" + fn foo(x: String) { + let x : &str = &x<|>; + }"#, + 21, + ); + } + + #[test] + fn test_resolve_local_name_shadow() { + do_check_local_name( + r" + fn foo(x: String) { + let x : &str = &x; + x<|> + } + ", + 53, + ); + } + + #[test] + fn ref_patterns_contribute_bindings() { + do_check_local_name( + r" + fn foo() { + if let Some(&from) = bar() { + from<|>; + } + } + ", + 53, + ); + } +} diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs deleted file mode 100644 index afba6606986..00000000000 --- a/crates/ra_hir/src/expr/scope.rs +++ /dev/null @@ -1,353 +0,0 @@ -//! FIXME: write short doc here - -use std::sync::Arc; - -use ra_arena::{impl_arena_id, Arena, RawId}; -use rustc_hash::FxHashMap; - -use crate::{ - db::HirDatabase, - expr::{Body, Expr, ExprId, Pat, PatId, Statement}, - DefWithBody, Name, -}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ScopeId(RawId); -impl_arena_id!(ScopeId); - -#[derive(Debug, PartialEq, Eq)] -pub struct ExprScopes { - scopes: Arena, - scope_by_expr: FxHashMap, -} - -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct ScopeEntry { - name: Name, - pat: PatId, -} - -impl ScopeEntry { - pub(crate) fn name(&self) -> &Name { - &self.name - } - - pub(crate) fn pat(&self) -> PatId { - self.pat - } -} - -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct ScopeData { - parent: Option, - entries: Vec, -} - -impl ExprScopes { - pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { - let body = db.body(def); - let res = ExprScopes::new(&*body); - Arc::new(res) - } - - fn new(body: &Body) -> ExprScopes { - let mut scopes = - ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; - let root = scopes.root_scope(); - scopes.add_params_bindings(body, root, body.params()); - compute_expr_scopes(body.body_expr(), body, &mut scopes, root); - scopes - } - - pub(crate) fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { - &self.scopes[scope].entries - } - - pub(crate) fn scope_chain(&self, scope: Option) -> impl Iterator + '_ { - std::iter::successors(scope, move |&scope| self.scopes[scope].parent) - } - - pub(crate) fn scope_for(&self, expr: ExprId) -> Option { - self.scope_by_expr.get(&expr).copied() - } - - pub(crate) fn scope_by_expr(&self) -> &FxHashMap { - &self.scope_by_expr - } - - fn root_scope(&mut self) -> ScopeId { - self.scopes.alloc(ScopeData { parent: None, entries: vec![] }) - } - - fn new_scope(&mut self, parent: ScopeId) -> ScopeId { - self.scopes.alloc(ScopeData { parent: Some(parent), entries: vec![] }) - } - - fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { - match &body[pat] { - Pat::Bind { name, .. } => { - // 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) - } - p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), - } - } - - fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) { - params.iter().for_each(|pat| self.add_bindings(body, scope, *pat)); - } - - fn set_scope(&mut self, node: ExprId, scope: ScopeId) { - self.scope_by_expr.insert(node, scope); - } -} - -fn compute_block_scopes( - statements: &[Statement], - tail: Option, - body: &Body, - scopes: &mut ExprScopes, - mut scope: ScopeId, -) { - for stmt in statements { - match stmt { - Statement::Let { pat, initializer, .. } => { - if let Some(expr) = initializer { - scopes.set_scope(*expr, scope); - compute_expr_scopes(*expr, body, scopes, scope); - } - scope = scopes.new_scope(scope); - scopes.add_bindings(body, scope, *pat); - } - Statement::Expr(expr) => { - scopes.set_scope(*expr, scope); - compute_expr_scopes(*expr, body, scopes, scope); - } - } - } - if let Some(expr) = tail { - compute_expr_scopes(expr, body, scopes, scope); - } -} - -fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { - scopes.set_scope(expr, scope); - match &body[expr] { - Expr::Block { statements, tail } => { - compute_block_scopes(&statements, *tail, body, scopes, scope); - } - Expr::For { iterable, pat, body: body_expr } => { - compute_expr_scopes(*iterable, body, scopes, scope); - let scope = scopes.new_scope(scope); - scopes.add_bindings(body, scope, *pat); - compute_expr_scopes(*body_expr, body, scopes, scope); - } - Expr::Lambda { args, body: body_expr, .. } => { - let scope = scopes.new_scope(scope); - scopes.add_params_bindings(body, scope, &args); - compute_expr_scopes(*body_expr, body, scopes, scope); - } - Expr::Match { expr, arms } => { - compute_expr_scopes(*expr, body, scopes, scope); - for arm in arms { - let scope = scopes.new_scope(scope); - for pat in &arm.pats { - scopes.add_bindings(body, scope, *pat); - } - scopes.set_scope(arm.expr, scope); - compute_expr_scopes(arm.expr, body, scopes, scope); - } - } - e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)), - }; -} - -#[cfg(test)] -mod tests { - use hir_expand::Source; - use ra_db::{fixture::WithFixture, SourceDatabase}; - use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; - use test_utils::{assert_eq_text, extract_offset}; - - use crate::{source_binder::SourceAnalyzer, test_db::TestDB}; - - fn do_check(code: &str, expected: &[&str]) { - let (off, code) = extract_offset(code); - let code = { - let mut buf = String::new(); - let off = u32::from(off) as usize; - buf.push_str(&code[..off]); - buf.push_str("marker"); - buf.push_str(&code[off..]); - buf - }; - - let (db, file_id) = TestDB::with_single_file(&code); - let file = db.parse(file_id).ok().unwrap(); - let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); - let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); - - let scopes = analyzer.scopes(); - let expr_id = analyzer - .body_source_map() - .node_expr(Source { file_id: file_id.into(), ast: &marker.into() }) - .unwrap(); - let scope = scopes.scope_for(expr_id); - - let actual = scopes - .scope_chain(scope) - .flat_map(|scope| scopes.entries(scope)) - .map(|it| it.name().to_string()) - .collect::>() - .join("\n"); - let expected = expected.join("\n"); - assert_eq_text!(&expected, &actual); - } - - #[test] - fn test_lambda_scope() { - do_check( - r" - fn quux(foo: i32) { - let f = |bar, baz: i32| { - <|> - }; - }", - &["bar", "baz", "foo"], - ); - } - - #[test] - fn test_call_scope() { - do_check( - r" - fn quux() { - f(|x| <|> ); - }", - &["x"], - ); - } - - #[test] - fn test_method_call_scope() { - do_check( - r" - fn quux() { - z.f(|x| <|> ); - }", - &["x"], - ); - } - - #[test] - fn test_loop_scope() { - do_check( - r" - fn quux() { - loop { - let x = (); - <|> - }; - }", - &["x"], - ); - } - - #[test] - fn test_match() { - do_check( - r" - fn quux() { - match () { - Some(x) => { - <|> - } - }; - }", - &["x"], - ); - } - - #[test] - fn test_shadow_variable() { - do_check( - r" - fn foo(x: String) { - let x : &str = &x<|>; - }", - &["x"], - ); - } - - fn do_check_local_name(code: &str, expected_offset: u32) { - let (off, code) = extract_offset(code); - - let (db, file_id) = TestDB::with_single_file(&code); - let file = db.parse(file_id).ok().unwrap(); - let expected_name = find_node_at_offset::(file.syntax(), expected_offset.into()) - .expect("failed to find a name at the target offset"); - let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); - let analyzer = SourceAnalyzer::new(&db, file_id, name_ref.syntax(), None); - - let local_name_entry = analyzer.resolve_local_name(&name_ref).unwrap(); - let local_name = - local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); - assert_eq!(local_name.range(), expected_name.syntax().text_range()); - } - - #[test] - fn test_resolve_local_name() { - do_check_local_name( - r#" - fn foo(x: i32, y: u32) { - { - let z = x * 2; - } - { - let t = x<|> * 3; - } - }"#, - 21, - ); - } - - #[test] - fn test_resolve_local_name_declaration() { - do_check_local_name( - r#" - fn foo(x: String) { - let x : &str = &x<|>; - }"#, - 21, - ); - } - - #[test] - fn test_resolve_local_name_shadow() { - do_check_local_name( - r" - fn foo(x: String) { - let x : &str = &x; - x<|> - } - ", - 53, - ); - } - - #[test] - fn ref_patterns_contribute_bindings() { - do_check_local_name( - r" - fn foo() { - if let Some(&from) = bar() { - from<|>; - } - } - ", - 53, - ); - } -} diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index b932b0c8cdb..2f3e12eb83d 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -13,10 +13,7 @@ use rustc_hash::FxHashSet; use crate::{ code_model::Crate, db::{DefDatabase, HirDatabase}, - expr::{ - scope::{ExprScopes, ScopeId}, - PatId, - }, + expr::{ExprScopes, PatId, ScopeId}, generics::GenericParams, impl_block::ImplBlock, Adt, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, PerNs, Static, Struct, Trait, diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 88eed1137f7..e337a3d4a51 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -23,11 +23,7 @@ use rustc_hash::FxHashSet; use crate::{ db::HirDatabase, - expr::{ - self, - scope::{ExprScopes, ScopeId}, - BodySourceMap, - }, + expr::{self, BodySourceMap, ExprScopes, ScopeId}, ids::LocationCtx, resolve::{ScopeDef, TypeNs, ValueNs}, ty::method_resolution::{self, implements_trait}, diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index bff17fd62a2..c3e9d0c2353 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -1,5 +1,6 @@ //! FIXME: write short doc here mod lower; +pub mod scope; use std::{ops::Index, sync::Arc}; diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs new file mode 100644 index 00000000000..dd8d06d1124 --- /dev/null +++ b/crates/ra_hir_def/src/body/scope.rs @@ -0,0 +1,157 @@ +//! FIXME: write short doc here + +use hir_expand::name::Name; +use ra_arena::{impl_arena_id, Arena, RawId}; +use rustc_hash::FxHashMap; + +use crate::{ + body::Body, + expr::{Expr, ExprId, Pat, PatId, Statement}, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ScopeId(RawId); +impl_arena_id!(ScopeId); + +#[derive(Debug, PartialEq, Eq)] +pub struct ExprScopes { + scopes: Arena, + scope_by_expr: FxHashMap, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct ScopeEntry { + name: Name, + pat: PatId, +} + +impl ScopeEntry { + pub fn name(&self) -> &Name { + &self.name + } + + pub fn pat(&self) -> PatId { + self.pat + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct ScopeData { + parent: Option, + entries: Vec, +} + +impl ExprScopes { + pub fn new(body: &Body) -> ExprScopes { + let mut scopes = + ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; + let root = scopes.root_scope(); + scopes.add_params_bindings(body, root, body.params()); + compute_expr_scopes(body.body_expr(), body, &mut scopes, root); + scopes + } + + pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { + &self.scopes[scope].entries + } + + pub fn scope_chain(&self, scope: Option) -> impl Iterator + '_ { + std::iter::successors(scope, move |&scope| self.scopes[scope].parent) + } + + pub fn scope_for(&self, expr: ExprId) -> Option { + self.scope_by_expr.get(&expr).copied() + } + + pub fn scope_by_expr(&self) -> &FxHashMap { + &self.scope_by_expr + } + + fn root_scope(&mut self) -> ScopeId { + self.scopes.alloc(ScopeData { parent: None, entries: vec![] }) + } + + fn new_scope(&mut self, parent: ScopeId) -> ScopeId { + self.scopes.alloc(ScopeData { parent: Some(parent), entries: vec![] }) + } + + fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { + match &body[pat] { + Pat::Bind { name, .. } => { + // 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) + } + p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), + } + } + + fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) { + params.iter().for_each(|pat| self.add_bindings(body, scope, *pat)); + } + + fn set_scope(&mut self, node: ExprId, scope: ScopeId) { + self.scope_by_expr.insert(node, scope); + } +} + +fn compute_block_scopes( + statements: &[Statement], + tail: Option, + body: &Body, + scopes: &mut ExprScopes, + mut scope: ScopeId, +) { + for stmt in statements { + match stmt { + Statement::Let { pat, initializer, .. } => { + if let Some(expr) = initializer { + scopes.set_scope(*expr, scope); + compute_expr_scopes(*expr, body, scopes, scope); + } + scope = scopes.new_scope(scope); + scopes.add_bindings(body, scope, *pat); + } + Statement::Expr(expr) => { + scopes.set_scope(*expr, scope); + compute_expr_scopes(*expr, body, scopes, scope); + } + } + } + if let Some(expr) = tail { + compute_expr_scopes(expr, body, scopes, scope); + } +} + +fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { + scopes.set_scope(expr, scope); + match &body[expr] { + Expr::Block { statements, tail } => { + compute_block_scopes(&statements, *tail, body, scopes, scope); + } + Expr::For { iterable, pat, body: body_expr } => { + compute_expr_scopes(*iterable, body, scopes, scope); + let scope = scopes.new_scope(scope); + scopes.add_bindings(body, scope, *pat); + compute_expr_scopes(*body_expr, body, scopes, scope); + } + Expr::Lambda { args, body: body_expr, .. } => { + let scope = scopes.new_scope(scope); + scopes.add_params_bindings(body, scope, &args); + compute_expr_scopes(*body_expr, body, scopes, scope); + } + Expr::Match { expr, arms } => { + compute_expr_scopes(*expr, body, scopes, scope); + for arm in arms { + let scope = scopes.new_scope(scope); + for pat in &arm.pats { + scopes.add_bindings(body, scope, *pat); + } + scopes.set_scope(arm.expr, scope); + compute_expr_scopes(arm.expr, body, scopes, scope); + } + } + e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)), + }; +} From ef02296b9fe2c2e42b9390a3a14ee860f08fd02c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 17:36:27 +0300 Subject: [PATCH 23/25] Simplify parsing --- .../ra_parser/src/grammar/expressions/atom.rs | 34 +++++++++---------- crates/ra_parser/src/token_set.rs | 4 +-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 4952bd1891b..f06191963f0 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -40,24 +40,24 @@ pub(crate) fn literal(p: &mut Parser) -> Option { // E.g. for after the break in `if break {}`, this should not match pub(super) const ATOM_EXPR_FIRST: TokenSet = LITERAL_FIRST.union(paths::PATH_FIRST).union(token_set![ - L_PAREN, - L_CURLY, - L_BRACK, - PIPE, - MOVE_KW, - BOX_KW, - IF_KW, - WHILE_KW, - MATCH_KW, - UNSAFE_KW, - RETURN_KW, - BREAK_KW, - CONTINUE_KW, + T!['('], + T!['{'], + T!['['], + T![|], + T![move], + T![box], + T![if], + T![while], + T![match], + T![unsafe], + T![return], + T![break], + T![continue], + T![async], + T![try], + T![loop], + T![for], LIFETIME, - ASYNC_KW, - TRY_KW, - LOOP_KW, - FOR_KW, ]); const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; diff --git a/crates/ra_parser/src/token_set.rs b/crates/ra_parser/src/token_set.rs index 6dc061889f5..2a6952c013a 100644 --- a/crates/ra_parser/src/token_set.rs +++ b/crates/ra_parser/src/token_set.rs @@ -30,8 +30,8 @@ const fn mask(kind: SyntaxKind) -> u128 { #[macro_export] macro_rules! token_set { - ($($t:ident),*) => { TokenSet::empty()$(.union(TokenSet::singleton($t)))* }; - ($($t:ident),* ,) => { token_set!($($t),*) }; + ($($t:expr),*) => { TokenSet::empty()$(.union(TokenSet::singleton($t)))* }; + ($($t:expr),* ,) => { token_set!($($t),*) }; } #[test] From 1583ab1558022d0fdbbc10d3a440a2d3daa4a840 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Nov 2019 17:37:22 +0300 Subject: [PATCH 24/25] Move body queries to hir_def --- crates/ra_hir/src/code_model.rs | 28 ++++++++++++------ crates/ra_hir/src/db.rs | 19 ++++-------- crates/ra_hir/src/expr.rs | 43 +++------------------------- crates/ra_hir/src/from_id.rs | 14 +++++++-- crates/ra_hir/src/from_source.rs | 4 +-- crates/ra_hir/src/source_binder.rs | 2 +- crates/ra_hir/src/ty/infer.rs | 5 ++-- crates/ra_hir/src/ty/traits/chalk.rs | 4 +-- crates/ra_hir_def/src/body.rs | 34 ++++++++++++++++++++-- crates/ra_hir_def/src/body/scope.rs | 10 ++++++- crates/ra_hir_def/src/db.rs | 12 +++++++- crates/ra_hir_def/src/lib.rs | 10 +++++++ 12 files changed, 110 insertions(+), 75 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 2fd4ccb1090..962d5a8c15f 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -8,6 +8,7 @@ use std::sync::Arc; use hir_def::{ adt::VariantData, + body::scope::ExprScopes, builtin_type::BuiltinType, type_ref::{Mutability, TypeRef}, CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, @@ -539,6 +540,7 @@ pub trait HasBody: Copy { fn infer(self, db: &impl HirDatabase) -> Arc; fn body(self, db: &impl HirDatabase) -> Arc; fn body_source_map(self, db: &impl HirDatabase) -> Arc; + fn expr_scopes(self, db: &impl HirDatabase) -> Arc; } impl HasBody for T @@ -550,11 +552,15 @@ where } fn body(self, db: &impl HirDatabase) -> Arc { - db.body(self.into()) + self.into().body(db) } fn body_source_map(self, db: &impl HirDatabase) -> Arc { - db.body_with_source_map(self.into()).1 + self.into().body_source_map(db) + } + + fn expr_scopes(self, db: &impl HirDatabase) -> Arc { + self.into().expr_scopes(db) } } @@ -564,11 +570,15 @@ impl HasBody for DefWithBody { } fn body(self, db: &impl HirDatabase) -> Arc { - db.body(self) + db.body(self.into()) } fn body_source_map(self, db: &impl HirDatabase) -> Arc { - db.body_with_source_map(self).1 + db.body_with_source_map(self.into()).1 + } + + fn expr_scopes(self, db: &impl HirDatabase) -> Arc { + db.expr_scopes(self.into()) } } @@ -662,11 +672,11 @@ impl Function { } pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc { - db.body_with_source_map(self.into()).1 + db.body_with_source_map(self.id.into()).1 } pub fn body(self, db: &impl HirDatabase) -> Arc { - db.body(self.into()) + db.body(self.id.into()) } pub fn ty(self, db: &impl HirDatabase) -> Ty { @@ -1079,7 +1089,7 @@ pub struct Local { impl Local { pub fn name(self, db: &impl HirDatabase) -> Option { - let body = db.body(self.parent); + let body = self.parent.body(db); match &body[self.pat_id] { Pat::Bind { name, .. } => Some(name.clone()), _ => None, @@ -1091,7 +1101,7 @@ impl Local { } pub fn is_mut(self, db: &impl HirDatabase) -> bool { - let body = db.body(self.parent); + let body = self.parent.body(db); match &body[self.pat_id] { Pat::Bind { mode, .. } => match mode { BindingAnnotation::Mutable | BindingAnnotation::RefMut => true, @@ -1115,7 +1125,7 @@ impl Local { } pub fn source(self, db: &impl HirDatabase) -> Source> { - let (_body, source_map) = db.body_with_source_map(self.parent); + let source_map = self.parent.body_source_map(db); let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... let root = src.file_syntax(db); src.map(|ast| ast.map(|it| it.cast().unwrap().to_node(&root), |it| it.to_node(&root))) diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 14f6b5df416..c60029c0188 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -8,7 +8,6 @@ use ra_syntax::SmolStr; use crate::{ debug::HirDebugDatabase, - expr::{Body, BodySourceMap}, generics::{GenericDef, GenericParams}, ids, impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks}, @@ -19,13 +18,14 @@ use crate::{ InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor, }, type_alias::TypeAliasData, - Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Static, - StructField, Trait, TypeAlias, + Const, ConstData, Crate, DefWithBody, FnData, Function, Module, Static, StructField, Trait, + TypeAlias, }; pub use hir_def::db::{ - CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, EnumDataQuery, InternDatabase, - InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, + BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, + EnumDataQuery, ExprScopesQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, + RawItemsWithSourceMapQuery, StructDataQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, @@ -85,9 +85,6 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { #[salsa::query_group(HirDatabaseStorage)] #[salsa::requires(salsa::Database)] pub trait HirDatabase: DefDatabase + AstDatabase { - #[salsa::invoke(crate::expr::expr_scopes_query)] - fn expr_scopes(&self, def: DefWithBody) -> Arc; - #[salsa::invoke(crate::ty::infer_query)] fn infer(&self, def: DefWithBody) -> Arc; @@ -113,12 +110,6 @@ pub trait HirDatabase: DefDatabase + AstDatabase { #[salsa::invoke(crate::ty::generic_defaults_query)] fn generic_defaults(&self, def: GenericDef) -> Substs; - #[salsa::invoke(crate::expr::body_with_source_map_query)] - fn body_with_source_map(&self, def: DefWithBody) -> (Arc, Arc); - - #[salsa::invoke(crate::expr::body_query)] - fn body(&self, def: DefWithBody) -> Arc; - #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] fn impls_in_crate(&self, krate: Crate) -> Arc; diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index f02104b2d7b..9262325f234 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -4,9 +4,9 @@ pub(crate) mod validation; use std::sync::Arc; -use ra_syntax::{ast, AstPtr}; +use ra_syntax::AstPtr; -use crate::{db::HirDatabase, DefWithBody, HasSource, Resolver}; +use crate::{db::HirDatabase, DefWithBody, HasBody, Resolver}; pub use hir_def::{ body::{ @@ -19,48 +19,13 @@ pub use hir_def::{ }, }; -pub(crate) fn body_with_source_map_query( - db: &impl HirDatabase, - def: DefWithBody, -) -> (Arc, Arc) { - let mut params = None; - - let (file_id, body) = match def { - DefWithBody::Function(f) => { - let src = f.source(db); - params = src.ast.param_list(); - (src.file_id, src.ast.body().map(ast::Expr::from)) - } - DefWithBody::Const(c) => { - let src = c.source(db); - (src.file_id, src.ast.body()) - } - DefWithBody::Static(s) => { - let src = s.source(db); - (src.file_id, src.ast.body()) - } - }; - let expander = hir_def::body::Expander::new(db, file_id, def.module(db).id); - let (body, source_map) = Body::new(db, expander, params, body); - (Arc::new(body), Arc::new(source_map)) -} - -pub(crate) fn body_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { - db.body_with_source_map(def).0 -} - -pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { - let body = db.body(def); - Arc::new(ExprScopes::new(&*body)) -} - // needs arbitrary_self_types to be a method... or maybe move to the def? pub(crate) fn resolver_for_expr( db: &impl HirDatabase, owner: DefWithBody, expr_id: ExprId, ) -> Resolver { - let scopes = db.expr_scopes(owner); + let scopes = owner.expr_scopes(db); resolver_for_scope(db, owner, scopes.scope_for(expr_id)) } @@ -70,7 +35,7 @@ pub(crate) fn resolver_for_scope( scope_id: Option, ) -> Resolver { let mut r = owner.resolver(db); - let scopes = db.expr_scopes(owner); + let scopes = owner.expr_scopes(db); let scope_chain = scopes.scope_chain(scope_id).collect::>(); for scope in scope_chain.into_iter().rev() { r = r.push_expr_scope(Arc::clone(&scopes), scope); diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index 089dbc9084a..9633ef5861b 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -3,9 +3,9 @@ //! It's unclear if we need this long-term, but it's definitelly useful while we //! are splitting the hir. -use hir_def::{AdtId, EnumVariantId, ModuleDefId}; +use hir_def::{AdtId, DefWithBodyId, EnumVariantId, ModuleDefId}; -use crate::{Adt, EnumVariant, ModuleDef}; +use crate::{Adt, DefWithBody, EnumVariant, ModuleDef}; macro_rules! from_id { ($(($id:path, $ty:path)),*) => {$( @@ -61,3 +61,13 @@ impl From for ModuleDef { } } } + +impl From for DefWithBodyId { + fn from(def: DefWithBody) -> Self { + match def { + DefWithBody::Function(it) => DefWithBodyId::FunctionId(it.id), + DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id), + DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id), + } + } +} diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 4b561c63dea..9793af85875 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -10,7 +10,7 @@ use ra_syntax::{ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, ids::{AstItemDef, LocationCtx}, - AstId, Const, Crate, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, + AstId, Const, Crate, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, }; @@ -144,7 +144,7 @@ impl Local { }; Some(res) })?; - let (_body, source_map) = db.body_with_source_map(parent); + let source_map = parent.body_source_map(db); let src = src.map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?; Some(Local { parent, pat_id }) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index e337a3d4a51..ca40e3b5448 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -146,7 +146,7 @@ impl SourceAnalyzer { let def_with_body = def_with_body_from_child_node(db, file_id, node); if let Some(def) = def_with_body { let source_map = def.body_source_map(db); - let scopes = db.expr_scopes(def); + let scopes = def.expr_scopes(db); let scope = match offset { None => scope_for(&scopes, &source_map, file_id.into(), &node), Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index c092608642d..c35378cc413 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -43,7 +43,8 @@ use crate::{ expr::{BindingAnnotation, Body, ExprId, PatId}, resolve::{Resolver, TypeNs}, ty::infer::diagnostics::InferenceDiagnostic, - Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, IntTy, Path, StructField, + Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, + StructField, }; macro_rules! ty_app { @@ -214,7 +215,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), db, owner, - body: db.body(owner), + body: owner.body(db), resolver, } } diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index de322dd523f..75351c17d51 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -22,7 +22,7 @@ use crate::{ ApplicationTy, GenericPredicate, Namespace, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }, - AssocItem, Crate, ImplBlock, Trait, TypeAlias, + AssocItem, Crate, HasBody, ImplBlock, Trait, TypeAlias, }; /// This represents a trait whose name we could not resolve. @@ -714,7 +714,7 @@ fn closure_fn_trait_impl_datum( let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait - let num_args: u16 = match &db.body(data.def)[data.expr] { + let num_args: u16 = match &data.def.body(db)[data.expr] { crate::expr::Expr::Lambda { args, .. } => args.len() as u16, _ => { log::warn!("closure for closure type {:?} not found", data); diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index c3e9d0c2353..85dc4feb0a3 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -17,7 +17,7 @@ use crate::{ expr::{Expr, ExprId, Pat, PatId}, nameres::CrateDefMap, path::Path, - ModuleId, + AstItemDef, DefWithBodyId, ModuleId, }; pub struct Expander { @@ -141,7 +141,37 @@ pub struct BodySourceMap { } impl Body { - pub fn new( + pub(crate) fn body_with_source_map_query( + db: &impl DefDatabase2, + def: DefWithBodyId, + ) -> (Arc, Arc) { + let mut params = None; + + let (file_id, module, body) = match def { + DefWithBodyId::FunctionId(f) => { + let src = f.source(db); + params = src.ast.param_list(); + (src.file_id, f.module(db), src.ast.body().map(ast::Expr::from)) + } + DefWithBodyId::ConstId(c) => { + let src = c.source(db); + (src.file_id, c.module(db), src.ast.body()) + } + DefWithBodyId::StaticId(s) => { + let src = s.source(db); + (src.file_id, s.module(db), src.ast.body()) + } + }; + let expander = Expander::new(db, file_id, module); + let (body, source_map) = Body::new(db, expander, params, body); + (Arc::new(body), Arc::new(source_map)) + } + + pub(crate) fn body_query(db: &impl DefDatabase2, def: DefWithBodyId) -> Arc { + db.body_with_source_map(def).0 + } + + fn new( db: &impl DefDatabase2, expander: Expander, params: Option, diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index dd8d06d1124..09a39e721e6 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs @@ -1,4 +1,5 @@ //! FIXME: write short doc here +use std::sync::Arc; use hir_expand::name::Name; use ra_arena::{impl_arena_id, Arena, RawId}; @@ -6,7 +7,9 @@ use rustc_hash::FxHashMap; use crate::{ body::Body, + db::DefDatabase2, expr::{Expr, ExprId, Pat, PatId, Statement}, + DefWithBodyId, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -42,7 +45,12 @@ pub struct ScopeData { } impl ExprScopes { - pub fn new(body: &Body) -> ExprScopes { + pub(crate) fn expr_scopes_query(db: &impl DefDatabase2, def: DefWithBodyId) -> Arc { + let body = db.body(def); + Arc::new(ExprScopes::new(&*body)) + } + + fn new(body: &Body) -> ExprScopes { let mut scopes = ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; let root = scopes.root_scope(); diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 29cf71a594c..40b5920d9bf 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -7,11 +7,12 @@ use ra_syntax::ast; use crate::{ adt::{EnumData, StructData}, + body::{scope::ExprScopes, Body, BodySourceMap}, nameres::{ raw::{ImportSourceMap, RawItems}, CrateDefMap, }, - EnumId, StructOrUnionId, + DefWithBodyId, EnumId, StructOrUnionId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -52,4 +53,13 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { #[salsa::invoke(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc; + + #[salsa::invoke(Body::body_with_source_map_query)] + fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc, Arc); + + #[salsa::invoke(Body::body_query)] + fn body(&self, def: DefWithBodyId) -> Arc; + + #[salsa::invoke(ExprScopes::expr_scopes_query)] + fn expr_scopes(&self, def: DefWithBodyId) -> Arc; } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 4a758bb835e..3fab7965ca6 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -374,3 +374,13 @@ impl_froms!( TypeAliasId, BuiltinType ); + +/// The defs which have a body. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum DefWithBodyId { + FunctionId(FunctionId), + StaticId(StaticId), + ConstId(ConstId), +} + +impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId); From fc9c2915c74ac120a9b52c9003f768a9a4e30a55 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Thu, 14 Nov 2019 11:47:18 -0500 Subject: [PATCH 25/25] Even if jemalloc feature is used do not use it on msvc Fixes #2233 --- crates/ra_prof/Cargo.toml | 36 ++++++++++++++++-------------- crates/ra_prof/src/lib.rs | 2 +- crates/ra_prof/src/memory_usage.rs | 4 ++-- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/crates/ra_prof/Cargo.toml b/crates/ra_prof/Cargo.toml index 7db4498c3bf..bb241258cfc 100644 --- a/crates/ra_prof/Cargo.toml +++ b/crates/ra_prof/Cargo.toml @@ -1,17 +1,19 @@ -[package] -edition = "2018" -name = "ra_prof" -version = "0.1.0" -authors = ["rust-analyzer developers"] -publish = false - -[dependencies] -once_cell = "1.0.1" -itertools = "0.8.0" -backtrace = "0.3.28" -jemallocator = { version = "0.3.2", optional = true } -jemalloc-ctl = { version = "0.3.2", optional = true } - -[features] -jemalloc = [ "jemallocator", "jemalloc-ctl" ] -cpu_profiler = [] +[package] +edition = "2018" +name = "ra_prof" +version = "0.1.0" +authors = ["rust-analyzer developers"] +publish = false + +[dependencies] +once_cell = "1.0.1" +itertools = "0.8.0" +backtrace = "0.3.28" + +[target.'cfg(not(target_env = "msvc"))'.dependencies] +jemallocator = { version = "0.3.2", optional = true } +jemalloc-ctl = { version = "0.3.2", optional = true } + +[features] +jemalloc = [ "jemallocator", "jemalloc-ctl" ] +cpu_profiler = [] diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index e5385f51b25..845b2221c8f 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -24,7 +24,7 @@ pub use crate::memory_usage::{Bytes, MemoryUsage}; // We use jemalloc mainly to get heap usage statistics, actual performance // difference is not measures. -#[cfg(feature = "jemalloc")] +#[cfg(all(feature = "jemalloc", not(target_env = "msvc")))] #[global_allocator] static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; diff --git a/crates/ra_prof/src/memory_usage.rs b/crates/ra_prof/src/memory_usage.rs index ad005ea14f1..9768f656c42 100644 --- a/crates/ra_prof/src/memory_usage.rs +++ b/crates/ra_prof/src/memory_usage.rs @@ -8,7 +8,7 @@ pub struct MemoryUsage { } impl MemoryUsage { - #[cfg(feature = "jemalloc")] + #[cfg(all(feature = "jemalloc", not(target_env = "msvc")))] pub fn current() -> MemoryUsage { jemalloc_ctl::epoch::advance().unwrap(); MemoryUsage { @@ -17,7 +17,7 @@ impl MemoryUsage { } } - #[cfg(not(feature = "jemalloc"))] + #[cfg(any(not(feature = "jemalloc"), target_env = "msvc"))] pub fn current() -> MemoryUsage { MemoryUsage { allocated: Bytes(0), resident: Bytes(0) } }