mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	Merge #1817
1817: Support path starting with a type r=matklad a=uHOOCCOOHu The path syntax `<Ty>::foo` Co-authored-by: uHOOCCOOHu <hooccooh1896@gmail.com>
This commit is contained in:
		
						commit
						ba583091e6
					
				@ -504,7 +504,7 @@ fn apply_auto_import(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> {
 | 
					pub fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
 | 
				
			||||||
    let mut ps = Vec::<SmolStr>::with_capacity(10);
 | 
					    let mut ps = Vec::<SmolStr>::with_capacity(10);
 | 
				
			||||||
    match path.kind {
 | 
					    match path.kind {
 | 
				
			||||||
        hir::PathKind::Abs => ps.push("".into()),
 | 
					        hir::PathKind::Abs => ps.push("".into()),
 | 
				
			||||||
@ -512,11 +512,12 @@ pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> {
 | 
				
			|||||||
        hir::PathKind::Plain => {}
 | 
					        hir::PathKind::Plain => {}
 | 
				
			||||||
        hir::PathKind::Self_ => ps.push("self".into()),
 | 
					        hir::PathKind::Self_ => ps.push("self".into()),
 | 
				
			||||||
        hir::PathKind::Super => ps.push("super".into()),
 | 
					        hir::PathKind::Super => ps.push("super".into()),
 | 
				
			||||||
 | 
					        hir::PathKind::Type(_) => return None,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    for s in path.segments.iter() {
 | 
					    for s in path.segments.iter() {
 | 
				
			||||||
        ps.push(s.name.to_string().into());
 | 
					        ps.push(s.name.to_string().into());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ps
 | 
					    Some(ps)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This function produces sequence of text edits into edit
 | 
					// This function produces sequence of text edits into edit
 | 
				
			||||||
@ -552,7 +553,7 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let hir_path = hir::Path::from_ast(path.clone())?;
 | 
					    let hir_path = hir::Path::from_ast(path.clone())?;
 | 
				
			||||||
    let segments = collect_hir_path_segments(&hir_path);
 | 
					    let segments = collect_hir_path_segments(&hir_path)?;
 | 
				
			||||||
    if segments.len() < 2 {
 | 
					    if segments.len() < 2 {
 | 
				
			||||||
        return None;
 | 
					        return None;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -7,8 +7,7 @@ use crate::{
 | 
				
			|||||||
    db::HirDatabase,
 | 
					    db::HirDatabase,
 | 
				
			||||||
    diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr},
 | 
					    diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr},
 | 
				
			||||||
    expr::AstPtr,
 | 
					    expr::AstPtr,
 | 
				
			||||||
    name,
 | 
					    path::known,
 | 
				
			||||||
    path::{PathKind, PathSegment},
 | 
					 | 
				
			||||||
    ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
 | 
					    ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
 | 
				
			||||||
    Adt, Function, Name, Path,
 | 
					    Adt, Function, Name, Path,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -108,14 +107,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
 | 
				
			|||||||
            None => return,
 | 
					            None => return,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let std_result_path = Path {
 | 
					        let std_result_path = known::std_result_result();
 | 
				
			||||||
            kind: PathKind::Abs,
 | 
					 | 
				
			||||||
            segments: vec![
 | 
					 | 
				
			||||||
                PathSegment { name: name::STD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::RESULT_MOD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::RESULT_TYPE, args_and_bindings: None },
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let resolver = self.func.resolver(db);
 | 
					        let resolver = self.func.resolver(db);
 | 
				
			||||||
        let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
 | 
					        let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
 | 
				
			||||||
 | 
				
			|||||||
@ -85,6 +85,7 @@ impl AsName for ra_db::Dependency {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Primitives
 | 
				
			||||||
pub(crate) const ISIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"isize"));
 | 
					pub(crate) const ISIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"isize"));
 | 
				
			||||||
pub(crate) const I8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"i8"));
 | 
					pub(crate) const I8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"i8"));
 | 
				
			||||||
pub(crate) const I16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i16"));
 | 
					pub(crate) const I16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i16"));
 | 
				
			||||||
@ -102,24 +103,30 @@ pub(crate) const F64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f64")
 | 
				
			|||||||
pub(crate) const BOOL: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"bool"));
 | 
					pub(crate) const BOOL: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"bool"));
 | 
				
			||||||
pub(crate) const CHAR: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"char"));
 | 
					pub(crate) const CHAR: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"char"));
 | 
				
			||||||
pub(crate) const STR: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"str"));
 | 
					pub(crate) const STR: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"str"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Special names
 | 
				
			||||||
pub(crate) const SELF_PARAM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"self"));
 | 
					pub(crate) const SELF_PARAM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"self"));
 | 
				
			||||||
pub(crate) const SELF_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Self"));
 | 
					pub(crate) const SELF_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Self"));
 | 
				
			||||||
