aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/display.rs2
-rw-r--r--crates/hir/src/lib.rs4
-rw-r--r--crates/hir_def/src/find_path.rs30
-rw-r--r--crates/hir_ty/src/db.rs1
-rw-r--r--crates/hir_ty/src/lower.rs34
-rw-r--r--crates/hir_ty/src/tests/regression.rs38
-rw-r--r--crates/hir_ty/src/utils.rs52
-rw-r--r--crates/ide/src/runnables.rs6
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs2
-rw-r--r--crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs2
-rw-r--r--crates/ide_assists/src/utils/suggest_name.rs2
-rw-r--r--crates/ide_completion/src/completions/postfix/format_like.rs2
-rw-r--r--crates/ide_completion/src/context.rs4
-rw-r--r--crates/ide_completion/src/render/enum_variant.rs2
14 files changed, 141 insertions, 40 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 01a4d205f..508ac37c2 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -170,7 +170,7 @@ impl HirDisplay for Field {
170 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 170 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
171 write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?; 171 write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
172 write!(f, "{}: ", self.name(f.db))?; 172 write!(f, "{}: ", self.name(f.db))?;
173 self.signature_ty(f.db).hir_fmt(f) 173 self.ty(f.db).hir_fmt(f)
174 } 174 }
175} 175}
176 176
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 0acfa582a..d8ccfde0c 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -509,7 +509,7 @@ impl Field {
509 /// placeholder types for type parameters). This is good for showing 509 /// placeholder types for type parameters). This is good for showing
510 /// signature help, but not so good to actually get the type of the field 510 /// signature help, but not so good to actually get the type of the field
511 /// when you actually have a variable of the struct. 511 /// when you actually have a variable of the struct.
512 pub fn signature_ty(&self, db: &dyn HirDatabase) -> Type { 512 pub fn ty(&self, db: &dyn HirDatabase) -> Type {
513 let var_id = self.parent.into(); 513 let var_id = self.parent.into();
514 let generic_def_id: GenericDefId = match self.parent { 514 let generic_def_id: GenericDefId = match self.parent {
515 VariantDef::Struct(it) => it.id.into(), 515 VariantDef::Struct(it) => it.id.into(),
@@ -1984,7 +1984,7 @@ impl Type {
1984 None 1984 None
1985 } 1985 }
1986 1986
1987 pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { 1987 pub fn type_arguments(&self) -> impl Iterator<Item = Type> + '_ {
1988 self.ty 1988 self.ty
1989 .strip_references() 1989 .strip_references()
1990 .as_adt() 1990 .as_adt()
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index dc3f2908f..c06a37294 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -130,7 +130,8 @@ fn find_path_inner(
130 } 130 }
131 131
132 // - if the item is the crate root of a dependency crate, return the name from the extern prelude 132 // - if the item is the crate root of a dependency crate, return the name from the extern prelude
133 for (name, def_id) in root.def_map(db).extern_prelude() { 133 let root_def_map = root.def_map(db);
134 for (name, def_id) in root_def_map.extern_prelude() {
134 if item == ItemInNs::Types(*def_id) { 135 if item == ItemInNs::Types(*def_id) {
135 let name = scope_name.unwrap_or_else(|| name.clone()); 136 let name = scope_name.unwrap_or_else(|| name.clone());
136 return Some(ModPath::from_segments(PathKind::Plain, vec![name])); 137 return Some(ModPath::from_segments(PathKind::Plain, vec![name]));
@@ -138,7 +139,8 @@ fn find_path_inner(
138 } 139 }
139 140
140 // - if the item is in the prelude, return the name from there 141 // - if the item is in the prelude, return the name from there
141 if let Some(prelude_module) = def_map.prelude() { 142 if let Some(prelude_module) = root_def_map.prelude() {
143 // Preludes in block DefMaps are ignored, only the crate DefMap is searched
142 let prelude_def_map = prelude_module.def_map(db); 144 let prelude_def_map = prelude_module.def_map(db);
143 let prelude_scope: &crate::item_scope::ItemScope = 145 let prelude_scope: &crate::item_scope::ItemScope =
144 &prelude_def_map[prelude_module.local_id].scope; 146 &prelude_def_map[prelude_module.local_id].scope;
@@ -1057,4 +1059,28 @@ fn f() {
1057 "dep", 1059 "dep",
1058 ); 1060 );
1059 } 1061 }
1062
1063 #[test]
1064 fn prelude_with_inner_items() {
1065 check_found_path(
1066 r#"
1067//- /main.rs crate:main deps:std
1068fn f() {
1069 fn inner() {}
1070 $0
1071}
1072//- /std.rs crate:std
1073pub mod prelude {
1074 pub enum Option { None }
1075 pub use Option::*;
1076}
1077#[prelude_import]
1078pub use prelude::*;
1079 "#,
1080 "None",
1081 "None",
1082 "None",
1083 "None",
1084 );
1085 }
1060} 1086}
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index cf67d4266..9da0a02e3 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -70,6 +70,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
70 fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; 70 fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>;
71 71
72 #[salsa::invoke(crate::lower::generic_defaults_query)] 72 #[salsa::invoke(crate::lower::generic_defaults_query)]
73 #[salsa::cycle(crate::lower::generic_defaults_recover)]
73 fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>; 74 fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>;
74 75
75 #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] 76 #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 7fd46becd..c99dd8d0a 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -414,17 +414,16 @@ impl<'a> TyLoweringContext<'a> {
414 self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, self_ty); 414 self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, self_ty);
415 let ty = if remaining_segments.len() == 1 { 415 let ty = if remaining_segments.len() == 1 {
416 let segment = remaining_segments.first().unwrap(); 416 let segment = remaining_segments.first().unwrap();
417 let found = associated_type_by_name_including_super_traits( 417 let found = self
418 self.db, 418 .db
419 trait_ref, 419 .trait_data(trait_ref.hir_trait_id())
420 &segment.name, 420 .associated_type_by_name(&segment.name);
421 );
422 match found { 421 match found {
423 Some((super_trait_ref, associated_ty)) => { 422 Some(associated_ty) => {
424 // FIXME handle type parameters on the segment 423 // FIXME handle type parameters on the segment
425 TyKind::Alias(AliasTy::Projection(ProjectionTy { 424 TyKind::Alias(AliasTy::Projection(ProjectionTy {
426 associated_ty_id: to_assoc_type_id(associated_ty), 425 associated_ty_id: to_assoc_type_id(associated_ty),
427 substitution: super_trait_ref.substitution, 426 substitution: trait_ref.substitution,
428 })) 427 }))
429 .intern(&Interner) 428 .intern(&Interner)
430 } 429 }
@@ -1089,6 +1088,27 @@ pub(crate) fn generic_defaults_query(
1089 defaults 1088 defaults
1090} 1089}
1091 1090
1091pub(crate) fn generic_defaults_recover(
1092 db: &dyn HirDatabase,
1093 _cycle: &[String],
1094 def: &GenericDefId,
1095) -> Arc<[Binders<Ty>]> {
1096 let generic_params = generics(db.upcast(), *def);
1097
1098 // we still need one default per parameter
1099 let defaults = generic_params
1100 .iter()
1101 .enumerate()
1102 .map(|(idx, _)| {
1103 let ty = TyKind::Error.intern(&Interner);
1104
1105 crate::make_only_type_binders(idx, ty)
1106 })
1107 .collect();
1108
1109 defaults
1110}
1111
1092fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { 1112fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1093 let data = db.function_data(def); 1113 let data = db.function_data(def);
1094 let resolver = def.resolver(db.upcast()); 1114 let resolver = def.resolver(db.upcast());
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index 9cd9f473d..d14f5c9bb 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -1012,3 +1012,41 @@ fn lifetime_from_chalk_during_deref() {
1012 "#, 1012 "#,
1013 ) 1013 )
1014} 1014}
1015
1016#[test]
1017fn issue_8686() {
1018 check_infer(
1019 r#"
1020pub trait Try: FromResidual {
1021 type Output;
1022 type Residual;
1023}
1024pub trait FromResidual<R = <Self as Try>::Residual> {
1025 fn from_residual(residual: R) -> Self;
1026}
1027
1028struct ControlFlow<B, C>;
1029impl<B, C> Try for ControlFlow<B, C> {
1030 type Output = C;
1031 type Residual = ControlFlow<B, !>;
1032}
1033impl<B, C> FromResidual for ControlFlow<B, C> {
1034 fn from_residual(r: ControlFlow<B, !>) -> Self { ControlFlow }
1035}
1036
1037fn test() {
1038 ControlFlow::from_residual(ControlFlow::<u32, !>);
1039}
1040 "#,
1041 expect![[r#"
1042 144..152 'residual': R
1043 365..366 'r': ControlFlow<B, !>
1044 395..410 '{ ControlFlow }': ControlFlow<B, C>
1045 397..408 'ControlFlow': ControlFlow<B, C>
1046 424..482 '{ ...!>); }': ()
1047 430..456 'Contro...sidual': fn from_residual<ControlFlow<u32, {unknown}>, ControlFlow<u32, !>>(ControlFlow<u32, !>) -> ControlFlow<u32, {unknown}>
1048 430..479 'Contro...2, !>)': ControlFlow<u32, {unknown}>
1049 457..478 'Contro...32, !>': ControlFlow<u32, !>
1050 "#]],
1051 );
1052}
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 2f04ee57a..2f490fb92 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -1,6 +1,8 @@
1//! Helper functions for working with def, which don't need to be a separate 1//! Helper functions for working with def, which don't need to be a separate
2//! query, but can't be computed directly from `*Data` (ie, which need a `db`). 2//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
3 3
4use std::iter;
5
4use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex}; 6use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex};
5use hir_def::{ 7use hir_def::{
6 db::DefDatabase, 8 db::DefDatabase,
@@ -14,8 +16,12 @@ use hir_def::{
14 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, 16 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId,
15}; 17};
16use hir_expand::name::{name, Name}; 18use hir_expand::name::{name, Name};
19use rustc_hash::FxHashSet;
17 20
18use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TraitRefExt, TyKind, WhereClause}; 21use crate::{
22 db::HirDatabase, ChalkTraitId, Interner, Substitution, TraitRef, TraitRefExt, TyKind,
23 WhereClause,
24};
19 25
20fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 26fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
21 let resolver = trait_.resolver(db); 27 let resolver = trait_.resolver(db);
@@ -102,25 +108,35 @@ pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
102/// `all_super_traits` is that we keep track of type parameters; for example if 108/// `all_super_traits` is that we keep track of type parameters; for example if
103/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get 109/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
104/// `Self: OtherTrait<i32>`. 110/// `Self: OtherTrait<i32>`.
105pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> { 111pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> SuperTraits {
106 // FIXME: replace by Chalk's `super_traits`, maybe make this a query 112 SuperTraits { db, seen: iter::once(trait_ref.trait_id).collect(), stack: vec![trait_ref] }
113}
107 114
108 // we need to take care a bit here to avoid infinite loops in case of cycles 115pub(super) struct SuperTraits<'a> {
109 // (i.e. if we have `trait A: B; trait B: A;`) 116 db: &'a dyn HirDatabase,
110 let mut result = vec![trait_ref]; 117 stack: Vec<TraitRef>,
111 let mut i = 0; 118 seen: FxHashSet<ChalkTraitId>,
112 while i < result.len() { 119}
113 let t = &result[i]; 120
114 // yeah this is quadratic, but trait hierarchies should be flat 121impl<'a> SuperTraits<'a> {
115 // enough that this doesn't matter 122 fn elaborate(&mut self, trait_ref: &TraitRef) {
116 for tt in direct_super_trait_refs(db, t) { 123 let mut trait_refs = direct_super_trait_refs(self.db, trait_ref);
117 if !result.iter().any(|tr| tr.trait_id == tt.trait_id) { 124 trait_refs.retain(|tr| !self.seen.contains(&tr.trait_id));
118 result.push(tt); 125 self.stack.extend(trait_refs);
119 } 126 }
127}
128
129impl<'a> Iterator for SuperTraits<'a> {
130 type Item = TraitRef;
131
132 fn next(&mut self) -> Option<Self::Item> {
133 if let Some(next) = self.stack.pop() {
134 self.elaborate(&next);
135 Some(next)
136 } else {
137 None
120 } 138 }
121 i += 1;
122 } 139 }
123 result
124} 140}
125 141
126pub(super) fn associated_type_by_name_including_super_traits( 142pub(super) fn associated_type_by_name_including_super_traits(
@@ -128,7 +144,7 @@ pub(super) fn associated_type_by_name_including_super_traits(
128 trait_ref: TraitRef, 144 trait_ref: TraitRef,
129 name: &Name, 145 name: &Name,
130) -> Option<(TraitRef, TypeAliasId)> { 146) -> Option<(TraitRef, TypeAliasId)> {
131 all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| { 147 all_super_trait_refs(db, trait_ref).find_map(|t| {
132 let assoc_type = db.trait_data(t.hir_trait_id()).associated_type_by_name(name)?; 148 let assoc_type = db.trait_data(t.hir_trait_id()).associated_type_by_name(name)?;
133 Some((t, assoc_type)) 149 Some((t, assoc_type))
134 }) 150 })
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 3eb9e27ee..f76715d84 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -304,11 +304,11 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op
304 let name = adt.name(sema.db); 304 let name = adt.name(sema.db);
305 let idx = path.rfind(':').map_or(0, |idx| idx + 1); 305 let idx = path.rfind(':').map_or(0, |idx| idx + 1);
306 let (prefix, suffix) = path.split_at(idx); 306 let (prefix, suffix) = path.split_at(idx);
307 let mut ty_params = ty.type_parameters().peekable(); 307 let mut ty_args = ty.type_arguments().peekable();
308 let params = if ty_params.peek().is_some() { 308 let params = if ty_args.peek().is_some() {
309 format!( 309 format!(
310 "<{}>", 310 "<{}>",
311 ty_params.format_with(", ", |ty, cb| cb(&ty.display(sema.db))) 311 ty_args.format_with(", ", |ty, cb| cb(&ty.display(sema.db)))
312 ) 312 )
313 } else { 313 } else {
314 String::new() 314 String::new()
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index 5f80a40c8..b30652a9d 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -1183,7 +1183,7 @@ fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Opti
1183 } 1183 }
1184 FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => { 1184 FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
1185 let handler_ty = parent_ret_ty 1185 let handler_ty = parent_ret_ty
1186 .type_parameters() 1186 .type_arguments()
1187 .nth(1) 1187 .nth(1)
1188 .map(|ty| make_ty(&ty, ctx, module)) 1188 .map(|ty| make_ty(&ty, ctx, module))
1189 .unwrap_or_else(make::ty_unit); 1189 .unwrap_or_else(make::ty_unit);
diff --git a/crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs b/crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs
index c13c6eebe..ce6998d82 100644
--- a/crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs
@@ -91,7 +91,7 @@ fn existing_from_impl(
91 91
92 let enum_type = enum_.ty(sema.db); 92 let enum_type = enum_.ty(sema.db);
93 93
94 let wrapped_type = variant.fields(sema.db).get(0)?.signature_ty(sema.db); 94 let wrapped_type = variant.fields(sema.db).get(0)?.ty(sema.db);
95 95
96 if enum_type.impls_trait(sema.db, from_trait, &[wrapped_type]) { 96 if enum_type.impls_trait(sema.db, from_trait, &[wrapped_type]) {
97 Some(()) 97 Some(())
diff --git a/crates/ide_assists/src/utils/suggest_name.rs b/crates/ide_assists/src/utils/suggest_name.rs
index 533624c1f..deafcd630 100644
--- a/crates/ide_assists/src/utils/suggest_name.rs
+++ b/crates/ide_assists/src/utils/suggest_name.rs
@@ -227,7 +227,7 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase) -> Option<String> {
227 let name = adt.name(db).to_string(); 227 let name = adt.name(db).to_string();
228 228
229 if WRAPPER_TYPES.contains(&name.as_str()) { 229 if WRAPPER_TYPES.contains(&name.as_str()) {
230 let inner_ty = ty.type_parameters().next()?; 230 let inner_ty = ty.type_arguments().next()?;
231 return name_of_type(&inner_ty, db); 231 return name_of_type(&inner_ty, db);
232 } 232 }
233 233
diff --git a/crates/ide_completion/src/completions/postfix/format_like.rs b/crates/ide_completion/src/completions/postfix/format_like.rs
index e86ffa8f8..0dcb3e898 100644
--- a/crates/ide_completion/src/completions/postfix/format_like.rs
+++ b/crates/ide_completion/src/completions/postfix/format_like.rs
@@ -1,4 +1,4 @@
1// Feature: Format String Completion. 1// Feature: Format String Completion
2// 2//
3// `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`. 3// `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`.
4// 4//
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 32f81aec1..b005bd773 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -347,7 +347,7 @@ impl<'a> CompletionContext<'a> {
347 .and_then(|node| ast::RecordExprField::cast(node)) 347 .and_then(|node| ast::RecordExprField::cast(node))
348 .and_then(|rf| self.sema.resolve_record_field(&rf).zip(Some(rf))) 348 .and_then(|rf| self.sema.resolve_record_field(&rf).zip(Some(rf)))
349 .map(|(f, rf)|( 349 .map(|(f, rf)|(
350 Some(f.0.signature_ty(self.db)), 350 Some(f.0.ty(self.db)),
351 rf.field_name().map(NameOrNameRef::NameRef), 351 rf.field_name().map(NameOrNameRef::NameRef),
352 )) 352 ))
353 .unwrap_or((None, None)) 353 .unwrap_or((None, None))
@@ -357,7 +357,7 @@ impl<'a> CompletionContext<'a> {
357 self.sema 357 self.sema
358 .resolve_record_field(&it) 358 .resolve_record_field(&it)
359 .map(|f|( 359 .map(|f|(
360 Some(f.0.signature_ty(self.db)), 360 Some(f.0.ty(self.db)),
361 it.field_name().map(NameOrNameRef::NameRef), 361 it.field_name().map(NameOrNameRef::NameRef),
362 )) 362 ))
363 .unwrap_or((None, None)) 363 .unwrap_or((None, None))
diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs
index 832f5ced1..0c0c71134 100644
--- a/crates/ide_completion/src/render/enum_variant.rs
+++ b/crates/ide_completion/src/render/enum_variant.rs
@@ -93,7 +93,7 @@ impl<'a> EnumRender<'a> {
93 .variant 93 .variant
94 .fields(self.ctx.db()) 94 .fields(self.ctx.db())
95 .into_iter() 95 .into_iter()
96 .map(|field| (field.name(self.ctx.db()), field.signature_ty(self.ctx.db()))); 96 .map(|field| (field.name(self.ctx.db()), field.ty(self.ctx.db())));
97 97
98 match self.variant_kind { 98 match self.variant_kind {
99 StructKind::Tuple | StructKind::Unit => format!( 99 StructKind::Tuple | StructKind::Unit => format!(