diff --git a/Cargo.lock b/Cargo.lock index 333ea6fc91ae..89678bce5e17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - [[package]] name = "addr2line" version = "0.15.2" @@ -47,11 +45,17 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" +[[package]] +name = "array_iterator" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "769af754c2afad9a410ffdfdae3c0e48b98fba3d72bfe0b5316b277e7d1566e1" + [[package]] name = "arrayvec" -version = "0.7.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "atty" @@ -611,6 +615,7 @@ dependencies = [ name = "ide_completion" version = "0.0.0" dependencies = [ + "array_iterator", "base_db", "cov-mark", "either", @@ -813,9 +818,9 @@ dependencies = [ [[package]] name = "lsp-server" -version = "0.5.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c351c75989da23b355226dc188dc2b52538a7f4f218d70fd7393c6b62b110444" +checksum = "69b18dfe0e4a380b872aa79d8e0ee6c3d7a9682466e84b83ad807c88b3545f79" dependencies = [ "crossbeam-channel", "log", diff --git a/Cargo.toml b/Cargo.toml index 4d6908fa93e9..fd3d9781fd3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -resolver = "2" +#resolver = "2" members = ["xtask/", "lib/*", "crates/*"] exclude = ["crates/proc_macro_test/imp"] diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml index 192490620150..c418d6112cb8 100644 --- a/crates/hir/Cargo.toml +++ b/crates/hir/Cargo.toml @@ -12,7 +12,7 @@ doctest = false log = "0.4.8" rustc-hash = "1.1.0" either = "1.5.3" -arrayvec = "0.7" +arrayvec = "0.5.1" itertools = "0.10.0" smallvec = "1.4.0" once_cell = "1" diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 9c74d8c5f744..406c8a26c0b6 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2669,7 +2669,7 @@ pub enum ScopeDef { } impl ScopeDef { - pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> { + pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> { let mut items = ArrayVec::new(); match (def.take_types(), def.take_values()) { diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index cc320227f803..d2f2af3c43a6 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -51,14 +51,12 @@ impl PathResolution { PathResolution::Def(ModuleDef::BuiltinType(builtin)) => { Some(TypeNs::BuiltinType((*builtin).into())) } - PathResolution::Def( - ModuleDef::Const(_) - | ModuleDef::Variant(_) - | ModuleDef::Function(_) - | ModuleDef::Module(_) - | ModuleDef::Static(_) - | ModuleDef::Trait(_), - ) => None, + PathResolution::Def(ModuleDef::Const(_)) + | PathResolution::Def(ModuleDef::Variant(_)) + | PathResolution::Def(ModuleDef::Function(_)) + | PathResolution::Def(ModuleDef::Module(_)) + | PathResolution::Def(ModuleDef::Static(_)) + | PathResolution::Def(ModuleDef::Trait(_)) => None, PathResolution::Def(ModuleDef::TypeAlias(alias)) => { Some(TypeNs::TypeAliasId((*alias).into())) } @@ -67,7 +65,8 @@ impl PathResolution { } PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), - PathResolution::AssocItem(AssocItem::Const(_) | AssocItem::Function(_)) => None, + PathResolution::AssocItem(AssocItem::Const(_)) + | PathResolution::AssocItem(AssocItem::Function(_)) => None, PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => { Some(TypeNs::TypeAliasId((*alias).into())) } diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index 603c594f2aa4..d2ef8e50d39a 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs @@ -65,7 +65,7 @@ impl<'a> Printer<'a> { fn blank(&mut self) { let mut iter = self.buf.chars().rev().fuse(); match (iter.next(), iter.next()) { - (Some('\n'), Some('\n') | None) | (None, None) => {} + (Some('\n'), Some('\n')) | (Some('\n'), None) | (None, None) => {} (Some('\n'), Some(_)) => { self.buf.push('\n'); } @@ -79,7 +79,7 @@ impl<'a> Printer<'a> { fn whitespace(&mut self) { match self.buf.chars().next_back() { - None | Some('\n' | ' ') => {} + None | Some('\n') | Some(' ') => {} _ => self.buf.push(' '), } } @@ -721,18 +721,20 @@ impl<'a> Printer<'a> { impl<'a> Write for Printer<'a> { fn write_str(&mut self, s: &str) -> fmt::Result { - for line in s.split_inclusive('\n') { + match self.buf.chars().last() { + Some('\n') | None => {} + _ => self.buf.push('\n'), + } + + for line in s.split('\n') { if self.needs_indent { - match self.buf.chars().last() { - Some('\n') | None => {} - _ => self.buf.push('\n'), - } + self.buf.push('\n'); self.buf.push_str(&" ".repeat(self.indent_level)); self.needs_indent = false; } self.buf.push_str(line); - self.needs_indent = line.ends_with('\n'); + self.needs_indent = true; } Ok(()) diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 79452bba548f..dd0155a42f88 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -1270,7 +1270,7 @@ impl DefCollector<'_> { for directive in &self.unresolved_imports { if let ImportSource::Import { id: import, use_tree } = &directive.import.source { match (directive.import.path.segments().first(), &directive.import.path.kind) { - (Some(krate), PathKind::Plain | PathKind::Abs) => { + (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => { if diagnosed_extern_crates.contains(krate) { continue; } diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index a11439c3b54b..1841fe98968c 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -605,7 +605,8 @@ fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> { ModuleDefId::ConstId(it) => ValueNs::ConstId(it), ModuleDefId::StaticId(it) => ValueNs::StaticId(it), - ModuleDefId::AdtId(AdtId::EnumId(_) | AdtId::UnionId(_)) + ModuleDefId::AdtId(AdtId::EnumId(_)) + | ModuleDefId::AdtId(AdtId::UnionId(_)) | ModuleDefId::TraitId(_) | ModuleDefId::TypeAliasId(_) | ModuleDefId::BuiltinType(_) diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 7d335582ed02..512dcd3c3642 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs @@ -187,8 +187,9 @@ impl Visibility { /// visible in unrelated modules). pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> { match (self, other) { - (Visibility::Module(_) | Visibility::Public, Visibility::Public) - | (Visibility::Public, Visibility::Module(_)) => Some(Visibility::Public), + (Visibility::Module(_), Visibility::Public) + | (Visibility::Public, Visibility::Module(_)) + | (Visibility::Public, Visibility::Public) => Some(Visibility::Public), (Visibility::Module(mod_a), Visibility::Module(mod_b)) => { if mod_a.krate != mod_b.krate { return None; diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 848522411557..05c6c3fb1644 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs @@ -146,11 +146,10 @@ impl HygieneInfo { (&self.macro_arg.1, InFile::new(loc.kind.file_id(), arg_start)) } mbe::Origin::Def => match (&*self.macro_def, self.def_start) { - ( - TokenExpander::MacroDef { def_site_token_map, .. } - | TokenExpander::MacroRules { def_site_token_map, .. }, - Some(tt), - ) => (def_site_token_map, tt), + (TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt)) + | (TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) => { + (def_site_token_map, tt) + } _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"), }, }; diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index c31426d7cc7e..33107aa2484f 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs @@ -368,11 +368,10 @@ impl ExpansionInfo { let (token_map, tt) = match origin { mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), mbe::Origin::Def => match (&*self.macro_def, self.def.as_ref()) { - ( - db::TokenExpander::MacroRules { def_site_token_map, .. } - | db::TokenExpander::MacroDef { def_site_token_map, .. }, - Some(tt), - ) => (def_site_token_map, tt.as_ref().map(|tt| tt.syntax().clone())), + (db::TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) + | (db::TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt)) => { + (def_site_token_map, tt.as_ref().map(|tt| tt.syntax().clone())) + } _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"), }, }; diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index f8280e0c5c40..f410432fa898 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml @@ -11,7 +11,7 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" itertools = "0.10.0" -arrayvec = "0.7" +arrayvec = "0.5.1" smallvec = "1.2.0" ena = "0.14.0" log = "0.4.8" diff --git a/crates/hir_ty/src/consteval.rs b/crates/hir_ty/src/consteval.rs index ab1afce081f3..6f0bf8f8c6c9 100644 --- a/crates/hir_ty/src/consteval.rs +++ b/crates/hir_ty/src/consteval.rs @@ -38,7 +38,8 @@ impl ConstExt for Const { // FIXME: support more than just evaluating literals pub fn eval_usize(expr: &Expr) -> Option<u64> { match expr { - Expr::Literal(Literal::Uint(v, None | Some(BuiltinUint::Usize))) => (*v).try_into().ok(), + Expr::Literal(Literal::Uint(v, None)) + | Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => (*v).try_into().ok(), _ => None, } } diff --git a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs index e3d640a7969e..471cd49210b0 100644 --- a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs +++ b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs @@ -84,7 +84,10 @@ impl IntRange { #[inline] fn is_integral(ty: &Ty) -> bool { match ty.kind(&Interner) { - TyKind::Scalar(Scalar::Char | Scalar::Int(_) | Scalar::Uint(_) | Scalar::Bool) => true, + TyKind::Scalar(Scalar::Char) + | TyKind::Scalar(Scalar::Int(_)) + | TyKind::Scalar(Scalar::Uint(_)) + | TyKind::Scalar(Scalar::Bool) => true, _ => false, } } @@ -378,7 +381,7 @@ impl Constructor { // Wildcards cover anything (_, Wildcard) => true, // The missing ctors are not covered by anything in the matrix except wildcards. - (Missing | Wildcard, _) => false, + (Missing, _) | (Wildcard, _) => false, (Single, Single) => true, (Variant(self_id), Variant(other_id)) => self_id == other_id, @@ -520,7 +523,7 @@ impl SplitWildcard { } } TyKind::Scalar(Scalar::Char) => unhandled(), - TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(), + TyKind::Scalar(Scalar::Int(..)) | TyKind::Scalar(Scalar::Uint(..)) => unhandled(), TyKind::Never if !cx.feature_exhaustive_patterns() && !pcx.is_top_level => { smallvec![NonExhaustive] } diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index d2e999a730f7..8a0d0d38c8c4 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -71,7 +71,11 @@ impl CoerceMany { // pointers to have a chance at getting a match. See // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 let sig = match (self.expected_ty.kind(&Interner), expr_ty.kind(&Interner)) { - (TyKind::FnDef(..) | TyKind::Closure(..), TyKind::FnDef(..) | TyKind::Closure(..)) => { + (TyKind::FnDef(..), TyKind::FnDef(..)) | +(TyKind::FnDef(..), TyKind::Closure(..)) | + (TyKind::Closure(..), TyKind::FnDef(..)) | +(TyKind::Closure(..), TyKind::Closure(..)) + => { // FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure, // we should be coercing the closure to a fn pointer of the safety of the FnDef cov_mark::hit!(coerce_fn_reification); @@ -611,7 +615,8 @@ fn safe_to_unsafe_fn_ty(fn_ty: FnPointer) -> FnPointer { fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError> { match (from, to) { - (Mutability::Mut, Mutability::Mut | Mutability::Not) + (Mutability::Mut, Mutability::Mut) + | (Mutability::Mut, Mutability::Not) | (Mutability::Not, Mutability::Not) => Ok(()), (Mutability::Not, Mutability::Mut) => Err(TypeError), } diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index f1bc6895c82c..576705047233 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -623,11 +623,11 @@ impl<'a> InferenceContext<'a> { UnaryOp::Neg => { match inner_ty.kind(&Interner) { // Fast path for builtins - TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_)) - | TyKind::InferenceVar( - _, - TyVariableKind::Integer | TyVariableKind::Float, - ) => inner_ty, + TyKind::Scalar(Scalar::Int(_)) + | TyKind::Scalar(Scalar::Uint(_)) + | TyKind::Scalar(Scalar::Float(_)) + | TyKind::InferenceVar(_, TyVariableKind::Integer) + | TyKind::InferenceVar(_, TyVariableKind::Float) => inner_ty, // Otherwise we resolve via the std::ops::Neg trait _ => self .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), @@ -636,7 +636,9 @@ impl<'a> InferenceContext<'a> { UnaryOp::Not => { match inner_ty.kind(&Interner) { // Fast path for builtins - TyKind::Scalar(Scalar::Bool | Scalar::Int(_) | Scalar::Uint(_)) + TyKind::Scalar(Scalar::Bool) + | TyKind::Scalar(Scalar::Int(_)) + | TyKind::Scalar(Scalar::Uint(_)) | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty, // Otherwise we resolve via the std::ops::Not trait _ => self @@ -763,7 +765,7 @@ impl<'a> InferenceContext<'a> { Expr::Array(array) => { let elem_ty = match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(&Interner)) { - Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st.clone(), + Some(TyKind::Array(st, _)) | Some(TyKind::Slice(st)) => st.clone(), _ => self.table.new_type_var(), }; let mut coerce = CoerceMany::new(elem_ty.clone()); diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 86e2d1b8dfab..cd8d78bcfc24 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -301,11 +301,10 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool { Expr::Literal(Literal::String(..)) => false, _ => true, }, - Pat::Bind { - mode: BindingAnnotation::Mutable | BindingAnnotation::Unannotated, - subpat: Some(subpat), - .. - } => is_non_ref_pat(body, *subpat), + Pat::Bind { mode: BindingAnnotation::Mutable, subpat: Some(subpat), .. } + | Pat::Bind { mode: BindingAnnotation::Unannotated, subpat: Some(subpat), .. } => { + is_non_ref_pat(body, *subpat) + } Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Box { .. } | Pat::Missing => false, } } diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 3d233b1e20ab..133e20b1fa91 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -309,12 +309,12 @@ pub fn def_crates( db: &dyn HirDatabase, ty: &Ty, cur_crate: CrateId, -) -> Option<ArrayVec<CrateId, 2>> { +) -> Option<ArrayVec<[CrateId; 2]>> { // Types like slice can have inherent impls in several crates, (core and alloc). // The corresponding impls are marked with lang items, so we can use them to find the required crates. macro_rules! lang_item_crate { ($($name:expr),+ $(,)?) => {{ - let mut v = ArrayVec::<LangItemTarget, 2>::new(); + let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); $( v.extend(db.lang_item(cur_crate, $name.into())); )+ diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs index 5ef6342d57bd..0222de2bc210 100644 --- a/crates/hir_ty/src/op.rs +++ b/crates/hir_ty/src/op.rs @@ -8,15 +8,17 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { match op { BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), BinaryOp::Assignment { .. } => TyBuilder::unit(), - BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => { + BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { // all integer combinations are valid here if matches!( lhs_ty.kind(&Interner), - TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) + TyKind::Scalar(Scalar::Int(_)) + | TyKind::Scalar(Scalar::Uint(_)) | TyKind::InferenceVar(_, TyVariableKind::Integer) ) && matches!( rhs_ty.kind(&Interner), - TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) + TyKind::Scalar(Scalar::Int(_)) + | TyKind::Scalar(Scalar::Uint(_)) | TyKind::InferenceVar(_, TyVariableKind::Integer) ) { lhs_ty @@ -30,15 +32,15 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { | (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_))) | (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::Float(_))) => rhs_ty, // ({int}, int) | ({int}, uint) - ( - TyKind::InferenceVar(_, TyVariableKind::Integer), - TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)), - ) => rhs_ty, + (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Int(_))) + | (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Uint(_))) => { + rhs_ty + } // (int, {int}) | (uint, {int}) - ( - TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)), - TyKind::InferenceVar(_, TyVariableKind::Integer), - ) => lhs_ty, + (TyKind::Scalar(Scalar::Int(_)), TyKind::InferenceVar(_, TyVariableKind::Integer)) + | (TyKind::Scalar(Scalar::Uint(_)), TyKind::InferenceVar(_, TyVariableKind::Integer)) => { + lhs_ty + } // ({float} | float) (TyKind::InferenceVar(_, TyVariableKind::Float), TyKind::Scalar(Scalar::Float(_))) => { rhs_ty @@ -67,15 +69,21 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { BinaryOp::Assignment { op: None } => lhs_ty, BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty.kind(&Interner) { TyKind::Scalar(_) | TyKind::Str => lhs_ty, - TyKind::InferenceVar(_, TyVariableKind::Integer | TyVariableKind::Float) => lhs_ty, + TyKind::InferenceVar(_, TyVariableKind::Integer) + | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty, _ => TyKind::Error.intern(&Interner), }, - BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => TyKind::Error.intern(&Interner), + BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { + TyKind::Error.intern(&Interner) + } BinaryOp::CmpOp(CmpOp::Ord { .. }) | BinaryOp::Assignment { op: Some(_) } | BinaryOp::ArithOp(_) => match lhs_ty.kind(&Interner) { - TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_)) => lhs_ty, - TyKind::InferenceVar(_, TyVariableKind::Integer | TyVariableKind::Float) => lhs_ty, + TyKind::Scalar(Scalar::Int(_)) + | TyKind::Scalar(Scalar::Uint(_)) + | TyKind::Scalar(Scalar::Float(_)) => lhs_ty, + TyKind::InferenceVar(_, TyVariableKind::Integer) + | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty, _ => TyKind::Error.intern(&Interner), }, } diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 076b2c8cba33..fc083a416f3f 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs @@ -3,6 +3,7 @@ use std::{array, iter}; +use arrayvec::ArrayVec; use base_db::CrateId; use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex}; use hir_def::{ @@ -30,7 +31,8 @@ pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: CrateId) -> impl Iterator<I db.lang_item(krate, "fn_mut".into()), db.lang_item(krate, "fn_once".into()), ]; - array::IntoIter::new(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait()) + // FIXME: Replace ArrayVec when into_iter is a thing on arrays + ArrayVec::from(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait()) } fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 305836f79d83..5279faa753a7 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -169,7 +169,7 @@ fn retain_adt_literal_usages( }); usages.references.retain(|_, it| !it.is_empty()); } - Definition::ModuleDef(hir::ModuleDef::Adt(_) | hir::ModuleDef::Variant(_)) => { + Definition::ModuleDef(hir::ModuleDef::Adt(_)) | Definition::ModuleDef(hir::ModuleDef::Variant(_)) => { refs.for_each(|it| { it.retain(|reference| reference.name.as_name_ref().map_or(false, is_lit_name_ref)) }); diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index b8e62a1a860d..b4085818733e 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -296,7 +296,7 @@ fn traverse( Some(parent) => { // We only care Name and Name_ref match (token.kind(), parent.kind()) { - (IDENT, NAME | NAME_REF) => parent.into(), + (IDENT, NAME) | (IDENT, NAME_REF) => parent.into(), _ => token.into(), } } @@ -312,7 +312,7 @@ fn traverse( Some(parent) => { // We only care Name and Name_ref match (token.kind(), parent.kind()) { - (IDENT, NAME | NAME_REF) => parent.into(), + (IDENT, NAME) | (IDENT, NAME_REF) => parent.into(), _ => token.into(), } } diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index 4f0b1f5b7905..1a85dbd80161 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs @@ -1407,7 +1407,7 @@ fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) for (param, usages) in usages_for_param { for usage in usages { match usage.syntax().ancestors().skip(1).find_map(ast::Expr::cast) { - Some(ast::Expr::MethodCallExpr(_) | ast::Expr::FieldExpr(_)) => { + Some(ast::Expr::MethodCallExpr(_)) | Some(ast::Expr::FieldExpr(_)) => { // do nothing } Some(ast::Expr::RefExpr(node)) diff --git a/crates/ide_assists/src/handlers/remove_dbg.rs b/crates/ide_assists/src/handlers/remove_dbg.rs index e6aab9e84813..da48c26503a5 100644 --- a/crates/ide_assists/src/handlers/remove_dbg.rs +++ b/crates/ide_assists/src/handlers/remove_dbg.rs @@ -71,31 +71,69 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let wrap = match ast::Expr::cast(parent) { Some(parent) => match (expr, parent) { (ast::Expr::CastExpr(_), ast::Expr::CastExpr(_)) => false, - ( - ast::Expr::BoxExpr(_) | ast::Expr::PrefixExpr(_) | ast::Expr::RefExpr(_), - ast::Expr::AwaitExpr(_) - | ast::Expr::CallExpr(_) - | ast::Expr::CastExpr(_) - | ast::Expr::FieldExpr(_) - | ast::Expr::IndexExpr(_) - | ast::Expr::MethodCallExpr(_) - | ast::Expr::RangeExpr(_) - | ast::Expr::TryExpr(_), - ) => true, - ( - ast::Expr::BinExpr(_) | ast::Expr::CastExpr(_) | ast::Expr::RangeExpr(_), - ast::Expr::AwaitExpr(_) - | ast::Expr::BinExpr(_) - | ast::Expr::CallExpr(_) - | ast::Expr::CastExpr(_) - | ast::Expr::FieldExpr(_) - | ast::Expr::IndexExpr(_) - | ast::Expr::MethodCallExpr(_) - | ast::Expr::PrefixExpr(_) - | ast::Expr::RangeExpr(_) - | ast::Expr::RefExpr(_) - | ast::Expr::TryExpr(_), - ) => true, + + (ast::Expr::BoxExpr(_), ast::Expr::AwaitExpr(_)) | + (ast::Expr::BoxExpr(_), ast::Expr::CallExpr(_)) | + (ast::Expr::BoxExpr(_), ast::Expr::CastExpr(_)) | + (ast::Expr::BoxExpr(_), ast::Expr::FieldExpr(_)) | + (ast::Expr::BoxExpr(_), ast::Expr::IndexExpr(_)) | + (ast::Expr::BoxExpr(_), ast::Expr::MethodCallExpr(_)) | + (ast::Expr::BoxExpr(_), ast::Expr::RangeExpr(_)) | + (ast::Expr::BoxExpr(_), ast::Expr::TryExpr(_)) => true, + + (ast::Expr::PrefixExpr(_), ast::Expr::AwaitExpr(_)) | + (ast::Expr::PrefixExpr(_), ast::Expr::CallExpr(_)) | + (ast::Expr::PrefixExpr(_), ast::Expr::CastExpr(_)) | + (ast::Expr::PrefixExpr(_), ast::Expr::FieldExpr(_)) | + (ast::Expr::PrefixExpr(_), ast::Expr::IndexExpr(_)) | + (ast::Expr::PrefixExpr(_), ast::Expr::MethodCallExpr(_)) | + (ast::Expr::PrefixExpr(_), ast::Expr::RangeExpr(_)) | + (ast::Expr::PrefixExpr(_), ast::Expr::TryExpr(_)) => true, + + (ast::Expr::RefExpr(_), ast::Expr::AwaitExpr(_)) | + (ast::Expr::RefExpr(_), ast::Expr::CallExpr(_)) | + (ast::Expr::RefExpr(_), ast::Expr::CastExpr(_)) | + (ast::Expr::RefExpr(_), ast::Expr::FieldExpr(_)) | + (ast::Expr::RefExpr(_), ast::Expr::IndexExpr(_)) | + (ast::Expr::RefExpr(_), ast::Expr::MethodCallExpr(_)) | + (ast::Expr::RefExpr(_), ast::Expr::RangeExpr(_)) | + (ast::Expr::RefExpr(_), ast::Expr::TryExpr(_)) => true, + + (ast::Expr::BinExpr(_), ast::Expr::AwaitExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::BinExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::CallExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::CastExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::FieldExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::IndexExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::MethodCallExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::PrefixExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::RangeExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::RefExpr(_)) | + (ast::Expr::BinExpr(_), ast::Expr::TryExpr(_)) => true, + + (ast::Expr::CastExpr(_), ast::Expr::AwaitExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::BinExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::CallExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::FieldExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::IndexExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::MethodCallExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::PrefixExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::RangeExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::RefExpr(_)) | + (ast::Expr::CastExpr(_), ast::Expr::TryExpr(_)) => true, + + (ast::Expr::RangeExpr(_), ast::Expr::AwaitExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::BinExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::CallExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::CastExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::FieldExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::IndexExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::MethodCallExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::PrefixExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::RangeExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::RefExpr(_)) | + (ast::Expr::RangeExpr(_), ast::Expr::TryExpr(_)) => true, + _ => false, }, None => false, diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs index 5cd3642ce0d8..8c3d307b3f3f 100644 --- a/crates/ide_assists/src/tests.rs +++ b/crates/ide_assists/src/tests.rs @@ -182,10 +182,9 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: "unresolved assist should not contain source changes" ), (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"), - ( - None, - ExpectedResult::After(_) | ExpectedResult::Target(_) | ExpectedResult::Unresolved, - ) => { + (None, ExpectedResult::After(_)) + | (None, ExpectedResult::Target(_)) + | (None, ExpectedResult::Unresolved) => { panic!("code action is not applicable") } (None, ExpectedResult::NotApplicable) => (), diff --git a/crates/ide_completion/Cargo.toml b/crates/ide_completion/Cargo.toml index 447744da17c2..d2dda48c68c5 100644 --- a/crates/ide_completion/Cargo.toml +++ b/crates/ide_completion/Cargo.toml @@ -22,6 +22,7 @@ text_edit = { path = "../text_edit", version = "0.0.0" } base_db = { path = "../base_db", version = "0.0.0" } ide_db = { path = "../ide_db", version = "0.0.0" } profile = { path = "../profile", version = "0.0.0" } +array_iterator = "1.8.0" # completions crate should depend only on the top-level `hir` package. if you need # something from some `hir_xxx` subpackage, reexport the API via `hir`. diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs index 53cee3f4e254..a6090f3c64db 100644 --- a/crates/ide_completion/src/completions/attribute.rs +++ b/crates/ide_completion/src/completions/attribute.rs @@ -3,6 +3,7 @@ //! This module uses a bit of static metadata to provide completions //! for built-in attributes. +use array_iterator::ArrayIterator; use hir::HasAttrs; use ide_db::helpers::generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}; use once_cell::sync::Lazy; @@ -168,7 +169,7 @@ macro_rules! attrs { #[rustfmt::skip] static KIND_TO_ATTRIBUTES: Lazy<FxHashMap<SyntaxKind, &[&str]>> = Lazy::new(|| { use SyntaxKind::*; - std::array::IntoIter::new([ + ArrayIterator::new([ ( SOURCE_FILE, attrs!( diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index ed0f902017a7..b2d5d0054266 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -86,11 +86,9 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon // Don't suggest attribute macros and derives. hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(), // no values in type places - hir::ScopeDef::ModuleDef( - hir::ModuleDef::Function(_) - | hir::ModuleDef::Variant(_) - | hir::ModuleDef::Static(_), - ) + hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(_)) + | hir::ScopeDef::ModuleDef(hir::ModuleDef::Variant(_)) + | hir::ScopeDef::ModuleDef(hir::ModuleDef::Static(_)) | hir::ScopeDef::Local(_) => !ctx.expects_type(), // unless its a constant in a generic arg list position hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) => { @@ -104,13 +102,9 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon } } } - hir::PathResolution::Def( - def - @ - (hir::ModuleDef::Adt(_) - | hir::ModuleDef::TypeAlias(_) - | hir::ModuleDef::BuiltinType(_)), - ) => { + hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_)) + | hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) + | hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => { if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def { add_enum_variants(acc, ctx, e); } diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index facfe005186f..1f5faeb7be27 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -1,5 +1,6 @@ //! Completion of names from the current scope, e.g. locals and imported items. +use array_iterator::ArrayIterator; use hir::ScopeDef; use syntax::{ast, AstNode}; @@ -19,11 +20,11 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC } }); - std::array::IntoIter::new(["self::", "super::", "crate::"]) + ArrayIterator::new(["self::", "super::", "crate::"]) .for_each(|kw| acc.add_keyword(ctx, kw)); return; } - std::array::IntoIter::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw)); + ArrayIterator::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw)); if ctx.expects_item() || ctx.expects_assoc_item() { // only show macros in {Assoc}ItemList @@ -44,7 +45,8 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC ctx.scope.process_all_names(&mut |name, res| { let add_resolution = match res { ScopeDef::MacroDef(mac) => mac.is_fn_like(), - ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => true, + ScopeDef::ModuleDef(hir::ModuleDef::Trait(_)) | + ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true, _ => false, }; if add_resolution { @@ -92,11 +94,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC // Don't suggest attribute macros and derives. ScopeDef::MacroDef(mac) => mac.is_fn_like(), // no values in type places - ScopeDef::ModuleDef( - hir::ModuleDef::Function(_) - | hir::ModuleDef::Variant(_) - | hir::ModuleDef::Static(_), - ) + ScopeDef::ModuleDef(hir::ModuleDef::Function(_)) + | ScopeDef::ModuleDef(hir::ModuleDef::Variant(_)) + | ScopeDef::ModuleDef(hir::ModuleDef::Static(_)) | ScopeDef::Local(_) => !ctx.expects_type(), // unless its a constant in a generic arg list position ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index f0da98739fd3..17001406cd99 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -242,23 +242,24 @@ impl<'a> CompletionContext<'a> { } pub(crate) fn expects_assoc_item(&self) -> bool { - matches!(self.completion_location, Some(ImmediateLocation::Trait | ImmediateLocation::Impl)) + matches!( + self.completion_location, + Some(ImmediateLocation::Trait) | Some(ImmediateLocation::Impl) + ) } pub(crate) fn has_dot_receiver(&self) -> bool { matches!( &self.completion_location, - Some(ImmediateLocation::FieldAccess { receiver, .. } | ImmediateLocation::MethodCall { receiver,.. }) + Some(ImmediateLocation::FieldAccess { receiver, .. }) | Some(ImmediateLocation::MethodCall { receiver,.. }) if receiver.is_some() ) } pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> { match &self.completion_location { - Some( - ImmediateLocation::MethodCall { receiver, .. } - | ImmediateLocation::FieldAccess { receiver, .. }, - ) => receiver.as_ref(), + Some(ImmediateLocation::MethodCall { receiver, .. }) + | Some(ImmediateLocation::FieldAccess { receiver, .. }) => receiver.as_ref(), _ => None, } } @@ -282,28 +283,28 @@ impl<'a> CompletionContext<'a> { pub(crate) fn expects_ident_pat_or_ref_expr(&self) -> bool { matches!( self.completion_location, - Some(ImmediateLocation::IdentPat | ImmediateLocation::RefExpr) + Some(ImmediateLocation::IdentPat) | Some(ImmediateLocation::RefExpr) ) } pub(crate) fn expect_field(&self) -> bool { matches!( self.completion_location, - Some(ImmediateLocation::RecordField | ImmediateLocation::TupleField) + Some(ImmediateLocation::RecordField) | Some(ImmediateLocation::TupleField) ) } pub(crate) fn in_use_tree(&self) -> bool { matches!( self.completion_location, - Some(ImmediateLocation::Use | ImmediateLocation::UseTree) + Some(ImmediateLocation::Use) | Some(ImmediateLocation::UseTree) ) } pub(crate) fn has_impl_or_trait_prev_sibling(&self) -> bool { matches!( self.prev_sibling, - Some(ImmediatePrevSibling::ImplDefType | ImmediatePrevSibling::TraitDefName) + Some(ImmediatePrevSibling::ImplDefType) | Some(ImmediatePrevSibling::TraitDefName) ) } @@ -324,16 +325,14 @@ impl<'a> CompletionContext<'a> { || self.previous_token_is(T![unsafe]) || matches!( self.prev_sibling, - Some(ImmediatePrevSibling::Attribute | ImmediatePrevSibling::Visibility) + Some(ImmediatePrevSibling::Attribute) | Some(ImmediatePrevSibling::Visibility) ) || matches!( self.completion_location, - Some( - ImmediateLocation::Attribute(_) - | ImmediateLocation::ModDeclaration(_) - | ImmediateLocation::RecordPat(_) - | ImmediateLocation::RecordExpr(_) - ) + Some(ImmediateLocation::Attribute(_)) + | Some(ImmediateLocation::ModDeclaration(_)) + | Some(ImmediateLocation::RecordPat(_)) + | Some(ImmediateLocation::RecordExpr(_)) ) } @@ -707,8 +706,8 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> { fn has_ref(token: &SyntaxToken) -> bool { let mut token = token.clone(); - for skip in [WHITESPACE, IDENT, T![mut]] { - if token.kind() == skip { + for skip in [WHITESPACE, IDENT, T![mut]].iter() { + if &token.kind() == skip { token = match token.prev_token() { Some(it) => it, None => return false, diff --git a/crates/ide_completion/src/render/builder_ext.rs b/crates/ide_completion/src/render/builder_ext.rs index 33d3a5ee1889..749dfc665a02 100644 --- a/crates/ide_completion/src/render/builder_ext.rs +++ b/crates/ide_completion/src/render/builder_ext.rs @@ -32,7 +32,7 @@ impl Builder { cov_mark::hit!(no_parens_in_use_item); return false; } - if matches!(ctx.path_call_kind(), Some(CallKind::Expr | CallKind::Pat)) + if matches!(ctx.path_call_kind(), Some(CallKind::Expr) | Some(CallKind::Pat)) | matches!( ctx.completion_location, Some(ImmediateLocation::MethodCall { has_parens: true, .. }) diff --git a/crates/ide_completion/src/tests/sourcegen.rs b/crates/ide_completion/src/tests/sourcegen.rs index ed3ac7203b9f..c48cefd7bd54 100644 --- a/crates/ide_completion/src/tests/sourcegen.rs +++ b/crates/ide_completion/src/tests/sourcegen.rs @@ -56,16 +56,51 @@ fn generate_lint_descriptor(buf: &mut String) { .skip(1) .filter(|l| !l.is_empty()) .map(|line| { - let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); - let (_default_level, description) = - rest.trim().split_once(char::is_whitespace).unwrap(); - (name.trim(), Cow::Borrowed(description.trim())) + let mut name: &str = ""; + let mut _default_level: &str= ""; + let mut description: String = "".to_string(); + let mut splitted = line.trim().split(char::is_whitespace); + let mut piece = splitted.next(); + while !piece.is_some() { + match piece{ + None => piece = splitted.next(), + Some(piece_v) => {name = piece_v; break;} + } + } + while !piece.is_some() { + match piece{ + None => piece = splitted.next(), + Some(piece_v) => {_default_level = piece_v; break;} + } + } + while !piece.is_some() { + match piece{ + None => piece = splitted.next(), + Some(_piece_v) => {description = splitted.collect::<Vec<&str>>().join(" "); break;} + } + } + (name.trim(), Cow::Owned(description.trim().to_string())) }) .collect::<Vec<_>>(); lints.extend( stdout[start_lint_groups..end_lint_groups].lines().skip(1).filter(|l| !l.is_empty()).map( |line| { - let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); + let mut name: &str = ""; + let mut lints: String = "".to_string(); + let mut splitted = line.trim().split(char::is_whitespace); + let mut piece = splitted.next(); + while !piece.is_some() { + match piece{ + None => piece = splitted.next(), + Some(piece_v) => {name = piece_v; break;} + } + } + while !piece.is_some() { + match piece{ + None => piece = splitted.next(), + Some(piece_v) => {lints = splitted.collect::<Vec<&str>>().join(" "); break;} + } + } (name.trim(), format!("lint group for: {}", lints.trim()).into()) }, ), diff --git a/crates/ide_db/src/line_index.rs b/crates/ide_db/src/line_index.rs index 816edfe6a8e2..8e9d8cca233d 100644 --- a/crates/ide_db/src/line_index.rs +++ b/crates/ide_db/src/line_index.rs @@ -3,6 +3,7 @@ use std::iter; use rustc_hash::FxHashMap; +use stdx::partition_point; use syntax::{TextRange, TextSize}; #[derive(Clone, Debug, PartialEq, Eq)] @@ -96,7 +97,7 @@ impl LineIndex { } pub fn line_col(&self, offset: TextSize) -> LineCol { - let line = self.newlines.partition_point(|&it| it <= offset) - 1; + let line = partition_point(&self.newlines, |&it| it <= offset) - 1; let line_start_offset = self.newlines[line]; let col = offset - line_start_offset; LineCol { line: line as u32, col: col.into() } @@ -117,8 +118,8 @@ impl LineIndex { } pub fn lines(&self, range: TextRange) -> impl Iterator<Item = TextRange> + '_ { - let lo = self.newlines.partition_point(|&it| it < range.start()); - let hi = self.newlines.partition_point(|&it| it <= range.end()); + let lo = partition_point(&self.newlines, |&it| it < range.start()); + let hi = partition_point(&self.newlines, |&it| it <= range.end()); let all = iter::once(range.start()) .chain(self.newlines[lo..hi].iter().copied()) .chain(iter::once(range.end())); diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 0d694b1a7820..5c4680d193c0 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs @@ -804,17 +804,33 @@ impl<'a> TtIter<'a> { }; match (punct.char, second, third) { - ('.', '.', Some('.' | '=')) | ('<', '<', Some('=')) | ('>', '>', Some('=')) => { + ('.', '.', Some('.')) + | ('.', '.', Some('=')) + | ('<', '<', Some('=')) + | ('>', '>', Some('=')) => { let tt2 = self.next().unwrap().clone(); let tt3 = self.next().unwrap().clone(); Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into()) } - ('-' | '!' | '*' | '/' | '&' | '%' | '^' | '+' | '<' | '=' | '>' | '|', '=', _) - | ('-' | '=' | '>', '>', _) + ('-', '=', _) + | ('-', '>', _) | (':', ':', _) + | ('!', '=', _) | ('.', '.', _) + | ('*', '=', _) + | ('/', '=', _) | ('&', '&', _) + | ('&', '=', _) + | ('%', '=', _) + | ('^', '=', _) + | ('+', '=', _) | ('<', '<', _) + | ('<', '=', _) + | ('=', '=', _) + | ('=', '>', _) + | ('>', '=', _) + | ('>', '>', _) + | ('|', '=', _) | ('|', '|', _) => { let tt2 = self.next().unwrap().clone(); Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2] }.into()) diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs index 8f028c619415..205b9ffa5f3e 100644 --- a/crates/parser/src/grammar/params.rs +++ b/crates/parser/src/grammar/params.rs @@ -194,7 +194,8 @@ fn opt_self_param(p: &mut Parser, m: Marker) -> Result<(), Marker> { if !matches!( (p.current(), la1, la2, la3), (T![&], T![self], _, _) - | (T![&], T![mut] | LIFETIME_IDENT, T![self], _) + | (T![&], T![mut], T![self], _) + | (T![&], LIFETIME_IDENT, T![self], _) | (T![&], LIFETIME_IDENT, T![mut], T![self]) ) { return Err(m); diff --git a/crates/project_model/src/cfg_flag.rs b/crates/project_model/src/cfg_flag.rs index bfdfd458fbfc..e92962cf6727 100644 --- a/crates/project_model/src/cfg_flag.rs +++ b/crates/project_model/src/cfg_flag.rs @@ -4,6 +4,7 @@ use std::str::FromStr; use cfg::CfgOptions; +use stdx::split_once; #[derive(Clone, Eq, PartialEq, Debug)] pub enum CfgFlag { @@ -14,7 +15,7 @@ pub enum CfgFlag { impl FromStr for CfgFlag { type Err = String; fn from_str(s: &str) -> Result<Self, Self::Err> { - let res = match s.split_once('=') { + let res = match split_once(s, '=') { Some((key, value)) => { if !(value.starts_with('"') && value.ends_with('"')) { return Err(format!("Invalid cfg ({:?}), value should be in quotes", s)); diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 9ff95d004662..3400875eda75 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -32,7 +32,7 @@ serde_path_to_error = "0.1" threadpool = "1.7.1" rayon = "1.5" mimalloc = { version = "0.1.19", default-features = false, optional = true } -lsp-server = "0.5.1" +lsp-server = "0.5.0" tracing = "0.1" tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } tracing-tree = { version = "0.1.4" } diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 95751cae6db3..eca9e6d04dcc 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -274,13 +274,7 @@ impl GlobalState { .flat_map(|it| it.to_roots(workspace_build_data.as_ref())) .filter(|it| it.is_member) .flat_map(|root| { - root.include.into_iter().flat_map(|it| { - [ - format!("{}/**/*.rs", it.display()), - format!("{}/**/Cargo.toml", it.display()), - format!("{}/**/Cargo.lock", it.display()), - ] - }) + root.include.into_iter().map(|it| format!("{}/**/*.rs", it.display())) }) .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index e83d5db437d1..ed2c7b31ed03 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -65,6 +65,20 @@ pub fn replace(buf: &mut String, from: char, to: &str) { *buf = buf.replace(from, to) } +// https://github.com/rust-lang/rust/issues/74773 +pub fn split_once(haystack: &str, delim: char) -> Option<(&str, &str)> { + let mut split = haystack.splitn(2, delim); + let prefix = split.next()?; + let suffix = split.next()?; + Some((prefix, suffix)) +} +pub fn rsplit_once(haystack: &str, delim: char) -> Option<(&str, &str)> { + let mut split = haystack.rsplitn(2, delim); + let suffix = split.next()?; + let prefix = split.next()?; + Some((prefix, suffix)) +} + pub fn trim_indent(mut text: &str) -> String { if text.starts_with('\n') { text = &text[1..]; @@ -75,7 +89,7 @@ pub fn trim_indent(mut text: &str) -> String { .map(|it| it.len() - it.trim_start().len()) .min() .unwrap_or(0); - text.split_inclusive('\n') + lines_with_ends(text) .map( |line| { if line.len() <= indent { @@ -88,12 +102,70 @@ pub fn trim_indent(mut text: &str) -> String { .collect() } +pub fn lines_with_ends(text: &str) -> LinesWithEnds { + LinesWithEnds { text } +} + +pub struct LinesWithEnds<'a> { + text: &'a str, +} + +impl<'a> Iterator for LinesWithEnds<'a> { + type Item = &'a str; + fn next(&mut self) -> Option<&'a str> { + if self.text.is_empty() { + return None; + } + let idx = self.text.find('\n').map_or(self.text.len(), |it| it + 1); + let (res, next) = self.text.split_at(idx); + self.text = next; + Some(res) + } +} + +/// Returns `idx` such that: +/// +/// ```text +/// ∀ x in slice[..idx]: pred(x) +/// && ∀ x in slice[idx..]: !pred(x) +/// ``` +/// +/// https://github.com/rust-lang/rust/issues/73831 +pub fn partition_point<T, P>(slice: &[T], mut pred: P) -> usize +where + P: FnMut(&T) -> bool, +{ + let mut left = 0; + let mut right = slice.len(); + + while left != right { + let mid = left + (right - left) / 2; + // SAFETY: + // When left < right, left <= mid < right. + // Therefore left always increases and right always decreases, + // and either of them is selected. + // In both cases left <= right is satisfied. + // Therefore if left < right in a step, + // left <= right is satisfied in the next step. + // Therefore as long as left != right, 0 <= left < right <= len is satisfied + // and if this case 0 <= mid < len is satisfied too. + let value = unsafe { slice.get_unchecked(mid) }; + if pred(value) { + left = mid + 1; + } else { + right = mid; + } + } + + left +} + pub fn equal_range_by<T, F>(slice: &[T], mut key: F) -> ops::Range<usize> where F: FnMut(&T) -> Ordering, { - let start = slice.partition_point(|it| key(it) == Ordering::Less); - let len = slice[start..].partition_point(|it| key(it) == Ordering::Equal); + let start = partition_point(slice, |it| key(it) == Ordering::Less); + let len = partition_point(&slice[start..], |it| key(it) == Ordering::Equal); start..start + len } diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index e0fb33933c62..2cb5597d7f6f 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml @@ -15,7 +15,7 @@ itertools = "0.10.0" rowan = "=0.13.0-pre.7" rustc_lexer = { version = "725.0.0", package = "rustc-ap-rustc_lexer" } rustc-hash = "1.1.0" -arrayvec = "0.7" +arrayvec = "0.5.1" once_cell = "1.3.1" indexmap = "1.4.0" smol_str = { version = "0.1.15", features = ["serde"] } diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs index 44656267fed5..0aa40bbb7232 100644 --- a/crates/test_utils/src/fixture.rs +++ b/crates/test_utils/src/fixture.rs @@ -62,7 +62,7 @@ //! ``` use rustc_hash::FxHashMap; -use stdx::trim_indent; +use stdx::{lines_with_ends, split_once, trim_indent}; #[derive(Debug, Eq, PartialEq)] pub struct Fixture { @@ -107,14 +107,15 @@ impl Fixture { let mut res: Vec<Fixture> = Vec::new(); if fixture.starts_with("//- minicore:") { - let first_line = fixture.split_inclusive('\n').next().unwrap(); - mini_core = Some(MiniCore::parse(first_line)); + let first_line = fixture.split('\n').next().unwrap().to_owned() + "\n"; + + mini_core = Some(MiniCore::parse(&first_line)); fixture = &fixture[first_line.len()..]; } let default = if fixture.contains("//-") { None } else { Some("//- /main.rs") }; - for (ix, line) in default.into_iter().chain(fixture.split_inclusive('\n')).enumerate() { + for (ix, line) in default.into_iter().chain(lines_with_ends(&fixture)).enumerate() { if line.contains("//-") { assert!( line.starts_with("//-"), @@ -164,16 +165,28 @@ impl Fixture { let mut env = FxHashMap::default(); let mut introduce_new_source_root = false; for component in components[1..].iter() { - let (key, value) = component - .split_once(':') - .unwrap_or_else(|| panic!("invalid meta line: {:?}", meta)); + let mut splitted = component.split(':'); + let key: &str; + let value: &str; + match splitted.next() { + Some(key_part) => { + match splitted.next() { + Some(value_part) => { + key = key_part; + value = value_part; + } + None => {panic!("invalid meta line: {:?}", meta);} + } + } + None => {panic!("invalid meta line: {:?}", meta);} + } match key { "crate" => krate = Some(value.to_string()), "deps" => deps = value.split(',').map(|it| it.to_string()).collect(), "edition" => edition = Some(value.to_string()), "cfg" => { for entry in value.split(',') { - match entry.split_once('=') { + match split_once(entry, '=') { Some((k, v)) => cfg_key_values.push((k.to_string(), v.to_string())), None => cfg_atoms.push(entry.to_string()), } @@ -181,7 +194,7 @@ impl Fixture { } "env" => { for key in value.split(',') { - if let Some((k, v)) = key.split_once('=') { + if let Some((k, v)) = split_once(key, '=') { env.insert(k.into(), v.into()); } } @@ -237,7 +250,7 @@ impl MiniCore { pub fn source_code(mut self) -> String { let mut buf = String::new(); let raw_mini_core = include_str!("./minicore.rs"); - let mut lines = raw_mini_core.split_inclusive('\n'); + let mut lines = raw_mini_core.split('\n'); let mut parsing_flags = false; let mut implications = Vec::new(); @@ -245,7 +258,7 @@ impl MiniCore { // Parse `//!` preamble and extract flags and dependencies. for line in lines.by_ref() { let line = match line.strip_prefix("//!") { - Some(it) => it, + Some(it) => it.to_string() + "\n", None => { assert!(line.trim().is_empty()); break; @@ -253,14 +266,33 @@ impl MiniCore { }; if parsing_flags { - let (flag, deps) = line.split_once(':').unwrap(); + let flag: String; + let deps: String; + let mut splitted = line.split(':'); + match splitted.next() { + Some(flag_v) => { + flag = flag_v.to_owned(); + match splitted.next() { + Some(deps_v) => { + deps = deps_v.to_owned(); + }, + None => { + deps = "".to_owned(); + } + } + }, + None => { + flag = "".to_owned(); + deps = "".to_owned(); + } + } let flag = flag.trim(); - self.valid_flags.push(flag.to_string()); + self.valid_flags.push(flag.to_string().to_owned()); for dep in deps.split(", ") { let dep = dep.trim(); if !dep.is_empty() { - self.assert_valid_flag(dep); - implications.push((flag, dep)); + self.assert_valid_flag(&dep); + implications.push((flag.to_owned(), dep.to_owned())); } } } @@ -277,8 +309,8 @@ impl MiniCore { // Fixed point loop to compute transitive closure of flags. loop { let mut changed = false; - for &(u, v) in implications.iter() { - if self.has_flag(u) && !self.has_flag(v) { + for (u, v) in implications.iter() { + if self.has_flag(&u) && !self.has_flag(&v) { self.activated_flags.push(v.to_string()); changed = true; } diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index d9c22c1803e1..e1d8e8429fbf 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs @@ -18,7 +18,7 @@ use std::{ }; use profile::StopWatch; -use stdx::is_ci; +use stdx::{is_ci, lines_with_ends}; use text_size::{TextRange, TextSize}; pub use dissimilar::diff as __diff; @@ -222,7 +222,7 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { let mut line_start_map = BTreeMap::new(); let mut line_start: TextSize = 0.into(); let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); - for line in text.split_inclusive('\n') { + for line in lines_with_ends(text) { let mut this_line_annotations = Vec::new(); let line_length = if let Some(idx) = line.find("//") { let annotation_offset = TextSize::of(&line[..idx + "//".len()]); diff --git a/crates/vfs/src/vfs_path.rs b/crates/vfs/src/vfs_path.rs index 0ad56e00d7cb..08e7090dce62 100644 --- a/crates/vfs/src/vfs_path.rs +++ b/crates/vfs/src/vfs_path.rs @@ -390,7 +390,8 @@ impl VirtualPath { match (file_stem, extension) { (None, None) => None, - (None | Some(""), Some(_)) => Some((file_name, None)), + (None, Some(_)) => Some((file_name, None)), + ( Some(""), Some(_)) => Some((file_name, None)), (Some(file_stem), extension) => Some((file_stem, extension)), } } diff --git a/xtask/src/install.rs b/xtask/src/install.rs index 64ab12b42a9a..91d6a28533e5 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs @@ -8,7 +8,7 @@ use xshell::{cmd, pushd}; use crate::flags; // Latest stable, feel free to send a PR if this lags behind. -const REQUIRED_RUST_VERSION: u32 = 53; +const REQUIRED_RUST_VERSION: u32 = 51; impl flags::Install { pub(crate) fn run(self) -> Result<()> {