pub(crate) const MACRO_RULES: Name = Name::new(SmolStr::new_inline_from_ascii(11, b"macro_rules"));
 | 
					pub(crate) const MACRO_RULES: Name = Name::new(SmolStr::new_inline_from_ascii(11, b"macro_rules"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Components of known path (value or mod name)
 | 
				
			||||||
pub(crate) const STD: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"std"));
 | 
					pub(crate) const STD: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"std"));
 | 
				
			||||||
pub(crate) const ITER: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"iter"));
 | 
					pub(crate) const ITER: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"iter"));
 | 
				
			||||||
pub(crate) const INTO_ITERATOR: Name =
 | 
					 | 
				
			||||||
    Name::new(SmolStr::new_inline_from_ascii(12, b"IntoIterator"));
 | 
					 | 
				
			||||||
pub(crate) const ITEM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item"));
 | 
					 | 
				
			||||||
pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops"));
 | 
					pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops"));
 | 
				
			||||||
pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try"));
 | 
					pub(crate) const FUTURE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future"));
 | 
				
			||||||
pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
 | 
					pub(crate) const RESULT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result"));
 | 
				
			||||||
pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future"));
 | 
					pub(crate) const BOXED: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Components of known path (type name)
 | 
				
			||||||
 | 
					pub(crate) const INTO_ITERATOR_TYPE: Name =
 | 
				
			||||||
 | 
					    Name::new(SmolStr::new_inline_from_ascii(12, b"IntoIterator"));
 | 
				
			||||||
 | 
					pub(crate) const ITEM_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item"));
 | 
				
			||||||
 | 
					pub(crate) const TRY_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try"));
 | 
				
			||||||
 | 
					pub(crate) const OK_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
 | 
				
			||||||
pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future"));
 | 
					pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future"));
 | 
				
			||||||
pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result"));
 | 
					 | 
				
			||||||
pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result"));
 | 
					pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result"));
 | 
				
			||||||
pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
 | 
					pub(crate) const OUTPUT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
 | 
				
			||||||
pub(crate) const TARGET: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target"));
 | 
					pub(crate) const TARGET_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target"));
 | 
				
			||||||
pub(crate) const BOXED_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed"));
 | 
					 | 
				
			||||||
pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box"));
 | 
					pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn resolve_name(text: &SmolStr) -> SmolStr {
 | 
					fn resolve_name(text: &SmolStr) -> SmolStr {
 | 
				
			||||||
 | 
				
			|||||||
@ -382,6 +382,11 @@ impl CrateDefMap {
 | 
				
			|||||||
                    return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
 | 
					                    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 {
 | 
					        for (i, segment) in segments {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
use std::sync::Arc;
 | 
					use std::{iter, sync::Arc};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use ra_syntax::{
 | 
					use ra_syntax::{
 | 
				
			||||||
    ast::{self, NameOwner, TypeAscriptionOwner},
 | 
					    ast::{self, NameOwner, TypeAscriptionOwner},
 | 
				
			||||||
@ -42,7 +42,7 @@ pub enum GenericArg {
 | 
				
			|||||||
    // or lifetime...
 | 
					    // or lifetime...
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 | 
				
			||||||
pub enum PathKind {
 | 
					pub enum PathKind {
 | 
				
			||||||
    Plain,
 | 
					    Plain,
 | 
				
			||||||
    Self_,
 | 
					    Self_,
 | 
				
			||||||
@ -50,6 +50,8 @@ pub enum PathKind {
 | 
				
			|||||||
    Crate,
 | 
					    Crate,
 | 
				
			||||||
    // Absolute path
 | 
					    // Absolute path
 | 
				
			||||||
    Abs,
 | 
					    Abs,
 | 
				
			||||||
 | 
					    // Type based path like `<T>::foo`
 | 
				
			||||||
 | 
					    Type(Box<TypeRef>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Path {
 | 
					impl Path {
 | 
				
			||||||
@ -63,6 +65,16 @@ impl Path {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> 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.
 | 
					    /// Converts an `ast::Path` to `Path`. Works with use trees.
 | 
				
			||||||
    pub fn from_ast(mut path: ast::Path) -> Option<Path> {
 | 
					    pub fn from_ast(mut path: ast::Path) -> Option<Path> {
 | 
				
			||||||
        let mut kind = PathKind::Plain;
 | 
					        let mut kind = PathKind::Plain;
 | 
				
			||||||
@ -92,25 +104,33 @@ impl Path {
 | 
				
			|||||||
                ast::PathSegmentKind::Type { type_ref, trait_ref } => {
 | 
					                ast::PathSegmentKind::Type { type_ref, trait_ref } => {
 | 
				
			||||||
                    assert!(path.qualifier().is_none()); // this can only occur at the first segment
 | 
					                    assert!(path.qualifier().is_none()); // this can only occur at the first segment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // FIXME: handle <T> syntax (type segments without trait)
 | 
					                    let self_type = TypeRef::from_ast(type_ref?);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    match trait_ref {
 | 
				
			||||||
 | 
					                        // <T>::foo
 | 
				
			||||||
 | 
					                        None => {
 | 
				
			||||||
 | 
					                            kind = PathKind::Type(Box::new(self_type));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
 | 
					                        // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
 | 
				
			||||||
                    let path = Path::from_ast(trait_ref?.path()?)?;
 | 
					                        Some(trait_ref) => {
 | 
				
			||||||
 | 
					                            let path = Path::from_ast(trait_ref.path()?)?;
 | 
				
			||||||
                            kind = path.kind;
 | 
					                            kind = path.kind;
 | 
				
			||||||
                            let mut prefix_segments = path.segments;
 | 
					                            let mut prefix_segments = path.segments;
 | 
				
			||||||
                            prefix_segments.reverse();
 | 
					                            prefix_segments.reverse();
 | 
				
			||||||
                            segments.extend(prefix_segments);
 | 
					                            segments.extend(prefix_segments);
 | 
				
			||||||
                            // Insert the type reference (T in the above example) as Self parameter for the trait
 | 
					                            // Insert the type reference (T in the above example) as Self parameter for the trait
 | 
				
			||||||
                    let self_type = TypeRef::from_ast(type_ref?);
 | 
					 | 
				
			||||||
                            let mut last_segment = segments.last_mut()?;
 | 
					                            let mut last_segment = segments.last_mut()?;
 | 
				
			||||||
                            if last_segment.args_and_bindings.is_none() {
 | 
					                            if last_segment.args_and_bindings.is_none() {
 | 
				
			||||||
                        last_segment.args_and_bindings = Some(Arc::new(GenericArgs::empty()));
 | 
					                                last_segment.args_and_bindings =
 | 
				
			||||||
 | 
					                                    Some(Arc::new(GenericArgs::empty()));
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
                            let args = last_segment.args_and_bindings.as_mut().unwrap();
 | 
					                            let args = last_segment.args_and_bindings.as_mut().unwrap();
 | 
				
			||||||
                            let mut args_inner = Arc::make_mut(args);
 | 
					                            let mut args_inner = Arc::make_mut(args);
 | 
				
			||||||
                            args_inner.has_self_type = true;
 | 
					                            args_inner.has_self_type = true;
 | 
				
			||||||
                            args_inner.args.insert(0, GenericArg::Type(self_type));
 | 
					                            args_inner.args.insert(0, GenericArg::Type(self_type));
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                ast::PathSegmentKind::CrateKw => {
 | 
					                ast::PathSegmentKind::CrateKw => {
 | 
				
			||||||
                    kind = PathKind::Crate;
 | 
					                    kind = PathKind::Crate;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
@ -214,7 +234,7 @@ impl GenericArgs {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if let Some(ret_type) = ret_type {
 | 
					        if let Some(ret_type) = ret_type {
 | 
				
			||||||
            let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
 | 
					            let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
 | 
				
			||||||
            bindings.push((name::OUTPUT, type_ref))
 | 
					            bindings.push((name::OUTPUT_TYPE, type_ref))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if args.is_empty() && bindings.is_empty() {
 | 
					        if args.is_empty() && bindings.is_empty() {
 | 
				
			||||||
            None
 | 
					            None
 | 
				
			||||||
@ -230,10 +250,7 @@ impl GenericArgs {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl From<Name> for Path {
 | 
					impl From<Name> for Path {
 | 
				
			||||||
    fn from(name: Name) -> Path {
 | 
					    fn from(name: Name) -> Path {
 | 
				
			||||||
        Path {
 | 
					        Path::from_simple_segments(PathKind::Plain, iter::once(name))
 | 
				
			||||||
            kind: PathKind::Plain,
 | 
					 | 
				
			||||||
            segments: vec![PathSegment { name, args_and_bindings: None }],
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -287,6 +304,7 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
 | 
				
			|||||||
    let segment = path.segment()?;
 | 
					    let segment = path.segment()?;
 | 
				
			||||||
    let res = match segment.kind()? {
 | 
					    let res = match segment.kind()? {
 | 
				
			||||||
        ast::PathSegmentKind::Name(name) => {
 | 
					        ast::PathSegmentKind::Name(name) => {
 | 
				
			||||||
 | 
					            // no type args in use
 | 
				
			||||||
            let mut res = prefix
 | 
					            let mut res = prefix
 | 
				
			||||||
                .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
 | 
					                .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
 | 
				
			||||||
            res.segments.push(PathSegment {
 | 
					            res.segments.push(PathSegment {
 | 
				
			||||||
@ -299,19 +317,19 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
 | 
				
			|||||||
            if prefix.is_some() {
 | 
					            if prefix.is_some() {
 | 
				
			||||||
                return None;
 | 
					                return None;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Path { kind: PathKind::Crate, segments: Vec::new() }
 | 
					            Path::from_simple_segments(PathKind::Crate, iter::empty())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ast::PathSegmentKind::SelfKw => {
 | 
					        ast::PathSegmentKind::SelfKw => {
 | 
				
			||||||
            if prefix.is_some() {
 | 
					            if prefix.is_some() {
 | 
				
			||||||
                return None;
 | 
					                return None;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Path { kind: PathKind::Self_, segments: Vec::new() }
 | 
					            Path::from_simple_segments(PathKind::Self_, iter::empty())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ast::PathSegmentKind::SuperKw => {
 | 
					        ast::PathSegmentKind::SuperKw => {
 | 
				
			||||||
            if prefix.is_some() {
 | 
					            if prefix.is_some() {
 | 
				
			||||||
                return None;
 | 
					                return None;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Path { kind: PathKind::Super, segments: Vec::new() }
 | 
					            Path::from_simple_segments(PathKind::Super, iter::empty())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ast::PathSegmentKind::Type { .. } => {
 | 
					        ast::PathSegmentKind::Type { .. } => {
 | 
				
			||||||
            // not allowed in imports
 | 
					            // not allowed in imports
 | 
				
			||||||
@ -320,3 +338,31 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
    Some(res)
 | 
					    Some(res)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod known {
 | 
				
			||||||
 | 
					    use super::{Path, PathKind};
 | 
				
			||||||
 | 
					    use crate::name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn std_iter_into_iterator() -> Path {
 | 
				
			||||||
 | 
					        Path::from_simple_segments(
 | 
				
			||||||
 | 
					            PathKind::Abs,
 | 
				
			||||||
 | 
					            vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE],
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn std_ops_try() -> Path {
 | 
				
			||||||
 | 
					        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE])
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn std_result_result() -> Path {
 | 
				
			||||||
 | 
					        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn std_future_future() -> Path {
 | 
				
			||||||
 | 
					        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn std_boxed_box() -> Path {
 | 
				
			||||||
 | 
					        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE])
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@ use crate::{
 | 
				
			|||||||
    name::{Name, SELF_PARAM, SELF_TYPE},
 | 
					    name::{Name, SELF_PARAM, SELF_TYPE},
 | 
				
			||||||
    nameres::{CrateDefMap, CrateModuleId, PerNs},
 | 
					    nameres::{CrateDefMap, CrateModuleId, PerNs},
 | 
				
			||||||
    path::{Path, PathKind},
 | 
					    path::{Path, PathKind},
 | 
				
			||||||
 | 
					    type_ref::TypeRef,
 | 
				
			||||||
    Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct,
 | 
					    Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct,
 | 
				
			||||||
    Trait, TypeAlias,
 | 
					    Trait, TypeAlias,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -64,9 +65,10 @@ pub enum TypeNs {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub enum ValueOrPartial {
 | 
					pub enum ResolveValueResult<'a> {
 | 
				
			||||||
    ValueNs(ValueNs),
 | 
					    ValueNs(ValueNs),
 | 
				
			||||||
    Partial(TypeNs, usize),
 | 
					    Partial(TypeNs, usize),
 | 
				
			||||||
 | 
					    TypeRef(&'a TypeRef),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
@ -183,11 +185,15 @@ impl Resolver {
 | 
				
			|||||||
        Some(res)
 | 
					        Some(res)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub(crate) fn resolve_path_in_value_ns(
 | 
					    pub(crate) fn resolve_path_in_value_ns<'p>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        db: &impl HirDatabase,
 | 
					        db: &impl HirDatabase,
 | 
				
			||||||
        path: &Path,
 | 
					        path: &'p Path,
 | 
				
			||||||
    ) -> Option<ValueOrPartial> {
 | 
					    ) -> Option<ResolveValueResult<'p>> {
 | 
				
			||||||
 | 
					        if let PathKind::Type(type_ref) = &path.kind {
 | 
				
			||||||
 | 
					            return Some(ResolveValueResult::TypeRef(type_ref));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let n_segments = path.segments.len();
 | 
					        let n_segments = path.segments.len();
 | 
				
			||||||
        let tmp = SELF_PARAM;
 | 
					        let tmp = SELF_PARAM;
 | 
				
			||||||
        let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name };
 | 
					        let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name };
 | 
				
			||||||
@ -208,7 +214,7 @@ impl Resolver {
 | 
				
			|||||||
                        .find(|entry| entry.name() == first_name);
 | 
					                        .find(|entry| entry.name() == first_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if let Some(e) = entry {
 | 
					                    if let Some(e) = entry {
 | 
				
			||||||
                        return Some(ValueOrPartial::ValueNs(ValueNs::LocalBinding(e.pat())));
 | 
					                        return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(e.pat())));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Scope::ExprScope(_) => continue,
 | 
					                Scope::ExprScope(_) => continue,
 | 
				
			||||||
@ -216,7 +222,7 @@ impl Resolver {
 | 
				
			|||||||
                Scope::GenericParams(params) if n_segments > 1 => {
 | 
					                Scope::GenericParams(params) if n_segments > 1 => {
 | 
				
			||||||
                    if let Some(param) = params.find_by_name(first_name) {
 | 
					                    if let Some(param) = params.find_by_name(first_name) {
 | 
				
			||||||
                        let ty = TypeNs::GenericParam(param.idx);
 | 
					                        let ty = TypeNs::GenericParam(param.idx);
 | 
				
			||||||
                        return Some(ValueOrPartial::Partial(ty, 1));
 | 
					                        return Some(ResolveValueResult::Partial(ty, 1));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Scope::GenericParams(_) => continue,
 | 
					                Scope::GenericParams(_) => continue,
 | 
				
			||||||
@ -224,7 +230,7 @@ impl Resolver {
 | 
				
			|||||||
                Scope::ImplBlockScope(impl_) if n_segments > 1 => {
 | 
					                Scope::ImplBlockScope(impl_) if n_segments > 1 => {
 | 
				
			||||||
                    if first_name == &SELF_TYPE {
 | 
					                    if first_name == &SELF_TYPE {
 | 
				
			||||||
                        let ty = TypeNs::SelfType(*impl_);
 | 
					                        let ty = TypeNs::SelfType(*impl_);
 | 
				
			||||||
                        return Some(ValueOrPartial::Partial(ty, 1));
 | 
					                        return Some(ResolveValueResult::Partial(ty, 1));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Scope::ImplBlockScope(_) => continue,
 | 
					                Scope::ImplBlockScope(_) => continue,
 | 
				
			||||||
@ -247,7 +253,7 @@ impl Resolver {
 | 
				
			|||||||
                                | ModuleDef::BuiltinType(_)
 | 
					                                | ModuleDef::BuiltinType(_)
 | 
				
			||||||
                                | ModuleDef::Module(_) => return None,
 | 
					                                | ModuleDef::Module(_) => return None,
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
                            Some(ValueOrPartial::ValueNs(value))
 | 
					                            Some(ResolveValueResult::ValueNs(value))
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        Some(idx) => {
 | 
					                        Some(idx) => {
 | 
				
			||||||
                            let ty = match module_def.take_types()? {
 | 
					                            let ty = match module_def.take_types()? {
 | 
				
			||||||
@ -262,7 +268,7 @@ impl Resolver {
 | 
				
			|||||||
                                | ModuleDef::Const(_)
 | 
					                                | ModuleDef::Const(_)
 | 
				
			||||||
                                | ModuleDef::Static(_) => return None,
 | 
					                                | ModuleDef::Static(_) => return None,
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
                            Some(ValueOrPartial::Partial(ty, idx))
 | 
					                            Some(ResolveValueResult::Partial(ty, idx))
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -277,8 +283,8 @@ impl Resolver {
 | 
				
			|||||||
        path: &Path,
 | 
					        path: &Path,
 | 
				
			||||||
    ) -> Option<ValueNs> {
 | 
					    ) -> Option<ValueNs> {
 | 
				
			||||||
        match self.resolve_path_in_value_ns(db, path)? {
 | 
					        match self.resolve_path_in_value_ns(db, path)? {
 | 
				
			||||||
            ValueOrPartial::ValueNs(it) => Some(it),
 | 
					            ResolveValueResult::ValueNs(it) => Some(it),
 | 
				
			||||||
            ValueOrPartial::Partial(..) => None,
 | 
					            ResolveValueResult::Partial(..) | ResolveValueResult::TypeRef(_) => None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,8 +25,7 @@ use crate::{
 | 
				
			|||||||
        BodySourceMap,
 | 
					        BodySourceMap,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    ids::LocationCtx,
 | 
					    ids::LocationCtx,
 | 
				
			||||||
    name,
 | 
					    path::known,
 | 
				
			||||||
    path::{PathKind, PathSegment},
 | 
					 | 
				
			||||||
    resolve::{ScopeDef, TypeNs, ValueNs},
 | 
					    resolve::{ScopeDef, TypeNs, ValueNs},
 | 
				
			||||||
    ty::method_resolution::implements_trait,
 | 
					    ty::method_resolution::implements_trait,
 | 
				
			||||||
    AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef,
 | 
					    AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef,
 | 
				
			||||||
@ -433,14 +432,7 @@ impl SourceAnalyzer {
 | 
				
			|||||||
    /// Checks that particular type `ty` implements `std::future::Future`.
 | 
					    /// Checks that particular type `ty` implements `std::future::Future`.
 | 
				
			||||||
    /// This function is used in `.await` syntax completion.
 | 
					    /// This function is used in `.await` syntax completion.
 | 
				
			||||||
    pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool {
 | 
					    pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool {
 | 
				
			||||||
        let std_future_path = Path {
 | 
					        let std_future_path = known::std_future_future();
 | 
				
			||||||
            kind: PathKind::Abs,
 | 
					 | 
				
			||||||
            segments: vec![
 | 
					 | 
				
			||||||
                PathSegment { name: name::STD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::FUTURE_MOD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None },
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
 | 
					        let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
 | 
				
			||||||
            Some(it) => it,
 | 
					            Some(it) => it,
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,7 @@ fn deref_by_trait(
 | 
				
			|||||||
        crate::lang_item::LangItemTarget::Trait(t) => t,
 | 
					        crate::lang_item::LangItemTarget::Trait(t) => t,
 | 
				
			||||||
        _ => return None,
 | 
					        _ => return None,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    let target = deref_trait.associated_type_by_name(db, &name::TARGET)?;
 | 
					    let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if target.generic_params(db).count_params_including_parent() != 1 {
 | 
					    if target.generic_params(db).count_params_including_parent() != 1 {
 | 
				
			||||||
        // the Target type + Deref trait should only have one generic parameter,
 | 
					        // the Target type + Deref trait should only have one generic parameter,
 | 
				
			||||||
 | 
				
			|||||||
@ -44,11 +44,12 @@ use crate::{
 | 
				
			|||||||
    generics::{GenericParams, HasGenericParams},
 | 
					    generics::{GenericParams, HasGenericParams},
 | 
				
			||||||
    name,
 | 
					    name,
 | 
				
			||||||
    nameres::Namespace,
 | 
					    nameres::Namespace,
 | 
				
			||||||
    path::{GenericArg, GenericArgs, PathKind, PathSegment},
 | 
					    path::{known, GenericArg, GenericArgs},
 | 
				
			||||||
    resolve::{Resolver, TypeNs, ValueNs, ValueOrPartial},
 | 
					    resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
 | 
				
			||||||
    ty::infer::diagnostics::InferenceDiagnostic,
 | 
					    ty::infer::diagnostics::InferenceDiagnostic,
 | 
				
			||||||
    type_ref::{Mutability, TypeRef},
 | 
					    type_ref::{Mutability, TypeRef},
 | 
				
			||||||
    Adt, ConstData, DefWithBody, FnData, Function, HasBody, ImplItem, Name, Path, StructField,
 | 
					    Adt, ConstData, DefWithBody, Either, FnData, Function, HasBody, ImplItem, Name, Path,
 | 
				
			||||||
 | 
					    StructField,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod unify;
 | 
					mod unify;
 | 
				
			||||||
@ -470,9 +471,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
 | 
				
			|||||||
        let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?;
 | 
					        let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (value, self_subst) = match value_or_partial {
 | 
					        let (value, self_subst) = match value_or_partial {
 | 
				
			||||||
            ValueOrPartial::ValueNs(it) => (it, None),
 | 
					            ResolveValueResult::ValueNs(it) => (it, None),
 | 
				
			||||||
            ValueOrPartial::Partial(def, remaining_index) => {
 | 
					            ResolveValueResult::Partial(def, remaining_index) => {
 | 
				
			||||||
                self.resolve_assoc_item(def, path, remaining_index, id)?
 | 
					                self.resolve_assoc_item(Either::A(def), path, remaining_index, id)?
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ResolveValueResult::TypeRef(type_ref) => {
 | 
				
			||||||
 | 
					                let ty = self.make_ty(type_ref);
 | 
				
			||||||
 | 
					                self.resolve_assoc_item(Either::B(ty), path, 0, id)?
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -503,7 +508,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn resolve_assoc_item(
 | 
					    fn resolve_assoc_item(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        mut def: TypeNs,
 | 
					        mut def_or_ty: Either<TypeNs, Ty>,
 | 
				
			||||||
        path: &Path,
 | 
					        path: &Path,
 | 
				
			||||||
        remaining_index: usize,
 | 
					        remaining_index: usize,
 | 
				
			||||||
        id: ExprOrPatId,
 | 
					        id: ExprOrPatId,
 | 
				
			||||||
@ -516,7 +521,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
 | 
				
			|||||||
        // resolve intermediate segments
 | 
					        // resolve intermediate segments
 | 
				
			||||||
        for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
 | 
					        for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
 | 
				
			||||||
            let is_last_segment = i == path.segments[remaining_index..].len() - 1;
 | 
					            let is_last_segment = i == path.segments[remaining_index..].len() - 1;
 | 
				
			||||||
            ty = {
 | 
					            ty = match def_or_ty {
 | 
				
			||||||
 | 
					                Either::A(def) => {
 | 
				
			||||||
                    let typable: TypableDef = match def {
 | 
					                    let typable: TypableDef = match def {
 | 
				
			||||||
                        TypeNs::Adt(it) => it.into(),
 | 
					                        TypeNs::Adt(it) => it.into(),
 | 
				
			||||||
                        TypeNs::TypeAlias(it) => it.into(),
 | 
					                        TypeNs::TypeAlias(it) => it.into(),
 | 
				
			||||||
@ -540,6 +546,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
 | 
				
			|||||||
                        typable,
 | 
					                        typable,
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    ty.subst(&substs)
 | 
					                    ty.subst(&substs)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Either::B(ty) => ty,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            if is_last_segment {
 | 
					            if is_last_segment {
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
@ -550,15 +558,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
 | 
				
			|||||||
            log::debug!("looking for path segment: {:?}", segment);
 | 
					            log::debug!("looking for path segment: {:?}", segment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let ty = mem::replace(&mut ty, Ty::Unknown);
 | 
					            let ty = mem::replace(&mut ty, Ty::Unknown);
 | 
				
			||||||
            def = ty.iterate_impl_items(self.db, krate, |item| {
 | 
					            def_or_ty = ty.iterate_impl_items(self.db, krate, |item| {
 | 
				
			||||||
                match item {
 | 
					                match item {
 | 
				
			||||||
                    crate::ImplItem::Method(_) => None,
 | 
					                    crate::ImplItem::Method(_) => None,
 | 
				
			||||||
                    crate::ImplItem::Const(_) => None,
 | 
					                    crate::ImplItem::Const(_) => None,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // FIXME: Resolve associated types
 | 
					                    // FIXME: Resolve associated types
 | 
				
			||||||
                    crate::ImplItem::TypeAlias(_) => {
 | 
					                    crate::ImplItem::TypeAlias(_) => {
 | 
				
			||||||
                        // Some(TypeNs::TypeAlias(..))
 | 
					                        // Some(Either::A(TypeNs::TypeAlias(..)))
 | 
				
			||||||
                        None::<TypeNs>
 | 
					                        None
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            })?;
 | 
					            })?;
 | 
				
			||||||
@ -1434,57 +1442,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn resolve_into_iter_item(&self) -> Option<TypeAlias> {
 | 
					    fn resolve_into_iter_item(&self) -> Option<TypeAlias> {
 | 
				
			||||||
        let into_iter_path = Path {
 | 
					        let path = known::std_iter_into_iterator();
 | 
				
			||||||
            kind: PathKind::Abs,
 | 
					        let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
 | 
				
			||||||
            segments: vec![
 | 
					        trait_.associated_type_by_name(self.db, &name::ITEM_TYPE)
 | 
				
			||||||
                PathSegment { name: name::STD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::ITER, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::INTO_ITERATOR, args_and_bindings: None },
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let trait_ = self.resolver.resolve_known_trait(self.db, &into_iter_path)?;
 | 
					 | 
				
			||||||
        trait_.associated_type_by_name(self.db, &name::ITEM)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn resolve_ops_try_ok(&self) -> Option<TypeAlias> {
 | 
					    fn resolve_ops_try_ok(&self) -> Option<TypeAlias> {
 | 
				
			||||||
        let ops_try_path = Path {
 | 
					        let path = known::std_ops_try();
 | 
				
			||||||
            kind: PathKind::Abs,
 | 
					        let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
 | 
				
			||||||
            segments: vec![
 | 
					        trait_.associated_type_by_name(self.db, &name::OK_TYPE)
 | 
				
			||||||
                PathSegment { name: name::STD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::OPS, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::TRY, args_and_bindings: None },
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let trait_ = self.resolver.resolve_known_trait(self.db, &ops_try_path)?;
 | 
					 | 
				
			||||||
        trait_.associated_type_by_name(self.db, &name::OK)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn resolve_future_future_output(&self) -> Option<TypeAlias> {
 | 
					    fn resolve_future_future_output(&self) -> Option<TypeAlias> {
 | 
				
			||||||
        let future_future_path = Path {
 | 
					        let path = known::std_future_future();
 | 
				
			||||||
            kind: PathKind::Abs,
 | 
					        let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
 | 
				
			||||||
            segments: vec![
 | 
					        trait_.associated_type_by_name(self.db, &name::OUTPUT_TYPE)
 | 
				
			||||||
                PathSegment { name: name::STD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::FUTURE_MOD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None },
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let trait_ = self.resolver.resolve_known_trait(self.db, &future_future_path)?;
 | 
					 | 
				
			||||||
        trait_.associated_type_by_name(self.db, &name::OUTPUT)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn resolve_boxed_box(&self) -> Option<Adt> {
 | 
					    fn resolve_boxed_box(&self) -> Option<Adt> {
 | 
				
			||||||
        let boxed_box_path = Path {
 | 
					        let path = known::std_boxed_box();
 | 
				
			||||||
            kind: PathKind::Abs,
 | 
					        let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
 | 
				
			||||||
            segments: vec![
 | 
					 | 
				
			||||||
                PathSegment { name: name::STD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::BOXED_MOD, args_and_bindings: None },
 | 
					 | 
				
			||||||
                PathSegment { name: name::BOX_TYPE, args_and_bindings: None },
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        let struct_ = self.resolver.resolve_known_struct(self.db, &boxed_box_path)?;
 | 
					 | 
				
			||||||
        Some(Adt::Struct(struct_))
 | 
					        Some(Adt::Struct(struct_))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -281,6 +281,64 @@ fn test() {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn infer_path_type() {
 | 
				
			||||||
 | 
					    assert_snapshot!(
 | 
				
			||||||
 | 
					        infer(r#"
 | 
				
			||||||
 | 
					struct S;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl S {
 | 
				
			||||||
 | 
					    fn foo() -> i32 { 1 }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test() {
 | 
				
			||||||
 | 
					    S::foo();
 | 
				
			||||||
 | 
					    <S>::foo();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					"#),
 | 
				
			||||||
 | 
					        @r###"
 | 
				
			||||||
 | 
					    [41; 46) '{ 1 }': i32
 | 
				
			||||||
 | 
					    [43; 44) '1': i32
 | 
				
			||||||
 | 
					    [60; 93) '{     ...o(); }': ()
 | 
				
			||||||
 | 
					    [66; 72) 'S::foo': fn foo() -> i32
 | 
				
			||||||
 | 
					    [66; 74) 'S::foo()': i32
 | 
				
			||||||
 | 
					    [80; 88) '<S>::foo': fn foo() -> i32
 | 
				
			||||||
 | 
					    [80; 90) '<S>::foo()': i32
 | 
				
			||||||
 | 
					"###
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn infer_slice_method() {
 | 
				
			||||||
 | 
					    assert_snapshot!(
 | 
				
			||||||
 | 
					        infer(r#"
 | 
				
			||||||
 | 
					#[lang = "slice"]
 | 
				
			||||||
 | 
					impl<T> [T] {
 | 
				
			||||||
 | 
					    fn foo(&self) -> T {
 | 
				
			||||||
 | 
					        loop {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[lang = "slice_alloc"]
 | 
				
			||||||
 | 
					impl<T> [T] {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test() {
 | 
				
			||||||
 | 
					    <[_]>::foo(b"foo");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					"#),
 | 
				
			||||||
 | 
					        @r###"
 | 
				
			||||||
 | 
					    [45; 49) 'self': &[T]
 | 
				
			||||||
 | 
					    [56; 79) '{     ...     }': !
 | 
				
			||||||
 | 
					    [66; 73) 'loop {}': !
 | 
				
			||||||
 | 
					    [71; 73) '{}': ()
 | 
				
			||||||
 | 
					    [133; 160) '{     ...o"); }': ()
 | 
				
			||||||
 | 
					    [139; 149) '<[_]>::foo': fn foo<u8>(&[T]) -> T
 | 
				
			||||||
 | 
					    [139; 157) '<[_]>:..."foo")': u8
 | 
				
			||||||
 | 
					    [150; 156) 'b"foo"': &[u8]
 | 
				
			||||||
 | 
					"###
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn infer_struct() {
 | 
					fn infer_struct() {
 | 
				
			||||||
    assert_snapshot!(
 | 
					    assert_snapshot!(
 | 
				
			||||||
 | 
				
			|||||||
@ -2385,6 +2385,9 @@ impl PathSegment {
 | 
				
			|||||||
    pub fn ret_type(&self) -> Option<RetType> {
 | 
					    pub fn ret_type(&self) -> Option<RetType> {
 | 
				
			||||||
        AstChildren::new(&self.syntax).next()
 | 
					        AstChildren::new(&self.syntax).next()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn path_type(&self) -> Option<PathType> {
 | 
				
			||||||
 | 
					        AstChildren::new(&self.syntax).next()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 | 
				
			||||||
pub struct PathType {
 | 
					pub struct PathType {
 | 
				
			||||||
 | 
				
			|||||||
@ -689,7 +689,7 @@ Grammar(
 | 
				
			|||||||
            ]
 | 
					            ]
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        "PathSegment": (
 | 
					        "PathSegment": (
 | 
				
			||||||
            options: [ "NameRef", "TypeArgList", "ParamList", "RetType" ]
 | 
					            options: [ "NameRef", "TypeArgList", "ParamList", "RetType", "PathType" ]
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        "TypeArgList": (collections: [
 | 
					        "TypeArgList": (collections: [
 | 
				
			||||||
            ("type_args", "TypeArg"),
 | 
					            ("type_args", "TypeArg"),
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user