}
ps.push(chain.into());
}
- hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None,
+ hir::PathKind::DollarCrate(_) => return None,
}
ps.extend(path.segments().iter().map(|it| it.name.to_string().into()));
Some(ps)
db::DefDatabase,
expr::{Expr, ExprId, Pat, PatId},
nameres::{BuiltinShadowMode, CrateDefMap},
- path::Path,
+ path::{ModPath, Path},
src::HasSource,
DefWithBodyId, HasModule, Lookup, ModuleId,
};
db.ast_id_map(self.current_file_id).ast_id(¯o_call),
);
- if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) {
+ if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) {
if let Some(def) = self.resolve_path_as_macro(db, &path) {
let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
let file_id = call_id.as_file();
Path::from_src(path, &self.hygiene)
}
- fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
+ fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> {
+ ModPath::from_src(path, &self.hygiene)
+ }
+
+ fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> {
self.crate_def_map
- .resolve_path(db, self.module.local_id, path.mod_path(), BuiltinShadowMode::Other)
+ .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
.0
.take_macros()
}
return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
}
}
- PathKind::Type(_) => {
- // This is handled in `infer::infer_path_expr`
- // The result returned here does not matter
- return ResolvePathResult::empty(ReachedFixedPoint::Yes);
- }
};
for (i, segment) in segments {
Crate,
/// Absolute path (::foo)
Abs,
- /// Type based path like `<T>::foo`
- Type(Box<TypeRef>),
/// `$crate` from macro expansion
DollarCrate(CrateId),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
+ /// Type based path like `<T>::foo`
+ type_anchor: Option<Box<TypeRef>>,
mod_path: ModPath,
/// Invariant: the same len as self.path.segments
generic_args: Vec<Option<Arc<GenericArgs>>>,
/// 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`
&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(),
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(),
impl From<Name> 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],
}
/// It correctly handles `$crate` based path from macro call.
pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
let mut kind = PathKind::Plain;
+ let mut type_anchor = None;
let mut segments = Vec::new();
let mut generic_args = Vec::new();
loop {
match trait_ref {
// <T>::foo
None => {
- kind = PathKind::Type(Box::new(self_type));
+ type_anchor = Some(Box::new(self_type));
+ kind = PathKind::Plain;
}
// <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
Some(trait_ref) => {
segments.reverse();
generic_args.reverse();
let mod_path = ModPath { kind, segments };
- return Some(Path { mod_path, generic_args });
+ return Some(Path { type_anchor, mod_path, generic_args });
fn qualifier(path: &ast::Path) -> Option<ast::Path> {
if let Some(q) = path.qualifier() {
use std::iter;
use hir_def::{
- path::{Path, PathKind, PathSegment},
+ path::{Path, PathSegment},
resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
AssocItemId, ContainerId, Lookup,
};
path: &Path,
id: ExprOrPatId,
) -> Option<Ty> {
- let (value, self_subst) = if let PathKind::Type(type_ref) = path.kind() {
+ let (value, self_subst) = if let Some(type_ref) = path.type_anchor() {
if path.segments().is_empty() {
// This can't actually happen syntax-wise
return None;
use hir_def::{
builtin_type::BuiltinType,
generics::WherePredicate,
- path::{GenericArg, Path, PathKind, PathSegment, PathSegments},
+ path::{GenericArg, Path, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs},
type_ref::{TypeBound, TypeRef},
AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
TypeRef::Path(path) => path,
_ => return None,
};
- if let PathKind::Type(_) = path.kind() {
+ if path.type_anchor().is_some() {
return None;
}
if path.segments().len() > 1 {
pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
// Resolve the path (in type namespace)
- if let PathKind::Type(type_ref) = path.kind() {
+ if let Some(type_ref) = path.type_anchor() {
let ty = Ty::from_hir(db, resolver, &type_ref);
return Ty::from_type_relative_path(db, resolver, ty, path.segments());
}