From ccd1b0800a5de5e046e6e9a4b6f49030c1ce3639 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 28 Nov 2019 12:50:26 +0300 Subject: Rename Source -> InFile --- crates/ra_hir_def/src/path.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 6810a26db..10688df4d 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -13,7 +13,7 @@ use ra_syntax::{ AstNode, }; -use crate::{type_ref::TypeRef, Source}; +use crate::{type_ref::TypeRef, InFile}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { @@ -67,7 +67,7 @@ pub enum PathKind { impl Path { /// Calls `cb` with all paths, represented by this use item. pub(crate) fn expand_use_item( - item_src: Source, + item_src: InFile, hygiene: &Hygiene, mut cb: impl FnMut(Path, &ast::UseTree, bool, Option), ) { -- cgit v1.2.3 From 4992d2bf79e9da6db759eb8e1715f90f31ec7eb9 Mon Sep 17 00:00:00 2001 From: oxalica Date: Fri, 29 Nov 2019 03:10:16 +0800 Subject: Infer range types --- crates/ra_hir_def/src/path.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 10688df4d..ff252fe44 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -409,6 +409,36 @@ pub mod known { Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE]) } + pub fn std_ops_range() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TYPE]) + } + + pub fn std_ops_range_from() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FROM_TYPE]) + } + + pub fn std_ops_range_full() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FULL_TYPE]) + } + + pub fn std_ops_range_inclusive() -> Path { + Path::from_simple_segments( + PathKind::Abs, + vec![name::STD, name::OPS, name::RANGE_INCLUSIVE_TYPE], + ) + } + + pub fn std_ops_range_to() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TO_TYPE]) + } + + pub fn std_ops_range_to_inclusive() -> Path { + Path::from_simple_segments( + PathKind::Abs, + vec![name::STD, name::OPS, name::RANGE_TO_INCLUSIVE_TYPE], + ) + } + pub fn std_result_result() -> Path { Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE]) } -- cgit v1.2.3 From 009437f5d9949d2276aa26040e03af0ab328acf3 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Tue, 3 Dec 2019 11:07:56 -0500 Subject: Replace `ra_hir_expand::either` with crate --- crates/ra_hir_def/src/path.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index ff252fe44..3030dcdf6 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -2,8 +2,8 @@ use std::{iter, sync::Arc}; +use either::Either; use hir_expand::{ - either::Either, hygiene::Hygiene, name::{self, AsName, Name}, }; @@ -111,7 +111,7 @@ impl Path { ast::PathSegmentKind::Name(name_ref) => { // FIXME: this should just return name match hygiene.name_ref_to_name(name_ref) { - Either::A(name) => { + Either::Left(name) => { let args = segment .type_arg_list() .and_then(GenericArgs::from_ast) @@ -125,7 +125,7 @@ impl Path { let segment = PathSegment { name, args_and_bindings: args }; segments.push(segment); } - Either::B(crate_id) => { + Either::Right(crate_id) => { kind = PathKind::DollarCrate(crate_id); break; } @@ -347,7 +347,7 @@ fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Opt let res = match segment.kind()? { ast::PathSegmentKind::Name(name_ref) => { match hygiene.name_ref_to_name(name_ref) { - Either::A(name) => { + Either::Left(name) => { // no type args in use let mut res = prefix.unwrap_or_else(|| Path { kind: PathKind::Plain, @@ -359,7 +359,7 @@ fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Opt }); res } - Either::B(crate_id) => { + Either::Right(crate_id) => { return Some(Path::from_simple_segments( PathKind::DollarCrate(crate_id), iter::empty(), -- cgit v1.2.3 From 18f6a995d0fc1f45099f3cc810a5d55d5401b41b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 5 Dec 2019 15:10:33 +0100 Subject: Add expansion infrastructure for derive macros --- crates/ra_hir_def/src/path.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3030dcdf6..e547b2f03 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -199,6 +199,11 @@ impl Path { name_ref.as_name().into() } + /// Converts an `tt::Ident` into a single-identifier `Path`. + pub(crate) fn from_tt_ident(ident: &tt::Ident) -> Path { + ident.as_name().into() + } + /// `true` is this path is a single identifier, like `foo` pub fn is_ident(&self) -> bool { self.kind == PathKind::Plain && self.segments.len() == 1 -- cgit v1.2.3 From 125559c14b0e85bb69e9b2759d7ecd33a73ea443 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 17:15:57 +0100 Subject: Move use tree lowering to a separate module --- crates/ra_hir_def/src/path.rs | 107 ++---------------------------------------- 1 file changed, 3 insertions(+), 104 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index e547b2f03..ddb53ee7c 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -1,4 +1,5 @@ //! A desugared representation of paths like `crate::foo` or `::bar`. +mod lower_use; use std::{iter, sync::Arc}; @@ -9,7 +10,7 @@ use hir_expand::{ }; use ra_db::CrateId; use ra_syntax::{ - ast::{self, NameOwner, TypeAscriptionOwner}, + ast::{self, TypeAscriptionOwner}, AstNode, }; @@ -72,7 +73,7 @@ impl Path { mut cb: impl FnMut(Path, &ast::UseTree, bool, Option), ) { if let Some(tree) = item_src.value.use_tree() { - expand_use_tree(None, tree, hygiene, &mut cb); + lower_use::lower_use_tree(None, tree, hygiene, &mut cb); } } @@ -296,108 +297,6 @@ impl From for Path { } } -fn expand_use_tree( - prefix: Option, - tree: ast::UseTree, - hygiene: &Hygiene, - cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option), -) { - if let Some(use_tree_list) = tree.use_tree_list() { - let prefix = match tree.path() { - // E.g. use something::{{{inner}}}; - None => prefix, - // E.g. `use something::{inner}` (prefix is `None`, path is `something`) - // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) - Some(path) => match convert_path(prefix, path, hygiene) { - Some(it) => Some(it), - None => return, // FIXME: report errors somewhere - }, - }; - for child_tree in use_tree_list.use_trees() { - expand_use_tree(prefix.clone(), child_tree, hygiene, cb); - } - } else { - let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); - if let Some(ast_path) = tree.path() { - // Handle self in a path. - // E.g. `use something::{self, <...>}` - if ast_path.qualifier().is_none() { - if let Some(segment) = ast_path.segment() { - if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { - if let Some(prefix) = prefix { - cb(prefix, &tree, false, alias); - return; - } - } - } - } - if let Some(path) = convert_path(prefix, ast_path, hygiene) { - let is_glob = tree.has_star(); - cb(path, &tree, is_glob, alias) - } - // FIXME: report errors somewhere - // We get here if we do - } - } -} - -fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Option { - let prefix = if let Some(qual) = path.qualifier() { - Some(convert_path(prefix, qual, hygiene)?) - } else { - prefix - }; - - let segment = path.segment()?; - let res = match segment.kind()? { - ast::PathSegmentKind::Name(name_ref) => { - match hygiene.name_ref_to_name(name_ref) { - Either::Left(name) => { - // no type args in use - let mut res = prefix.unwrap_or_else(|| Path { - kind: PathKind::Plain, - segments: Vec::with_capacity(1), - }); - res.segments.push(PathSegment { - name, - args_and_bindings: None, // no type args in use - }); - res - } - Either::Right(crate_id) => { - return Some(Path::from_simple_segments( - PathKind::DollarCrate(crate_id), - iter::empty(), - )) - } - } - } - ast::PathSegmentKind::CrateKw => { - if prefix.is_some() { - return None; - } - Path::from_simple_segments(PathKind::Crate, iter::empty()) - } - ast::PathSegmentKind::SelfKw => { - if prefix.is_some() { - return None; - } - Path::from_simple_segments(PathKind::Self_, iter::empty()) - } - ast::PathSegmentKind::SuperKw => { - if prefix.is_some() { - return None; - } - Path::from_simple_segments(PathKind::Super, iter::empty()) - } - ast::PathSegmentKind::Type { .. } => { - // not allowed in imports - return None; - } - }; - Some(res) -} - pub mod known { use hir_expand::name; -- cgit v1.2.3 From 332f2205b092744265914a4064b61161ba368df3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 17:17:57 +0100 Subject: Correct obsolete comment --- crates/ra_hir_def/src/path.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index ddb53ee7c..ec9d13e82 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -29,8 +29,7 @@ pub struct PathSegment { } /// Generic arguments to a path segment (e.g. the `i32` in `Option`). This -/// can (in the future) also include bindings of associated types, like in -/// `Iterator`. +/// also includes bindings of associated types, like in `Iterator`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GenericArgs { pub args: Vec, -- cgit v1.2.3 From 77052090515c1bb2a00236b3a57cdd778e581c8c Mon Sep 17 00:00:00 2001 From: Emil Lauridsen Date: Fri, 13 Dec 2019 12:44:42 +0100 Subject: Correctly infer - and ! using std::ops::{Neg,Not} --- crates/ra_hir_def/src/path.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index ec9d13e82..50f0cad94 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -342,6 +342,14 @@ pub mod known { ) } + pub fn std_ops_neg() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::NEG_TYPE]) + } + + pub fn std_ops_not() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::NOT_TYPE]) + } + pub fn std_result_result() -> Path { Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE]) } -- cgit v1.2.3 From 259c42f00e2e85594c7373166bc8467ce375a045 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Dec 2019 21:43:53 +0100 Subject: Add macros for known names and paths --- crates/ra_hir_def/src/path.rs | 45 +++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 25 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 50f0cad94..36ad27867 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -6,7 +6,7 @@ use std::{iter, sync::Arc}; use either::Either; use hir_expand::{ hygiene::Hygiene, - name::{self, AsName, Name}, + name::{AsName, Name, N}, }; use ra_db::CrateId; use ra_syntax::{ @@ -276,7 +276,7 @@ impl GenericArgs { } if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); - bindings.push((name::OUTPUT_TYPE, type_ref)) + bindings.push((N![Output], type_ref)) } if args.is_empty() && bindings.is_empty() { None @@ -297,68 +297,63 @@ impl From for Path { } pub mod known { - use hir_expand::name; + use hir_expand::name::N; use super::{Path, PathKind}; + macro_rules! P { + ($start:ident $(:: $seg:ident)*) => { Path::from_simple_segments(PathKind::Abs, vec![N![$start], $(N![$seg],)*]) }; + } + pub fn std_iter_into_iterator() -> Path { - Path::from_simple_segments( - PathKind::Abs, - vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE], - ) + P![std::iter::IntoIterator] } pub fn std_ops_try() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE]) + P![std::ops::Try] } pub fn std_ops_range() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TYPE]) + P![std::ops::Range] } pub fn std_ops_range_from() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FROM_TYPE]) + P![std::ops::RangeFrom] } pub fn std_ops_range_full() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FULL_TYPE]) + P![std::ops::RangeFull] } pub fn std_ops_range_inclusive() -> Path { - Path::from_simple_segments( - PathKind::Abs, - vec![name::STD, name::OPS, name::RANGE_INCLUSIVE_TYPE], - ) + P![std::ops::RangeInclusive] } pub fn std_ops_range_to() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TO_TYPE]) + P![std::ops::RangeTo] } pub fn std_ops_range_to_inclusive() -> Path { - Path::from_simple_segments( - PathKind::Abs, - vec![name::STD, name::OPS, name::RANGE_TO_INCLUSIVE_TYPE], - ) + P![std::ops::RangeToInclusive] } pub fn std_ops_neg() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::NEG_TYPE]) + P![std::ops::Neg] } pub fn std_ops_not() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::NOT_TYPE]) + P![std::ops::Not] } pub fn std_result_result() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE]) + P![std::result::Result] } pub fn std_future_future() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE]) + P![std::future::Future] } pub fn std_boxed_box() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE]) + P![std::boxed::Box] } } -- cgit v1.2.3 From 6911bc89a784ce72b4dfd8e0ba72bd22ce898395 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Dec 2019 22:01:06 +0100 Subject: Rename N! to name! --- crates/ra_hir_def/src/path.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 36ad27867..c1376af36 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -6,7 +6,7 @@ use std::{iter, sync::Arc}; use either::Either; use hir_expand::{ hygiene::Hygiene, - name::{AsName, Name, N}, + name::{name, AsName, Name}, }; use ra_db::CrateId; use ra_syntax::{ @@ -276,7 +276,7 @@ impl GenericArgs { } if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); - bindings.push((N![Output], type_ref)) + bindings.push((name![Output], type_ref)) } if args.is_empty() && bindings.is_empty() { None @@ -297,12 +297,12 @@ impl From for Path { } pub mod known { - use hir_expand::name::N; + use hir_expand::name::name; use super::{Path, PathKind}; macro_rules! P { - ($start:ident $(:: $seg:ident)*) => { Path::from_simple_segments(PathKind::Abs, vec![N![$start], $(N![$seg],)*]) }; + ($start:ident $(:: $seg:ident)*) => { Path::from_simple_segments(PathKind::Abs, vec![name![$start], $(name![$seg],)*]) }; } pub fn std_iter_into_iterator() -> Path { -- cgit v1.2.3 From f02fcc16444fcd18ccd51b43fa01bf0233e044fa Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Dec 2019 22:32:44 +0100 Subject: Use path macro --- crates/ra_hir_def/src/path.rs | 95 +++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 63 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index c1376af36..1e9eb14ea 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -76,10 +76,7 @@ impl Path { } } - pub(crate) fn from_simple_segments( - kind: PathKind, - segments: impl IntoIterator, - ) -> Path { + pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator) -> Path { Path { kind, segments: segments @@ -296,64 +293,36 @@ impl From for Path { } } -pub mod known { - use hir_expand::name::name; - - use super::{Path, PathKind}; - - macro_rules! P { - ($start:ident $(:: $seg:ident)*) => { Path::from_simple_segments(PathKind::Abs, vec![name![$start], $(name![$seg],)*]) }; - } - - pub fn std_iter_into_iterator() -> Path { - P![std::iter::IntoIterator] - } - - pub fn std_ops_try() -> Path { - P![std::ops::Try] - } - - pub fn std_ops_range() -> Path { - P![std::ops::Range] - } - - pub fn std_ops_range_from() -> Path { - P![std::ops::RangeFrom] - } - - pub fn std_ops_range_full() -> Path { - P![std::ops::RangeFull] - } - - pub fn std_ops_range_inclusive() -> Path { - P![std::ops::RangeInclusive] - } - - pub fn std_ops_range_to() -> Path { - P![std::ops::RangeTo] - } - - pub fn std_ops_range_to_inclusive() -> Path { - P![std::ops::RangeToInclusive] - } - - pub fn std_ops_neg() -> Path { - P![std::ops::Neg] - } - - pub fn std_ops_not() -> Path { - P![std::ops::Not] - } - - pub fn std_result_result() -> Path { - P![std::result::Result] - } - - pub fn std_future_future() -> Path { - P![std::future::Future] - } +pub use hir_expand::name as __name; + +#[macro_export] +macro_rules! __known_path { + (std::iter::IntoIterator) => {}; + (std::result::Result) => {}; + (std::ops::Range) => {}; + (std::ops::RangeFrom) => {}; + (std::ops::RangeFull) => {}; + (std::ops::RangeTo) => {}; + (std::ops::RangeToInclusive) => {}; + (std::ops::RangeInclusive) => {}; + (std::boxed::Box) => {}; + (std::future::Future) => {}; + (std::ops::Try) => {}; + (std::ops::Neg) => {}; + (std::ops::Not) => {}; + ($path:path) => { + compile_error!("Please register your known path in the path module") + }; +} - pub fn std_boxed_box() -> Path { - P![std::boxed::Box] - } +#[macro_export] +macro_rules! __path { + ($start:ident $(:: $seg:ident)*) => ({ + $crate::__known_path!($start $(:: $seg)*); + $crate::path::Path::from_simple_segments($crate::path::PathKind::Abs, vec![ + $crate::path::__name![$start], $($crate::path::__name![$seg],)* + ]) + }); } + +pub use crate::__path as path; -- cgit v1.2.3 From 2619950b3b405324ab1c1745876165c834b3b4b9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 13 Dec 2019 12:12:36 +0100 Subject: Use different types for path with and without generics --- crates/ra_hir_def/src/path.rs | 345 ++++++++++++++++++------------------------ 1 file changed, 145 insertions(+), 200 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 1e9eb14ea..20d6d98ea 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -1,31 +1,78 @@ //! A desugared representation of paths like `crate::foo` or `::bar`. -mod lower_use; +mod lower; use std::{iter, sync::Arc}; -use either::Either; use hir_expand::{ hygiene::Hygiene, - name::{name, AsName, Name}, + name::{AsName, Name}, }; use ra_db::CrateId; -use ra_syntax::{ - ast::{self, TypeAscriptionOwner}, - AstNode, -}; +use ra_syntax::ast; use crate::{type_ref::TypeRef, InFile}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Path { +pub struct ModPath { pub kind: PathKind, - pub segments: Vec, + pub segments: Vec, +} + +impl ModPath { + pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option { + lower::lower_path(path, hygiene).map(|it| it.mod_path) + } + + pub fn from_simple_segments( + kind: PathKind, + segments: impl IntoIterator, + ) -> ModPath { + let segments = segments.into_iter().collect::>(); + ModPath { kind, segments } + } + + pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath { + name_ref.as_name().into() + } + + /// Converts an `tt::Ident` into a single-identifier `Path`. + pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath { + ident.as_name().into() + } + + /// Calls `cb` with all paths, represented by this use item. + pub(crate) fn expand_use_item( + item_src: InFile, + hygiene: &Hygiene, + mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option), + ) { + if let Some(tree) = item_src.value.use_tree() { + lower::lower_use_tree(None, tree, hygiene, &mut cb); + } + } + + pub fn is_ident(&self) -> bool { + self.kind == PathKind::Plain && self.segments.len() == 1 + } + + pub fn is_self(&self) -> bool { + self.kind == PathKind::Self_ && self.segments.is_empty() + } + + /// If this path is a single identifier, like `foo`, return its name. + pub fn as_ident(&self) -> Option<&Name> { + if self.kind != PathKind::Plain || self.segments.len() > 1 { + return None; + } + self.segments.first() + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct PathSegment { - pub name: Name, - pub args_and_bindings: Option>, +pub struct Path { + mod_path: ModPath, + /// Invariant: the same len as self.path.segments + generic_args: Vec>>, } /// Generic arguments to a path segment (e.g. the `i32` in `Option`). This @@ -65,221 +112,110 @@ pub enum PathKind { } impl Path { - /// Calls `cb` with all paths, represented by this use item. - pub(crate) fn expand_use_item( - item_src: InFile, - hygiene: &Hygiene, - mut cb: impl FnMut(Path, &ast::UseTree, bool, Option), - ) { - if let Some(tree) = item_src.value.use_tree() { - lower_use::lower_use_tree(None, tree, hygiene, &mut cb); - } - } - - pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator) -> Path { - Path { - kind, - segments: segments - .into_iter() - .map(|name| PathSegment { name, args_and_bindings: None }) - .collect(), - } - } - /// Converts an `ast::Path` to `Path`. Works with use trees. /// DEPRECATED: It does not handle `$crate` from macro call. pub fn from_ast(path: ast::Path) -> Option { - Path::from_src(path, &Hygiene::new_unhygienic()) + lower::lower_path(path, &Hygiene::new_unhygienic()) } /// Converts an `ast::Path` to `Path`. Works with use trees. /// It correctly handles `$crate` based path from macro call. - pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option { - let mut kind = PathKind::Plain; - let mut segments = Vec::new(); - loop { - let segment = path.segment()?; - - if segment.has_colon_colon() { - kind = PathKind::Abs; - } - - match segment.kind()? { - ast::PathSegmentKind::Name(name_ref) => { - // FIXME: this should just return name - match hygiene.name_ref_to_name(name_ref) { - Either::Left(name) => { - let args = segment - .type_arg_list() - .and_then(GenericArgs::from_ast) - .or_else(|| { - GenericArgs::from_fn_like_path_ast( - segment.param_list(), - segment.ret_type(), - ) - }) - .map(Arc::new); - let segment = PathSegment { name, args_and_bindings: args }; - segments.push(segment); - } - Either::Right(crate_id) => { - kind = PathKind::DollarCrate(crate_id); - break; - } - } - } - ast::PathSegmentKind::Type { type_ref, trait_ref } => { - assert!(path.qualifier().is_none()); // this can only occur at the first segment - - let self_type = TypeRef::from_ast(type_ref?); - - match trait_ref { - // ::foo - None => { - kind = PathKind::Type(Box::new(self_type)); - } - // >::Foo desugars to Trait::Foo - Some(trait_ref) => { - let path = Path::from_src(trait_ref.path()?, hygiene)?; - kind = path.kind; - let mut prefix_segments = path.segments; - prefix_segments.reverse(); - segments.extend(prefix_segments); - // Insert the type reference (T in the above example) as Self parameter for the trait - let mut last_segment = segments.last_mut()?; - if last_segment.args_and_bindings.is_none() { - last_segment.args_and_bindings = - Some(Arc::new(GenericArgs::empty())); - }; - let args = last_segment.args_and_bindings.as_mut().unwrap(); - let mut args_inner = Arc::make_mut(args); - args_inner.has_self_type = true; - args_inner.args.insert(0, GenericArg::Type(self_type)); - } - } - } - ast::PathSegmentKind::CrateKw => { - kind = PathKind::Crate; - break; - } - ast::PathSegmentKind::SelfKw => { - kind = PathKind::Self_; - break; - } - ast::PathSegmentKind::SuperKw => { - kind = PathKind::Super; - break; - } - } - path = match qualifier(&path) { - Some(it) => it, - None => break, - }; - } - segments.reverse(); - return Some(Path { kind, segments }); - - fn qualifier(path: &ast::Path) -> Option { - if let Some(q) = path.qualifier() { - return Some(q); - } - // FIXME: this bottom up traversal is not too precise. - // Should we handle do a top-down analysis, recording results? - let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?; - let use_tree = use_tree_list.parent_use_tree(); - use_tree.path() - } + pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option { + lower::lower_path(path, hygiene) } /// Converts an `ast::NameRef` into a single-identifier `Path`. pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { - name_ref.as_name().into() + Path { mod_path: name_ref.as_name().into(), generic_args: vec![None] } } - /// Converts an `tt::Ident` into a single-identifier `Path`. - pub(crate) fn from_tt_ident(ident: &tt::Ident) -> Path { - ident.as_name().into() + /// `true` if this path is just a standalone `self` + pub fn is_self(&self) -> bool { + self.mod_path.is_self() } - /// `true` is this path is a single identifier, like `foo` - pub fn is_ident(&self) -> bool { - self.kind == PathKind::Plain && self.segments.len() == 1 + pub fn kind(&self) -> &PathKind { + &self.mod_path.kind } - /// `true` if this path is just a standalone `self` - pub fn is_self(&self) -> bool { - self.kind == PathKind::Self_ && self.segments.is_empty() + pub fn segments(&self) -> PathSegments<'_> { + PathSegments { + segments: self.mod_path.segments.as_slice(), + generic_args: self.generic_args.as_slice(), + } } - /// If this path is a single identifier, like `foo`, return its name. - pub fn as_ident(&self) -> Option<&Name> { - if self.kind != PathKind::Plain || self.segments.len() > 1 { + pub fn mod_path(&self) -> &ModPath { + &self.mod_path + } + + pub fn qualifier(&self) -> Option { + if self.mod_path.is_ident() { return None; } - self.segments.first().map(|s| &s.name) + let res = Path { + mod_path: ModPath { + kind: self.mod_path.kind.clone(), + segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(), + }, + generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(), + }; + Some(res) } +} - pub fn expand_macro_expr(&self) -> Option { - self.as_ident().and_then(|name| Some(name.clone())) - } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PathSegment<'a> { + pub name: &'a Name, + pub args_and_bindings: Option<&'a GenericArgs>, +} - pub fn is_type_relative(&self) -> bool { - match self.kind { - PathKind::Type(_) => true, - _ => false, - } +pub struct PathSegments<'a> { + segments: &'a [Name], + generic_args: &'a [Option>], +} + +impl<'a> PathSegments<'a> { + pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] }; + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn len(&self) -> usize { + self.segments.len() + } + pub fn first(&self) -> Option> { + self.get(0) + } + pub fn last(&self) -> Option> { + self.get(self.len().checked_sub(1)?) + } + pub fn get(&self, idx: usize) -> Option> { + assert_eq!(self.segments.len(), self.generic_args.len()); + let res = PathSegment { + name: self.segments.get(idx)?, + args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it), + }; + Some(res) + } + pub fn skip(&self, len: usize) -> PathSegments<'a> { + assert_eq!(self.segments.len(), self.generic_args.len()); + PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] } + } + pub fn take(&self, len: usize) -> PathSegments<'a> { + assert_eq!(self.segments.len(), self.generic_args.len()); + PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] } + } + pub fn iter(&self) -> impl Iterator> { + self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment { + name, + args_and_bindings: args.as_ref().map(|it| &**it), + }) } } impl GenericArgs { pub(crate) fn from_ast(node: ast::TypeArgList) -> Option { - let mut args = Vec::new(); - for type_arg in node.type_args() { - let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); - args.push(GenericArg::Type(type_ref)); - } - // lifetimes ignored for now - let mut bindings = Vec::new(); - for assoc_type_arg in node.assoc_type_args() { - if let Some(name_ref) = assoc_type_arg.name_ref() { - let name = name_ref.as_name(); - let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref()); - bindings.push((name, type_ref)); - } - } - if args.is_empty() && bindings.is_empty() { - None - } else { - Some(GenericArgs { args, has_self_type: false, bindings }) - } - } - - /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) - /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). - pub(crate) fn from_fn_like_path_ast( - params: Option, - ret_type: Option, - ) -> Option { - let mut args = Vec::new(); - let mut bindings = Vec::new(); - if let Some(params) = params { - let mut param_types = Vec::new(); - for param in params.params() { - let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); - param_types.push(type_ref); - } - let arg = GenericArg::Type(TypeRef::Tuple(param_types)); - args.push(arg); - } - if let Some(ret_type) = ret_type { - let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); - bindings.push((name![Output], type_ref)) - } - if args.is_empty() && bindings.is_empty() { - None - } else { - Some(GenericArgs { args, has_self_type: false, bindings }) - } + lower::lower_generic_args(node) } pub(crate) fn empty() -> GenericArgs { @@ -289,7 +225,16 @@ impl GenericArgs { impl From for Path { fn from(name: Name) -> Path { - Path::from_simple_segments(PathKind::Plain, iter::once(name)) + Path { + mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)), + generic_args: vec![None], + } + } +} + +impl From for ModPath { + fn from(name: Name) -> ModPath { + ModPath::from_simple_segments(PathKind::Plain, iter::once(name)) } } @@ -319,7 +264,7 @@ macro_rules! __known_path { macro_rules! __path { ($start:ident $(:: $seg:ident)*) => ({ $crate::__known_path!($start $(:: $seg)*); - $crate::path::Path::from_simple_segments($crate::path::PathKind::Abs, vec![ + $crate::path::ModPath::from_simple_segments($crate::path::PathKind::Abs, vec![ $crate::path::__name![$start], $($crate::path::__name![$seg],)* ]) }); -- cgit v1.2.3 From aca022f1d49a6d945f3ef4f8c781d7337120b68d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 17 Dec 2019 15:38:28 +0100 Subject: Refactor PathKind --- crates/ra_hir_def/src/path.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 20d6d98ea..3b26e8337 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -56,7 +56,7 @@ impl ModPath { } pub fn is_self(&self) -> bool { - self.kind == PathKind::Self_ && self.segments.is_empty() + self.kind == PathKind::Super(0) && self.segments.is_empty() } /// If this path is a single identifier, like `foo`, return its name. @@ -100,8 +100,7 @@ pub enum GenericArg { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum PathKind { Plain, - Self_, - Super, + Super(u8), Crate, // Absolute path Abs, -- cgit v1.2.3 From d043689735edc12388e22f49b2319362f3b003fa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:04:20 +0100 Subject: Touch up docs --- crates/ra_hir_def/src/path.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3b26e8337..c37364f57 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -100,13 +100,14 @@ pub enum GenericArg { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum PathKind { Plain, + /// `self::` is `Super(0)` Super(u8), Crate, - // Absolute path + /// Absolute path (::foo) Abs, - // Type based path like `::foo` + /// Type based path like `::foo` Type(Box), - // `$crate` from macro expansion + /// `$crate` from macro expansion DollarCrate(CrateId), } -- cgit v1.2.3 From 88c6109897417e7ab815ea1711f49545bff94601 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:06:52 +0100 Subject: Move PathKindUp --- crates/ra_hir_def/src/path.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index c37364f57..e38d924fa 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -18,6 +18,20 @@ pub struct ModPath { pub segments: Vec, } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum PathKind { + Plain, + /// `self::` is `Super(0)` + Super(u8), + Crate, + /// Absolute path (::foo) + Abs, + /// Type based path like `::foo` + Type(Box), + /// `$crate` from macro expansion + DollarCrate(CrateId), +} + impl ModPath { pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option { lower::lower_path(path, hygiene).map(|it| it.mod_path) @@ -97,20 +111,6 @@ pub enum GenericArg { // or lifetime... } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum PathKind { - Plain, - /// `self::` is `Super(0)` - Super(u8), - Crate, - /// Absolute path (::foo) - Abs, - /// Type based path like `::foo` - Type(Box), - /// `$crate` from macro expansion - DollarCrate(CrateId), -} - impl Path { /// Converts an `ast::Path` to `Path`. Works with use trees. /// DEPRECATED: It does not handle `$crate` from macro call. -- cgit v1.2.3 From 04715cbe1caf92e55d393a352a12454ba958845e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:41:33 +0100 Subject: Forbid ::foo syntax in mod paths --- crates/ra_hir_def/src/path.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index e38d924fa..1e2da6b48 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -26,8 +26,6 @@ pub enum PathKind { Crate, /// Absolute path (::foo) Abs, - /// Type based path like `::foo` - Type(Box), /// `$crate` from macro expansion DollarCrate(CrateId), } @@ -84,6 +82,8 @@ impl ModPath { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { + /// Type based path like `::foo` + type_anchor: Option>, mod_path: ModPath, /// Invariant: the same len as self.path.segments generic_args: Vec>>, @@ -126,7 +126,7 @@ impl Path { /// Converts an `ast::NameRef` into a single-identifier `Path`. pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { - Path { mod_path: name_ref.as_name().into(), generic_args: vec![None] } + Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } } /// `true` if this path is just a standalone `self` @@ -138,6 +138,10 @@ impl Path { &self.mod_path.kind } + pub fn type_anchor(&self) -> Option<&TypeRef> { + self.type_anchor.as_ref().map(|it| &**it) + } + pub fn segments(&self) -> PathSegments<'_> { PathSegments { segments: self.mod_path.segments.as_slice(), @@ -154,6 +158,7 @@ impl Path { return None; } let res = Path { + type_anchor: self.type_anchor.clone(), mod_path: ModPath { kind: self.mod_path.kind.clone(), segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(), @@ -226,6 +231,7 @@ impl GenericArgs { impl From for Path { fn from(name: Name) -> Path { Path { + type_anchor: None, mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)), generic_args: vec![None], } -- cgit v1.2.3 From d33fc26e05c573f536e02afbffc354fa4f4a35f3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:42:49 +0100 Subject: Touch up docs --- crates/ra_hir_def/src/path.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 1e2da6b48..3fb0955d1 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -82,7 +82,8 @@ impl ModPath { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { - /// Type based path like `::foo` + /// Type based path like `::foo`. + /// Note that paths like `::foo` are desugard to `Trait::::foo`. type_anchor: Option>, mod_path: ModPath, /// Invariant: the same len as self.path.segments -- cgit v1.2.3 From afdeacf3c126b3e19bd1e50a912fee2b3f2d4aa9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:52:52 +0100 Subject: Remove dead code --- crates/ra_hir_def/src/path.rs | 5 ----- 1 file changed, 5 deletions(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3fb0955d1..7302cf0f1 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -130,11 +130,6 @@ impl Path { Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } } - /// `true` if this path is just a standalone `self` - pub fn is_self(&self) -> bool { - self.mod_path.is_self() - } - pub fn kind(&self) -> &PathKind { &self.mod_path.kind } -- cgit v1.2.3 From dddee23f43a0e1939124a607ba534e69a810843a Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Thu, 19 Dec 2019 12:45:07 +0800 Subject: Add std::ops::Index support for infering --- crates/ra_hir_def/src/path.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3b26e8337..9e37ac416 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -254,6 +254,7 @@ macro_rules! __known_path { (std::ops::Try) => {}; (std::ops::Neg) => {}; (std::ops::Not) => {}; + (std::ops::Index) => {}; ($path:path) => { compile_error!("Please register your known path in the path module") }; -- cgit v1.2.3 From f5947be0ea6eb909cbb63420c3304adedf470b26 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 20:15:54 +0100 Subject: Simplify --- crates/ra_hir_def/src/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir_def/src/path.rs') diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 00325cd99..8e1294201 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -135,7 +135,7 @@ impl Path { } pub fn type_anchor(&self) -> Option<&TypeRef> { - self.type_anchor.as_ref().map(|it| &**it) + self.type_anchor.as_deref() } pub fn segments(&self) -> PathSegments<'_> { -- cgit v1.2.3