diff options
Diffstat (limited to 'crates')
228 files changed, 8634 insertions, 7953 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index da4afb5eb..6ce377710 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs | |||
@@ -9,8 +9,8 @@ use test_utils::{ | |||
9 | use vfs::{file_set::FileSet, VfsPath}; | 9 | use vfs::{file_set::FileSet, VfsPath}; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | input::CrateName, Change, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, FileRange, | 12 | input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Edition, Env, FileId, |
13 | SourceDatabaseExt, SourceRoot, SourceRootId, | 13 | FilePosition, FileRange, SourceDatabaseExt, SourceRoot, SourceRootId, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | pub const WORKSPACE: SourceRootId = SourceRootId(0); | 16 | pub const WORKSPACE: SourceRootId = SourceRootId(0); |
@@ -24,6 +24,14 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
24 | (db, fixture.files[0]) | 24 | (db, fixture.files[0]) |
25 | } | 25 | } |
26 | 26 | ||
27 | fn with_many_files(ra_fixture: &str) -> (Self, Vec<FileId>) { | ||
28 | let fixture = ChangeFixture::parse(ra_fixture); | ||
29 | let mut db = Self::default(); | ||
30 | fixture.change.apply(&mut db); | ||
31 | assert!(fixture.file_position.is_none()); | ||
32 | (db, fixture.files) | ||
33 | } | ||
34 | |||
27 | fn with_files(ra_fixture: &str) -> Self { | 35 | fn with_files(ra_fixture: &str) -> Self { |
28 | let fixture = ChangeFixture::parse(ra_fixture); | 36 | let fixture = ChangeFixture::parse(ra_fixture); |
29 | let mut db = Self::default(); | 37 | let mut db = Self::default(); |
@@ -73,7 +81,7 @@ pub struct ChangeFixture { | |||
73 | 81 | ||
74 | impl ChangeFixture { | 82 | impl ChangeFixture { |
75 | pub fn parse(ra_fixture: &str) -> ChangeFixture { | 83 | pub fn parse(ra_fixture: &str) -> ChangeFixture { |
76 | let fixture = Fixture::parse(ra_fixture); | 84 | let (mini_core, fixture) = Fixture::parse(ra_fixture); |
77 | let mut change = Change::new(); | 85 | let mut change = Change::new(); |
78 | 86 | ||
79 | let mut files = Vec::new(); | 87 | let mut files = Vec::new(); |
@@ -98,7 +106,7 @@ impl ChangeFixture { | |||
98 | let (range_or_offset, text) = extract_range_or_offset(&entry.text); | 106 | let (range_or_offset, text) = extract_range_or_offset(&entry.text); |
99 | assert!(file_position.is_none()); | 107 | assert!(file_position.is_none()); |
100 | file_position = Some((file_id, range_or_offset)); | 108 | file_position = Some((file_id, range_or_offset)); |
101 | text.to_string() | 109 | text |
102 | } | 110 | } |
103 | } else { | 111 | } else { |
104 | entry.text.clone() | 112 | entry.text.clone() |
@@ -106,6 +114,9 @@ impl ChangeFixture { | |||
106 | 114 | ||
107 | let meta = FileMeta::from(entry); | 115 | let meta = FileMeta::from(entry); |
108 | assert!(meta.path.starts_with(&source_root_prefix)); | 116 | assert!(meta.path.starts_with(&source_root_prefix)); |
117 | if !meta.deps.is_empty() { | ||
118 | assert!(meta.krate.is_some(), "can't specify deps without naming the crate") | ||
119 | } | ||
109 | 120 | ||
110 | if meta.introduce_new_source_root { | 121 | if meta.introduce_new_source_root { |
111 | roots.push(SourceRoot::new_local(mem::take(&mut file_set))); | 122 | roots.push(SourceRoot::new_local(mem::take(&mut file_set))); |
@@ -158,6 +169,31 @@ impl ChangeFixture { | |||
158 | } | 169 | } |
159 | } | 170 | } |
160 | 171 | ||
172 | if let Some(mini_core) = mini_core { | ||
173 | let core_file = file_id; | ||
174 | file_id.0 += 1; | ||
175 | |||
176 | let mut fs = FileSet::default(); | ||
177 | fs.insert(core_file, VfsPath::new_virtual_path("/sysroot/core/lib.rs".to_string())); | ||
178 | roots.push(SourceRoot::new_library(fs)); | ||
179 | |||
180 | change.change_file(core_file, Some(Arc::new(mini_core.source_code()))); | ||
181 | |||
182 | let all_crates = crate_graph.crates_in_topological_order(); | ||
183 | |||
184 | let core_crate = crate_graph.add_crate_root( | ||
185 | core_file, | ||
186 | Edition::Edition2021, | ||
187 | Some(CrateDisplayName::from_canonical_name("core".to_string())), | ||
188 | CfgOptions::default(), | ||
189 | Env::default(), | ||
190 | Vec::new(), | ||
191 | ); | ||
192 | |||
193 | for krate in all_crates { | ||
194 | crate_graph.add_dep(krate, CrateName::new("core").unwrap(), core_crate).unwrap(); | ||
195 | } | ||
196 | } | ||
161 | roots.push(SourceRoot::new_local(mem::take(&mut file_set))); | 197 | roots.push(SourceRoot::new_local(mem::take(&mut file_set))); |
162 | change.set_roots(roots); | 198 | change.set_roots(roots); |
163 | change.set_crate_graph(crate_graph); | 199 | change.set_crate_graph(crate_graph); |
@@ -166,6 +202,7 @@ impl ChangeFixture { | |||
166 | } | 202 | } |
167 | } | 203 | } |
168 | 204 | ||
205 | #[derive(Debug)] | ||
169 | struct FileMeta { | 206 | struct FileMeta { |
170 | path: String, | 207 | path: String, |
171 | krate: Option<String>, | 208 | krate: Option<String>, |
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs index 03b8dd767..916d39a0b 100644 --- a/crates/cfg/src/lib.rs +++ b/crates/cfg/src/lib.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! cfg defines conditional compiling options, `cfg` attibute parser and evaluator | 1 | //! cfg defines conditional compiling options, `cfg` attribute parser and evaluator |
2 | 2 | ||
3 | mod cfg_expr; | 3 | mod cfg_expr; |
4 | mod dnf; | 4 | mod dnf; |
@@ -52,6 +52,7 @@ impl CfgOptions { | |||
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
55 | pub struct CfgDiff { | 56 | pub struct CfgDiff { |
56 | // Invariants: No duplicates, no atom that's both in `enable` and `disable`. | 57 | // Invariants: No duplicates, no atom that's both in `enable` and `disable`. |
57 | enable: Vec<CfgAtom>, | 58 | enable: Vec<CfgAtom>, |
@@ -59,6 +60,20 @@ pub struct CfgDiff { | |||
59 | } | 60 | } |
60 | 61 | ||
61 | impl CfgDiff { | 62 | impl CfgDiff { |
63 | /// Create a new CfgDiff. Will return None if the same item appears more than once in the set | ||
64 | /// of both. | ||
65 | pub fn new(enable: Vec<CfgAtom>, disable: Vec<CfgAtom>) -> Option<CfgDiff> { | ||
66 | let mut occupied = FxHashSet::default(); | ||
67 | for item in enable.iter().chain(disable.iter()) { | ||
68 | if !occupied.insert(item) { | ||
69 | // was present | ||
70 | return None; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | Some(CfgDiff { enable, disable }) | ||
75 | } | ||
76 | |||
62 | /// Returns the total number of atoms changed by this diff. | 77 | /// Returns the total number of atoms changed by this diff. |
63 | pub fn len(&self) -> usize { | 78 | pub fn len(&self) -> usize { |
64 | self.enable.len() + self.disable.len() | 79 | self.enable.len() + self.disable.len() |
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index dc10a4d0f..197149c5e 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs | |||
@@ -127,7 +127,7 @@ impl HasSource for Impl { | |||
127 | } | 127 | } |
128 | 128 | ||
129 | impl HasSource for TypeParam { | 129 | impl HasSource for TypeParam { |
130 | type Ast = Either<ast::Trait, ast::TypeParam>; | 130 | type Ast = Either<ast::TypeParam, ast::Trait>; |
131 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { | 131 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
132 | let child_source = self.id.parent.child_source(db.upcast()); | 132 | let child_source = self.id.parent.child_source(db.upcast()); |
133 | Some(child_source.map(|it| it[self.id.local_id].clone())) | 133 | Some(child_source.map(|it| it[self.id.local_id].clone())) |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5bc0b2338..b7eabaabb 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -2688,18 +2688,6 @@ impl ScopeDef { | |||
2688 | 2688 | ||
2689 | items | 2689 | items |
2690 | } | 2690 | } |
2691 | |||
2692 | pub fn is_value_def(&self) -> bool { | ||
2693 | matches!( | ||
2694 | self, | ||
2695 | ScopeDef::ModuleDef(ModuleDef::Function(_)) | ||
2696 | | ScopeDef::ModuleDef(ModuleDef::Variant(_)) | ||
2697 | | ScopeDef::ModuleDef(ModuleDef::Const(_)) | ||
2698 | | ScopeDef::ModuleDef(ModuleDef::Static(_)) | ||
2699 | | ScopeDef::GenericParam(GenericParam::ConstParam(_)) | ||
2700 | | ScopeDef::Local(_) | ||
2701 | ) | ||
2702 | } | ||
2703 | } | 2691 | } |
2704 | 2692 | ||
2705 | impl From<ItemInNs> for ScopeDef { | 2693 | impl From<ItemInNs> for ScopeDef { |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 613266e07..43162797e 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -51,12 +51,14 @@ impl PathResolution { | |||
51 | PathResolution::Def(ModuleDef::BuiltinType(builtin)) => { | 51 | PathResolution::Def(ModuleDef::BuiltinType(builtin)) => { |
52 | Some(TypeNs::BuiltinType((*builtin).into())) | 52 | Some(TypeNs::BuiltinType((*builtin).into())) |
53 | } | 53 | } |
54 | PathResolution::Def(ModuleDef::Const(_)) | 54 | PathResolution::Def( |
55 | | PathResolution::Def(ModuleDef::Variant(_)) | 55 | ModuleDef::Const(_) |
56 | | PathResolution::Def(ModuleDef::Function(_)) | 56 | | ModuleDef::Variant(_) |
57 | | PathResolution::Def(ModuleDef::Module(_)) | 57 | | ModuleDef::Function(_) |
58 | | PathResolution::Def(ModuleDef::Static(_)) | 58 | | ModuleDef::Module(_) |
59 | | PathResolution::Def(ModuleDef::Trait(_)) => None, | 59 | | ModuleDef::Static(_) |
60 | | ModuleDef::Trait(_), | ||
61 | ) => None, | ||
60 | PathResolution::Def(ModuleDef::TypeAlias(alias)) => { | 62 | PathResolution::Def(ModuleDef::TypeAlias(alias)) => { |
61 | Some(TypeNs::TypeAliasId((*alias).into())) | 63 | Some(TypeNs::TypeAliasId((*alias).into())) |
62 | } | 64 | } |
@@ -65,8 +67,7 @@ impl PathResolution { | |||
65 | } | 67 | } |
66 | PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), | 68 | PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), |
67 | PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), | 69 | PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), |
68 | PathResolution::AssocItem(AssocItem::Const(_)) | 70 | PathResolution::AssocItem(AssocItem::Const(_) | AssocItem::Function(_)) => None, |
69 | | PathResolution::AssocItem(AssocItem::Function(_)) => None, | ||
70 | PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => { | 71 | PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => { |
71 | Some(TypeNs::TypeAliasId((*alias).into())) | 72 | Some(TypeNs::TypeAliasId((*alias).into())) |
72 | } | 73 | } |
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 6933f6e3c..0f04b2bae 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -92,7 +92,7 @@ pub enum WherePredicateTypeTarget { | |||
92 | 92 | ||
93 | #[derive(Default)] | 93 | #[derive(Default)] |
94 | pub(crate) struct SourceMap { | 94 | pub(crate) struct SourceMap { |
95 | pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>, | 95 | pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::TypeParam, ast::Trait>>, |
96 | lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, | 96 | lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, |
97 | const_params: ArenaMap<LocalConstParamId, ast::ConstParam>, | 97 | const_params: ArenaMap<LocalConstParamId, ast::ConstParam>, |
98 | } | 98 | } |
@@ -199,7 +199,7 @@ impl GenericParams { | |||
199 | default: None, | 199 | default: None, |
200 | provenance: TypeParamProvenance::TraitSelf, | 200 | provenance: TypeParamProvenance::TraitSelf, |
201 | }); | 201 | }); |
202 | sm.type_params.insert(self_param_id, Either::Left(src.value.clone())); | 202 | sm.type_params.insert(self_param_id, Either::Right(src.value.clone())); |
203 | // add super traits as bounds on Self | 203 | // add super traits as bounds on Self |
204 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 204 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
205 | let self_param = TypeRef::Path(name![Self].into()); | 205 | let self_param = TypeRef::Path(name![Self].into()); |
@@ -277,7 +277,7 @@ impl GenericParams { | |||
277 | provenance: TypeParamProvenance::TypeParamList, | 277 | provenance: TypeParamProvenance::TypeParamList, |
278 | }; | 278 | }; |
279 | let param_id = self.types.alloc(param); | 279 | let param_id = self.types.alloc(param); |
280 | sm.type_params.insert(param_id, Either::Right(type_param.clone())); | 280 | sm.type_params.insert(param_id, Either::Left(type_param.clone())); |
281 | 281 | ||
282 | let type_ref = TypeRef::Path(name.into()); | 282 | let type_ref = TypeRef::Path(name.into()); |
283 | self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref)); | 283 | self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref)); |
@@ -413,7 +413,7 @@ impl GenericParams { | |||
413 | } | 413 | } |
414 | 414 | ||
415 | impl HasChildSource<LocalTypeParamId> for GenericDefId { | 415 | impl HasChildSource<LocalTypeParamId> for GenericDefId { |
416 | type Value = Either<ast::Trait, ast::TypeParam>; | 416 | type Value = Either<ast::TypeParam, ast::Trait>; |
417 | fn child_source( | 417 | fn child_source( |
418 | &self, | 418 | &self, |
419 | db: &dyn DefDatabase, | 419 | db: &dyn DefDatabase, |
@@ -449,7 +449,7 @@ impl ChildBySource for GenericDefId { | |||
449 | let sm = sm.as_ref(); | 449 | let sm = sm.as_ref(); |
450 | for (local_id, src) in sm.value.type_params.iter() { | 450 | for (local_id, src) in sm.value.type_params.iter() { |
451 | let id = TypeParamId { parent: *self, local_id }; | 451 | let id = TypeParamId { parent: *self, local_id }; |
452 | if let Either::Right(type_param) = src { | 452 | if let Either::Left(type_param) = src { |
453 | res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id) | 453 | res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id) |
454 | } | 454 | } |
455 | } | 455 | } |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 3f90bda74..5b1386406 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -674,7 +674,7 @@ impl<'a> Ctx<'a> { | |||
674 | default: None, | 674 | default: None, |
675 | provenance: TypeParamProvenance::TraitSelf, | 675 | provenance: TypeParamProvenance::TraitSelf, |
676 | }); | 676 | }); |
677 | sm.type_params.insert(self_param_id, Either::Left(trait_def.clone())); | 677 | sm.type_params.insert(self_param_id, Either::Right(trait_def.clone())); |
678 | // add super traits as bounds on Self | 678 | // add super traits as bounds on Self |
679 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 679 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
680 | let self_param = TypeRef::Path(name![Self].into()); | 680 | let self_param = TypeRef::Path(name![Self].into()); |
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index b1e1b70d0..e63bc8232 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs | |||
@@ -63,7 +63,7 @@ impl<'a> Printer<'a> { | |||
63 | fn blank(&mut self) { | 63 | fn blank(&mut self) { |
64 | let mut iter = self.buf.chars().rev().fuse(); | 64 | let mut iter = self.buf.chars().rev().fuse(); |
65 | match (iter.next(), iter.next()) { | 65 | match (iter.next(), iter.next()) { |
66 | (Some('\n'), Some('\n')) | (Some('\n'), None) | (None, None) => {} | 66 | (Some('\n'), Some('\n') | None) | (None, None) => {} |
67 | (Some('\n'), Some(_)) => { | 67 | (Some('\n'), Some(_)) => { |
68 | self.buf.push('\n'); | 68 | self.buf.push('\n'); |
69 | } | 69 | } |
@@ -77,7 +77,7 @@ impl<'a> Printer<'a> { | |||
77 | 77 | ||
78 | fn whitespace(&mut self) { | 78 | fn whitespace(&mut self) { |
79 | match self.buf.chars().next_back() { | 79 | match self.buf.chars().next_back() { |
80 | None | Some('\n') | Some(' ') => {} | 80 | None | Some('\n' | ' ') => {} |
81 | _ => self.buf.push(' '), | 81 | _ => self.buf.push(' '), |
82 | } | 82 | } |
83 | } | 83 | } |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 6fab58f15..927a7b6e8 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -1260,7 +1260,7 @@ impl DefCollector<'_> { | |||
1260 | for directive in &self.unresolved_imports { | 1260 | for directive in &self.unresolved_imports { |
1261 | if let ImportSource::Import { id: import, use_tree } = &directive.import.source { | 1261 | if let ImportSource::Import { id: import, use_tree } = &directive.import.source { |
1262 | match (directive.import.path.segments().first(), &directive.import.path.kind) { | 1262 | match (directive.import.path.segments().first(), &directive.import.path.kind) { |
1263 | (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => { | 1263 | (Some(krate), PathKind::Plain | PathKind::Abs) => { |
1264 | if diagnosed_extern_crates.contains(krate) { | 1264 | if diagnosed_extern_crates.contains(krate) { |
1265 | continue; | 1265 | continue; |
1266 | } | 1266 | } |
@@ -1992,8 +1992,8 @@ mod tests { | |||
1992 | collector.def_map | 1992 | collector.def_map |
1993 | } | 1993 | } |
1994 | 1994 | ||
1995 | fn do_resolve(code: &str) -> DefMap { | 1995 | fn do_resolve(not_ra_fixture: &str) -> DefMap { |
1996 | let (db, _file_id) = TestDB::with_single_file(code); | 1996 | let (db, _file_id) = TestDB::with_single_file(not_ra_fixture); |
1997 | let krate = db.test_crate(); | 1997 | let krate = db.test_crate(); |
1998 | 1998 | ||
1999 | let edition = db.crate_graph()[krate].edition; | 1999 | let edition = db.crate_graph()[krate].edition; |
@@ -2005,24 +2005,37 @@ mod tests { | |||
2005 | fn test_macro_expand_will_stop_1() { | 2005 | fn test_macro_expand_will_stop_1() { |
2006 | do_resolve( | 2006 | do_resolve( |
2007 | r#" | 2007 | r#" |
2008 | macro_rules! foo { | 2008 | macro_rules! foo { |
2009 | ($($ty:ty)*) => { foo!($($ty)*); } | 2009 | ($($ty:ty)*) => { foo!($($ty)*); } |
2010 | } | 2010 | } |
2011 | foo!(KABOOM); | 2011 | foo!(KABOOM); |
2012 | "#, | 2012 | "#, |
2013 | ); | ||
2014 | do_resolve( | ||
2015 | r#" | ||
2016 | macro_rules! foo { | ||
2017 | ($($ty:ty)*) => { foo!(() $($ty)*); } | ||
2018 | } | ||
2019 | foo!(KABOOM); | ||
2020 | "#, | ||
2013 | ); | 2021 | ); |
2014 | } | 2022 | } |
2015 | 2023 | ||
2016 | #[ignore] // this test does succeed, but takes quite a while :/ | 2024 | #[ignore] |
2017 | #[test] | 2025 | #[test] |
2018 | fn test_macro_expand_will_stop_2() { | 2026 | fn test_macro_expand_will_stop_2() { |
2027 | // FIXME: this test does succeed, but takes quite a while: 90 seconds in | ||
2028 | // the release mode. That's why the argument is not an ra_fixture -- | ||
2029 | // otherwise injection highlighting gets stuck. | ||
2030 | // | ||
2031 | // We need to find a way to fail this faster. | ||
2019 | do_resolve( | 2032 | do_resolve( |
2020 | r#" | 2033 | r#" |
2021 | macro_rules! foo { | 2034 | macro_rules! foo { |
2022 | ($($ty:ty)*) => { foo!($($ty)* $($ty)*); } | 2035 | ($($ty:ty)*) => { foo!($($ty)* $($ty)*); } |
2023 | } | 2036 | } |
2024 | foo!(KABOOM); | 2037 | foo!(KABOOM); |
2025 | "#, | 2038 | "#, |
2026 | ); | 2039 | ); |
2027 | } | 2040 | } |
2028 | } | 2041 | } |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index d4681fa3e..49c573087 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -605,8 +605,7 @@ fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> { | |||
605 | ModuleDefId::ConstId(it) => ValueNs::ConstId(it), | 605 | ModuleDefId::ConstId(it) => ValueNs::ConstId(it), |
606 | ModuleDefId::StaticId(it) => ValueNs::StaticId(it), | 606 | ModuleDefId::StaticId(it) => ValueNs::StaticId(it), |
607 | 607 | ||
608 | ModuleDefId::AdtId(AdtId::EnumId(_)) | 608 | ModuleDefId::AdtId(AdtId::EnumId(_) | AdtId::UnionId(_)) |
609 | | ModuleDefId::AdtId(AdtId::UnionId(_)) | ||
610 | | ModuleDefId::TraitId(_) | 609 | | ModuleDefId::TraitId(_) |
611 | | ModuleDefId::TypeAliasId(_) | 610 | | ModuleDefId::TypeAliasId(_) |
612 | | ModuleDefId::BuiltinType(_) | 611 | | ModuleDefId::BuiltinType(_) |
@@ -641,8 +640,7 @@ pub trait HasResolver: Copy { | |||
641 | impl HasResolver for ModuleId { | 640 | impl HasResolver for ModuleId { |
642 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | 641 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { |
643 | let mut def_map = self.def_map(db); | 642 | let mut def_map = self.def_map(db); |
644 | let mut modules = Vec::new(); | 643 | let mut modules = vec![(def_map.clone(), self.local_id)]; |
645 | modules.push((def_map.clone(), self.local_id)); | ||
646 | while let Some(parent) = def_map.parent() { | 644 | while let Some(parent) = def_map.parent() { |
647 | def_map = parent.def_map(db); | 645 | def_map = parent.def_map(db); |
648 | modules.push((def_map.clone(), parent.local_id)); | 646 | modules.push((def_map.clone(), parent.local_id)); |
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 83500f54e..aeb1e7726 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs | |||
@@ -172,9 +172,8 @@ impl Visibility { | |||
172 | /// visible in unrelated modules). | 172 | /// visible in unrelated modules). |
173 | pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> { | 173 | pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> { |
174 | match (self, other) { | 174 | match (self, other) { |
175 | (Visibility::Module(_), Visibility::Public) | 175 | (Visibility::Module(_) | Visibility::Public, Visibility::Public) |
176 | | (Visibility::Public, Visibility::Module(_)) | 176 | | (Visibility::Public, Visibility::Module(_)) => Some(Visibility::Public), |
177 | | (Visibility::Public, Visibility::Public) => Some(Visibility::Public), | ||
178 | (Visibility::Module(mod_a), Visibility::Module(mod_b)) => { | 177 | (Visibility::Module(mod_a), Visibility::Module(mod_b)) => { |
179 | if mod_a.krate != mod_b.krate { | 178 | if mod_a.krate != mod_b.krate { |
180 | return None; | 179 | return None; |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index f24d1d919..4c83a2efe 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -202,7 +202,7 @@ fn assert_expand( | |||
202 | 202 | ||
203 | let arg_tts = args.into_iter().flat_map(|arg| { | 203 | let arg_tts = args.into_iter().flat_map(|arg| { |
204 | quote! { &(#arg), } | 204 | quote! { &(#arg), } |
205 | }.token_trees).collect::<Vec<_>>(); | 205 | }.token_trees); |
206 | 206 | ||
207 | let expanded = quote! { | 207 | let expanded = quote! { |
208 | { { (##arg_tts); } } | 208 | { { (##arg_tts); } } |
@@ -254,7 +254,7 @@ fn format_args_expand( | |||
254 | let _format_string = args.remove(0); | 254 | let _format_string = args.remove(0); |
255 | let arg_tts = args.into_iter().flat_map(|arg| { | 255 | let arg_tts = args.into_iter().flat_map(|arg| { |
256 | quote! { std::fmt::ArgumentV1::new(&(#arg), std::fmt::Display::fmt), } | 256 | quote! { std::fmt::ArgumentV1::new(&(#arg), std::fmt::Display::fmt), } |
257 | }.token_trees).collect::<Vec<_>>(); | 257 | }.token_trees); |
258 | let expanded = quote! { | 258 | let expanded = quote! { |
259 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) | 259 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) |
260 | }; | 260 | }; |
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 05c6c3fb1..848522411 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs | |||
@@ -146,10 +146,11 @@ impl HygieneInfo { | |||
146 | (&self.macro_arg.1, InFile::new(loc.kind.file_id(), arg_start)) | 146 | (&self.macro_arg.1, InFile::new(loc.kind.file_id(), arg_start)) |
147 | } | 147 | } |
148 | mbe::Origin::Def => match (&*self.macro_def, self.def_start) { | 148 | mbe::Origin::Def => match (&*self.macro_def, self.def_start) { |
149 | (TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt)) | 149 | ( |
150 | | (TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) => { | 150 | TokenExpander::MacroDef { def_site_token_map, .. } |
151 | (def_site_token_map, tt) | 151 | | TokenExpander::MacroRules { def_site_token_map, .. }, |
152 | } | 152 | Some(tt), |
153 | ) => (def_site_token_map, tt), | ||
153 | _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"), | 154 | _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"), |
154 | }, | 155 | }, |
155 | }; | 156 | }; |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index 33107aa24..c31426d7c 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -368,10 +368,11 @@ impl ExpansionInfo { | |||
368 | let (token_map, tt) = match origin { | 368 | let (token_map, tt) = match origin { |
369 | mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), | 369 | mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), |
370 | mbe::Origin::Def => match (&*self.macro_def, self.def.as_ref()) { | 370 | mbe::Origin::Def => match (&*self.macro_def, self.def.as_ref()) { |
371 | (db::TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) | 371 | ( |
372 | | (db::TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt)) => { | 372 | db::TokenExpander::MacroRules { def_site_token_map, .. } |
373 | (def_site_token_map, tt.as_ref().map(|tt| tt.syntax().clone())) | 373 | | db::TokenExpander::MacroDef { def_site_token_map, .. }, |
374 | } | 374 | Some(tt), |
375 | ) => (def_site_token_map, tt.as_ref().map(|tt| tt.syntax().clone())), | ||
375 | _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"), | 376 | _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"), |
376 | }, | 377 | }, |
377 | }; | 378 | }; |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index a1894e8d8..74129eb21 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -20,7 +20,7 @@ rustc-hash = "1.1.0" | |||
20 | scoped-tls = "1" | 20 | scoped-tls = "1" |
21 | chalk-solve = { version = "0.68", default-features = false } | 21 | chalk-solve = { version = "0.68", default-features = false } |
22 | chalk-ir = "0.68" | 22 | chalk-ir = "0.68" |
23 | chalk-recursive = "0.68" | 23 | chalk-recursive = { version = "0.68", default-features = false } |
24 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 24 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
25 | once_cell = { version = "1.5.0" } | 25 | once_cell = { version = "1.5.0" } |
26 | 26 | ||
diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs index a4c09c742..a55b99de0 100644 --- a/crates/hir_ty/src/chalk_db.rs +++ b/crates/hir_ty/src/chalk_db.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | //! about the code that Chalk needs. | 2 | //! about the code that Chalk needs. |
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use cov_mark::hit; | ||
5 | use log::debug; | 6 | use log::debug; |
6 | 7 | ||
7 | use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds}; | 8 | use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds}; |
@@ -106,7 +107,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
106 | }; | 107 | }; |
107 | 108 | ||
108 | fn local_impls(db: &dyn HirDatabase, module: ModuleId) -> Option<Arc<TraitImpls>> { | 109 | fn local_impls(db: &dyn HirDatabase, module: ModuleId) -> Option<Arc<TraitImpls>> { |
109 | db.trait_impls_in_block(module.containing_block()?) | 110 | let block = module.containing_block()?; |
111 | hit!(block_local_impls); | ||
112 | db.trait_impls_in_block(block) | ||
110 | } | 113 | } |
111 | 114 | ||
112 | // Note: Since we're using impls_for_trait, only impls where the trait | 115 | // Note: Since we're using impls_for_trait, only impls where the trait |
diff --git a/crates/hir_ty/src/consteval.rs b/crates/hir_ty/src/consteval.rs index 6f0bf8f8c..ab1afce08 100644 --- a/crates/hir_ty/src/consteval.rs +++ b/crates/hir_ty/src/consteval.rs | |||
@@ -38,8 +38,7 @@ impl ConstExt for Const { | |||
38 | // FIXME: support more than just evaluating literals | 38 | // FIXME: support more than just evaluating literals |
39 | pub fn eval_usize(expr: &Expr) -> Option<u64> { | 39 | pub fn eval_usize(expr: &Expr) -> Option<u64> { |
40 | match expr { | 40 | match expr { |
41 | Expr::Literal(Literal::Uint(v, None)) | 41 | Expr::Literal(Literal::Uint(v, None | Some(BuiltinUint::Usize))) => (*v).try_into().ok(), |
42 | | Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => (*v).try_into().ok(), | ||
43 | _ => None, | 42 | _ => None, |
44 | } | 43 | } |
45 | } | 44 | } |
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index b809b96a0..dc8f20138 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -56,7 +56,7 @@ impl BodyValidationDiagnostic { | |||
56 | pub fn collect(db: &dyn HirDatabase, owner: DefWithBodyId) -> Vec<BodyValidationDiagnostic> { | 56 | pub fn collect(db: &dyn HirDatabase, owner: DefWithBodyId) -> Vec<BodyValidationDiagnostic> { |
57 | let _p = profile::span("BodyValidationDiagnostic::collect"); | 57 | let _p = profile::span("BodyValidationDiagnostic::collect"); |
58 | let infer = db.infer(owner); | 58 | let infer = db.infer(owner); |
59 | let mut validator = ExprValidator::new(owner, infer.clone()); | 59 | let mut validator = ExprValidator::new(owner, infer); |
60 | validator.validate_body(db); | 60 | validator.validate_body(db); |
61 | validator.diagnostics | 61 | validator.diagnostics |
62 | } | 62 | } |
diff --git a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs index 471cd4921..e3d640a79 100644 --- a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs +++ b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs | |||
@@ -84,10 +84,7 @@ impl IntRange { | |||
84 | #[inline] | 84 | #[inline] |
85 | fn is_integral(ty: &Ty) -> bool { | 85 | fn is_integral(ty: &Ty) -> bool { |
86 | match ty.kind(&Interner) { | 86 | match ty.kind(&Interner) { |
87 | TyKind::Scalar(Scalar::Char) | 87 | TyKind::Scalar(Scalar::Char | Scalar::Int(_) | Scalar::Uint(_) | Scalar::Bool) => true, |
88 | | TyKind::Scalar(Scalar::Int(_)) | ||
89 | | TyKind::Scalar(Scalar::Uint(_)) | ||
90 | | TyKind::Scalar(Scalar::Bool) => true, | ||
91 | _ => false, | 88 | _ => false, |
92 | } | 89 | } |
93 | } | 90 | } |
@@ -381,7 +378,7 @@ impl Constructor { | |||
381 | // Wildcards cover anything | 378 | // Wildcards cover anything |
382 | (_, Wildcard) => true, | 379 | (_, Wildcard) => true, |
383 | // The missing ctors are not covered by anything in the matrix except wildcards. | 380 | // The missing ctors are not covered by anything in the matrix except wildcards. |
384 | (Missing, _) | (Wildcard, _) => false, | 381 | (Missing | Wildcard, _) => false, |
385 | 382 | ||
386 | (Single, Single) => true, | 383 | (Single, Single) => true, |
387 | (Variant(self_id), Variant(other_id)) => self_id == other_id, | 384 | (Variant(self_id), Variant(other_id)) => self_id == other_id, |
@@ -523,7 +520,7 @@ impl SplitWildcard { | |||
523 | } | 520 | } |
524 | } | 521 | } |
525 | TyKind::Scalar(Scalar::Char) => unhandled(), | 522 | TyKind::Scalar(Scalar::Char) => unhandled(), |
526 | TyKind::Scalar(Scalar::Int(..)) | TyKind::Scalar(Scalar::Uint(..)) => unhandled(), | 523 | TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(), |
527 | TyKind::Never if !cx.feature_exhaustive_patterns() && !pcx.is_top_level => { | 524 | TyKind::Never if !cx.feature_exhaustive_patterns() && !pcx.is_top_level => { |
528 | smallvec![NonExhaustive] | 525 | smallvec![NonExhaustive] |
529 | } | 526 | } |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 4b7f31521..7be914451 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -47,10 +47,7 @@ impl<'a> InferenceContext<'a> { | |||
47 | // pointers to have a chance at getting a match. See | 47 | // pointers to have a chance at getting a match. See |
48 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 | 48 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 |
49 | let sig = match (ty1.kind(&Interner), ty2.kind(&Interner)) { | 49 | let sig = match (ty1.kind(&Interner), ty2.kind(&Interner)) { |
50 | (TyKind::FnDef(..), TyKind::FnDef(..)) | 50 | (TyKind::FnDef(..) | TyKind::Closure(..), TyKind::FnDef(..) | TyKind::Closure(..)) => { |
51 | | (TyKind::Closure(..), TyKind::FnDef(..)) | ||
52 | | (TyKind::FnDef(..), TyKind::Closure(..)) | ||
53 | | (TyKind::Closure(..), TyKind::Closure(..)) => { | ||
54 | // FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure, | 51 | // FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure, |
55 | // we should be coercing the closure to a fn pointer of the safety of the FnDef | 52 | // we should be coercing the closure to a fn pointer of the safety of the FnDef |
56 | cov_mark::hit!(coerce_fn_reification); | 53 | cov_mark::hit!(coerce_fn_reification); |
@@ -448,8 +445,7 @@ fn safe_to_unsafe_fn_ty(fn_ty: FnPointer) -> FnPointer { | |||
448 | 445 | ||
449 | fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError> { | 446 | fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError> { |
450 | match (from, to) { | 447 | match (from, to) { |
451 | (Mutability::Mut, Mutability::Mut) | 448 | (Mutability::Mut, Mutability::Mut | Mutability::Not) |
452 | | (Mutability::Mut, Mutability::Not) | ||
453 | | (Mutability::Not, Mutability::Not) => Ok(()), | 449 | | (Mutability::Not, Mutability::Not) => Ok(()), |
454 | (Mutability::Not, Mutability::Mut) => Err(TypeError), | 450 | (Mutability::Not, Mutability::Mut) => Err(TypeError), |
455 | } | 451 | } |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 5ea2e5934..c3a5b979f 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -367,7 +367,7 @@ impl<'a> InferenceContext<'a> { | |||
367 | Expr::Path(p) => { | 367 | Expr::Path(p) => { |
368 | // FIXME this could be more efficient... | 368 | // FIXME this could be more efficient... |
369 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); | 369 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); |
370 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(self.err_ty()) | 370 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or_else(|| self.err_ty()) |
371 | } | 371 | } |
372 | Expr::Continue { .. } => TyKind::Never.intern(&Interner), | 372 | Expr::Continue { .. } => TyKind::Never.intern(&Interner), |
373 | Expr::Break { expr, label } => { | 373 | Expr::Break { expr, label } => { |
@@ -511,7 +511,7 @@ impl<'a> InferenceContext<'a> { | |||
511 | _ => None, | 511 | _ => None, |
512 | } | 512 | } |
513 | }) | 513 | }) |
514 | .unwrap_or(self.err_ty()); | 514 | .unwrap_or_else(|| self.err_ty()); |
515 | let ty = self.insert_type_vars(ty); | 515 | let ty = self.insert_type_vars(ty); |
516 | self.normalize_associated_types_in(ty) | 516 | self.normalize_associated_types_in(ty) |
517 | } | 517 | } |
@@ -593,11 +593,11 @@ impl<'a> InferenceContext<'a> { | |||
593 | UnaryOp::Neg => { | 593 | UnaryOp::Neg => { |
594 | match inner_ty.kind(&Interner) { | 594 | match inner_ty.kind(&Interner) { |
595 | // Fast path for builtins | 595 | // Fast path for builtins |
596 | TyKind::Scalar(Scalar::Int(_)) | 596 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_)) |
597 | | TyKind::Scalar(Scalar::Uint(_)) | 597 | | TyKind::InferenceVar( |
598 | | TyKind::Scalar(Scalar::Float(_)) | 598 | _, |
599 | | TyKind::InferenceVar(_, TyVariableKind::Integer) | 599 | TyVariableKind::Integer | TyVariableKind::Float, |
600 | | TyKind::InferenceVar(_, TyVariableKind::Float) => inner_ty, | 600 | ) => inner_ty, |
601 | // Otherwise we resolve via the std::ops::Neg trait | 601 | // Otherwise we resolve via the std::ops::Neg trait |
602 | _ => self | 602 | _ => self |
603 | .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), | 603 | .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), |
@@ -606,9 +606,7 @@ impl<'a> InferenceContext<'a> { | |||
606 | UnaryOp::Not => { | 606 | UnaryOp::Not => { |
607 | match inner_ty.kind(&Interner) { | 607 | match inner_ty.kind(&Interner) { |
608 | // Fast path for builtins | 608 | // Fast path for builtins |
609 | TyKind::Scalar(Scalar::Bool) | 609 | TyKind::Scalar(Scalar::Bool | Scalar::Int(_) | Scalar::Uint(_)) |
610 | | TyKind::Scalar(Scalar::Int(_)) | ||
611 | | TyKind::Scalar(Scalar::Uint(_)) | ||
612 | | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty, | 610 | | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty, |
613 | // Otherwise we resolve via the std::ops::Not trait | 611 | // Otherwise we resolve via the std::ops::Not trait |
614 | _ => self | 612 | _ => self |
@@ -735,7 +733,7 @@ impl<'a> InferenceContext<'a> { | |||
735 | Expr::Array(array) => { | 733 | Expr::Array(array) => { |
736 | let elem_ty = | 734 | let elem_ty = |
737 | match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(&Interner)) { | 735 | match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(&Interner)) { |
738 | Some(TyKind::Array(st, _)) | Some(TyKind::Slice(st)) => st.clone(), | 736 | Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st.clone(), |
739 | _ => self.table.new_type_var(), | 737 | _ => self.table.new_type_var(), |
740 | }; | 738 | }; |
741 | 739 | ||
@@ -820,8 +818,10 @@ impl<'a> InferenceContext<'a> { | |||
820 | for stmt in statements { | 818 | for stmt in statements { |
821 | match stmt { | 819 | match stmt { |
822 | Statement::Let { pat, type_ref, initializer } => { | 820 | Statement::Let { pat, type_ref, initializer } => { |
823 | let decl_ty = | 821 | let decl_ty = type_ref |
824 | type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(self.err_ty()); | 822 | .as_ref() |
823 | .map(|tr| self.make_ty(tr)) | ||
824 | .unwrap_or_else(|| self.err_ty()); | ||
825 | 825 | ||
826 | // Always use the declared type when specified | 826 | // Always use the declared type when specified |
827 | let mut ty = decl_ty.clone(); | 827 | let mut ty = decl_ty.clone(); |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 035f4ded6..c79ed91ea 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -192,7 +192,7 @@ impl<'a> InferenceContext<'a> { | |||
192 | Pat::Path(path) => { | 192 | Pat::Path(path) => { |
193 | // FIXME use correct resolver for the surrounding expression | 193 | // FIXME use correct resolver for the surrounding expression |
194 | let resolver = self.resolver.clone(); | 194 | let resolver = self.resolver.clone(); |
195 | self.infer_path(&resolver, path, pat.into()).unwrap_or(self.err_ty()) | 195 | self.infer_path(&resolver, path, pat.into()).unwrap_or_else(|| self.err_ty()) |
196 | } | 196 | } |
197 | Pat::Bind { mode, name: _, subpat } => { | 197 | Pat::Bind { mode, name: _, subpat } => { |
198 | let mode = if mode == &BindingAnnotation::Unannotated { | 198 | let mode = if mode == &BindingAnnotation::Unannotated { |
@@ -297,10 +297,11 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool { | |||
297 | Expr::Literal(Literal::String(..)) => false, | 297 | Expr::Literal(Literal::String(..)) => false, |
298 | _ => true, | 298 | _ => true, |
299 | }, | 299 | }, |
300 | Pat::Bind { mode: BindingAnnotation::Mutable, subpat: Some(subpat), .. } | 300 | Pat::Bind { |
301 | | Pat::Bind { mode: BindingAnnotation::Unannotated, subpat: Some(subpat), .. } => { | 301 | mode: BindingAnnotation::Mutable | BindingAnnotation::Unannotated, |
302 | is_non_ref_pat(body, *subpat) | 302 | subpat: Some(subpat), |
303 | } | 303 | .. |
304 | } => is_non_ref_pat(body, *subpat), | ||
304 | Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Box { .. } | Pat::Missing => false, | 305 | Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Box { .. } | Pat::Missing => false, |
305 | } | 306 | } |
306 | } | 307 | } |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 817a65c20..ea03b6a6c 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -562,7 +562,7 @@ impl<'a> TyLoweringContext<'a> { | |||
562 | }, | 562 | }, |
563 | ); | 563 | ); |
564 | 564 | ||
565 | ty.unwrap_or(TyKind::Error.intern(&Interner)) | 565 | ty.unwrap_or_else(|| TyKind::Error.intern(&Interner)) |
566 | } else { | 566 | } else { |
567 | TyKind::Error.intern(&Interner) | 567 | TyKind::Error.intern(&Interner) |
568 | } | 568 | } |
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs index 0222de2bc..5ef6342d5 100644 --- a/crates/hir_ty/src/op.rs +++ b/crates/hir_ty/src/op.rs | |||
@@ -8,17 +8,15 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { | |||
8 | match op { | 8 | match op { |
9 | BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), | 9 | BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), |
10 | BinaryOp::Assignment { .. } => TyBuilder::unit(), | 10 | BinaryOp::Assignment { .. } => TyBuilder::unit(), |
11 | BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { | 11 | BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => { |
12 | // all integer combinations are valid here | 12 | // all integer combinations are valid here |
13 | if matches!( | 13 | if matches!( |
14 | lhs_ty.kind(&Interner), | 14 | lhs_ty.kind(&Interner), |
15 | TyKind::Scalar(Scalar::Int(_)) | 15 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) |
16 | | TyKind::Scalar(Scalar::Uint(_)) | ||
17 | | TyKind::InferenceVar(_, TyVariableKind::Integer) | 16 | | TyKind::InferenceVar(_, TyVariableKind::Integer) |
18 | ) && matches!( | 17 | ) && matches!( |
19 | rhs_ty.kind(&Interner), | 18 | rhs_ty.kind(&Interner), |
20 | TyKind::Scalar(Scalar::Int(_)) | 19 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) |
21 | | TyKind::Scalar(Scalar::Uint(_)) | ||
22 | | TyKind::InferenceVar(_, TyVariableKind::Integer) | 20 | | TyKind::InferenceVar(_, TyVariableKind::Integer) |
23 | ) { | 21 | ) { |
24 | lhs_ty | 22 | lhs_ty |
@@ -32,15 +30,15 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { | |||
32 | | (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_))) | 30 | | (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_))) |
33 | | (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::Float(_))) => rhs_ty, | 31 | | (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::Float(_))) => rhs_ty, |
34 | // ({int}, int) | ({int}, uint) | 32 | // ({int}, int) | ({int}, uint) |
35 | (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Int(_))) | 33 | ( |
36 | | (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Uint(_))) => { | 34 | TyKind::InferenceVar(_, TyVariableKind::Integer), |
37 | rhs_ty | 35 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)), |
38 | } | 36 | ) => rhs_ty, |
39 | // (int, {int}) | (uint, {int}) | 37 | // (int, {int}) | (uint, {int}) |
40 | (TyKind::Scalar(Scalar::Int(_)), TyKind::InferenceVar(_, TyVariableKind::Integer)) | 38 | ( |
41 | | (TyKind::Scalar(Scalar::Uint(_)), TyKind::InferenceVar(_, TyVariableKind::Integer)) => { | 39 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)), |
42 | lhs_ty | 40 | TyKind::InferenceVar(_, TyVariableKind::Integer), |
43 | } | 41 | ) => lhs_ty, |
44 | // ({float} | float) | 42 | // ({float} | float) |
45 | (TyKind::InferenceVar(_, TyVariableKind::Float), TyKind::Scalar(Scalar::Float(_))) => { | 43 | (TyKind::InferenceVar(_, TyVariableKind::Float), TyKind::Scalar(Scalar::Float(_))) => { |
46 | rhs_ty | 44 | rhs_ty |
@@ -69,21 +67,15 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | |||
69 | BinaryOp::Assignment { op: None } => lhs_ty, | 67 | BinaryOp::Assignment { op: None } => lhs_ty, |
70 | BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty.kind(&Interner) { | 68 | BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty.kind(&Interner) { |
71 | TyKind::Scalar(_) | TyKind::Str => lhs_ty, | 69 | TyKind::Scalar(_) | TyKind::Str => lhs_ty, |
72 | TyKind::InferenceVar(_, TyVariableKind::Integer) | 70 | TyKind::InferenceVar(_, TyVariableKind::Integer | TyVariableKind::Float) => lhs_ty, |
73 | | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty, | ||
74 | _ => TyKind::Error.intern(&Interner), | 71 | _ => TyKind::Error.intern(&Interner), |
75 | }, | 72 | }, |
76 | BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { | 73 | BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => TyKind::Error.intern(&Interner), |
77 | TyKind::Error.intern(&Interner) | ||
78 | } | ||
79 | BinaryOp::CmpOp(CmpOp::Ord { .. }) | 74 | BinaryOp::CmpOp(CmpOp::Ord { .. }) |
80 | | BinaryOp::Assignment { op: Some(_) } | 75 | | BinaryOp::Assignment { op: Some(_) } |
81 | | BinaryOp::ArithOp(_) => match lhs_ty.kind(&Interner) { | 76 | | BinaryOp::ArithOp(_) => match lhs_ty.kind(&Interner) { |
82 | TyKind::Scalar(Scalar::Int(_)) | 77 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_)) => lhs_ty, |
83 | | TyKind::Scalar(Scalar::Uint(_)) | 78 | TyKind::InferenceVar(_, TyVariableKind::Integer | TyVariableKind::Float) => lhs_ty, |
84 | | TyKind::Scalar(Scalar::Float(_)) => lhs_ty, | ||
85 | TyKind::InferenceVar(_, TyVariableKind::Integer) | ||
86 | | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty, | ||
87 | _ => TyKind::Error.intern(&Interner), | 79 | _ => TyKind::Error.intern(&Interner), |
88 | }, | 80 | }, |
89 | } | 81 | } |
diff --git a/crates/hir_ty/src/test_db.rs b/crates/hir_ty/src/test_db.rs index 4640ea821..b99a03492 100644 --- a/crates/hir_ty/src/test_db.rs +++ b/crates/hir_ty/src/test_db.rs | |||
@@ -86,16 +86,20 @@ impl FileLoader for TestDB { | |||
86 | } | 86 | } |
87 | 87 | ||
88 | impl TestDB { | 88 | impl TestDB { |
89 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { | 89 | pub(crate) fn module_for_file_opt(&self, file_id: FileId) -> Option<ModuleId> { |
90 | for &krate in self.relevant_crates(file_id).iter() { | 90 | for &krate in self.relevant_crates(file_id).iter() { |
91 | let crate_def_map = self.crate_def_map(krate); | 91 | let crate_def_map = self.crate_def_map(krate); |
92 | for (local_id, data) in crate_def_map.modules() { | 92 | for (local_id, data) in crate_def_map.modules() { |
93 | if data.origin.file_id() == Some(file_id) { | 93 | if data.origin.file_id() == Some(file_id) { |
94 | return crate_def_map.module_id(local_id); | 94 | return Some(crate_def_map.module_id(local_id)); |
95 | } | 95 | } |
96 | } | 96 | } |
97 | } | 97 | } |
98 | panic!("Can't find module for file") | 98 | None |
99 | } | ||
100 | |||
101 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { | ||
102 | self.module_for_file_opt(file_id).unwrap() | ||
99 | } | 103 | } |
100 | 104 | ||
101 | pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> { | 105 | pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> { |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index b873585c4..0651f34ae 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -11,23 +11,21 @@ mod incremental; | |||
11 | 11 | ||
12 | use std::{collections::HashMap, env, sync::Arc}; | 12 | use std::{collections::HashMap, env, sync::Arc}; |
13 | 13 | ||
14 | use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; | 14 | use base_db::{fixture::WithFixture, FileRange, SourceDatabaseExt}; |
15 | use expect_test::Expect; | 15 | use expect_test::Expect; |
16 | use hir_def::{ | 16 | use hir_def::{ |
17 | body::{Body, BodySourceMap, SyntheticSyntax}, | 17 | body::{Body, BodySourceMap, SyntheticSyntax}, |
18 | child_by_source::ChildBySource, | ||
19 | db::DefDatabase, | 18 | db::DefDatabase, |
19 | expr::{ExprId, PatId}, | ||
20 | item_scope::ItemScope, | 20 | item_scope::ItemScope, |
21 | keys, | ||
22 | nameres::DefMap, | 21 | nameres::DefMap, |
23 | src::HasSource, | 22 | src::HasSource, |
24 | AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, | 23 | AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, |
25 | }; | 24 | }; |
26 | use hir_expand::{db::AstDatabase, InFile}; | 25 | use hir_expand::{db::AstDatabase, InFile}; |
27 | use once_cell::race::OnceBool; | 26 | use once_cell::race::OnceBool; |
28 | use stdx::format_to; | 27 | use stdx::format_to; |
29 | use syntax::{ | 28 | use syntax::{ |
30 | algo, | ||
31 | ast::{self, AstNode, NameOwner}, | 29 | ast::{self, AstNode, NameOwner}, |
32 | SyntaxNode, | 30 | SyntaxNode, |
33 | }; | 31 | }; |
@@ -59,51 +57,55 @@ fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> { | |||
59 | } | 57 | } |
60 | 58 | ||
61 | fn check_types(ra_fixture: &str) { | 59 | fn check_types(ra_fixture: &str) { |
62 | check_types_impl(ra_fixture, false) | 60 | check_impl(ra_fixture, false, true, false) |
63 | } | 61 | } |
64 | 62 | ||
65 | fn check_types_source_code(ra_fixture: &str) { | 63 | fn check_types_source_code(ra_fixture: &str) { |
66 | check_types_impl(ra_fixture, true) | 64 | check_impl(ra_fixture, false, true, true) |
67 | } | ||
68 | |||
69 | fn check_types_impl(ra_fixture: &str, display_source: bool) { | ||
70 | let _tracing = setup_tracing(); | ||
71 | let db = TestDB::with_files(ra_fixture); | ||
72 | let mut checked_one = false; | ||
73 | for (file_id, annotations) in db.extract_annotations() { | ||
74 | for (range, expected) in annotations { | ||
75 | let ty = type_at_range(&db, FileRange { file_id, range }); | ||
76 | let actual = if display_source { | ||
77 | let module = db.module_for_file(file_id); | ||
78 | ty.display_source_code(&db, module).unwrap() | ||
79 | } else { | ||
80 | ty.display_test(&db).to_string() | ||
81 | }; | ||
82 | assert_eq!(expected, actual); | ||
83 | checked_one = true; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | assert!(checked_one, "no `//^` annotations found"); | ||
88 | } | 65 | } |
89 | 66 | ||
90 | fn check_no_mismatches(ra_fixture: &str) { | 67 | fn check_no_mismatches(ra_fixture: &str) { |
91 | check_mismatches_impl(ra_fixture, true) | 68 | check_impl(ra_fixture, true, false, false) |
92 | } | 69 | } |
93 | 70 | ||
94 | #[allow(unused)] | 71 | fn check(ra_fixture: &str) { |
95 | fn check_mismatches(ra_fixture: &str) { | 72 | check_impl(ra_fixture, false, false, false) |
96 | check_mismatches_impl(ra_fixture, false) | ||
97 | } | 73 | } |
98 | 74 | ||
99 | fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | 75 | fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_source: bool) { |
100 | let _tracing = setup_tracing(); | 76 | let _tracing = setup_tracing(); |
101 | let (db, file_id) = TestDB::with_single_file(ra_fixture); | 77 | let (db, files) = TestDB::with_many_files(ra_fixture); |
102 | let module = db.module_for_file(file_id); | 78 | |
103 | let def_map = module.def_map(&db); | 79 | let mut had_annotations = false; |
80 | let mut mismatches = HashMap::new(); | ||
81 | let mut types = HashMap::new(); | ||
82 | for (file_id, annotations) in db.extract_annotations() { | ||
83 | for (range, expected) in annotations { | ||
84 | let file_range = FileRange { file_id, range }; | ||
85 | if only_types { | ||
86 | types.insert(file_range, expected); | ||
87 | } else if expected.starts_with("type: ") { | ||
88 | types.insert(file_range, expected.trim_start_matches("type: ").to_string()); | ||
89 | } else if expected.starts_with("expected") { | ||
90 | mismatches.insert(file_range, expected); | ||
91 | } else { | ||
92 | panic!("unexpected annotation: {}", expected); | ||
93 | } | ||
94 | had_annotations = true; | ||
95 | } | ||
96 | } | ||
97 | assert!(had_annotations || allow_none, "no `//^` annotations found"); | ||
104 | 98 | ||
105 | let mut defs: Vec<DefWithBodyId> = Vec::new(); | 99 | let mut defs: Vec<DefWithBodyId> = Vec::new(); |
106 | visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it)); | 100 | for file_id in files { |
101 | let module = db.module_for_file_opt(file_id); | ||
102 | let module = match module { | ||
103 | Some(m) => m, | ||
104 | None => continue, | ||
105 | }; | ||
106 | let def_map = module.def_map(&db); | ||
107 | visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it)); | ||
108 | } | ||
107 | defs.sort_by_key(|def| match def { | 109 | defs.sort_by_key(|def| match def { |
108 | DefWithBodyId::FunctionId(it) => { | 110 | DefWithBodyId::FunctionId(it) => { |
109 | let loc = it.lookup(&db); | 111 | let loc = it.lookup(&db); |
@@ -118,37 +120,59 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | |||
118 | loc.source(&db).value.syntax().text_range().start() | 120 | loc.source(&db).value.syntax().text_range().start() |
119 | } | 121 | } |
120 | }); | 122 | }); |
121 | let mut mismatches = HashMap::new(); | 123 | let mut unexpected_type_mismatches = String::new(); |
122 | let mut push_mismatch = |src_ptr: InFile<SyntaxNode>, mismatch: TypeMismatch| { | ||
123 | let range = src_ptr.value.text_range(); | ||
124 | if src_ptr.file_id.call_node(&db).is_some() { | ||
125 | panic!("type mismatch in macro expansion"); | ||
126 | } | ||
127 | let file_range = FileRange { file_id: src_ptr.file_id.original_file(&db), range }; | ||
128 | let actual = format!( | ||
129 | "expected {}, got {}", | ||
130 | mismatch.expected.display_test(&db), | ||
131 | mismatch.actual.display_test(&db) | ||
132 | ); | ||
133 | mismatches.insert(file_range, actual); | ||
134 | }; | ||
135 | for def in defs { | 124 | for def in defs { |
136 | let (_body, body_source_map) = db.body_with_source_map(def); | 125 | let (_body, body_source_map) = db.body_with_source_map(def); |
137 | let inference_result = db.infer(def); | 126 | let inference_result = db.infer(def); |
127 | |||
128 | for (pat, ty) in inference_result.type_of_pat.iter() { | ||
129 | let node = match pat_node(&body_source_map, pat, &db) { | ||
130 | Some(value) => value, | ||
131 | None => continue, | ||
132 | }; | ||
133 | let range = node.as_ref().original_file_range(&db); | ||
134 | if let Some(expected) = types.remove(&range) { | ||
135 | let actual = if display_source { | ||
136 | ty.display_source_code(&db, def.module(&db)).unwrap() | ||
137 | } else { | ||
138 | ty.display_test(&db).to_string() | ||
139 | }; | ||
140 | assert_eq!(actual, expected); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | for (expr, ty) in inference_result.type_of_expr.iter() { | ||
145 | let node = match expr_node(&body_source_map, expr, &db) { | ||
146 | Some(value) => value, | ||
147 | None => continue, | ||
148 | }; | ||
149 | let range = node.as_ref().original_file_range(&db); | ||
150 | if let Some(expected) = types.remove(&range) { | ||
151 | let actual = if display_source { | ||
152 | ty.display_source_code(&db, def.module(&db)).unwrap() | ||
153 | } else { | ||
154 | ty.display_test(&db).to_string() | ||
155 | }; | ||
156 | assert_eq!(actual, expected); | ||
157 | } | ||
158 | } | ||
159 | |||
138 | for (pat, mismatch) in inference_result.pat_type_mismatches() { | 160 | for (pat, mismatch) in inference_result.pat_type_mismatches() { |
139 | let syntax_ptr = match body_source_map.pat_syntax(pat) { | 161 | let node = match pat_node(&body_source_map, pat, &db) { |
140 | Ok(sp) => { | 162 | Some(value) => value, |
141 | let root = db.parse_or_expand(sp.file_id).unwrap(); | 163 | None => continue, |
142 | sp.map(|ptr| { | ||
143 | ptr.either( | ||
144 | |it| it.to_node(&root).syntax().clone(), | ||
145 | |it| it.to_node(&root).syntax().clone(), | ||
146 | ) | ||
147 | }) | ||
148 | } | ||
149 | Err(SyntheticSyntax) => continue, | ||
150 | }; | 164 | }; |
151 | push_mismatch(syntax_ptr, mismatch.clone()); | 165 | let range = node.as_ref().original_file_range(&db); |
166 | let actual = format!( | ||
167 | "expected {}, got {}", | ||
168 | mismatch.expected.display_test(&db), | ||
169 | mismatch.actual.display_test(&db) | ||
170 | ); | ||
171 | if let Some(annotation) = mismatches.remove(&range) { | ||
172 | assert_eq!(actual, annotation); | ||
173 | } else { | ||
174 | format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual); | ||
175 | } | ||
152 | } | 176 | } |
153 | for (expr, mismatch) in inference_result.expr_type_mismatches() { | 177 | for (expr, mismatch) in inference_result.expr_type_mismatches() { |
154 | let node = match body_source_map.expr_syntax(expr) { | 178 | let node = match body_source_map.expr_syntax(expr) { |
@@ -158,45 +182,70 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | |||
158 | } | 182 | } |
159 | Err(SyntheticSyntax) => continue, | 183 | Err(SyntheticSyntax) => continue, |
160 | }; | 184 | }; |
161 | push_mismatch(node, mismatch.clone()); | 185 | let range = node.as_ref().original_file_range(&db); |
162 | } | 186 | let actual = format!( |
163 | } | 187 | "expected {}, got {}", |
164 | let mut checked_one = false; | 188 | mismatch.expected.display_test(&db), |
165 | for (file_id, annotations) in db.extract_annotations() { | 189 | mismatch.actual.display_test(&db) |
166 | for (range, expected) in annotations { | 190 | ); |
167 | let file_range = FileRange { file_id, range }; | 191 | if let Some(annotation) = mismatches.remove(&range) { |
168 | if let Some(mismatch) = mismatches.remove(&file_range) { | 192 | assert_eq!(actual, annotation); |
169 | assert_eq!(mismatch, expected); | ||
170 | } else { | 193 | } else { |
171 | assert!(false, "Expected mismatch not encountered: {}\n", expected); | 194 | format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual); |
172 | } | 195 | } |
173 | checked_one = true; | ||
174 | } | 196 | } |
175 | } | 197 | } |
198 | |||
176 | let mut buf = String::new(); | 199 | let mut buf = String::new(); |
177 | for (range, mismatch) in mismatches { | 200 | if !unexpected_type_mismatches.is_empty() { |
178 | format_to!(buf, "{:?}: {}\n", range.range, mismatch,); | 201 | format_to!(buf, "Unexpected type mismatches:\n{}", unexpected_type_mismatches); |
202 | } | ||
203 | if !mismatches.is_empty() { | ||
204 | format_to!(buf, "Unchecked mismatch annotations:\n"); | ||
205 | for m in mismatches { | ||
206 | format_to!(buf, "{:?}: {}\n", m.0.range, m.1); | ||
207 | } | ||
179 | } | 208 | } |
180 | assert!(buf.is_empty(), "Unexpected type mismatches:\n{}", buf); | 209 | if !types.is_empty() { |
210 | format_to!(buf, "Unchecked type annotations:\n"); | ||
211 | for t in types { | ||
212 | format_to!(buf, "{:?}: type {}\n", t.0.range, t.1); | ||
213 | } | ||
214 | } | ||
215 | assert!(buf.is_empty(), "{}", buf); | ||
216 | } | ||
181 | 217 | ||
182 | assert!(checked_one || allow_none, "no `//^` annotations found"); | 218 | fn expr_node( |
219 | body_source_map: &BodySourceMap, | ||
220 | expr: ExprId, | ||
221 | db: &TestDB, | ||
222 | ) -> Option<InFile<SyntaxNode>> { | ||
223 | Some(match body_source_map.expr_syntax(expr) { | ||
224 | Ok(sp) => { | ||
225 | let root = db.parse_or_expand(sp.file_id).unwrap(); | ||
226 | sp.map(|ptr| ptr.to_node(&root).syntax().clone()) | ||
227 | } | ||
228 | Err(SyntheticSyntax) => return None, | ||
229 | }) | ||
183 | } | 230 | } |
184 | 231 | ||
185 | fn type_at_range(db: &TestDB, pos: FileRange) -> Ty { | 232 | fn pat_node( |
186 | let file = db.parse(pos.file_id).ok().unwrap(); | 233 | body_source_map: &BodySourceMap, |
187 | let expr = algo::find_node_at_range::<ast::Expr>(file.syntax(), pos.range).unwrap(); | 234 | pat: PatId, |
188 | let fn_def = expr.syntax().ancestors().find_map(ast::Fn::cast).unwrap(); | 235 | db: &TestDB, |
189 | let module = db.module_for_file(pos.file_id); | 236 | ) -> Option<InFile<SyntaxNode>> { |
190 | let func = *module.child_by_source(db)[keys::FUNCTION] | 237 | Some(match body_source_map.pat_syntax(pat) { |
191 | .get(&InFile::new(pos.file_id.into(), fn_def)) | 238 | Ok(sp) => { |
192 | .unwrap(); | 239 | let root = db.parse_or_expand(sp.file_id).unwrap(); |
193 | 240 | sp.map(|ptr| { | |
194 | let (_body, source_map) = db.body_with_source_map(func.into()); | 241 | ptr.either( |
195 | if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { | 242 | |it| it.to_node(&root).syntax().clone(), |
196 | let infer = db.infer(func.into()); | 243 | |it| it.to_node(&root).syntax().clone(), |
197 | return infer[expr_id].clone(); | 244 | ) |
198 | } | 245 | }) |
199 | panic!("Can't find expression") | 246 | } |
247 | Err(SyntheticSyntax) => return None, | ||
248 | }) | ||
200 | } | 249 | } |
201 | 250 | ||
202 | fn infer(ra_fixture: &str) -> String { | 251 | fn infer(ra_fixture: &str) -> String { |
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs index 71047703d..87089f09d 100644 --- a/crates/hir_ty/src/tests/coercion.rs +++ b/crates/hir_ty/src/tests/coercion.rs | |||
@@ -1,380 +1,157 @@ | |||
1 | use expect_test::expect; | 1 | use super::{check, check_no_mismatches, check_types}; |
2 | |||
3 | use super::{check_infer, check_infer_with_mismatches, check_no_mismatches, check_types}; | ||
4 | 2 | ||
5 | #[test] | 3 | #[test] |
6 | fn infer_block_expr_type_mismatch() { | 4 | fn block_expr_type_mismatch() { |
7 | check_infer( | 5 | // FIXME fix double type mismatch |
6 | check( | ||
8 | r" | 7 | r" |
9 | fn test() { | 8 | fn test() { |
10 | let a: i32 = { 1i64 }; | 9 | let a: i32 = { 1i64 }; |
11 | } | 10 | // ^^^^^^^^ expected i32, got i64 |
11 | // ^^^^ expected i32, got i64 | ||
12 | } | ||
12 | ", | 13 | ", |
13 | expect![[r" | ||
14 | 10..40 '{ ...4 }; }': () | ||
15 | 20..21 'a': i32 | ||
16 | 29..37 '{ 1i64 }': i64 | ||
17 | 31..35 '1i64': i64 | ||
18 | "]], | ||
19 | ); | 14 | ); |
20 | } | 15 | } |
21 | 16 | ||
22 | #[test] | 17 | #[test] |
23 | fn coerce_places() { | 18 | fn coerce_places() { |
24 | check_infer( | 19 | check_no_mismatches( |
25 | r#" | 20 | r#" |
26 | struct S<T> { a: T } | 21 | //- minicore: coerce_unsized |
22 | struct S<T> { a: T } | ||
27 | 23 | ||
28 | fn f<T>(_: &[T]) -> T { loop {} } | 24 | fn f<T>(_: &[T]) -> T { loop {} } |
29 | fn g<T>(_: S<&[T]>) -> T { loop {} } | 25 | fn g<T>(_: S<&[T]>) -> T { loop {} } |
30 | 26 | ||
31 | fn gen<T>() -> *mut [T; 2] { loop {} } | 27 | fn gen<T>() -> *mut [T; 2] { loop {} } |
32 | fn test1<U>() -> *mut [U] { | 28 | fn test1<U>() -> *mut [U] { |
33 | gen() | 29 | gen() |
34 | } | 30 | } |
35 | |||
36 | fn test2() { | ||
37 | let arr: &[u8; 1] = &[1]; | ||
38 | |||
39 | let a: &[_] = arr; | ||
40 | let b = f(arr); | ||
41 | let c: &[_] = { arr }; | ||
42 | let d = g(S { a: arr }); | ||
43 | let e: [&[_]; 1] = [arr]; | ||
44 | let f: [&[_]; 2] = [arr; 2]; | ||
45 | let g: (&[_], &[_]) = (arr, arr); | ||
46 | } | ||
47 | 31 | ||
48 | #[lang = "sized"] | 32 | fn test2() { |
49 | pub trait Sized {} | 33 | let arr: &[u8; 1] = &[1]; |
50 | #[lang = "unsize"] | ||
51 | pub trait Unsize<T: ?Sized> {} | ||
52 | #[lang = "coerce_unsized"] | ||
53 | pub trait CoerceUnsized<T> {} | ||
54 | 34 | ||
55 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | 35 | let a: &[_] = arr; |
56 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | 36 | let b = f(arr); |
57 | "#, | 37 | let c: &[_] = { arr }; |
58 | expect![[r#" | 38 | let d = g(S { a: arr }); |
59 | 30..31 '_': &[T] | 39 | let e: [&[_]; 1] = [arr]; |
60 | 44..55 '{ loop {} }': T | 40 | let f: [&[_]; 2] = [arr; 2]; |
61 | 46..53 'loop {}': ! | 41 | let g: (&[_], &[_]) = (arr, arr); |
62 | 51..53 '{}': () | 42 | } |
63 | 64..65 '_': S<&[T]> | 43 | "#, |
64 | 81..92 '{ loop {} }': T | ||
65 | 83..90 'loop {}': ! | ||
66 | 88..90 '{}': () | ||
67 | 121..132 '{ loop {} }': *mut [T; 2] | ||
68 | 123..130 'loop {}': ! | ||
69 | 128..130 '{}': () | ||
70 | 159..172 '{ gen() }': *mut [U] | ||
71 | 165..168 'gen': fn gen<U>() -> *mut [U; 2] | ||
72 | 165..170 'gen()': *mut [U; 2] | ||
73 | 185..419 '{ ...rr); }': () | ||
74 | 195..198 'arr': &[u8; 1] | ||
75 | 211..215 '&[1]': &[u8; 1] | ||
76 | 212..215 '[1]': [u8; 1] | ||
77 | 213..214 '1': u8 | ||
78 | 226..227 'a': &[u8] | ||
79 | 236..239 'arr': &[u8; 1] | ||
80 | 249..250 'b': u8 | ||
81 | 253..254 'f': fn f<u8>(&[u8]) -> u8 | ||
82 | 253..259 'f(arr)': u8 | ||
83 | 255..258 'arr': &[u8; 1] | ||
84 | 269..270 'c': &[u8] | ||
85 | 279..286 '{ arr }': &[u8] | ||
86 | 281..284 'arr': &[u8; 1] | ||
87 | 296..297 'd': u8 | ||
88 | 300..301 'g': fn g<u8>(S<&[u8]>) -> u8 | ||
89 | 300..315 'g(S { a: arr })': u8 | ||
90 | 302..314 'S { a: arr }': S<&[u8]> | ||
91 | 309..312 'arr': &[u8; 1] | ||
92 | 325..326 'e': [&[u8]; 1] | ||
93 | 340..345 '[arr]': [&[u8]; 1] | ||
94 | 341..344 'arr': &[u8; 1] | ||
95 | 355..356 'f': [&[u8]; 2] | ||
96 | 370..378 '[arr; 2]': [&[u8]; 2] | ||
97 | 371..374 'arr': &[u8; 1] | ||
98 | 376..377 '2': usize | ||
99 | 388..389 'g': (&[u8], &[u8]) | ||
100 | 406..416 '(arr, arr)': (&[u8], &[u8]) | ||
101 | 407..410 'arr': &[u8; 1] | ||
102 | 412..415 'arr': &[u8; 1] | ||
103 | "#]], | ||
104 | ); | 44 | ); |
105 | } | 45 | } |
106 | 46 | ||
107 | #[test] | 47 | #[test] |
108 | fn infer_let_stmt_coerce() { | 48 | fn let_stmt_coerce() { |
109 | check_infer( | 49 | check_no_mismatches( |
110 | r" | 50 | r" |
111 | fn test() { | 51 | //- minicore: coerce_unsized |
112 | let x: &[isize] = &[1]; | 52 | fn test() { |
113 | let x: *const [isize] = &[1]; | 53 | let x: &[isize] = &[1]; |
114 | } | 54 | let x: *const [isize] = &[1]; |
115 | ", | 55 | } |
116 | expect![[r#" | 56 | ", |
117 | 10..75 '{ ...[1]; }': () | ||
118 | 20..21 'x': &[isize] | ||
119 | 34..38 '&[1]': &[isize; 1] | ||
120 | 35..38 '[1]': [isize; 1] | ||
121 | 36..37 '1': isize | ||
122 | 48..49 'x': *const [isize] | ||
123 | 68..72 '&[1]': &[isize; 1] | ||
124 | 69..72 '[1]': [isize; 1] | ||
125 | 70..71 '1': isize | ||
126 | "#]], | ||
127 | ); | 57 | ); |
128 | } | 58 | } |
129 | 59 | ||
130 | #[test] | 60 | #[test] |
131 | fn infer_custom_coerce_unsized() { | 61 | fn custom_coerce_unsized() { |
132 | check_infer( | 62 | check( |
133 | r#" | 63 | r#" |
134 | struct A<T: ?Sized>(*const T); | 64 | //- minicore: coerce_unsized |
135 | struct B<T: ?Sized>(*const T); | 65 | use core::{marker::Unsize, ops::CoerceUnsized}; |
136 | struct C<T: ?Sized> { inner: *const T } | ||
137 | 66 | ||
138 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} | 67 | struct A<T: ?Sized>(*const T); |
139 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {} | 68 | struct B<T: ?Sized>(*const T); |
69 | struct C<T: ?Sized> { inner: *const T } | ||
140 | 70 | ||
141 | fn foo1<T>(x: A<[T]>) -> A<[T]> { x } | 71 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} |
142 | fn foo2<T>(x: B<[T]>) -> B<[T]> { x } | 72 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {} |
143 | fn foo3<T>(x: C<[T]>) -> C<[T]> { x } | ||
144 | 73 | ||
145 | fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | 74 | fn foo1<T>(x: A<[T]>) -> A<[T]> { x } |
146 | let d = foo1(a); | 75 | fn foo2<T>(x: B<[T]>) -> B<[T]> { x } |
147 | let e = foo2(b); | 76 | fn foo3<T>(x: C<[T]>) -> C<[T]> { x } |
148 | let f = foo3(c); | ||
149 | } | ||
150 | 77 | ||
151 | 78 | fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | |
152 | #[lang = "sized"] | 79 | let d = foo1(a); |
153 | pub trait Sized {} | 80 | // ^ expected A<[{unknown}]>, got A<[u8; 2]> |
154 | #[lang = "unsize"] | 81 | let e = foo2(b); |
155 | pub trait Unsize<T: ?Sized> {} | 82 | // ^ type: B<[u8]> |
156 | #[lang = "coerce_unsized"] | 83 | let f = foo3(c); |
157 | pub trait CoerceUnsized<T> {} | 84 | // ^ type: C<[u8]> |
158 | 85 | } | |
159 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | 86 | "#, |
160 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
161 | "#, | ||
162 | expect![[r#" | ||
163 | 257..258 'x': A<[T]> | ||
164 | 278..283 '{ x }': A<[T]> | ||
165 | 280..281 'x': A<[T]> | ||
166 | 295..296 'x': B<[T]> | ||
167 | 316..321 '{ x }': B<[T]> | ||
168 | 318..319 'x': B<[T]> | ||
169 | 333..334 'x': C<[T]> | ||
170 | 354..359 '{ x }': C<[T]> | ||
171 | 356..357 'x': C<[T]> | ||
172 | 369..370 'a': A<[u8; 2]> | ||
173 | 384..385 'b': B<[u8; 2]> | ||
174 | 399..400 'c': C<[u8; 2]> | ||
175 | 414..480 '{ ...(c); }': () | ||
176 | 424..425 'd': A<[{unknown}]> | ||
177 | 428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]> | ||
178 | 428..435 'foo1(a)': A<[{unknown}]> | ||
179 | 433..434 'a': A<[u8; 2]> | ||
180 | 445..446 'e': B<[u8]> | ||
181 | 449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]> | ||
182 | 449..456 'foo2(b)': B<[u8]> | ||
183 | 454..455 'b': B<[u8; 2]> | ||
184 | 466..467 'f': C<[u8]> | ||
185 | 470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]> | ||
186 | 470..477 'foo3(c)': C<[u8]> | ||
187 | 475..476 'c': C<[u8; 2]> | ||
188 | "#]], | ||
189 | ); | 87 | ); |
190 | } | 88 | } |
191 | 89 | ||
192 | #[test] | 90 | #[test] |
193 | fn infer_if_coerce() { | 91 | fn if_coerce() { |
194 | check_infer( | 92 | check_no_mismatches( |
195 | r#" | 93 | r#" |
196 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 94 | //- minicore: coerce_unsized |
197 | fn test() { | 95 | fn foo<T>(x: &[T]) -> &[T] { x } |
198 | let x = if true { | 96 | fn test() { |
199 | foo(&[1]) | 97 | let x = if true { |
200 | } else { | 98 | foo(&[1]) |
201 | &[1] | 99 | } else { |
202 | }; | 100 | &[1] |
203 | } | 101 | }; |
204 | 102 | } | |
205 | 103 | "#, | |
206 | #[lang = "sized"] | ||
207 | pub trait Sized {} | ||
208 | #[lang = "unsize"] | ||
209 | pub trait Unsize<T: ?Sized> {} | ||
210 | "#, | ||
211 | expect![[r#" | ||
212 | 10..11 'x': &[T] | ||
213 | 27..38 '{ loop {} }': &[T] | ||
214 | 29..36 'loop {}': ! | ||
215 | 34..36 '{}': () | ||
216 | 49..125 '{ ... }; }': () | ||
217 | 59..60 'x': &[i32] | ||
218 | 63..122 'if tru... }': &[i32] | ||
219 | 66..70 'true': bool | ||
220 | 71..96 '{ ... }': &[i32] | ||
221 | 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
222 | 81..90 'foo(&[1])': &[i32] | ||
223 | 85..89 '&[1]': &[i32; 1] | ||
224 | 86..89 '[1]': [i32; 1] | ||
225 | 87..88 '1': i32 | ||
226 | 102..122 '{ ... }': &[i32; 1] | ||
227 | 112..116 '&[1]': &[i32; 1] | ||
228 | 113..116 '[1]': [i32; 1] | ||
229 | 114..115 '1': i32 | ||
230 | "#]], | ||
231 | ); | 104 | ); |
232 | } | 105 | } |
233 | 106 | ||
234 | #[test] | 107 | #[test] |
235 | fn infer_if_else_coerce() { | 108 | fn if_else_coerce() { |
236 | check_infer( | 109 | check_no_mismatches( |
237 | r#" | 110 | r#" |
238 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 111 | //- minicore: coerce_unsized |
239 | fn test() { | 112 | fn foo<T>(x: &[T]) -> &[T] { x } |
240 | let x = if true { | 113 | fn test() { |
241 | &[1] | 114 | let x = if true { |
242 | } else { | 115 | &[1] |
243 | foo(&[1]) | 116 | } else { |
244 | }; | 117 | foo(&[1]) |
245 | } | 118 | }; |
246 | 119 | } | |
247 | #[lang = "sized"] | 120 | "#, |
248 | pub trait Sized {} | ||
249 | #[lang = "unsize"] | ||
250 | pub trait Unsize<T: ?Sized> {} | ||
251 | #[lang = "coerce_unsized"] | ||
252 | pub trait CoerceUnsized<T> {} | ||
253 | |||
254 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
255 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
256 | "#, | ||
257 | expect![[r#" | ||
258 | 10..11 'x': &[T] | ||
259 | 27..38 '{ loop {} }': &[T] | ||
260 | 29..36 'loop {}': ! | ||
261 | 34..36 '{}': () | ||
262 | 49..125 '{ ... }; }': () | ||
263 | 59..60 'x': &[i32] | ||
264 | 63..122 'if tru... }': &[i32] | ||
265 | 66..70 'true': bool | ||
266 | 71..91 '{ ... }': &[i32; 1] | ||
267 | 81..85 '&[1]': &[i32; 1] | ||
268 | 82..85 '[1]': [i32; 1] | ||
269 | 83..84 '1': i32 | ||
270 | 97..122 '{ ... }': &[i32] | ||
271 | 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
272 | 107..116 'foo(&[1])': &[i32] | ||
273 | 111..115 '&[1]': &[i32; 1] | ||
274 | 112..115 '[1]': [i32; 1] | ||
275 | 113..114 '1': i32 | ||
276 | "#]], | ||
277 | ) | 121 | ) |
278 | } | 122 | } |
279 | 123 | ||
280 | #[test] | 124 | #[test] |
281 | fn infer_match_first_coerce() { | 125 | fn match_first_coerce() { |
282 | check_infer( | 126 | check_no_mismatches( |
283 | r#" | 127 | r#" |
284 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 128 | //- minicore: coerce_unsized |
285 | fn test(i: i32) { | 129 | fn foo<T>(x: &[T]) -> &[T] { x } |
286 | let x = match i { | 130 | fn test(i: i32) { |
287 | 2 => foo(&[2]), | 131 | let x = match i { |
288 | 1 => &[1], | 132 | 2 => foo(&[2]), |
289 | _ => &[3], | 133 | 1 => &[1], |
290 | }; | 134 | _ => &[3], |
291 | } | 135 | }; |
292 | 136 | } | |
293 | #[lang = "sized"] | 137 | "#, |
294 | pub trait Sized {} | ||
295 | #[lang = "unsize"] | ||
296 | pub trait Unsize<T: ?Sized> {} | ||
297 | "#, | ||
298 | expect![[r#" | ||
299 | 10..11 'x': &[T] | ||
300 | 27..38 '{ loop {} }': &[T] | ||
301 | 29..36 'loop {}': ! | ||
302 | 34..36 '{}': () | ||
303 | 47..48 'i': i32 | ||
304 | 55..149 '{ ... }; }': () | ||
305 | 65..66 'x': &[i32] | ||
306 | 69..146 'match ... }': &[i32] | ||
307 | 75..76 'i': i32 | ||
308 | 87..88 '2': i32 | ||
309 | 87..88 '2': i32 | ||
310 | 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
311 | 92..101 'foo(&[2])': &[i32] | ||
312 | 96..100 '&[2]': &[i32; 1] | ||
313 | 97..100 '[2]': [i32; 1] | ||
314 | 98..99 '2': i32 | ||
315 | 111..112 '1': i32 | ||
316 | 111..112 '1': i32 | ||
317 | 116..120 '&[1]': &[i32; 1] | ||
318 | 117..120 '[1]': [i32; 1] | ||
319 | 118..119 '1': i32 | ||
320 | 130..131 '_': i32 | ||
321 | 135..139 '&[3]': &[i32; 1] | ||
322 | 136..139 '[3]': [i32; 1] | ||
323 | 137..138 '3': i32 | ||
324 | "#]], | ||
325 | ); | 138 | ); |
326 | } | 139 | } |
327 | 140 | ||
328 | #[test] | 141 | #[test] |
329 | fn infer_match_second_coerce() { | 142 | fn match_second_coerce() { |
330 | check_infer( | 143 | check_no_mismatches( |
331 | r#" | 144 | r#" |
332 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 145 | //- minicore: coerce_unsized |
333 | fn test(i: i32) { | 146 | fn foo<T>(x: &[T]) -> &[T] { loop {} } |
334 | let x = match i { | 147 | fn test(i: i32) { |
335 | 1 => &[1], | 148 | let x = match i { |
336 | 2 => foo(&[2]), | 149 | 1 => &[1], |
337 | _ => &[3], | 150 | 2 => foo(&[2]), |
338 | }; | 151 | _ => &[3], |
339 | } | 152 | }; |
340 | 153 | } | |
341 | #[lang = "sized"] | 154 | "#, |
342 | pub trait Sized {} | ||
343 | #[lang = "unsize"] | ||
344 | pub trait Unsize<T: ?Sized> {} | ||
345 | #[lang = "coerce_unsized"] | ||
346 | pub trait CoerceUnsized<T> {} | ||
347 | |||
348 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
349 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
350 | "#, | ||
351 | expect![[r#" | ||
352 | 10..11 'x': &[T] | ||
353 | 27..38 '{ loop {} }': &[T] | ||
354 | 29..36 'loop {}': ! | ||
355 | 34..36 '{}': () | ||
356 | 47..48 'i': i32 | ||
357 | 55..149 '{ ... }; }': () | ||
358 | 65..66 'x': &[i32] | ||
359 | 69..146 'match ... }': &[i32] | ||
360 | 75..76 'i': i32 | ||
361 | 87..88 '1': i32 | ||
362 | 87..88 '1': i32 | ||
363 | 92..96 '&[1]': &[i32; 1] | ||
364 | 93..96 '[1]': [i32; 1] | ||
365 | 94..95 '1': i32 | ||
366 | 106..107 '2': i32 | ||
367 | 106..107 '2': i32 | ||
368 | 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
369 | 111..120 'foo(&[2])': &[i32] | ||
370 | 115..119 '&[2]': &[i32; 1] | ||
371 | 116..119 '[2]': [i32; 1] | ||
372 | 117..118 '2': i32 | ||
373 | 130..131 '_': i32 | ||
374 | 135..139 '&[3]': &[i32; 1] | ||
375 | 136..139 '[3]': [i32; 1] | ||
376 | 137..138 '3': i32 | ||
377 | "#]], | ||
378 | ); | 155 | ); |
379 | } | 156 | } |
380 | 157 | ||
@@ -382,207 +159,103 @@ fn infer_match_second_coerce() { | |||
382 | fn coerce_merge_one_by_one1() { | 159 | fn coerce_merge_one_by_one1() { |
383 | cov_mark::check!(coerce_merge_fail_fallback); | 160 | cov_mark::check!(coerce_merge_fail_fallback); |
384 | 161 | ||
385 | check_infer( | 162 | check( |
386 | r" | 163 | r" |
387 | fn test() { | 164 | fn test() { |
388 | let t = &mut 1; | 165 | let t = &mut 1; |
389 | let x = match 1 { | 166 | let x = match 1 { |
390 | 1 => t as *mut i32, | 167 | 1 => t as *mut i32, |
391 | 2 => t as &i32, | 168 | 2 => t as &i32, |
392 | _ => t as *const i32, | 169 | //^^^^^^^^^ expected *mut i32, got &i32 |
393 | }; | 170 | _ => t as *const i32, |
394 | } | 171 | }; |
172 | x; | ||
173 | //^ type: *const i32 | ||
174 | } | ||
395 | ", | 175 | ", |
396 | expect![[r" | ||
397 | 10..144 '{ ... }; }': () | ||
398 | 20..21 't': &mut i32 | ||
399 | 24..30 '&mut 1': &mut i32 | ||
400 | 29..30 '1': i32 | ||
401 | 40..41 'x': *const i32 | ||
402 | 44..141 'match ... }': *const i32 | ||
403 | 50..51 '1': i32 | ||
404 | 62..63 '1': i32 | ||
405 | 62..63 '1': i32 | ||
406 | 67..68 't': &mut i32 | ||
407 | 67..80 't as *mut i32': *mut i32 | ||
408 | 90..91 '2': i32 | ||
409 | 90..91 '2': i32 | ||
410 | 95..96 't': &mut i32 | ||
411 | 95..104 't as &i32': &i32 | ||
412 | 114..115 '_': i32 | ||
413 | 119..120 't': &mut i32 | ||
414 | 119..134 't as *const i32': *const i32 | ||
415 | "]], | ||
416 | ); | 176 | ); |
417 | } | 177 | } |
418 | 178 | ||
419 | #[test] | 179 | #[test] |
420 | fn return_coerce_unknown() { | 180 | fn return_coerce_unknown() { |
421 | check_infer_with_mismatches( | 181 | check_types( |
422 | r" | 182 | r" |
423 | fn foo() -> u32 { | 183 | fn foo() -> u32 { |
424 | return unknown; | 184 | return unknown; |
425 | } | 185 | //^^^^^^^ u32 |
186 | } | ||
426 | ", | 187 | ", |
427 | expect![[r" | ||
428 | 16..39 '{ ...own; }': u32 | ||
429 | 22..36 'return unknown': ! | ||
430 | 29..36 'unknown': u32 | ||
431 | "]], | ||
432 | ); | 188 | ); |
433 | } | 189 | } |
434 | 190 | ||
435 | #[test] | 191 | #[test] |
436 | fn coerce_autoderef() { | 192 | fn coerce_autoderef() { |
437 | check_infer_with_mismatches( | 193 | check_no_mismatches( |
438 | r" | 194 | r" |
439 | struct Foo; | 195 | struct Foo; |
440 | fn takes_ref_foo(x: &Foo) {} | 196 | fn takes_ref_foo(x: &Foo) {} |
441 | fn test() { | 197 | fn test() { |
442 | takes_ref_foo(&Foo); | 198 | takes_ref_foo(&Foo); |
443 | takes_ref_foo(&&Foo); | 199 | takes_ref_foo(&&Foo); |
444 | takes_ref_foo(&&&Foo); | 200 | takes_ref_foo(&&&Foo); |
445 | } | 201 | }", |
446 | ", | ||
447 | expect![[r" | ||
448 | 29..30 'x': &Foo | ||
449 | 38..40 '{}': () | ||
450 | 51..132 '{ ...oo); }': () | ||
451 | 57..70 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
452 | 57..76 'takes_...(&Foo)': () | ||
453 | 71..75 '&Foo': &Foo | ||
454 | 72..75 'Foo': Foo | ||
455 | 82..95 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
456 | 82..102 'takes_...&&Foo)': () | ||
457 | 96..101 '&&Foo': &&Foo | ||
458 | 97..101 '&Foo': &Foo | ||
459 | 98..101 'Foo': Foo | ||
460 | 108..121 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
461 | 108..129 'takes_...&&Foo)': () | ||
462 | 122..128 '&&&Foo': &&&Foo | ||
463 | 123..128 '&&Foo': &&Foo | ||
464 | 124..128 '&Foo': &Foo | ||
465 | 125..128 'Foo': Foo | ||
466 | "]], | ||
467 | ); | 202 | ); |
468 | } | 203 | } |
469 | 204 | ||
470 | #[test] | 205 | #[test] |
471 | fn coerce_autoderef_generic() { | 206 | fn coerce_autoderef_generic() { |
472 | check_infer_with_mismatches( | 207 | check_no_mismatches( |
473 | r" | 208 | r#" |
474 | struct Foo; | 209 | struct Foo; |
475 | fn takes_ref<T>(x: &T) -> T { *x } | 210 | fn takes_ref<T>(x: &T) -> T { *x } |
476 | fn test() { | 211 | fn test() { |
477 | takes_ref(&Foo); | 212 | takes_ref(&Foo); |
478 | takes_ref(&&Foo); | 213 | takes_ref(&&Foo); |
479 | takes_ref(&&&Foo); | 214 | takes_ref(&&&Foo); |
480 | } | 215 | } |
481 | ", | 216 | "#, |
482 | expect![[r" | ||
483 | 28..29 'x': &T | ||
484 | 40..46 '{ *x }': T | ||
485 | 42..44 '*x': T | ||
486 | 43..44 'x': &T | ||
487 | 57..126 '{ ...oo); }': () | ||
488 | 63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo | ||
489 | 63..78 'takes_ref(&Foo)': Foo | ||
490 | 73..77 '&Foo': &Foo | ||
491 | 74..77 'Foo': Foo | ||
492 | 84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo | ||
493 | 84..100 'takes_...&&Foo)': &Foo | ||
494 | 94..99 '&&Foo': &&Foo | ||
495 | 95..99 '&Foo': &Foo | ||
496 | 96..99 'Foo': Foo | ||
497 | 106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo | ||
498 | 106..123 'takes_...&&Foo)': &&Foo | ||
499 | 116..122 '&&&Foo': &&&Foo | ||
500 | 117..122 '&&Foo': &&Foo | ||
501 | 118..122 '&Foo': &Foo | ||
502 | 119..122 'Foo': Foo | ||
503 | "]], | ||
504 | ); | 217 | ); |
505 | } | 218 | } |
506 | 219 | ||
507 | #[test] | 220 | #[test] |
508 | fn coerce_autoderef_block() { | 221 | fn coerce_autoderef_block() { |
509 | check_infer_with_mismatches( | 222 | check_no_mismatches( |
510 | r#" | 223 | r#" |
511 | struct String {} | 224 | //- minicore: deref |
512 | #[lang = "deref"] | 225 | struct String {} |
513 | trait Deref { type Target; } | 226 | impl core::ops::Deref for String { type Target = str; } |
514 | impl Deref for String { type Target = str; } | 227 | fn takes_ref_str(x: &str) {} |
515 | fn takes_ref_str(x: &str) {} | 228 | fn returns_string() -> String { loop {} } |
516 | fn returns_string() -> String { loop {} } | 229 | fn test() { |
517 | fn test() { | 230 | takes_ref_str(&{ returns_string() }); |
518 | takes_ref_str(&{ returns_string() }); | 231 | } |
519 | } | 232 | "#, |
520 | "#, | ||
521 | expect![[r" | ||
522 | 126..127 'x': &str | ||
523 | 135..137 '{}': () | ||
524 | 168..179 '{ loop {} }': String | ||
525 | 170..177 'loop {}': ! | ||
526 | 175..177 '{}': () | ||
527 | 190..235 '{ ... }); }': () | ||
528 | 196..209 'takes_ref_str': fn takes_ref_str(&str) | ||
529 | 196..232 'takes_...g() })': () | ||
530 | 210..231 '&{ ret...ng() }': &String | ||
531 | 211..231 '{ retu...ng() }': String | ||
532 | 213..227 'returns_string': fn returns_string() -> String | ||
533 | 213..229 'return...ring()': String | ||
534 | "]], | ||
535 | ); | 233 | ); |
536 | } | 234 | } |
537 | 235 | ||
538 | #[test] | 236 | #[test] |
539 | fn closure_return_coerce() { | 237 | fn closure_return_coerce() { |
540 | check_infer_with_mismatches( | 238 | check_no_mismatches( |
541 | r" | 239 | r" |
542 | fn foo() { | 240 | fn foo() { |
543 | let x = || { | 241 | let x = || { |
544 | if true { | 242 | if true { |
545 | return &1u32; | 243 | return &1u32; |
546 | } | ||
547 | &&1u32 | ||
548 | }; | ||
549 | } | 244 | } |
550 | ", | 245 | &&1u32 |
551 | expect![[r" | 246 | }; |
552 | 9..105 '{ ... }; }': () | 247 | }", |
553 | 19..20 'x': || -> &u32 | ||
554 | 23..102 '|| { ... }': || -> &u32 | ||
555 | 26..102 '{ ... }': &u32 | ||
556 | 36..81 'if tru... }': () | ||
557 | 39..43 'true': bool | ||
558 | 44..81 '{ ... }': () | ||
559 | 58..70 'return &1u32': ! | ||
560 | 65..70 '&1u32': &u32 | ||
561 | 66..70 '1u32': u32 | ||
562 | 90..96 '&&1u32': &&u32 | ||
563 | 91..96 '&1u32': &u32 | ||
564 | 92..96 '1u32': u32 | ||
565 | "]], | ||
566 | ); | 248 | ); |
567 | } | 249 | } |
568 | 250 | ||
569 | #[test] | 251 | #[test] |
570 | fn coerce_fn_item_to_fn_ptr() { | 252 | fn coerce_fn_item_to_fn_ptr() { |
571 | check_infer_with_mismatches( | 253 | check_no_mismatches( |
572 | r" | 254 | r" |
573 | fn foo(x: u32) -> isize { 1 } | 255 | fn foo(x: u32) -> isize { 1 } |
574 | fn test() { | 256 | fn test() { |
575 | let f: fn(u32) -> isize = foo; | 257 | let f: fn(u32) -> isize = foo; |
576 | } | 258 | }", |
577 | ", | ||
578 | expect![[r" | ||
579 | 7..8 'x': u32 | ||
580 | 24..29 '{ 1 }': isize | ||
581 | 26..27 '1': isize | ||
582 | 40..78 '{ ...foo; }': () | ||
583 | 50..51 'f': fn(u32) -> isize | ||
584 | 72..75 'foo': fn foo(u32) -> isize | ||
585 | "]], | ||
586 | ); | 259 | ); |
587 | } | 260 | } |
588 | 261 | ||
@@ -590,340 +263,160 @@ fn coerce_fn_item_to_fn_ptr() { | |||
590 | fn coerce_fn_items_in_match_arms() { | 263 | fn coerce_fn_items_in_match_arms() { |
591 | cov_mark::check!(coerce_fn_reification); | 264 | cov_mark::check!(coerce_fn_reification); |
592 | 265 | ||
593 | check_infer_with_mismatches( | 266 | check_types( |
594 | r" | 267 | r" |
595 | fn foo1(x: u32) -> isize { 1 } | 268 | fn foo1(x: u32) -> isize { 1 } |
596 | fn foo2(x: u32) -> isize { 2 } | 269 | fn foo2(x: u32) -> isize { 2 } |
597 | fn foo3(x: u32) -> isize { 3 } | 270 | fn foo3(x: u32) -> isize { 3 } |
598 | fn test() { | 271 | fn test() { |
599 | let x = match 1 { | 272 | let x = match 1 { |
600 | 1 => foo1, | 273 | 1 => foo1, |
601 | 2 => foo2, | 274 | 2 => foo2, |
602 | _ => foo3, | 275 | _ => foo3, |
603 | }; | 276 | }; |
604 | } | 277 | x; |
605 | ", | 278 | //^ fn(u32) -> isize |
606 | expect![[r" | 279 | }", |
607 | 8..9 'x': u32 | ||
608 | 25..30 '{ 1 }': isize | ||
609 | 27..28 '1': isize | ||
610 | 39..40 'x': u32 | ||
611 | 56..61 '{ 2 }': isize | ||
612 | 58..59 '2': isize | ||
613 | 70..71 'x': u32 | ||
614 | 87..92 '{ 3 }': isize | ||
615 | 89..90 '3': isize | ||
616 | 103..192 '{ ... }; }': () | ||
617 | 113..114 'x': fn(u32) -> isize | ||
618 | 117..189 'match ... }': fn(u32) -> isize | ||
619 | 123..124 '1': i32 | ||
620 | 135..136 '1': i32 | ||
621 | 135..136 '1': i32 | ||
622 | 140..144 'foo1': fn foo1(u32) -> isize | ||
623 | 154..155 '2': i32 | ||
624 | 154..155 '2': i32 | ||
625 | 159..163 'foo2': fn foo2(u32) -> isize | ||
626 | 173..174 '_': i32 | ||
627 | 178..182 'foo3': fn foo3(u32) -> isize | ||
628 | "]], | ||
629 | ); | 280 | ); |
630 | } | 281 | } |
631 | 282 | ||
632 | #[test] | 283 | #[test] |
633 | fn coerce_closure_to_fn_ptr() { | 284 | fn coerce_closure_to_fn_ptr() { |
634 | check_infer_with_mismatches( | 285 | check_no_mismatches( |
635 | r" | 286 | r" |
636 | fn test() { | 287 | fn test() { |
637 | let f: fn(u32) -> isize = |x| { 1 }; | 288 | let f: fn(u32) -> isize = |x| { 1 }; |
638 | } | 289 | }", |
639 | ", | ||
640 | expect![[r" | ||
641 | 10..54 '{ ...1 }; }': () | ||
642 | 20..21 'f': fn(u32) -> isize | ||
643 | 42..51 '|x| { 1 }': |u32| -> isize | ||
644 | 43..44 'x': u32 | ||
645 | 46..51 '{ 1 }': isize | ||
646 | 48..49 '1': isize | ||
647 | "]], | ||
648 | ); | 290 | ); |
649 | } | 291 | } |
650 | 292 | ||
651 | #[test] | 293 | #[test] |
652 | fn coerce_placeholder_ref() { | 294 | fn coerce_placeholder_ref() { |
653 | // placeholders should unify, even behind references | 295 | // placeholders should unify, even behind references |
654 | check_infer_with_mismatches( | 296 | check_no_mismatches( |
655 | r" | 297 | r" |
656 | struct S<T> { t: T } | 298 | struct S<T> { t: T } |
657 | impl<TT> S<TT> { | 299 | impl<TT> S<TT> { |
658 | fn get(&self) -> &TT { | 300 | fn get(&self) -> &TT { |
659 | &self.t | 301 | &self.t |
660 | } | 302 | } |
661 | } | 303 | }", |
662 | ", | ||
663 | expect![[r" | ||
664 | 50..54 'self': &S<TT> | ||
665 | 63..86 '{ ... }': &TT | ||
666 | 73..80 '&self.t': &TT | ||
667 | 74..78 'self': &S<TT> | ||
668 | 74..80 'self.t': TT | ||
669 | "]], | ||
670 | ); | 304 | ); |
671 | } | 305 | } |
672 | 306 | ||
673 | #[test] | 307 | #[test] |
674 | fn coerce_unsize_array() { | 308 | fn coerce_unsize_array() { |
675 | check_infer_with_mismatches( | 309 | check_types( |
676 | r#" | 310 | r#" |
677 | #[lang = "unsize"] | 311 | //- minicore: coerce_unsized |
678 | pub trait Unsize<T> {} | 312 | fn test() { |
679 | #[lang = "coerce_unsized"] | 313 | let f: &[usize] = &[1, 2, 3]; |
680 | pub trait CoerceUnsized<T> {} | 314 | //^ usize |
681 | 315 | }"#, | |
682 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
683 | |||
684 | fn test() { | ||
685 | let f: &[usize] = &[1, 2, 3]; | ||
686 | } | ||
687 | "#, | ||
688 | expect![[r#" | ||
689 | 161..198 '{ ... 3]; }': () | ||
690 | 171..172 'f': &[usize] | ||
691 | 185..195 '&[1, 2, 3]': &[usize; 3] | ||
692 | 186..195 '[1, 2, 3]': [usize; 3] | ||
693 | 187..188 '1': usize | ||
694 | 190..191 '2': usize | ||
695 | 193..194 '3': usize | ||
696 | "#]], | ||
697 | ); | 316 | ); |
698 | } | 317 | } |
699 | 318 | ||
700 | #[test] | 319 | #[test] |
701 | fn coerce_unsize_trait_object_simple() { | 320 | fn coerce_unsize_trait_object_simple() { |
702 | check_infer_with_mismatches( | 321 | check_types( |
703 | r#" | ||
704 | #[lang = "sized"] | ||
705 | pub trait Sized {} | ||
706 | #[lang = "unsize"] | ||
707 | pub trait Unsize<T> {} | ||
708 | #[lang = "coerce_unsized"] | ||
709 | pub trait CoerceUnsized<T> {} | ||
710 | |||
711 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
712 | |||
713 | trait Foo<T, U> {} | ||
714 | trait Bar<U, T, X>: Foo<T, U> {} | ||
715 | trait Baz<T, X>: Bar<usize, T, X> {} | ||
716 | |||
717 | struct S<T, X>; | ||
718 | impl<T, X> Foo<T, usize> for S<T, X> {} | ||
719 | impl<T, X> Bar<usize, T, X> for S<T, X> {} | ||
720 | impl<T, X> Baz<T, X> for S<T, X> {} | ||
721 | |||
722 | fn test() { | ||
723 | let obj: &dyn Baz<i8, i16> = &S; | ||
724 | let obj: &dyn Bar<_, i8, i16> = &S; | ||
725 | let obj: &dyn Foo<i8, _> = &S; | ||
726 | } | ||
727 | "#, | ||
728 | expect![[r" | ||
729 | 424..539 '{ ... &S; }': () | ||
730 | 434..437 'obj': &dyn Baz<i8, i16> | ||
731 | 459..461 '&S': &S<i8, i16> | ||
732 | 460..461 'S': S<i8, i16> | ||
733 | 471..474 'obj': &dyn Bar<usize, i8, i16> | ||
734 | 499..501 '&S': &S<i8, i16> | ||
735 | 500..501 'S': S<i8, i16> | ||
736 | 511..514 'obj': &dyn Foo<i8, usize> | ||
737 | 534..536 '&S': &S<i8, {unknown}> | ||
738 | 535..536 'S': S<i8, {unknown}> | ||
739 | "]], | ||
740 | ); | ||
741 | } | ||
742 | |||
743 | #[test] | ||
744 | // The rust reference says this should be possible, but rustc doesn't implement | ||
745 | // it. We used to support it, but Chalk doesn't. | ||
746 | #[ignore] | ||
747 | fn coerce_unsize_trait_object_to_trait_object() { | ||
748 | check_infer_with_mismatches( | ||
749 | r#" | 322 | r#" |
750 | #[lang = "sized"] | 323 | //- minicore: coerce_unsized |
751 | pub trait Sized {} | 324 | trait Foo<T, U> {} |
752 | #[lang = "unsize"] | 325 | trait Bar<U, T, X>: Foo<T, U> {} |
753 | pub trait Unsize<T> {} | 326 | trait Baz<T, X>: Bar<usize, T, X> {} |
754 | #[lang = "coerce_unsized"] | 327 | |
755 | pub trait CoerceUnsized<T> {} | 328 | struct S<T, X>; |
756 | 329 | impl<T, X> Foo<T, usize> for S<T, X> {} | |
757 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | 330 | impl<T, X> Bar<usize, T, X> for S<T, X> {} |
758 | 331 | impl<T, X> Baz<T, X> for S<T, X> {} | |
759 | trait Foo<T, U> {} | 332 | |
760 | trait Bar<U, T, X>: Foo<T, U> {} | 333 | fn test() { |
761 | trait Baz<T, X>: Bar<usize, T, X> {} | 334 | let obj: &dyn Baz<i8, i16> = &S; |
762 | 335 | //^ S<i8, i16> | |
763 | struct S<T, X>; | 336 | let obj: &dyn Bar<_, i8, i16> = &S; |
764 | impl<T, X> Foo<T, usize> for S<T, X> {} | 337 | //^ S<i8, i16> |
765 | impl<T, X> Bar<usize, T, X> for S<T, X> {} | 338 | let obj: &dyn Foo<i8, _> = &S; |
766 | impl<T, X> Baz<T, X> for S<T, X> {} | 339 | //^ S<i8, {unknown}> |
767 | 340 | }"#, | |
768 | fn test() { | ||
769 | let obj: &dyn Baz<i8, i16> = &S; | ||
770 | let obj: &dyn Bar<_, _, _> = obj; | ||
771 | let obj: &dyn Foo<_, _> = obj; | ||
772 | let obj2: &dyn Baz<i8, i16> = &S; | ||
773 | let _: &dyn Foo<_, _> = obj2; | ||
774 | } | ||
775 | "#, | ||
776 | expect![[r" | ||
777 | 424..609 '{ ...bj2; }': () | ||
778 | 434..437 'obj': &dyn Baz<i8, i16> | ||
779 | 459..461 '&S': &S<i8, i16> | ||
780 | 460..461 'S': S<i8, i16> | ||
781 | 471..474 'obj': &dyn Bar<usize, i8, i16> | ||
782 | 496..499 'obj': &dyn Baz<i8, i16> | ||
783 | 509..512 'obj': &dyn Foo<i8, usize> | ||
784 | 531..534 'obj': &dyn Bar<usize, i8, i16> | ||
785 | 544..548 'obj2': &dyn Baz<i8, i16> | ||
786 | 570..572 '&S': &S<i8, i16> | ||
787 | 571..572 'S': S<i8, i16> | ||
788 | 582..583 '_': &dyn Foo<i8, usize> | ||
789 | 602..606 'obj2': &dyn Baz<i8, i16> | ||
790 | "]], | ||
791 | ); | 341 | ); |
792 | } | 342 | } |
793 | 343 | ||
794 | #[test] | 344 | #[test] |
795 | fn coerce_unsize_super_trait_cycle() { | 345 | fn coerce_unsize_super_trait_cycle() { |
796 | check_infer_with_mismatches( | 346 | check_no_mismatches( |
797 | r#" | 347 | r#" |
798 | #[lang = "sized"] | 348 | //- minicore: coerce_unsized |
799 | pub trait Sized {} | 349 | trait A {} |
800 | #[lang = "unsize"] | 350 | trait B: C + A {} |
801 | pub trait Unsize<T> {} | 351 | trait C: B {} |
802 | #[lang = "coerce_unsized"] | 352 | trait D: C |
803 | pub trait CoerceUnsized<T> {} | 353 | |
804 | 354 | struct S; | |
805 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | 355 | impl A for S {} |
806 | 356 | impl B for S {} | |
807 | trait A {} | 357 | impl C for S {} |
808 | trait B: C + A {} | 358 | impl D for S {} |
809 | trait C: B {} | 359 | |
810 | trait D: C | 360 | fn test() { |
811 | 361 | let obj: &dyn D = &S; | |
812 | struct S; | 362 | let obj: &dyn A = &S; |
813 | impl A for S {} | 363 | } |
814 | impl B for S {} | 364 | "#, |
815 | impl C for S {} | ||
816 | impl D for S {} | ||
817 | |||
818 | fn test() { | ||
819 | let obj: &dyn D = &S; | ||
820 | let obj: &dyn A = &S; | ||
821 | } | ||
822 | "#, | ||
823 | expect![[r" | ||
824 | 328..383 '{ ... &S; }': () | ||
825 | 338..341 'obj': &dyn D | ||
826 | 352..354 '&S': &S | ||
827 | 353..354 'S': S | ||
828 | 364..367 'obj': &dyn A | ||
829 | 378..380 '&S': &S | ||
830 | 379..380 'S': S | ||
831 | "]], | ||
832 | ); | 365 | ); |
833 | } | 366 | } |
834 | 367 | ||
835 | #[test] | 368 | #[test] |
836 | fn coerce_unsize_generic() { | 369 | fn coerce_unsize_generic() { |
837 | // FIXME: fix the type mismatches here | 370 | // FIXME: fix the type mismatches here |
838 | check_infer_with_mismatches( | 371 | check( |
839 | r#" | 372 | r#" |
840 | #[lang = "unsize"] | 373 | //- minicore: coerce_unsized |
841 | pub trait Unsize<T> {} | 374 | struct Foo<T> { t: T }; |
842 | #[lang = "coerce_unsized"] | 375 | struct Bar<T>(Foo<T>); |
843 | pub trait CoerceUnsized<T> {} | ||
844 | |||
845 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
846 | |||
847 | struct Foo<T> { t: T }; | ||
848 | struct Bar<T>(Foo<T>); | ||
849 | 376 | ||
850 | fn test() { | 377 | fn test() { |
851 | let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; | 378 | let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; |
852 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); | 379 | //^^^^^^^^^ expected [usize], got [usize; 3] |
853 | } | 380 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); |
854 | "#, | 381 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &Bar<[usize]>, got &Bar<[i32; 3]> |
855 | expect![[r#" | 382 | } |
856 | 209..317 '{ ... }); }': () | 383 | "#, |
857 | 219..220 '_': &Foo<[usize]> | ||
858 | 238..259 '&Foo {..., 3] }': &Foo<[usize]> | ||
859 | 239..259 'Foo { ..., 3] }': Foo<[usize]> | ||
860 | 248..257 '[1, 2, 3]': [usize; 3] | ||
861 | 249..250 '1': usize | ||
862 | 252..253 '2': usize | ||
863 | 255..256 '3': usize | ||
864 | 269..270 '_': &Bar<[usize]> | ||
865 | 288..314 '&Bar(F... 3] })': &Bar<[i32; 3]> | ||
866 | 289..292 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]> | ||
867 | 289..314 'Bar(Fo... 3] })': Bar<[i32; 3]> | ||
868 | 293..313 'Foo { ..., 3] }': Foo<[i32; 3]> | ||
869 | 302..311 '[1, 2, 3]': [i32; 3] | ||
870 | 303..304 '1': i32 | ||
871 | 306..307 '2': i32 | ||
872 | 309..310 '3': i32 | ||
873 | 248..257: expected [usize], got [usize; 3] | ||
874 | 288..314: expected &Bar<[usize]>, got &Bar<[i32; 3]> | ||
875 | "#]], | ||
876 | ); | 384 | ); |
877 | } | 385 | } |
878 | 386 | ||
879 | #[test] | 387 | #[test] |
880 | fn coerce_unsize_apit() { | 388 | fn coerce_unsize_apit() { |
881 | // FIXME: #8984 | 389 | // FIXME: #8984 |
882 | check_infer_with_mismatches( | 390 | check( |
883 | r#" | 391 | r#" |
884 | #[lang = "sized"] | 392 | //- minicore: coerce_unsized |
885 | pub trait Sized {} | ||
886 | #[lang = "unsize"] | ||
887 | pub trait Unsize<T> {} | ||
888 | #[lang = "coerce_unsized"] | ||
889 | pub trait CoerceUnsized<T> {} | ||
890 | |||
891 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
892 | |||
893 | trait Foo {} | 393 | trait Foo {} |
894 | 394 | ||
895 | fn test(f: impl Foo) { | 395 | fn test(f: impl Foo) { |
896 | let _: &dyn Foo = &f; | 396 | let _: &dyn Foo = &f; |
397 | //^^ expected &dyn Foo, got &impl Foo | ||
897 | } | 398 | } |
898 | "#, | 399 | "#, |
899 | expect![[r#" | ||
900 | 210..211 'f': impl Foo | ||
901 | 223..252 '{ ... &f; }': () | ||
902 | 233..234 '_': &dyn Foo | ||
903 | 247..249 '&f': &impl Foo | ||
904 | 248..249 'f': impl Foo | ||
905 | 247..249: expected &dyn Foo, got &impl Foo | ||
906 | "#]], | ||
907 | ); | 400 | ); |
908 | } | 401 | } |
909 | 402 | ||
910 | #[test] | 403 | #[test] |
911 | fn infer_two_closures_lub() { | 404 | fn two_closures_lub() { |
912 | check_types( | 405 | check_types( |
913 | r#" | 406 | r#" |
914 | fn foo(c: i32) { | 407 | fn foo(c: i32) { |
915 | let add = |a: i32, b: i32| a + b; | 408 | let add = |a: i32, b: i32| a + b; |
916 | let sub = |a, b| a - b; | 409 | let sub = |a, b| a - b; |
917 | //^ |i32, i32| -> i32 | 410 | //^^^^^^^^^^^^ |i32, i32| -> i32 |
918 | if c > 42 { add } else { sub }; | 411 | if c > 42 { add } else { sub }; |
919 | //^ fn(i32, i32) -> i32 | 412 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32 |
920 | } | 413 | } |
921 | "#, | 414 | "#, |
922 | ) | 415 | ) |
923 | } | 416 | } |
924 | 417 | ||
925 | #[test] | 418 | #[test] |
926 | fn infer_match_diverging_branch_1() { | 419 | fn match_diverging_branch_1() { |
927 | check_types( | 420 | check_types( |
928 | r#" | 421 | r#" |
929 | enum Result<T> { Ok(T), Err } | 422 | enum Result<T> { Ok(T), Err } |
@@ -942,7 +435,7 @@ fn test() -> i32 { | |||
942 | } | 435 | } |
943 | 436 | ||
944 | #[test] | 437 | #[test] |
945 | fn infer_match_diverging_branch_2() { | 438 | fn match_diverging_branch_2() { |
946 | // same as 1 except for order of branches | 439 | // same as 1 except for order of branches |
947 | check_types( | 440 | check_types( |
948 | r#" | 441 | r#" |
@@ -998,15 +491,7 @@ fn main() { | |||
998 | fn coerce_unsize_expected_type() { | 491 | fn coerce_unsize_expected_type() { |
999 | check_no_mismatches( | 492 | check_no_mismatches( |
1000 | r#" | 493 | r#" |
1001 | #[lang = "sized"] | 494 | //- minicore: coerce_unsized |
1002 | pub trait Sized {} | ||
1003 | #[lang = "unsize"] | ||
1004 | pub trait Unsize<T> {} | ||
1005 | #[lang = "coerce_unsized"] | ||
1006 | pub trait CoerceUnsized<T> {} | ||
1007 | |||
1008 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
1009 | |||
1010 | fn main() { | 495 | fn main() { |
1011 | let foo: &[u32] = &[1, 2]; | 496 | let foo: &[u32] = &[1, 2]; |
1012 | let foo: &[u32] = match true { | 497 | let foo: &[u32] = match true { |
diff --git a/crates/hir_ty/src/tests/display_source_code.rs b/crates/hir_ty/src/tests/display_source_code.rs index 3d29021aa..058cd02d7 100644 --- a/crates/hir_ty/src/tests/display_source_code.rs +++ b/crates/hir_ty/src/tests/display_source_code.rs | |||
@@ -10,8 +10,8 @@ mod foo { | |||
10 | 10 | ||
11 | fn bar() { | 11 | fn bar() { |
12 | let foo: foo::Foo = foo::Foo; | 12 | let foo: foo::Foo = foo::Foo; |
13 | foo | 13 | foo; |
14 | } //^ foo::Foo | 14 | } //^^^ foo::Foo |
15 | 15 | ||
16 | "#, | 16 | "#, |
17 | ); | 17 | ); |
@@ -25,7 +25,7 @@ struct Foo<T = u8> { t: T } | |||
25 | fn main() { | 25 | fn main() { |
26 | let foo = Foo { t: 5u8 }; | 26 | let foo = Foo { t: 5u8 }; |
27 | foo; | 27 | foo; |
28 | } //^ Foo | 28 | } //^^^ Foo |
29 | "#, | 29 | "#, |
30 | ); | 30 | ); |
31 | 31 | ||
@@ -35,7 +35,7 @@ struct Foo<K, T = u8> { k: K, t: T } | |||
35 | fn main() { | 35 | fn main() { |
36 | let foo = Foo { k: 400, t: 5u8 }; | 36 | let foo = Foo { k: 400, t: 5u8 }; |
37 | foo; | 37 | foo; |
38 | } //^ Foo<i32> | 38 | } //^^^ Foo<i32> |
39 | "#, | 39 | "#, |
40 | ); | 40 | ); |
41 | } | 41 | } |
@@ -50,7 +50,7 @@ fn foo() -> *const (impl Unpin + Sized) { loop {} } | |||
50 | fn main() { | 50 | fn main() { |
51 | let foo = foo(); | 51 | let foo = foo(); |
52 | foo; | 52 | foo; |
53 | } //^ *const (impl Unpin + Sized) | 53 | } //^^^ *const (impl Unpin + Sized) |
54 | "#, | 54 | "#, |
55 | ); | 55 | ); |
56 | } | 56 | } |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index d14103aab..2cf41e49e 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -435,11 +435,11 @@ fn processes_impls_generated_by_macros() { | |||
435 | macro_rules! m { | 435 | macro_rules! m { |
436 | ($ident:ident) => (impl Trait for $ident {}) | 436 | ($ident:ident) => (impl Trait for $ident {}) |
437 | } | 437 | } |
438 | trait Trait { fn foo(self) -> u128 {} } | 438 | trait Trait { fn foo(self) -> u128 { 0 } } |
439 | struct S; | 439 | struct S; |
440 | m!(S); | 440 | m!(S); |
441 | fn test() { S.foo(); } | 441 | fn test() { S.foo(); } |
442 | //^ u128 | 442 | //^^^^^^^ u128 |
443 | "#, | 443 | "#, |
444 | ); | 444 | ); |
445 | } | 445 | } |
@@ -457,7 +457,7 @@ impl S { | |||
457 | } | 457 | } |
458 | 458 | ||
459 | fn test() { S.foo(); } | 459 | fn test() { S.foo(); } |
460 | //^ u128 | 460 | //^^^^^^^ u128 |
461 | "#, | 461 | "#, |
462 | ); | 462 | ); |
463 | } | 463 | } |
@@ -479,7 +479,7 @@ impl S { | |||
479 | } | 479 | } |
480 | 480 | ||
481 | fn test() { S.foo(); } | 481 | fn test() { S.foo(); } |
482 | //^ u128 | 482 | //^^^^^^^ u128 |
483 | "#, | 483 | "#, |
484 | ); | 484 | ); |
485 | } | 485 | } |
@@ -743,7 +743,7 @@ include!("foo.rs"); | |||
743 | 743 | ||
744 | fn main() { | 744 | fn main() { |
745 | bar(); | 745 | bar(); |
746 | } //^ u32 | 746 | } //^^^^^ u32 |
747 | 747 | ||
748 | //- /foo.rs | 748 | //- /foo.rs |
749 | fn bar() -> u32 {0} | 749 | fn bar() -> u32 {0} |
@@ -781,7 +781,7 @@ include!("f/foo.rs"); | |||
781 | 781 | ||
782 | fn main() { | 782 | fn main() { |
783 | bar::bar(); | 783 | bar::bar(); |
784 | } //^ u32 | 784 | } //^^^^^^^^^^ u32 |
785 | 785 | ||
786 | //- /f/foo.rs | 786 | //- /f/foo.rs |
787 | pub mod bar; | 787 | pub mod bar; |
@@ -853,7 +853,7 @@ include!("foo.rs"); | |||
853 | 853 | ||
854 | fn main() { | 854 | fn main() { |
855 | RegisterBlock { }; | 855 | RegisterBlock { }; |
856 | //^ RegisterBlock | 856 | //^^^^^^^^^^^^^^^^^ RegisterBlock |
857 | } | 857 | } |
858 | "#; | 858 | "#; |
859 | let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data); | 859 | let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data); |
@@ -879,7 +879,7 @@ include!(concat!("f", "oo.rs")); | |||
879 | 879 | ||
880 | fn main() { | 880 | fn main() { |
881 | bar(); | 881 | bar(); |
882 | } //^ u32 | 882 | } //^^^^^ u32 |
883 | 883 | ||
884 | //- /foo.rs | 884 | //- /foo.rs |
885 | fn bar() -> u32 {0} | 885 | fn bar() -> u32 {0} |
@@ -905,7 +905,7 @@ include!(concat!(env!("OUT_DIR"), "/foo.rs")); | |||
905 | 905 | ||
906 | fn main() { | 906 | fn main() { |
907 | bar(); | 907 | bar(); |
908 | } //^ {unknown} | 908 | } //^^^^^ {unknown} |
909 | 909 | ||
910 | //- /foo.rs | 910 | //- /foo.rs |
911 | fn bar() -> u32 {0} | 911 | fn bar() -> u32 {0} |
@@ -923,7 +923,7 @@ macro_rules! include {() => {}} | |||
923 | include!("main.rs"); | 923 | include!("main.rs"); |
924 | 924 | ||
925 | fn main() { | 925 | fn main() { |
926 | 0 | 926 | 0; |
927 | } //^ i32 | 927 | } //^ i32 |
928 | "#, | 928 | "#, |
929 | ); | 929 | ); |
@@ -979,7 +979,7 @@ fn infer_derive_clone_simple() { | |||
979 | struct S; | 979 | struct S; |
980 | fn test() { | 980 | fn test() { |
981 | S.clone(); | 981 | S.clone(); |
982 | } //^ S | 982 | } //^^^^^^^^^ S |
983 | 983 | ||
984 | //- /lib.rs crate:core | 984 | //- /lib.rs crate:core |
985 | pub mod prelude { | 985 | pub mod prelude { |
@@ -1028,7 +1028,7 @@ pub struct S; | |||
1028 | use core::S; | 1028 | use core::S; |
1029 | fn test() { | 1029 | fn test() { |
1030 | S.clone(); | 1030 | S.clone(); |
1031 | } //^ S | 1031 | } //^^^^^^^^^ S |
1032 | "#, | 1032 | "#, |
1033 | ); | 1033 | ); |
1034 | } | 1034 | } |
@@ -1044,7 +1044,8 @@ struct S; | |||
1044 | struct Wrapper<T>(T); | 1044 | struct Wrapper<T>(T); |
1045 | struct NonClone; | 1045 | struct NonClone; |
1046 | fn test() { | 1046 | fn test() { |
1047 | (Wrapper(S).clone(), Wrapper(NonClone).clone()); | 1047 | let x = (Wrapper(S).clone(), Wrapper(NonClone).clone()); |
1048 | x; | ||
1048 | //^ (Wrapper<S>, {unknown}) | 1049 | //^ (Wrapper<S>, {unknown}) |
1049 | } | 1050 | } |
1050 | 1051 | ||
@@ -1079,7 +1080,7 @@ struct S{} | |||
1079 | 1080 | ||
1080 | fn test() { | 1081 | fn test() { |
1081 | S{}; | 1082 | S{}; |
1082 | } //^ S | 1083 | } //^^^ S |
1083 | "#, | 1084 | "#, |
1084 | ); | 1085 | ); |
1085 | } | 1086 | } |
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index f26b2c8a7..3f7a37295 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -257,7 +257,7 @@ fn test() { | |||
257 | mod foo { | 257 | mod foo { |
258 | struct S; | 258 | struct S; |
259 | impl S { | 259 | impl S { |
260 | fn thing() -> i128 {} | 260 | fn thing() -> i128 { 0 } |
261 | } | 261 | } |
262 | } | 262 | } |
263 | "#, | 263 | "#, |
@@ -267,164 +267,128 @@ mod foo { | |||
267 | #[test] | 267 | #[test] |
268 | fn infer_trait_method_simple() { | 268 | fn infer_trait_method_simple() { |
269 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 269 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
270 | check_infer( | 270 | check_types( |
271 | r#" | 271 | r#" |
272 | trait Trait1 { | 272 | trait Trait1 { |
273 | fn method(&self) -> u32; | 273 | fn method(&self) -> u32; |
274 | } | 274 | } |
275 | struct S1; | 275 | struct S1; |
276 | impl Trait1 for S1 {} | 276 | impl Trait1 for S1 {} |
277 | trait Trait2 { | 277 | trait Trait2 { |
278 | fn method(&self) -> i128; | 278 | fn method(&self) -> i128; |
279 | } | 279 | } |
280 | struct S2; | 280 | struct S2; |
281 | impl Trait2 for S2 {} | 281 | impl Trait2 for S2 {} |
282 | fn test() { | 282 | fn test() { |
283 | S1.method(); // -> u32 | 283 | S1.method(); |
284 | S2.method(); // -> i128 | 284 | //^^^^^^^^^^^ u32 |
285 | } | 285 | S2.method(); // -> i128 |
286 | //^^^^^^^^^^^ i128 | ||
287 | } | ||
286 | "#, | 288 | "#, |
287 | expect![[r#" | ||
288 | 30..34 'self': &Self | ||
289 | 109..113 'self': &Self | ||
290 | 169..227 '{ ...i128 }': () | ||
291 | 175..177 'S1': S1 | ||
292 | 175..186 'S1.method()': u32 | ||
293 | 202..204 'S2': S2 | ||
294 | 202..213 'S2.method()': i128 | ||
295 | "#]], | ||
296 | ); | 289 | ); |
297 | } | 290 | } |
298 | 291 | ||
299 | #[test] | 292 | #[test] |
300 | fn infer_trait_method_scoped() { | 293 | fn infer_trait_method_scoped() { |
301 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 294 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
302 | check_infer( | 295 | check_types( |
303 | r#" | 296 | r#" |
304 | struct S; | 297 | struct S; |
305 | mod foo { | 298 | mod foo { |
306 | pub trait Trait1 { | 299 | pub trait Trait1 { |
307 | fn method(&self) -> u32; | 300 | fn method(&self) -> u32; |
308 | } | 301 | } |
309 | impl Trait1 for super::S {} | 302 | impl Trait1 for super::S {} |
310 | } | 303 | } |
311 | mod bar { | 304 | mod bar { |
312 | pub trait Trait2 { | 305 | pub trait Trait2 { |
313 | fn method(&self) -> i128; | 306 | fn method(&self) -> i128; |
314 | } | 307 | } |
315 | impl Trait2 for super::S {} | 308 | impl Trait2 for super::S {} |
316 | } | 309 | } |
317 | 310 | ||
318 | mod foo_test { | 311 | mod foo_test { |
319 | use super::S; | 312 | use super::S; |
320 | use super::foo::Trait1; | 313 | use super::foo::Trait1; |
321 | fn test() { | 314 | fn test() { |
322 | S.method(); // -> u32 | 315 | S.method(); |
323 | } | 316 | //^^^^^^^^^^ u32 |
324 | } | 317 | } |
318 | } | ||
325 | 319 | ||
326 | mod bar_test { | 320 | mod bar_test { |
327 | use super::S; | 321 | use super::S; |
328 | use super::bar::Trait2; | 322 | use super::bar::Trait2; |
329 | fn test() { | 323 | fn test() { |
330 | S.method(); // -> i128 | 324 | S.method(); |
331 | } | 325 | //^^^^^^^^^^ i128 |
332 | } | 326 | } |
327 | } | ||
333 | "#, | 328 | "#, |
334 | expect![[r#" | ||
335 | 62..66 'self': &Self | ||
336 | 168..172 'self': &Self | ||
337 | 299..336 '{ ... }': () | ||
338 | 309..310 'S': S | ||
339 | 309..319 'S.method()': u32 | ||
340 | 415..453 '{ ... }': () | ||
341 | 425..426 'S': S | ||
342 | 425..435 'S.method()': i128 | ||
343 | "#]], | ||
344 | ); | 329 | ); |
345 | } | 330 | } |
346 | 331 | ||
347 | #[test] | 332 | #[test] |
348 | fn infer_trait_method_generic_1() { | 333 | fn infer_trait_method_generic_1() { |
349 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 334 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
350 | check_infer( | 335 | check_types( |
351 | r#" | 336 | r#" |
352 | trait Trait<T> { | 337 | trait Trait<T> { |
353 | fn method(&self) -> T; | 338 | fn method(&self) -> T; |
354 | } | 339 | } |
355 | struct S; | 340 | struct S; |
356 | impl Trait<u32> for S {} | 341 | impl Trait<u32> for S {} |
357 | fn test() { | 342 | fn test() { |
358 | S.method(); | 343 | S.method(); |
359 | } | 344 | //^^^^^^^^^^ u32 |
345 | } | ||
360 | "#, | 346 | "#, |
361 | expect![[r#" | ||
362 | 32..36 'self': &Self | ||
363 | 91..110 '{ ...d(); }': () | ||
364 | 97..98 'S': S | ||
365 | 97..107 'S.method()': u32 | ||
366 | "#]], | ||
367 | ); | 347 | ); |
368 | } | 348 | } |
369 | 349 | ||
370 | #[test] | 350 | #[test] |
371 | fn infer_trait_method_generic_more_params() { | 351 | fn infer_trait_method_generic_more_params() { |
372 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 352 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
373 | check_infer( | 353 | check_types( |
374 | r#" | 354 | r#" |
375 | trait Trait<T1, T2, T3> { | 355 | trait Trait<T1, T2, T3> { |
376 | fn method1(&self) -> (T1, T2, T3); | 356 | fn method1(&self) -> (T1, T2, T3); |
377 | fn method2(&self) -> (T3, T2, T1); | 357 | fn method2(&self) -> (T3, T2, T1); |
378 | } | 358 | } |
379 | struct S1; | 359 | struct S1; |
380 | impl Trait<u8, u16, u32> for S1 {} | 360 | impl Trait<u8, u16, u32> for S1 {} |
381 | struct S2; | 361 | struct S2; |
382 | impl<T> Trait<i8, i16, T> for S2 {} | 362 | impl<T> Trait<i8, i16, T> for S2 {} |
383 | fn test() { | 363 | fn test() { |
384 | S1.method1(); // u8, u16, u32 | 364 | S1.method1(); |
385 | S1.method2(); // u32, u16, u8 | 365 | //^^^^^^^^^^^^ (u8, u16, u32) |
386 | S2.method1(); // i8, i16, {unknown} | 366 | S1.method2(); |
387 | S2.method2(); // {unknown}, i16, i8 | 367 | //^^^^^^^^^^^^ (u32, u16, u8) |
388 | } | 368 | S2.method1(); |
369 | //^^^^^^^^^^^^ (i8, i16, {unknown}) | ||
370 | S2.method2(); | ||
371 | //^^^^^^^^^^^^ ({unknown}, i16, i8) | ||
372 | } | ||
389 | "#, | 373 | "#, |
390 | expect![[r#" | ||
391 | 42..46 'self': &Self | ||
392 | 81..85 'self': &Self | ||
393 | 209..360 '{ ..., i8 }': () | ||
394 | 215..217 'S1': S1 | ||
395 | 215..227 'S1.method1()': (u8, u16, u32) | ||
396 | 249..251 'S1': S1 | ||
397 | 249..261 'S1.method2()': (u32, u16, u8) | ||
398 | 283..285 'S2': S2 | ||
399 | 283..295 'S2.method1()': (i8, i16, {unknown}) | ||
400 | 323..325 'S2': S2 | ||
401 | 323..335 'S2.method2()': ({unknown}, i16, i8) | ||
402 | "#]], | ||
403 | ); | 374 | ); |
404 | } | 375 | } |
405 | 376 | ||
406 | #[test] | 377 | #[test] |
407 | fn infer_trait_method_generic_2() { | 378 | fn infer_trait_method_generic_2() { |
408 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 379 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
409 | check_infer( | 380 | check_types( |
410 | r#" | 381 | r#" |
411 | trait Trait<T> { | 382 | trait Trait<T> { |
412 | fn method(&self) -> T; | 383 | fn method(&self) -> T; |
413 | } | 384 | } |
414 | struct S<T>(T); | 385 | struct S<T>(T); |
415 | impl<U> Trait<U> for S<U> {} | 386 | impl<U> Trait<U> for S<U> {} |
416 | fn test() { | 387 | fn test() { |
417 | S(1u32).method(); | 388 | S(1u32).method(); |
418 | } | 389 | //^^^^^^^^^^^^^^^^ u32 |
390 | } | ||
419 | "#, | 391 | "#, |
420 | expect![[r#" | ||
421 | 32..36 'self': &Self | ||
422 | 101..126 '{ ...d(); }': () | ||
423 | 107..108 'S': S<u32>(u32) -> S<u32> | ||
424 | 107..114 'S(1u32)': S<u32> | ||
425 | 107..123 'S(1u32...thod()': u32 | ||
426 | 109..113 '1u32': u32 | ||
427 | "#]], | ||
428 | ); | 392 | ); |
429 | } | 393 | } |
430 | 394 | ||
@@ -685,10 +649,10 @@ fn method_resolution_unify_impl_self_type() { | |||
685 | check_types( | 649 | check_types( |
686 | r#" | 650 | r#" |
687 | struct S<T>; | 651 | struct S<T>; |
688 | impl S<u32> { fn foo(&self) -> u8 {} } | 652 | impl S<u32> { fn foo(&self) -> u8 { 0 } } |
689 | impl S<i32> { fn foo(&self) -> i8 {} } | 653 | impl S<i32> { fn foo(&self) -> i8 { 0 } } |
690 | fn test() { (S::<u32>.foo(), S::<i32>.foo()); } | 654 | fn test() { (S::<u32>.foo(), S::<i32>.foo()); } |
691 | //^ (u8, i8) | 655 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (u8, i8) |
692 | "#, | 656 | "#, |
693 | ); | 657 | ); |
694 | } | 658 | } |
@@ -702,7 +666,7 @@ struct S; | |||
702 | impl S { fn foo(&self) -> i8 { 0 } } | 666 | impl S { fn foo(&self) -> i8 { 0 } } |
703 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 667 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
704 | fn test() { S.foo(); } | 668 | fn test() { S.foo(); } |
705 | //^ u128 | 669 | //^^^^^^^ u128 |
706 | "#, | 670 | "#, |
707 | ); | 671 | ); |
708 | } | 672 | } |
@@ -716,7 +680,7 @@ struct S; | |||
716 | impl Clone for S {} | 680 | impl Clone for S {} |
717 | impl Clone for &S {} | 681 | impl Clone for &S {} |
718 | fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } | 682 | fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } |
719 | //^ (S, S, &S) | 683 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (S, S, &S) |
720 | "#, | 684 | "#, |
721 | ); | 685 | ); |
722 | } | 686 | } |
@@ -730,7 +694,7 @@ struct S; | |||
730 | impl S { fn foo(self) -> i8 { 0 } } | 694 | impl S { fn foo(self) -> i8 { 0 } } |
731 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | 695 | impl Trait for &S { fn foo(self) -> u128 { 0 } } |
732 | fn test() { (&S).foo(); } | 696 | fn test() { (&S).foo(); } |
733 | //^ u128 | 697 | //^^^^^^^^^^ u128 |
734 | "#, | 698 | "#, |
735 | ); | 699 | ); |
736 | } | 700 | } |
@@ -744,7 +708,7 @@ struct S; | |||
744 | impl S { fn foo(self) -> i8 { 0 } } | 708 | impl S { fn foo(self) -> i8 { 0 } } |
745 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 709 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
746 | fn test() { S.foo(); } | 710 | fn test() { S.foo(); } |
747 | //^ i8 | 711 | //^^^^^^^ i8 |
748 | "#, | 712 | "#, |
749 | ); | 713 | ); |
750 | } | 714 | } |
@@ -758,7 +722,7 @@ struct S; | |||
758 | impl S { fn foo(&self) -> i8 { 0 } } | 722 | impl S { fn foo(&self) -> i8 { 0 } } |
759 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | 723 | impl Trait for &S { fn foo(self) -> u128 { 0 } } |
760 | fn test() { S.foo(); } | 724 | fn test() { S.foo(); } |
761 | //^ i8 | 725 | //^^^^^^^ i8 |
762 | "#, | 726 | "#, |
763 | ); | 727 | ); |
764 | } | 728 | } |
@@ -771,7 +735,7 @@ trait Trait { fn foo(self) -> u128; } | |||
771 | struct S; | 735 | struct S; |
772 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 736 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
773 | fn test() { (&S).foo(); } | 737 | fn test() { (&S).foo(); } |
774 | //^ u128 | 738 | //^^^^^^^^^^ u128 |
775 | "#, | 739 | "#, |
776 | ); | 740 | ); |
777 | } | 741 | } |
@@ -780,14 +744,11 @@ fn test() { (&S).foo(); } | |||
780 | fn method_resolution_unsize_array() { | 744 | fn method_resolution_unsize_array() { |
781 | check_types( | 745 | check_types( |
782 | r#" | 746 | r#" |
783 | #[lang = "slice"] | 747 | //- minicore: slice |
784 | impl<T> [T] { | ||
785 | fn len(&self) -> usize { loop {} } | ||
786 | } | ||
787 | fn test() { | 748 | fn test() { |
788 | let a = [1, 2, 3]; | 749 | let a = [1, 2, 3]; |
789 | a.len(); | 750 | a.len(); |
790 | } //^ usize | 751 | } //^^^^^^^ usize |
791 | "#, | 752 | "#, |
792 | ); | 753 | ); |
793 | } | 754 | } |
@@ -802,7 +763,7 @@ impl Clone for S {} | |||
802 | 763 | ||
803 | fn test() { | 764 | fn test() { |
804 | S.clone(); | 765 | S.clone(); |
805 | //^ S | 766 | //^^^^^^^^^ S |
806 | } | 767 | } |
807 | 768 | ||
808 | //- /lib.rs crate:core | 769 | //- /lib.rs crate:core |
@@ -826,7 +787,7 @@ trait Trait { fn foo(self) -> u128; } | |||
826 | struct S; | 787 | struct S; |
827 | impl<T> Trait for T where T: UnknownTrait {} | 788 | impl<T> Trait for T where T: UnknownTrait {} |
828 | fn test() { (&S).foo(); } | 789 | fn test() { (&S).foo(); } |
829 | //^ u128 | 790 | //^^^^^^^^^^ u128 |
830 | "#, | 791 | "#, |
831 | ); | 792 | ); |
832 | } | 793 | } |
@@ -844,7 +805,7 @@ trait Trait { fn foo(self) -> u128; } | |||
844 | struct S; | 805 | struct S; |
845 | impl<T> Trait for T where T: Clone {} | 806 | impl<T> Trait for T where T: Clone {} |
846 | fn test() { (&S).foo(); } | 807 | fn test() { (&S).foo(); } |
847 | //^ {unknown} | 808 | //^^^^^^^^^^ {unknown} |
848 | "#, | 809 | "#, |
849 | ); | 810 | ); |
850 | } | 811 | } |
@@ -859,7 +820,7 @@ trait Trait { fn foo(self) -> u128; } | |||
859 | struct S; | 820 | struct S; |
860 | impl<T: Clone> Trait for T {} | 821 | impl<T: Clone> Trait for T {} |
861 | fn test() { (&S).foo(); } | 822 | fn test() { (&S).foo(); } |
862 | //^ {unknown} | 823 | //^^^^^^^^^^ {unknown} |
863 | "#, | 824 | "#, |
864 | ); | 825 | ); |
865 | } | 826 | } |
@@ -874,7 +835,7 @@ struct S; | |||
874 | impl Clone for S {} | 835 | impl Clone for S {} |
875 | impl<T> Trait for T where T: Clone {} | 836 | impl<T> Trait for T where T: Clone {} |
876 | fn test() { S.foo(); } | 837 | fn test() { S.foo(); } |
877 | //^ u128 | 838 | //^^^^^^^ u128 |
878 | "#, | 839 | "#, |
879 | ); | 840 | ); |
880 | } | 841 | } |
@@ -890,7 +851,7 @@ struct S2; | |||
890 | impl From<S2> for S1 {} | 851 | impl From<S2> for S1 {} |
891 | impl<T, U> Into<U> for T where U: From<T> {} | 852 | impl<T, U> Into<U> for T where U: From<T> {} |
892 | fn test() { S2.into(); } | 853 | fn test() { S2.into(); } |
893 | //^ {unknown} | 854 | //^^^^^^^^^ {unknown} |
894 | "#, | 855 | "#, |
895 | ); | 856 | ); |
896 | } | 857 | } |
@@ -906,7 +867,7 @@ struct S2; | |||
906 | impl From<S2> for S1 {} | 867 | impl From<S2> for S1 {} |
907 | impl<T, U: From<T>> Into<U> for T {} | 868 | impl<T, U: From<T>> Into<U> for T {} |
908 | fn test() { S2.into(); } | 869 | fn test() { S2.into(); } |
909 | //^ {unknown} | 870 | //^^^^^^^^^ {unknown} |
910 | "#, | 871 | "#, |
911 | ); | 872 | ); |
912 | } | 873 | } |
@@ -936,7 +897,7 @@ fn main() { | |||
936 | let a = Wrapper::<Foo<f32>>::new(1.0); | 897 | let a = Wrapper::<Foo<f32>>::new(1.0); |
937 | let b = Wrapper::<Bar<f32>>::new(1.0); | 898 | let b = Wrapper::<Bar<f32>>::new(1.0); |
938 | (a, b); | 899 | (a, b); |
939 | //^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>) | 900 | //^^^^^^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>) |
940 | } | 901 | } |
941 | "#, | 902 | "#, |
942 | ); | 903 | ); |
@@ -950,7 +911,7 @@ fn method_resolution_encountering_fn_type() { | |||
950 | fn foo() {} | 911 | fn foo() {} |
951 | trait FnOnce { fn call(self); } | 912 | trait FnOnce { fn call(self); } |
952 | fn test() { foo.call(); } | 913 | fn test() { foo.call(); } |
953 | //^ {unknown} | 914 | //^^^^^^^^^^ {unknown} |
954 | "#, | 915 | "#, |
955 | ); | 916 | ); |
956 | } | 917 | } |
@@ -1016,7 +977,7 @@ where | |||
1016 | Wrapper<T>: a::Foo, | 977 | Wrapper<T>: a::Foo, |
1017 | { | 978 | { |
1018 | t.foo(); | 979 | t.foo(); |
1019 | } //^ {unknown} | 980 | } //^^^^^^^ {unknown} |
1020 | "#, | 981 | "#, |
1021 | ); | 982 | ); |
1022 | } | 983 | } |
@@ -1033,7 +994,7 @@ impl A<i32> { | |||
1033 | 994 | ||
1034 | fn main() { | 995 | fn main() { |
1035 | A::from(3); | 996 | A::from(3); |
1036 | } //^ A<i32> | 997 | } //^^^^^^^^^^ A<i32> |
1037 | "#, | 998 | "#, |
1038 | ); | 999 | ); |
1039 | } | 1000 | } |
@@ -1061,7 +1022,7 @@ trait FnX {} | |||
1061 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} | 1022 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} |
1062 | 1023 | ||
1063 | fn test() { (S {}).method(); } | 1024 | fn test() { (S {}).method(); } |
1064 | //^ () | 1025 | //^^^^^^^^^^^^^^^ () |
1065 | "#, | 1026 | "#, |
1066 | ); | 1027 | ); |
1067 | } | 1028 | } |
@@ -1146,8 +1107,8 @@ impl<T> Slice<T> { | |||
1146 | 1107 | ||
1147 | fn main() { | 1108 | fn main() { |
1148 | let foo: Slice<u32>; | 1109 | let foo: Slice<u32>; |
1149 | (foo.into_vec()); // we don't actually support arbitrary self types, but we shouldn't crash at least | 1110 | foo.into_vec(); // we shouldn't crash on this at least |
1150 | } //^ {unknown} | 1111 | } //^^^^^^^^^^^^^^ {unknown} |
1151 | "#, | 1112 | "#, |
1152 | ); | 1113 | ); |
1153 | } | 1114 | } |
@@ -1168,7 +1129,7 @@ impl dyn Foo + '_ { | |||
1168 | fn main() { | 1129 | fn main() { |
1169 | let f = &42u32 as &dyn Foo; | 1130 | let f = &42u32 as &dyn Foo; |
1170 | f.dyn_foo(); | 1131 | f.dyn_foo(); |
1171 | // ^u32 | 1132 | // ^^^^^^^^^^^ u32 |
1172 | } | 1133 | } |
1173 | "#, | 1134 | "#, |
1174 | ); | 1135 | ); |
@@ -1178,11 +1139,7 @@ fn main() { | |||
1178 | fn autoderef_visibility_field() { | 1139 | fn autoderef_visibility_field() { |
1179 | check_infer( | 1140 | check_infer( |
1180 | r#" | 1141 | r#" |
1181 | #[lang = "deref"] | 1142 | //- minicore: deref |
1182 | pub trait Deref { | ||
1183 | type Target; | ||
1184 | fn deref(&self) -> &Self::Target; | ||
1185 | } | ||
1186 | mod a { | 1143 | mod a { |
1187 | pub struct Foo(pub char); | 1144 | pub struct Foo(pub char); |
1188 | pub struct Bar(i32); | 1145 | pub struct Bar(i32); |
@@ -1191,7 +1148,7 @@ mod a { | |||
1191 | Self(0) | 1148 | Self(0) |
1192 | } | 1149 | } |
1193 | } | 1150 | } |
1194 | impl super::Deref for Bar { | 1151 | impl core::ops::Deref for Bar { |
1195 | type Target = Foo; | 1152 | type Target = Foo; |
1196 | fn deref(&self) -> &Foo { | 1153 | fn deref(&self) -> &Foo { |
1197 | &Foo('z') | 1154 | &Foo('z') |
@@ -1205,22 +1162,21 @@ mod b { | |||
1205 | } | 1162 | } |
1206 | "#, | 1163 | "#, |
1207 | expect![[r#" | 1164 | expect![[r#" |
1208 | 67..71 'self': &Self | 1165 | 107..138 '{ ... }': Bar |
1209 | 200..231 '{ ... }': Bar | 1166 | 121..125 'Self': Bar(i32) -> Bar |
1210 | 214..218 'Self': Bar(i32) -> Bar | 1167 | 121..128 'Self(0)': Bar |
1211 | 214..221 'Self(0)': Bar | 1168 | 126..127 '0': i32 |
1212 | 219..220 '0': i32 | 1169 | 226..230 'self': &Bar |
1213 | 315..319 'self': &Bar | 1170 | 240..273 '{ ... }': &Foo |
1214 | 329..362 '{ ... }': &Foo | 1171 | 254..263 '&Foo('z')': &Foo |
1215 | 343..352 '&Foo('z')': &Foo | 1172 | 255..258 'Foo': Foo(char) -> Foo |
1216 | 344..347 'Foo': Foo(char) -> Foo | 1173 | 255..263 'Foo('z')': Foo |
1217 | 344..352 'Foo('z')': Foo | 1174 | 259..262 ''z'': char |
1218 | 348..351 ''z'': char | 1175 | 303..350 '{ ... }': () |
1219 | 392..439 '{ ... }': () | 1176 | 317..318 'x': char |
1220 | 406..407 'x': char | 1177 | 321..339 'super:...r::new': fn new() -> Bar |
1221 | 410..428 'super:...r::new': fn new() -> Bar | 1178 | 321..341 'super:...:new()': Bar |
1222 | 410..430 'super:...:new()': Bar | 1179 | 321..343 'super:...ew().0': char |
1223 | 410..432 'super:...ew().0': char | ||
1224 | "#]], | 1180 | "#]], |