Merge branch 'refs/heads/master' into feature/granular-scopes
This commit is contained in:
commit
5e4e713fc9
29 changed files with 487 additions and 324 deletions
|
|
@ -139,43 +139,40 @@ fn find_struct_impl(
|
|||
|
||||
let struct_ty = {
|
||||
let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() };
|
||||
hir::Struct::from_source(db, src).unwrap().ty(db)
|
||||
hir::Struct::from_source(db, src)?.ty(db)
|
||||
};
|
||||
|
||||
let mut found_new_fn = false;
|
||||
|
||||
let block = module.descendants().filter_map(ast::ImplBlock::cast).find(|impl_blk| {
|
||||
if found_new_fn {
|
||||
return false;
|
||||
}
|
||||
|
||||
let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| {
|
||||
let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() };
|
||||
let blk = hir::ImplBlock::from_source(db, src).unwrap();
|
||||
let blk = hir::ImplBlock::from_source(db, src)?;
|
||||
|
||||
let same_ty = blk.target_ty(db) == struct_ty;
|
||||
let not_trait_impl = blk.target_trait(db).is_none();
|
||||
|
||||
if !(same_ty && not_trait_impl) {
|
||||
return false;
|
||||
None
|
||||
} else {
|
||||
Some(impl_blk)
|
||||
}
|
||||
|
||||
found_new_fn = has_new_fn(impl_blk);
|
||||
true
|
||||
});
|
||||
|
||||
if found_new_fn {
|
||||
None
|
||||
} else {
|
||||
Some(block)
|
||||
if let Some(ref impl_blk) = block {
|
||||
if has_new_fn(impl_blk) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Some(block)
|
||||
}
|
||||
|
||||
fn has_new_fn(imp: &ast::ImplBlock) -> bool {
|
||||
if let Some(il) = imp.item_list() {
|
||||
for item in il.impl_items() {
|
||||
if let ast::ImplItem::FnDef(f) = item {
|
||||
if f.name().unwrap().text().eq_ignore_ascii_case("new") {
|
||||
return true;
|
||||
if let Some(name) = f.name() {
|
||||
if name.text().eq_ignore_ascii_case("new") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
|
|||
|
||||
pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
|
||||
let root = std::env::current_dir()?.join(root);
|
||||
let ws = ProjectWorkspace::discover(root.as_ref())?;
|
||||
let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?;
|
||||
let project_roots = ws.to_roots();
|
||||
let (sender, receiver) = unbounded();
|
||||
let sender = Box::new(move |t| sender.send(t).unwrap());
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use hir_def::{
|
|||
};
|
||||
use hir_expand::{
|
||||
diagnostics::DiagnosticSink,
|
||||
name::{self, AsName},
|
||||
name::{name, AsName},
|
||||
MacroDefId,
|
||||
};
|
||||
use hir_ty::{
|
||||
|
|
@ -723,7 +723,7 @@ impl Local {
|
|||
}
|
||||
|
||||
pub fn is_self(self, db: &impl HirDatabase) -> bool {
|
||||
self.name(db) == Some(name::SELF_PARAM)
|
||||
self.name(db) == Some(name![self])
|
||||
}
|
||||
|
||||
pub fn is_mut(self, db: &impl HirDatabase) -> bool {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use hir_def::{
|
|||
},
|
||||
expr::{ExprId, PatId},
|
||||
nameres::ModuleSource,
|
||||
path::known,
|
||||
path::path,
|
||||
resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
|
||||
AssocItemId, DefWithBodyId,
|
||||
};
|
||||
|
|
@ -418,7 +418,7 @@ impl SourceAnalyzer {
|
|||
/// Checks that particular type `ty` implements `std::future::Future`.
|
||||
/// This function is used in `.await` syntax completion.
|
||||
pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool {
|
||||
let std_future_path = known::std_future_future();
|
||||
let std_future_path = path![std::future::Future];
|
||||
|
||||
let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
|
||||
Some(it) => it.into(),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//! representation.
|
||||
|
||||
use either::Either;
|
||||
use hir_expand::name::{self, AsName, Name};
|
||||
use hir_expand::name::{name, AsName, Name};
|
||||
use ra_arena::Arena;
|
||||
use ra_syntax::{
|
||||
ast::{
|
||||
|
|
@ -68,7 +68,7 @@ where
|
|||
let ptr = AstPtr::new(&self_param);
|
||||
let param_pat = self.alloc_pat(
|
||||
Pat::Bind {
|
||||
name: name::SELF_PARAM,
|
||||
name: name![self],
|
||||
mode: BindingAnnotation::Unannotated,
|
||||
subpat: None,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use hir_expand::name::{self, Name};
|
||||
use hir_expand::name::{name, Name};
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Signedness {
|
||||
|
|
@ -52,26 +52,26 @@ pub enum BuiltinType {
|
|||
impl BuiltinType {
|
||||
#[rustfmt::skip]
|
||||
pub const ALL: &'static [(Name, BuiltinType)] = &[
|
||||
(name::CHAR, BuiltinType::Char),
|
||||
(name::BOOL, BuiltinType::Bool),
|
||||
(name::STR, BuiltinType::Str ),
|
||||
(name![char], BuiltinType::Char),
|
||||
(name![bool], BuiltinType::Bool),
|
||||
(name![str], BuiltinType::Str),
|
||||
|
||||
(name::ISIZE, BuiltinType::Int(BuiltinInt::ISIZE)),
|
||||
(name::I8, BuiltinType::Int(BuiltinInt::I8)),
|
||||
(name::I16, BuiltinType::Int(BuiltinInt::I16)),
|
||||
(name::I32, BuiltinType::Int(BuiltinInt::I32)),
|
||||
(name::I64, BuiltinType::Int(BuiltinInt::I64)),
|
||||
(name::I128, BuiltinType::Int(BuiltinInt::I128)),
|
||||
(name![isize], BuiltinType::Int(BuiltinInt::ISIZE)),
|
||||
(name![i8], BuiltinType::Int(BuiltinInt::I8)),
|
||||
(name![i16], BuiltinType::Int(BuiltinInt::I16)),
|
||||
(name![i32], BuiltinType::Int(BuiltinInt::I32)),
|
||||
(name![i64], BuiltinType::Int(BuiltinInt::I64)),
|
||||
(name![i128], BuiltinType::Int(BuiltinInt::I128)),
|
||||
|
||||
(name::USIZE, BuiltinType::Int(BuiltinInt::USIZE)),
|
||||
(name::U8, BuiltinType::Int(BuiltinInt::U8)),
|
||||
(name::U16, BuiltinType::Int(BuiltinInt::U16)),
|
||||
(name::U32, BuiltinType::Int(BuiltinInt::U32)),
|
||||
(name::U64, BuiltinType::Int(BuiltinInt::U64)),
|
||||
(name::U128, BuiltinType::Int(BuiltinInt::U128)),
|
||||
(name![usize], BuiltinType::Int(BuiltinInt::USIZE)),
|
||||
(name![u8], BuiltinType::Int(BuiltinInt::U8)),
|
||||
(name![u16], BuiltinType::Int(BuiltinInt::U16)),
|
||||
(name![u32], BuiltinType::Int(BuiltinInt::U32)),
|
||||
(name![u64], BuiltinType::Int(BuiltinInt::U64)),
|
||||
(name![u128], BuiltinType::Int(BuiltinInt::U128)),
|
||||
|
||||
(name::F32, BuiltinType::Float(BuiltinFloat::F32)),
|
||||
(name::F64, BuiltinType::Float(BuiltinFloat::F64)),
|
||||
(name![f32], BuiltinType::Float(BuiltinFloat::F32)),
|
||||
(name![f64], BuiltinType::Float(BuiltinFloat::F64)),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use hir_expand::{
|
||||
name::{self, AsName, Name},
|
||||
name::{name, AsName, Name},
|
||||
AstId,
|
||||
};
|
||||
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
|
||||
|
|
@ -37,7 +37,7 @@ impl FunctionData {
|
|||
let self_type = if let Some(type_ref) = self_param.ascribed_type() {
|
||||
TypeRef::from_ast(type_ref)
|
||||
} else {
|
||||
let self_type = TypeRef::Path(name::SELF_TYPE.into());
|
||||
let self_type = TypeRef::Path(name![Self].into());
|
||||
match self_param.kind() {
|
||||
ast::SelfParamKind::Owned => self_type,
|
||||
ast::SelfParamKind::Ref => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
name::{self, AsName, Name},
|
||||
name::{name, AsName, Name},
|
||||
InFile,
|
||||
};
|
||||
use ra_arena::{map::ArenaMap, Arena};
|
||||
|
|
@ -90,11 +90,11 @@ impl GenericParams {
|
|||
|
||||
// traits get the Self type as an implicit first type parameter
|
||||
let self_param_id =
|
||||
generics.types.alloc(TypeParamData { name: name::SELF_TYPE, default: None });
|
||||
generics.types.alloc(TypeParamData { name: name![Self], default: None });
|
||||
sm.insert(self_param_id, Either::Left(src.value.clone()));
|
||||
// add super traits as bounds on Self
|
||||
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
|
||||
let self_param = TypeRef::Path(name::SELF_TYPE.into());
|
||||
let self_param = TypeRef::Path(name![Self].into());
|
||||
generics.fill_bounds(&src.value, self_param);
|
||||
|
||||
generics.fill(&mut sm, &src.value);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
use hir_expand::{
|
||||
builtin_derive::find_builtin_derive,
|
||||
builtin_macro::find_builtin_macro,
|
||||
name::{self, AsName, Name},
|
||||
name::{name, AsName, Name},
|
||||
HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
||||
};
|
||||
use ra_cfg::CfgOptions;
|
||||
|
|
@ -918,7 +918,7 @@ where
|
|||
}
|
||||
|
||||
fn is_macro_rules(path: &Path) -> bool {
|
||||
path.as_ident() == Some(&name::MACRO_RULES)
|
||||
path.as_ident() == Some(&name![macro_rules])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::{iter, sync::Arc};
|
|||
use either::Either;
|
||||
use hir_expand::{
|
||||
hygiene::Hygiene,
|
||||
name::{self, AsName, Name},
|
||||
name::{name, AsName, Name},
|
||||
};
|
||||
use ra_db::CrateId;
|
||||
use ra_syntax::{
|
||||
|
|
@ -76,10 +76,7 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_simple_segments(
|
||||
kind: PathKind,
|
||||
segments: impl IntoIterator<Item = Name>,
|
||||
) -> Path {
|
||||
pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path {
|
||||
Path {
|
||||
kind,
|
||||
segments: segments
|
||||
|
|
@ -276,7 +273,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((name![Output], type_ref))
|
||||
}
|
||||
if args.is_empty() && bindings.is_empty() {
|
||||
None
|
||||
|
|
@ -296,61 +293,36 @@ impl From<Name> for Path {
|
|||
}
|
||||
}
|
||||
|
||||
pub mod known {
|
||||
use hir_expand::name;
|
||||
pub use hir_expand::name as __name;
|
||||
|
||||
use super::{Path, PathKind};
|
||||
|
||||
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_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])
|
||||
}
|
||||
|
||||
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])
|
||||
}
|
||||
#[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")
|
||||
};
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use hir_expand::{
|
||||
name::{self, Name},
|
||||
name::{name, Name},
|
||||
MacroDefId,
|
||||
};
|
||||
use ra_db::CrateId;
|
||||
|
|
@ -163,13 +163,13 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
Scope::ImplBlockScope(impl_) => {
|
||||
if first_name == &name::SELF_TYPE {
|
||||
if first_name == &name![Self] {
|
||||
let idx = if path.segments.len() == 1 { None } else { Some(1) };
|
||||
return Some((TypeNs::SelfType(*impl_), idx));
|
||||
}
|
||||
}
|
||||
Scope::AdtScope(adt) => {
|
||||
if first_name == &name::SELF_TYPE {
|
||||
if first_name == &name![Self] {
|
||||
let idx = if path.segments.len() == 1 { None } else { Some(1) };
|
||||
return Some((TypeNs::AdtSelfType(*adt), idx));
|
||||
}
|
||||
|
|
@ -223,7 +223,7 @@ impl Resolver {
|
|||
return None;
|
||||
}
|
||||
let n_segments = path.segments.len();
|
||||
let tmp = name::SELF_PARAM;
|
||||
let tmp = name![self];
|
||||
let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name };
|
||||
let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
|
||||
for scope in self.scopes.iter().rev() {
|
||||
|
|
@ -259,13 +259,13 @@ impl Resolver {
|
|||
Scope::GenericParams { .. } => continue,
|
||||
|
||||
Scope::ImplBlockScope(impl_) if n_segments > 1 => {
|
||||
if first_name == &name::SELF_TYPE {
|
||||
if first_name == &name![Self] {
|
||||
let ty = TypeNs::SelfType(*impl_);
|
||||
return Some(ResolveValueResult::Partial(ty, 1));
|
||||
}
|
||||
}
|
||||
Scope::AdtScope(adt) if n_segments > 1 => {
|
||||
if first_name == &name::SELF_TYPE {
|
||||
if first_name == &name![Self] {
|
||||
let ty = TypeNs::AdtSelfType(*adt);
|
||||
return Some(ResolveValueResult::Partial(ty, 1));
|
||||
}
|
||||
|
|
@ -439,10 +439,10 @@ impl Scope {
|
|||
}
|
||||
}
|
||||
Scope::ImplBlockScope(i) => {
|
||||
f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into()));
|
||||
f(name![Self], ScopeDef::ImplSelfType((*i).into()));
|
||||
}
|
||||
Scope::AdtScope(i) => {
|
||||
f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into()));
|
||||
f(name![Self], ScopeDef::AdtSelfType((*i).into()));
|
||||
}
|
||||
Scope::ExprScope(scope) => {
|
||||
scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ use crate::db::AstDatabase;
|
|||
use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind};
|
||||
|
||||
macro_rules! register_builtin {
|
||||
( $(($name:ident, $kind: ident) => $expand:ident),* ) => {
|
||||
( $($trait:ident => $expand:ident),* ) => {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum BuiltinDeriveExpander {
|
||||
$($kind),*
|
||||
$($trait),*
|
||||
}
|
||||
|
||||
impl BuiltinDeriveExpander {
|
||||
|
|
@ -26,7 +26,7 @@ macro_rules! register_builtin {
|
|||
tt: &tt::Subtree,
|
||||
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||
let expander = match *self {
|
||||
$( BuiltinDeriveExpander::$kind => $expand, )*
|
||||
$( BuiltinDeriveExpander::$trait => $expand, )*
|
||||
};
|
||||
expander(db, id, tt)
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ macro_rules! register_builtin {
|
|||
|
||||
pub fn find_builtin_derive(ident: &name::Name) -> Option<MacroDefId> {
|
||||
let kind = match ident {
|
||||
$( id if id == &name::$name => BuiltinDeriveExpander::$kind, )*
|
||||
$( id if id == &name::name![$trait] => BuiltinDeriveExpander::$trait, )*
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
|
@ -44,15 +44,15 @@ macro_rules! register_builtin {
|
|||
}
|
||||
|
||||
register_builtin! {
|
||||
(COPY_TRAIT, Copy) => copy_expand,
|
||||
(CLONE_TRAIT, Clone) => clone_expand,
|
||||
(DEFAULT_TRAIT, Default) => default_expand,
|
||||
(DEBUG_TRAIT, Debug) => debug_expand,
|
||||
(HASH_TRAIT, Hash) => hash_expand,
|
||||
(ORD_TRAIT, Ord) => ord_expand,
|
||||
(PARTIAL_ORD_TRAIT, PartialOrd) => partial_ord_expand,
|
||||
(EQ_TRAIT, Eq) => eq_expand,
|
||||
(PARTIAL_EQ_TRAIT, PartialEq) => partial_eq_expand
|
||||
Copy => copy_expand,
|
||||
Clone => clone_expand,
|
||||
Default => default_expand,
|
||||
Debug => debug_expand,
|
||||
Hash => hash_expand,
|
||||
Ord => ord_expand,
|
||||
PartialOrd => partial_ord_expand,
|
||||
Eq => eq_expand,
|
||||
PartialEq => partial_eq_expand
|
||||
}
|
||||
|
||||
struct BasicAdtInfo {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ macro_rules! register_builtin {
|
|||
ast_id: AstId<ast::MacroCall>,
|
||||
) -> Option<MacroDefId> {
|
||||
let kind = match ident {
|
||||
$( id if id == &name::$name => BuiltinFnLikeExpander::$kind, )*
|
||||
$( id if id == &name::name![$name] => BuiltinFnLikeExpander::$kind, )*
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
|
@ -44,15 +44,15 @@ macro_rules! register_builtin {
|
|||
}
|
||||
|
||||
register_builtin! {
|
||||
(COLUMN_MACRO, Column) => column_expand,
|
||||
(COMPILE_ERROR_MACRO, CompileError) => compile_error_expand,
|
||||
(FILE_MACRO, File) => file_expand,
|
||||
(LINE_MACRO, Line) => line_expand,
|
||||
(STRINGIFY_MACRO, Stringify) => stringify_expand,
|
||||
(FORMAT_ARGS_MACRO, FormatArgs) => format_args_expand,
|
||||
(column, Column) => column_expand,
|
||||
(compile_error, CompileError) => compile_error_expand,
|
||||
(file, File) => file_expand,
|
||||
(line, Line) => line_expand,
|
||||
(stringify, Stringify) => stringify_expand,
|
||||
(format_args, FormatArgs) => format_args_expand,
|
||||
// format_args_nl only differs in that it adds a newline in the end,
|
||||
// so we use the same stub expansion for now
|
||||
(FORMAT_ARGS_NL_MACRO, FormatArgsNl) => format_args_expand
|
||||
(format_args_nl, FormatArgsNl) => format_args_expand
|
||||
}
|
||||
|
||||
fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize {
|
||||
|
|
|
|||
|
|
@ -104,71 +104,99 @@ impl AsName for ra_db::Dependency {
|
|||
}
|
||||
}
|
||||
|
||||
// Primitives
|
||||
pub const ISIZE: Name = Name::new_inline_ascii(b"isize");
|
||||
pub const I8: Name = Name::new_inline_ascii(b"i8");
|
||||
pub const I16: Name = Name::new_inline_ascii(b"i16");
|
||||
pub const I32: Name = Name::new_inline_ascii(b"i32");
|
||||
pub const I64: Name = Name::new_inline_ascii(b"i64");
|
||||
pub const I128: Name = Name::new_inline_ascii(b"i128");
|
||||
pub const USIZE: Name = Name::new_inline_ascii(b"usize");
|
||||
pub const U8: Name = Name::new_inline_ascii(b"u8");
|
||||
pub const U16: Name = Name::new_inline_ascii(b"u16");
|
||||
pub const U32: Name = Name::new_inline_ascii(b"u32");
|
||||
pub const U64: Name = Name::new_inline_ascii(b"u64");
|
||||
pub const U128: Name = Name::new_inline_ascii(b"u128");
|
||||
pub const F32: Name = Name::new_inline_ascii(b"f32");
|
||||
pub const F64: Name = Name::new_inline_ascii(b"f64");
|
||||
pub const BOOL: Name = Name::new_inline_ascii(b"bool");
|
||||
pub const CHAR: Name = Name::new_inline_ascii(b"char");
|
||||
pub const STR: Name = Name::new_inline_ascii(b"str");
|
||||
pub mod known {
|
||||
macro_rules! known_names {
|
||||
($($ident:ident),* $(,)?) => {
|
||||
$(
|
||||
#[allow(bad_style)]
|
||||
pub const $ident: super::Name =
|
||||
super::Name::new_inline_ascii(stringify!($ident).as_bytes());
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
// Special names
|
||||
pub const SELF_PARAM: Name = Name::new_inline_ascii(b"self");
|
||||
pub const SELF_TYPE: Name = Name::new_inline_ascii(b"Self");
|
||||
pub const MACRO_RULES: Name = Name::new_inline_ascii(b"macro_rules");
|
||||
known_names!(
|
||||
// Primitives
|
||||
isize,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
usize,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
f32,
|
||||
f64,
|
||||
bool,
|
||||
char,
|
||||
str,
|
||||
// Special names
|
||||
macro_rules,
|
||||
// Components of known path (value or mod name)
|
||||
std,
|
||||
iter,
|
||||
ops,
|
||||
future,
|
||||
result,
|
||||
boxed,
|
||||
// Components of known path (type name)
|
||||
IntoIterator,
|
||||
Item,
|
||||
Try,
|
||||
Ok,
|
||||
Future,
|
||||
Result,
|
||||
Output,
|
||||
Target,
|
||||
Box,
|
||||
RangeFrom,
|
||||
RangeFull,
|
||||
RangeInclusive,
|
||||
RangeToInclusive,
|
||||
RangeTo,
|
||||
Range,
|
||||
Neg,
|
||||
Not,
|
||||
// Builtin macros
|
||||
file,
|
||||
column,
|
||||
compile_error,
|
||||
line,
|
||||
stringify,
|
||||
format_args,
|
||||
format_args_nl,
|
||||
// Builtin derives
|
||||
Copy,
|
||||
Clone,
|
||||
Default,
|
||||
Debug,
|
||||
Hash,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
Eq,
|
||||
PartialEq,
|
||||
);
|
||||
|
||||
// Components of known path (value or mod name)
|
||||
pub const STD: Name = Name::new_inline_ascii(b"std");
|
||||
pub const ITER: Name = Name::new_inline_ascii(b"iter");
|
||||
pub const OPS: Name = Name::new_inline_ascii(b"ops");
|
||||
pub const FUTURE: Name = Name::new_inline_ascii(b"future");
|
||||
pub const RESULT: Name = Name::new_inline_ascii(b"result");
|
||||
pub const BOXED: Name = Name::new_inline_ascii(b"boxed");
|
||||
// self/Self cannot be used as an identifier
|
||||
pub const SELF_PARAM: super::Name = super::Name::new_inline_ascii(b"self");
|
||||
pub const SELF_TYPE: super::Name = super::Name::new_inline_ascii(b"Self");
|
||||
|
||||
// Components of known path (type name)
|
||||
pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(b"IntoIterator");
|
||||
pub const ITEM_TYPE: Name = Name::new_inline_ascii(b"Item");
|
||||
pub const TRY_TYPE: Name = Name::new_inline_ascii(b"Try");
|
||||
pub const OK_TYPE: Name = Name::new_inline_ascii(b"Ok");
|
||||
pub const FUTURE_TYPE: Name = Name::new_inline_ascii(b"Future");
|
||||
pub const RESULT_TYPE: Name = Name::new_inline_ascii(b"Result");
|
||||
pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(b"Output");
|
||||
pub const TARGET_TYPE: Name = Name::new_inline_ascii(b"Target");
|
||||
pub const BOX_TYPE: Name = Name::new_inline_ascii(b"Box");
|
||||
pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(b"RangeFrom");
|
||||
pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(b"RangeFull");
|
||||
pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeInclusive");
|
||||
pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeToInclusive");
|
||||
pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(b"RangeTo");
|
||||
pub const RANGE_TYPE: Name = Name::new_inline_ascii(b"Range");
|
||||
#[macro_export]
|
||||
macro_rules! name {
|
||||
(self) => {
|
||||
$crate::name::known::SELF_PARAM
|
||||
};
|
||||
(Self) => {
|
||||
$crate::name::known::SELF_TYPE
|
||||
};
|
||||
($ident:ident) => {
|
||||
$crate::name::known::$ident
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Builtin Macros
|
||||
pub const FILE_MACRO: Name = Name::new_inline_ascii(b"file");
|
||||
pub const COLUMN_MACRO: Name = Name::new_inline_ascii(b"column");
|
||||
pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(b"compile_error");
|
||||
pub const LINE_MACRO: Name = Name::new_inline_ascii(b"line");
|
||||
pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(b"stringify");
|
||||
pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(b"format_args");
|
||||
pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(b"format_args_nl");
|
||||
|
||||
// Builtin derives
|
||||
pub const COPY_TRAIT: Name = Name::new_inline_ascii(b"Copy");
|
||||
pub const CLONE_TRAIT: Name = Name::new_inline_ascii(b"Clone");
|
||||
pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(b"Default");
|
||||
pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(b"Debug");
|
||||
pub const HASH_TRAIT: Name = Name::new_inline_ascii(b"Hash");
|
||||
pub const ORD_TRAIT: Name = Name::new_inline_ascii(b"Ord");
|
||||
pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(b"PartialOrd");
|
||||
pub const EQ_TRAIT: Name = Name::new_inline_ascii(b"Eq");
|
||||
pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(b"PartialEq");
|
||||
pub use crate::name;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
use std::iter::successors;
|
||||
|
||||
use hir_def::lang_item::LangItemTarget;
|
||||
use hir_expand::name;
|
||||
use hir_expand::name::name;
|
||||
use log::{info, warn};
|
||||
use ra_db::CrateId;
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ fn deref_by_trait(
|
|||
LangItemTarget::TraitId(it) => it,
|
||||
_ => return None,
|
||||
};
|
||||
let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?;
|
||||
let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
|
||||
|
||||
let generic_params = generics(db, target.into());
|
||||
if generic_params.len() != 1 {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use hir_def::{
|
||||
path::{known, Path},
|
||||
path::{path, Path},
|
||||
resolver::HasResolver,
|
||||
AdtId, FunctionId,
|
||||
};
|
||||
|
|
@ -124,7 +124,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let std_result_path = known::std_result_result();
|
||||
let std_result_path = path![std::result::Result];
|
||||
|
||||
let resolver = self.func.resolver(db);
|
||||
let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
|
||||
|
|
|
|||
|
|
@ -24,20 +24,20 @@ use hir_def::{
|
|||
body::Body,
|
||||
data::{ConstData, FunctionData},
|
||||
expr::{BindingAnnotation, ExprId, PatId},
|
||||
path::{known, Path},
|
||||
path::{path, Path},
|
||||
resolver::{HasResolver, Resolver, TypeNs},
|
||||
type_ref::{Mutability, TypeRef},
|
||||
AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId,
|
||||
};
|
||||
use hir_expand::{diagnostics::DiagnosticSink, name};
|
||||
use hir_expand::{diagnostics::DiagnosticSink, name::name};
|
||||
use ra_arena::map::ArenaMap;
|
||||
use ra_prof::profile;
|
||||
|
||||
use super::{
|
||||
primitive::{FloatTy, IntTy},
|
||||
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
|
||||
ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
|
||||
Uncertain,
|
||||
ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
|
||||
TypeWalk, Uncertain,
|
||||
};
|
||||
use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
|
||||
|
||||
|
|
@ -338,6 +338,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
self.table.resolve_ty_shallow(ty)
|
||||
}
|
||||
|
||||
fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
|
||||
match assoc_ty {
|
||||
Some(res_assoc_ty) => {
|
||||
let ty = self.table.new_type_var();
|
||||
let projection = ProjectionPredicate {
|
||||
ty: ty.clone(),
|
||||
projection_ty: ProjectionTy {
|
||||
associated_ty: res_assoc_ty,
|
||||
parameters: Substs::single(inner_ty),
|
||||
},
|
||||
};
|
||||
self.obligations.push(Obligation::Projection(projection));
|
||||
self.resolve_ty_as_possible(ty)
|
||||
}
|
||||
None => Ty::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
/// Recurses through the given type, normalizing associated types mentioned
|
||||
/// in it by replacing them by type variables and registering obligations to
|
||||
/// resolve later. This should be done once for every type we get from some
|
||||
|
|
@ -404,61 +422,73 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
}
|
||||
|
||||
fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
|
||||
let path = known::std_iter_into_iterator();
|
||||
let path = path![std::iter::IntoIterator];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE)
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Item])
|
||||
}
|
||||
|
||||
fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
|
||||
let path = known::std_ops_try();
|
||||
let path = path![std::ops::Try];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE)
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Ok])
|
||||
}
|
||||
|
||||
fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
|
||||
let path = path![std::ops::Neg];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
}
|
||||
|
||||
fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
|
||||
let path = path![std::ops::Not];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
}
|
||||
|
||||
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
|
||||
let path = known::std_future_future();
|
||||
let path = path![std::future::Future];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE)
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
}
|
||||
|
||||
fn resolve_boxed_box(&self) -> Option<AdtId> {
|
||||
let path = known::std_boxed_box();
|
||||
let path = path![std::boxed::Box];
|
||||
let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
|
||||
Some(struct_.into())
|
||||
}
|
||||
|
||||
fn resolve_range_full(&self) -> Option<AdtId> {
|
||||
let path = known::std_ops_range_full();
|
||||
let path = path![std::ops::RangeFull];
|
||||
let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
|
||||
Some(struct_.into())
|
||||
}
|
||||
|
||||
fn resolve_range(&self) -> Option<AdtId> {
|
||||
let path = known::std_ops_range();
|
||||
let path = path![std::ops::Range];
|
||||
let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
|
||||
Some(struct_.into())
|
||||
}
|
||||
|
||||
fn resolve_range_inclusive(&self) -> Option<AdtId> {
|
||||
let path = known::std_ops_range_inclusive();
|
||||
let path = path![std::ops::RangeInclusive];
|
||||
let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
|
||||
Some(struct_.into())
|
||||
}
|
||||
|
||||
fn resolve_range_from(&self) -> Option<AdtId> {
|
||||
let path = known::std_ops_range_from();
|
||||
let path = path![std::ops::RangeFrom];
|
||||
let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
|
||||
Some(struct_.into())
|
||||
}
|
||||
|
||||
fn resolve_range_to(&self) -> Option<AdtId> {
|
||||
let path = known::std_ops_range_to();
|
||||
let path = path![std::ops::RangeTo];
|
||||
let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
|
||||
Some(struct_.into())
|
||||
}
|
||||
|
||||
fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
|
||||
let path = known::std_ops_range_to_inclusive();
|
||||
let path = path![std::ops::RangeToInclusive];
|
||||
let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
|
||||
Some(struct_.into())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use hir_def::{
|
|||
resolver::resolver_for_expr,
|
||||
AdtId, ContainerId, Lookup, StructFieldId,
|
||||
};
|
||||
use hir_expand::name::{self, Name};
|
||||
use hir_expand::name::{name, Name};
|
||||
use ra_syntax::ast::RangeOp;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -19,8 +19,8 @@ use crate::{
|
|||
method_resolution, op,
|
||||
traits::InEnvironment,
|
||||
utils::{generics, variant_data, Generics},
|
||||
CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs,
|
||||
TraitRef, Ty, TypeCtor, TypeWalk, Uncertain,
|
||||
ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty,
|
||||
TypeCtor, TypeWalk, Uncertain,
|
||||
};
|
||||
|
||||
use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
|
||||
|
|
@ -95,21 +95,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
Expr::For { iterable, body, pat } => {
|
||||
let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
|
||||
|
||||
let pat_ty = match self.resolve_into_iter_item() {
|
||||
Some(into_iter_item_alias) => {
|
||||
let pat_ty = self.table.new_type_var();
|
||||
let projection = ProjectionPredicate {
|
||||
ty: pat_ty.clone(),
|
||||
projection_ty: ProjectionTy {
|
||||
associated_ty: into_iter_item_alias,
|
||||
parameters: Substs::single(iterable_ty),
|
||||
},
|
||||
};
|
||||
self.obligations.push(Obligation::Projection(projection));
|
||||
self.resolve_ty_as_possible(pat_ty)
|
||||
}
|
||||
None => Ty::Unknown,
|
||||
};
|
||||
let pat_ty =
|
||||
self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
|
||||
|
||||
self.infer_pat(*pat, &pat_ty, BindingMode::default());
|
||||
self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
|
||||
|
|
@ -284,40 +271,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
}
|
||||
Expr::Await { expr } => {
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
let ty = match self.resolve_future_future_output() {
|
||||
Some(future_future_output_alias) => {
|
||||
let ty = self.table.new_type_var();
|
||||
let projection = ProjectionPredicate {
|
||||
ty: ty.clone(),
|
||||
projection_ty: ProjectionTy {
|
||||
associated_ty: future_future_output_alias,
|
||||
parameters: Substs::single(inner_ty),
|
||||
},
|
||||
};
|
||||
self.obligations.push(Obligation::Projection(projection));
|
||||
self.resolve_ty_as_possible(ty)
|
||||
}
|
||||
None => Ty::Unknown,
|
||||
};
|
||||
let ty =
|
||||
self.resolve_associated_type(inner_ty, self.resolve_future_future_output());
|
||||
ty
|
||||
}
|
||||
Expr::Try { expr } => {
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
let ty = match self.resolve_ops_try_ok() {
|
||||
Some(ops_try_ok_alias) => {
|
||||
let ty = self.table.new_type_var();
|
||||
let projection = ProjectionPredicate {
|
||||
ty: ty.clone(),
|
||||
projection_ty: ProjectionTy {
|
||||
associated_ty: ops_try_ok_alias,
|
||||
parameters: Substs::single(inner_ty),
|
||||
},
|
||||
};
|
||||
self.obligations.push(Obligation::Projection(projection));
|
||||
self.resolve_ty_as_possible(ty)
|
||||
}
|
||||
None => Ty::Unknown,
|
||||
};
|
||||
let ty = self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok());
|
||||
ty
|
||||
}
|
||||
Expr::Cast { expr, type_ref } => {
|
||||
|
|
@ -372,31 +332,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
},
|
||||
UnaryOp::Neg => {
|
||||
match &inner_ty {
|
||||
Ty::Apply(a_ty) => match a_ty.ctor {
|
||||
TypeCtor::Int(Uncertain::Unknown)
|
||||
| TypeCtor::Int(Uncertain::Known(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
..
|
||||
}))
|
||||
| TypeCtor::Float(..) => inner_ty,
|
||||
_ => Ty::Unknown,
|
||||
},
|
||||
Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => {
|
||||
inner_ty
|
||||
}
|
||||
// FIXME: resolve ops::Neg trait
|
||||
_ => Ty::Unknown,
|
||||
// Fast path for builtins
|
||||
Ty::Apply(ApplicationTy {
|
||||
ctor:
|
||||
TypeCtor::Int(Uncertain::Known(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
..
|
||||
})),
|
||||
..
|
||||
})
|
||||
| Ty::Apply(ApplicationTy {
|
||||
ctor: TypeCtor::Int(Uncertain::Unknown),
|
||||
..
|
||||
})
|
||||
| Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. })
|
||||
| Ty::Infer(InferTy::IntVar(..))
|
||||
| Ty::Infer(InferTy::FloatVar(..)) => inner_ty,
|
||||
// Otherwise we resolve via the std::ops::Neg trait
|
||||
_ => self
|
||||
.resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
|
||||
}
|
||||
}
|
||||
UnaryOp::Not => {
|
||||
match &inner_ty {
|
||||
Ty::Apply(a_ty) => match a_ty.ctor {
|
||||
TypeCtor::Bool | TypeCtor::Int(_) => inner_ty,
|
||||
_ => Ty::Unknown,
|
||||
},
|
||||
Ty::Infer(InferTy::IntVar(..)) => inner_ty,
|
||||
// FIXME: resolve ops::Not trait for inner_ty
|
||||
_ => Ty::Unknown,
|
||||
// Fast path for builtins
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })
|
||||
| Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. })
|
||||
| Ty::Infer(InferTy::IntVar(..)) => inner_ty,
|
||||
// Otherwise we resolve via the std::ops::Not trait
|
||||
_ => self
|
||||
.resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -666,7 +631,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
// Parent arguments are unknown, except for the receiver type
|
||||
if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) {
|
||||
for (_id, param) in parent_generics {
|
||||
if param.name == name::SELF_TYPE {
|
||||
if param.name == name![Self] {
|
||||
substs.push(receiver_ty.clone());
|
||||
} else {
|
||||
substs.push(Ty::Unknown);
|
||||
|
|
|
|||
|
|
@ -115,6 +115,70 @@ mod collections {
|
|||
assert_eq!("&str", type_at_pos(&db, pos));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_ops_neg() {
|
||||
let (db, pos) = TestDB::with_position(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
|
||||
struct Bar;
|
||||
struct Foo;
|
||||
|
||||
impl std::ops::Neg for Bar {
|
||||
type Output = Foo;
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let a = Bar;
|
||||
let b = -a;
|
||||
b<|>;
|
||||
}
|
||||
|
||||
//- /std.rs crate:std
|
||||
|
||||
#[prelude_import] use ops::*;
|
||||
mod ops {
|
||||
pub trait Neg {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
assert_eq!("Foo", type_at_pos(&db, pos));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_ops_not() {
|
||||
let (db, pos) = TestDB::with_position(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
|
||||
struct Bar;
|
||||
struct Foo;
|
||||
|
||||
impl std::ops::Not for Bar {
|
||||
type Output = Foo;
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let a = Bar;
|
||||
let b = !a;
|
||||
b<|>;
|
||||
}
|
||||
|
||||
//- /std.rs crate:std
|
||||
|
||||
#[prelude_import] use ops::*;
|
||||
mod ops {
|
||||
pub trait Not {
|
||||
type Output;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
assert_eq!("Foo", type_at_pos(&db, pos));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_from_bound_1() {
|
||||
assert_snapshot!(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! This module provides the built-in trait implementations, e.g. to make
|
||||
//! closures implement `Fn`.
|
||||
use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId};
|
||||
use hir_expand::name;
|
||||
use hir_expand::name::name;
|
||||
use ra_db::CrateId;
|
||||
|
||||
use super::{AssocTyValue, Impl};
|
||||
|
|
@ -79,7 +79,7 @@ fn closure_fn_trait_impl_datum(
|
|||
// and don't want to return a valid value only to find out later that FnOnce
|
||||
// is broken
|
||||
let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
|
||||
let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?;
|
||||
let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
|
||||
|
||||
let num_args: u16 = match &db.body(data.def.into())[data.expr] {
|
||||
Expr::Lambda { args, .. } => args.len() as u16,
|
||||
|
|
@ -137,7 +137,7 @@ fn closure_fn_trait_output_assoc_ty_value(
|
|||
|
||||
let output_ty_id = db
|
||||
.trait_data(fn_once_trait)
|
||||
.associated_type_by_name(&name::OUTPUT_TYPE)
|
||||
.associated_type_by_name(&name![Output])
|
||||
.expect("assoc ty value should not exist");
|
||||
|
||||
BuiltinImplAssocTyValueData {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@ use hir_def::{
|
|||
type_ref::TypeRef,
|
||||
ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId,
|
||||
};
|
||||
use hir_expand::name::{self, Name};
|
||||
use hir_expand::name::{name, Name};
|
||||
|
||||
// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`.
|
||||
// We should return a `TraitREf` here.
|
||||
fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
|
||||
let resolver = trait_.resolver(db);
|
||||
// returning the iterator directly doesn't easily work because of
|
||||
|
|
@ -24,7 +22,7 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
|
|||
.where_predicates
|
||||
.iter()
|
||||
.filter_map(|pred| match &pred.type_ref {
|
||||
TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
|
||||
TypeRef::Path(p) if p.as_ident() == Some(&name![Self]) => pred.bound.as_path(),
|
||||
_ => None,
|
||||
})
|
||||
.filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ra_project_model::CargoFeatures;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
/// Client provided initialization options
|
||||
|
|
@ -37,6 +38,9 @@ pub struct ServerConfig {
|
|||
|
||||
/// Fine grained feature flags to disable specific features.
|
||||
pub feature_flags: FxHashMap<String, bool>,
|
||||
|
||||
/// Cargo feature configurations.
|
||||
pub cargo_features: CargoFeatures,
|
||||
}
|
||||
|
||||
impl Default for ServerConfig {
|
||||
|
|
@ -49,6 +53,7 @@ impl Default for ServerConfig {
|
|||
max_inlay_hint_length: None,
|
||||
with_sysroot: true,
|
||||
feature_flags: FxHashMap::default(),
|
||||
cargo_features: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,11 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem {
|
|||
deprecated: Some(self.deprecated()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if self.deprecated() {
|
||||
res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated])
|
||||
}
|
||||
|
||||
res.insert_text_format = Some(match self.insert_text_format() {
|
||||
InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet,
|
||||
InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText,
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ pub fn main_loop(
|
|||
let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot(
|
||||
ws_root.as_path(),
|
||||
config.with_sysroot,
|
||||
&config.cargo_features,
|
||||
);
|
||||
match workspace {
|
||||
Ok(workspace) => loaded_workspaces.push(workspace),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use cargo_metadata::{CargoOpt, MetadataCommand};
|
|||
use ra_arena::{impl_arena_id, Arena, RawId};
|
||||
use ra_db::Edition;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::Result;
|
||||
|
||||
|
|
@ -23,6 +24,20 @@ pub struct CargoWorkspace {
|
|||
pub(crate) workspace_root: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Default)]
|
||||
#[serde(rename_all = "camelCase", default)]
|
||||
pub struct CargoFeatures {
|
||||
/// Do not activate the `default` feature.
|
||||
pub no_default_features: bool,
|
||||
|
||||
/// Activate all available features
|
||||
pub all_features: bool,
|
||||
|
||||
/// List of features to activate.
|
||||
/// This will be ignored if `cargo_all_features` is true.
|
||||
pub features: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Package(RawId);
|
||||
impl_arena_id!(Package);
|
||||
|
|
@ -132,9 +147,21 @@ impl Target {
|
|||
}
|
||||
|
||||
impl CargoWorkspace {
|
||||
pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> {
|
||||
pub fn from_cargo_metadata(
|
||||
cargo_toml: &Path,
|
||||
cargo_features: &CargoFeatures,
|
||||
) -> Result<CargoWorkspace> {
|
||||
let mut meta = MetadataCommand::new();
|
||||
meta.manifest_path(cargo_toml).features(CargoOpt::AllFeatures);
|
||||
meta.manifest_path(cargo_toml);
|
||||
if cargo_features.all_features {
|
||||
meta.features(CargoOpt::AllFeatures);
|
||||
} else if cargo_features.no_default_features {
|
||||
// FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
|
||||
// https://github.com/oli-obk/cargo_metadata/issues/79
|
||||
meta.features(CargoOpt::NoDefaultFeatures);
|
||||
} else {
|
||||
meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone()));
|
||||
}
|
||||
if let Some(parent) = cargo_toml.parent() {
|
||||
meta.current_dir(parent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use rustc_hash::FxHashMap;
|
|||
use serde_json::from_reader;
|
||||
|
||||
pub use crate::{
|
||||
cargo_workspace::{CargoWorkspace, Package, Target, TargetKind},
|
||||
cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind},
|
||||
json_project::JsonProject,
|
||||
sysroot::Sysroot,
|
||||
};
|
||||
|
|
@ -60,11 +60,15 @@ impl PackageRoot {
|
|||
}
|
||||
|
||||
impl ProjectWorkspace {
|
||||
pub fn discover(path: &Path) -> Result<ProjectWorkspace> {
|
||||
ProjectWorkspace::discover_with_sysroot(path, true)
|
||||
pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result<ProjectWorkspace> {
|
||||
ProjectWorkspace::discover_with_sysroot(path, true, cargo_features)
|
||||
}
|
||||
|
||||
pub fn discover_with_sysroot(path: &Path, with_sysroot: bool) -> Result<ProjectWorkspace> {
|
||||
pub fn discover_with_sysroot(
|
||||
path: &Path,
|
||||
with_sysroot: bool,
|
||||
cargo_features: &CargoFeatures,
|
||||
) -> Result<ProjectWorkspace> {
|
||||
match find_rust_project_json(path) {
|
||||
Some(json_path) => {
|
||||
let file = File::open(json_path)?;
|
||||
|
|
@ -73,7 +77,7 @@ impl ProjectWorkspace {
|
|||
}
|
||||
None => {
|
||||
let cargo_toml = find_cargo_toml(path)?;
|
||||
let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml)?;
|
||||
let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)?;
|
||||
let sysroot =
|
||||
if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() };
|
||||
Ok(ProjectWorkspace::Cargo { cargo, sysroot })
|
||||
|
|
|
|||
|
|
@ -278,6 +278,21 @@
|
|||
"type": "number",
|
||||
"default": 20,
|
||||
"description": "Maximum length for inlay hints"
|
||||
},
|
||||
"rust-analyzer.cargoFeatures.noDefaultFeatures": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Do not activate the `default` feature"
|
||||
},
|
||||
"rust-analyzer.cargoFeatures.allFeatures": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Activate all available features"
|
||||
},
|
||||
"rust-analyzer.cargoFeatures.features": {
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"description": "List of features to activate"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@ export interface CargoWatchOptions {
|
|||
ignore: string[];
|
||||
}
|
||||
|
||||
export interface CargoFeatures {
|
||||
noDefaultFeatures: boolean;
|
||||
allFeatures: boolean;
|
||||
features: string[];
|
||||
}
|
||||
|
||||
export class Config {
|
||||
public highlightingOn = true;
|
||||
public rainbowHighlightingOn = false;
|
||||
|
|
@ -35,8 +41,14 @@ export class Config {
|
|||
command: '',
|
||||
ignore: [],
|
||||
};
|
||||
public cargoFeatures: CargoFeatures = {
|
||||
noDefaultFeatures: false,
|
||||
allFeatures: true,
|
||||
features: [],
|
||||
};
|
||||
|
||||
private prevEnhancedTyping: null | boolean = null;
|
||||
private prevCargoFeatures: null | CargoFeatures = null;
|
||||
|
||||
constructor() {
|
||||
vscode.workspace.onDidChangeConfiguration(_ =>
|
||||
|
|
@ -47,6 +59,8 @@ export class Config {
|
|||
|
||||
public userConfigChanged() {
|
||||
const config = vscode.workspace.getConfiguration('rust-analyzer');
|
||||
let requireReloadMessage = null;
|
||||
|
||||
if (config.has('highlightingOn')) {
|
||||
this.highlightingOn = config.get('highlightingOn') as boolean;
|
||||
}
|
||||
|
|
@ -74,19 +88,8 @@ export class Config {
|
|||
}
|
||||
|
||||
if (this.prevEnhancedTyping !== this.enableEnhancedTyping) {
|
||||
const reloadAction = 'Reload now';
|
||||
vscode.window
|
||||
.showInformationMessage(
|
||||
'Changing enhanced typing setting requires a reload',
|
||||
reloadAction,
|
||||
)
|
||||
.then(selectedAction => {
|
||||
if (selectedAction === reloadAction) {
|
||||
vscode.commands.executeCommand(
|
||||
'workbench.action.reloadWindow',
|
||||
);
|
||||
}
|
||||
});
|
||||
requireReloadMessage =
|
||||
'Changing enhanced typing setting requires a reload';
|
||||
this.prevEnhancedTyping = this.enableEnhancedTyping;
|
||||
}
|
||||
|
||||
|
|
@ -153,5 +156,53 @@ export class Config {
|
|||
if (config.has('withSysroot')) {
|
||||
this.withSysroot = config.get('withSysroot') || false;
|
||||
}
|
||||
|
||||
if (config.has('cargoFeatures.noDefaultFeatures')) {
|
||||
this.cargoFeatures.noDefaultFeatures = config.get(
|
||||
'cargoFeatures.noDefaultFeatures',
|
||||
false,
|
||||
);
|
||||
}
|
||||
if (config.has('cargoFeatures.allFeatures')) {
|
||||
this.cargoFeatures.allFeatures = config.get(
|
||||
'cargoFeatures.allFeatures',
|
||||
true,
|
||||
);
|
||||
}
|
||||
if (config.has('cargoFeatures.features')) {
|
||||
this.cargoFeatures.features = config.get(
|
||||
'cargoFeatures.features',
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
this.prevCargoFeatures !== null &&
|
||||
(this.cargoFeatures.allFeatures !==
|
||||
this.prevCargoFeatures.allFeatures ||
|
||||
this.cargoFeatures.noDefaultFeatures !==
|
||||
this.prevCargoFeatures.noDefaultFeatures ||
|
||||
this.cargoFeatures.features.length !==
|
||||
this.prevCargoFeatures.features.length ||
|
||||
this.cargoFeatures.features.some(
|
||||
(v, i) => v !== this.prevCargoFeatures!.features[i],
|
||||
))
|
||||
) {
|
||||
requireReloadMessage = 'Changing cargo features requires a reload';
|
||||
}
|
||||
this.prevCargoFeatures = { ...this.cargoFeatures };
|
||||
|
||||
if (requireReloadMessage !== null) {
|
||||
const reloadAction = 'Reload now';
|
||||
vscode.window
|
||||
.showInformationMessage(requireReloadMessage, reloadAction)
|
||||
.then(selectedAction => {
|
||||
if (selectedAction === reloadAction) {
|
||||
vscode.commands.executeCommand(
|
||||
'workbench.action.reloadWindow',
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ export class Server {
|
|||
useClientWatching: Server.config.useClientWatching,
|
||||
featureFlags: Server.config.featureFlags,
|
||||
withSysroot: Server.config.withSysroot,
|
||||
cargoFeatures: Server.config.cargoFeatures,
|
||||
},
|
||||
traceOutputChannel,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue