]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_def/src/path.rs
parameters.split_last()
[rust.git] / crates / hir_def / src / path.rs
index b528ff8bad74a62bafeab1b186203b67bbdb3db7..a6141174c8379b3c458bbde9b1205e1e87b64f74 100644 (file)
@@ -4,39 +4,15 @@
 use std::{
     fmt::{self, Display},
     iter,
-    sync::Arc,
 };
 
 use crate::{body::LowerCtx, intern::Interned, type_ref::LifetimeRef};
-use base_db::CrateId;
-use hir_expand::{
-    hygiene::Hygiene,
-    name::{name, Name},
-};
+use hir_expand::name::{name, Name};
 use syntax::ast;
 
-use crate::{
-    type_ref::{TypeBound, TypeRef},
-    InFile,
-};
+use crate::type_ref::{TypeBound, TypeRef};
 
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct ModPath {
-    pub kind: PathKind,
-    segments: Vec<Name>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum PathKind {
-    Plain,
-    /// `self::` is `Super(0)`
-    Super(u8),
-    Crate,
-    /// Absolute path (::foo)
-    Abs,
-    /// `$crate` from macro expansion
-    DollarCrate(CrateId),
-}
+pub use hir_expand::mod_path::{path, ModPath, PathKind};
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum ImportAlias {
@@ -46,74 +22,11 @@ pub enum ImportAlias {
     Alias(Name),
 }
 
-impl ModPath {
-    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
-        lower::lower_path(path, hygiene).map(|it| (*it.mod_path).clone())
-    }
-
-    pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath {
-        let segments = segments.into_iter().collect::<Vec<_>>();
-        ModPath { kind, segments }
-    }
-
-    /// Creates a `ModPath` from a `PathKind`, with no extra path segments.
-    pub const fn from_kind(kind: PathKind) -> ModPath {
-        ModPath { kind, segments: Vec::new() }
-    }
-
-    /// Calls `cb` with all paths, represented by this use item.
-    pub(crate) fn expand_use_item(
-        item_src: InFile<ast::Use>,
-        hygiene: &Hygiene,
-        mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<ImportAlias>),
-    ) {
-        if let Some(tree) = item_src.value.use_tree() {
-            lower::lower_use_tree(None, tree, hygiene, &mut cb);
-        }
-    }
-
-    pub fn segments(&self) -> &[Name] {
-        &self.segments
-    }
-
-    pub fn push_segment(&mut self, segment: Name) {
-        self.segments.push(segment);
-    }
-
-    pub fn pop_segment(&mut self) -> Option<Name> {
-        self.segments.pop()
-    }
-
-    /// Returns the number of segments in the path (counting special segments like `$crate` and
-    /// `super`).
-    pub fn len(&self) -> usize {
-        self.segments.len()
-            + match self.kind {
-                PathKind::Plain => 0,
-                PathKind::Super(i) => i as usize,
-                PathKind::Crate => 1,
-                PathKind::Abs => 0,
-                PathKind::DollarCrate(_) => 1,
-            }
-    }
-
-    pub fn is_ident(&self) -> bool {
-        self.as_ident().is_some()
-    }
-
-    pub fn is_self(&self) -> bool {
-        self.kind == PathKind::Super(0) && 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 {
-            return None;
-        }
-
-        match &*self.segments {
-            [name] => Some(name),
-            _ => None,
+impl Display for ImportAlias {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            ImportAlias::Underscore => f.write_str("_"),
+            ImportAlias::Alias(name) => f.write_str(&name.to_smol_str()),
         }
     }
 }
@@ -125,7 +38,7 @@ pub struct Path {
     type_anchor: Option<Interned<TypeRef>>,
     mod_path: Interned<ModPath>,
     /// Invariant: the same len as `self.mod_path.segments`
-    generic_args: Vec<Option<Arc<GenericArgs>>>,
+    generic_args: Box<[Option<Interned<GenericArgs>>]>,
 }
 
 /// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
@@ -141,6 +54,9 @@ pub struct GenericArgs {
     pub has_self_type: bool,
     /// Associated type bindings like in `Iterator<Item = T>`.
     pub bindings: Vec<AssociatedTypeBinding>,
+    /// Whether these generic args were desugared from `Trait(Arg) -> Output`
+    /// parenthesis notation typically used for the `Fn` traits.
+    pub desugared_from_fn: bool,
 }
 
 /// An associated type binding like in `Iterator<Item = T>`.
@@ -154,7 +70,7 @@ pub struct AssociatedTypeBinding {
     /// Bounds for the associated type, like in `Iterator<Item:
     /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds`
     /// feature.)
-    pub bounds: Vec<TypeBound>,
+    pub bounds: Vec<Interned<TypeBound>>,
 }
 
 /// A single generic argument.
@@ -167,15 +83,17 @@ pub enum GenericArg {
 impl Path {
     /// Converts an `ast::Path` to `Path`. Works with use trees.
     /// It correctly handles `$crate` based path from macro call.
-    pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
-        lower::lower_path(path, hygiene)
+    pub fn from_src(path: ast::Path, ctx: &LowerCtx) -> Option<Path> {
+        lower::lower_path(path, ctx)
     }
 
     /// Converts a known mod path to `Path`.
-    pub(crate) fn from_known_path(
+    pub fn from_known_path(
         path: ModPath,
-        generic_args: Vec<Option<Arc<GenericArgs>>>,
+        generic_args: impl Into<Box<[Option<Interned<GenericArgs>>]>>,
     ) -> Path {
+        let generic_args = generic_args.into();
+        assert_eq!(path.len(), generic_args.len());
         Path { type_anchor: None, mod_path: Interned::new(path), generic_args }
     }
 
@@ -188,10 +106,7 @@ pub fn type_anchor(&self) -> Option<&TypeRef> {
     }
 
     pub fn segments(&self) -> PathSegments<'_> {
-        PathSegments {
-            segments: self.mod_path.segments.as_slice(),
-            generic_args: self.generic_args.as_slice(),
-        }
+        PathSegments { segments: self.mod_path.segments(), generic_args: &self.generic_args }
     }
 
     pub fn mod_path(&self) -> &ModPath {
@@ -206,16 +121,16 @@ pub fn qualifier(&self) -> Option<Path> {
             type_anchor: self.type_anchor.clone(),
             mod_path: Interned::new(ModPath::from_segments(
                 self.mod_path.kind.clone(),
-                self.mod_path.segments[..self.mod_path.segments.len() - 1].iter().cloned(),
+                self.mod_path.segments()[..self.mod_path.segments().len() - 1].iter().cloned(),
             )),
-            generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(),
+            generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec().into(),
         };
         Some(res)
     }
 
     pub fn is_self_type(&self) -> bool {
         self.type_anchor.is_none()
-            && self.generic_args == &[None]
+            && *self.generic_args == [None]
             && self.mod_path.as_ident() == Some(&name!(Self))
     }
 }
@@ -228,7 +143,7 @@ pub struct PathSegment<'a> {
 
 pub struct PathSegments<'a> {
     segments: &'a [Name],
-    generic_args: &'a [Option<Arc<GenericArgs>>],
+    generic_args: &'a [Option<Interned<GenericArgs>>],
 }
 
 impl<'a> PathSegments<'a> {
@@ -275,7 +190,12 @@ pub(crate) fn from_ast(lower_ctx: &LowerCtx, node: ast::GenericArgList) -> Optio
     }
 
     pub(crate) fn empty() -> GenericArgs {
-        GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
+        GenericArgs {
+            args: Vec::new(),
+            has_self_type: false,
+            bindings: Vec::new(),
+            desugared_from_fn: false,
+        }
     }
 }
 
@@ -284,7 +204,7 @@ fn from(name: Name) -> Path {
         Path {
             type_anchor: None,
             mod_path: Interned::new(ModPath::from_segments(PathKind::Plain, iter::once(name))),
-            generic_args: vec![None],
+            generic_args: Box::new([None]),
         }
     }
 }
@@ -294,76 +214,3 @@ fn from(name: Name) -> Box<Path> {
         Box::new(Path::from(name))
     }
 }
-
-impl From<Name> for ModPath {
-    fn from(name: Name) -> ModPath {
-        ModPath::from_segments(PathKind::Plain, iter::once(name))
-    }
-}
-
-impl Display for ModPath {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut first_segment = true;
-        let mut add_segment = |s| -> fmt::Result {
-            if !first_segment {
-                f.write_str("::")?;
-            }
-            first_segment = false;
-            f.write_str(s)?;
-            Ok(())
-        };
-        match self.kind {
-            PathKind::Plain => {}
-            PathKind::Super(0) => add_segment("self")?,
-            PathKind::Super(n) => {
-                for _ in 0..n {
-                    add_segment("super")?;
-                }
-            }
-            PathKind::Crate => add_segment("crate")?,
-            PathKind::Abs => add_segment("")?,
-            PathKind::DollarCrate(_) => add_segment("$crate")?,
-        }
-        for segment in &self.segments {
-            if !first_segment {
-                f.write_str("::")?;
-            }
-            first_segment = false;
-            write!(f, "{}", segment)?;
-        }
-        Ok(())
-    }
-}
-
-pub use hir_expand::name as __name;
-
-#[macro_export]
-macro_rules! __known_path {
-    (core::iter::IntoIterator) => {};
-    (core::iter::Iterator) => {};
-    (core::result::Result) => {};
-    (core::option::Option) => {};
-    (core::ops::Range) => {};
-    (core::ops::RangeFrom) => {};
-    (core::ops::RangeFull) => {};
-    (core::ops::RangeTo) => {};
-    (core::ops::RangeToInclusive) => {};
-    (core::ops::RangeInclusive) => {};
-    (core::future::Future) => {};
-    (core::ops::Try) => {};
-    ($path:path) => {
-        compile_error!("Please register your known path in the path module")
-    };
-}
-
-#[macro_export]
-macro_rules! __path {
-    ($start:ident $(:: $seg:ident)*) => ({
-        $crate::__known_path!($start $(:: $seg)*);
-        $crate::path::ModPath::from_segments($crate::path::PathKind::Abs, vec![
-            $crate::path::__name![$start], $($crate::path::__name![$seg],)*
-        ])
-    });
-}
-
-pub use crate::__path as path;