aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/Cargo.toml12
-rw-r--r--crates/ra_hir_ty/src/db.rs31
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs283
-rw-r--r--crates/ra_hir_ty/src/diagnostics/expr.rs (renamed from crates/ra_hir_ty/src/expr.rs)287
-rw-r--r--crates/ra_hir_ty/src/diagnostics/match_check.rs (renamed from crates/ra_hir_ty/src/_match.rs)1678
-rw-r--r--crates/ra_hir_ty/src/diagnostics/unsafe_check.rs (renamed from crates/ra_hir_ty/src/unsafe_validation.rs)77
-rw-r--r--crates/ra_hir_ty/src/display.rs47
-rw-r--r--crates/ra_hir_ty/src/infer.rs17
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs25
-rw-r--r--crates/ra_hir_ty/src/lib.rs85
-rw-r--r--crates/ra_hir_ty/src/lower.rs61
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs71
-rw-r--r--crates/ra_hir_ty/src/test_db.rs105
-rw-r--r--crates/ra_hir_ty/src/tests.rs436
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs1386
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs620
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs1150
-rw-r--r--crates/ra_hir_ty/src/tests/never_type.rs315
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs1102
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs1137
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs3398
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs3402
-rw-r--r--crates/ra_hir_ty/src/traits.rs64
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs371
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs182
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/interner.rs29
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs184
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs28
-rw-r--r--crates/ra_hir_ty/src/utils.rs32
29 files changed, 7927 insertions, 8688 deletions
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index d6df48db2..cdabb359f 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -3,6 +3,7 @@ edition = "2018"
3name = "ra_hir_ty" 3name = "ra_hir_ty"
4version = "0.1.0" 4version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6license = "MIT OR Apache-2.0"
6 7
7[lib] 8[lib]
8doctest = false 9doctest = false
@@ -27,8 +28,13 @@ test_utils = { path = "../test_utils" }
27 28
28scoped-tls = "1" 29scoped-tls = "1"
29 30
30chalk-solve = { version = "0.15.0" } 31chalk-solve = { version = "0.18.0" }
31chalk-ir = { version = "0.15.0" } 32chalk-ir = { version = "0.18.0" }
33chalk-recursive = { version = "0.18.0" }
32 34
33[dev-dependencies] 35[dev-dependencies]
34insta = "0.16.0" 36expect = { path = "../expect" }
37
38tracing = "0.1"
39tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] }
40tracing-tree = { version = "0.1.3" }
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index dc06c0ee7..c773adc67 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -3,8 +3,8 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TypeParamId, 6 db::DefDatabase, expr::ExprId, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId,
7 VariantId, 7 TypeParamId, VariantId,
8}; 8};
9use ra_arena::map::ArenaMap; 9use ra_arena::map::ArenaMap;
10use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; 10use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
@@ -12,14 +12,13 @@ use ra_prof::profile;
12 12
13use crate::{ 13use crate::{
14 method_resolution::{InherentImpls, TraitImpls}, 14 method_resolution::{InherentImpls, TraitImpls},
15 traits::{chalk, AssocTyValue, Impl}, 15 traits::chalk,
16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, 16 Binders, CallableDefId, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
17 ReturnTypeImplTraits, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, 17 ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId,
18}; 18};
19use hir_expand::name::Name; 19use hir_expand::name::Name;
20 20
21#[salsa::query_group(HirDatabaseStorage)] 21#[salsa::query_group(HirDatabaseStorage)]
22#[salsa::requires(salsa::Database)]
23pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { 22pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
24 #[salsa::invoke(infer_wait)] 23 #[salsa::invoke(infer_wait)]
25 #[salsa::transparent] 24 #[salsa::transparent]
@@ -46,7 +45,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
46 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>; 45 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>;
47 46
48 #[salsa::invoke(crate::callable_item_sig)] 47 #[salsa::invoke(crate::callable_item_sig)]
49 fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig; 48 fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig;
50 49
51 #[salsa::invoke(crate::lower::return_type_impl_traits)] 50 #[salsa::invoke(crate::lower::return_type_impl_traits)]
52 fn return_type_impl_traits( 51 fn return_type_impl_traits(
@@ -78,17 +77,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
78 77
79 // Interned IDs for Chalk integration 78 // Interned IDs for Chalk integration
80 #[salsa::interned] 79 #[salsa::interned]
81 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; 80 fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId;
82 #[salsa::interned]
83 fn intern_callable_def(&self, callable_def: CallableDef) -> crate::CallableDefId;
84 #[salsa::interned] 81 #[salsa::interned]
85 fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; 82 fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId;
86 #[salsa::interned] 83 #[salsa::interned]
87 fn intern_impl_trait_id(&self, id: OpaqueTyId) -> InternedOpaqueTyId; 84 fn intern_impl_trait_id(&self, id: OpaqueTyId) -> InternedOpaqueTyId;
88 #[salsa::interned] 85 #[salsa::interned]
89 fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; 86 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> ClosureId;
90 #[salsa::interned]
91 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
92 87
93 #[salsa::invoke(chalk::associated_ty_data_query)] 88 #[salsa::invoke(chalk::associated_ty_data_query)]
94 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>; 89 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>;
@@ -152,3 +147,13 @@ impl_intern_key!(GlobalTypeParamId);
152#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
153pub struct InternedOpaqueTyId(salsa::InternId); 148pub struct InternedOpaqueTyId(salsa::InternId);
154impl_intern_key!(InternedOpaqueTyId); 149impl_intern_key!(InternedOpaqueTyId);
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
152pub struct ClosureId(salsa::InternId);
153impl_intern_key!(ClosureId);
154
155/// This exists just for Chalk, because Chalk just has a single `FnDefId` where
156/// we have different IDs for struct and enum variant constructors.
157#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
158pub struct InternedCallableDefId(salsa::InternId);
159impl_intern_key!(InternedCallableDefId);
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 0289911de..d3ee9cf55 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -1,13 +1,30 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2mod expr;
3mod match_check;
4mod unsafe_check;
2 5
3use std::any::Any; 6use std::any::Any;
4 7
8use hir_def::DefWithBodyId;
9use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
5use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; 10use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
11use ra_prof::profile;
6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; 12use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
7use stdx::format_to; 13use stdx::format_to;
8 14
9pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm, path::Path}; 15use crate::db::HirDatabase;
10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 16
17pub use crate::diagnostics::expr::{record_literal_missing_fields, record_pattern_missing_fields};
18
19pub fn validate_body(db: &dyn HirDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) {
20 let _p = profile("validate_body");
21 let infer = db.infer(owner);
22 infer.add_diagnostics(db, owner, sink);
23 let mut validator = expr::ExprValidator::new(owner, infer.clone(), sink);
24 validator.validate_body(db);
25 let mut validator = unsafe_check::UnsafeValidator::new(owner, infer, sink);
26 validator.validate_body(db);
27}
11 28
12#[derive(Debug)] 29#[derive(Debug)]
13pub struct NoSuchField { 30pub struct NoSuchField {
@@ -197,3 +214,265 @@ impl AstDiagnostic for MissingUnsafe {
197 ast::Expr::cast(node).unwrap() 214 ast::Expr::cast(node).unwrap()
198 } 215 }
199} 216}
217
218#[derive(Debug)]
219pub struct MismatchedArgCount {
220 pub file: HirFileId,
221 pub call_expr: AstPtr<ast::Expr>,
222 pub expected: usize,
223 pub found: usize,
224}
225
226impl Diagnostic for MismatchedArgCount {
227 fn message(&self) -> String {
228 let s = if self.expected == 1 { "" } else { "s" };
229 format!("Expected {} argument{}, found {}", self.expected, s, self.found)
230 }
231 fn source(&self) -> InFile<SyntaxNodePtr> {
232 InFile { file_id: self.file, value: self.call_expr.clone().into() }
233 }
234 fn as_any(&self) -> &(dyn Any + Send + 'static) {
235 self
236 }
237}
238
239impl AstDiagnostic for MismatchedArgCount {
240 type AST = ast::CallExpr;
241 fn ast(&self, db: &dyn AstDatabase) -> Self::AST {
242 let root = db.parse_or_expand(self.source().file_id).unwrap();
243 let node = self.source().value.to_node(&root);
244 ast::CallExpr::cast(node).unwrap()
245 }
246}
247
248#[cfg(test)]
249mod tests {
250 use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId};
251 use hir_expand::diagnostics::{Diagnostic, DiagnosticSink};
252 use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt};
253 use ra_syntax::{TextRange, TextSize};
254 use rustc_hash::FxHashMap;
255
256 use crate::{diagnostics::validate_body, test_db::TestDB};
257
258 impl TestDB {
259 fn diagnostics<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) {
260 let crate_graph = self.crate_graph();
261 for krate in crate_graph.iter() {
262 let crate_def_map = self.crate_def_map(krate);
263
264 let mut fns = Vec::new();
265 for (module_id, _) in crate_def_map.modules.iter() {
266 for decl in crate_def_map[module_id].scope.declarations() {
267 if let ModuleDefId::FunctionId(f) = decl {
268 fns.push(f)
269 }
270 }
271
272 for impl_id in crate_def_map[module_id].scope.impls() {
273 let impl_data = self.impl_data(impl_id);
274 for item in impl_data.items.iter() {
275 if let AssocItemId::FunctionId(f) = item {
276 fns.push(*f)
277 }
278 }
279 }
280 }
281
282 for f in fns {
283 let mut sink = DiagnosticSink::new(&mut cb);
284 validate_body(self, f.into(), &mut sink);
285 }
286 }
287 }
288 }
289
290 pub(crate) fn check_diagnostics(ra_fixture: &str) {
291 let db = TestDB::with_files(ra_fixture);
292 let annotations = db.extract_annotations();
293
294 let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default();
295 db.diagnostics(|d| {
296 // FXIME: macros...
297 let file_id = d.source().file_id.original_file(&db);
298 let range = d.syntax_node(&db).text_range();
299 let message = d.message().to_owned();
300 actual.entry(file_id).or_default().push((range, message));
301 });
302
303 for (file_id, diags) in actual.iter_mut() {
304 diags.sort_by_key(|it| it.0.start());
305 let text = db.file_text(*file_id);
306 // For multiline spans, place them on line start
307 for (range, content) in diags {
308 if text[*range].contains('\n') {
309 *range = TextRange::new(range.start(), range.start() + TextSize::from(1));
310 *content = format!("... {}", content);
311 }
312 }
313 }
314
315 assert_eq!(annotations, actual);
316 }
317
318 #[test]
319 fn no_such_field_diagnostics() {
320 check_diagnostics(
321 r#"
322struct S { foo: i32, bar: () }
323impl S {
324 fn new() -> S {
325 S {
326 //^... Missing structure fields:
327 //| - bar
328 foo: 92,
329 baz: 62,
330 //^^^^^^^ no such field
331 }
332 }
333}
334"#,
335 );
336 }
337 #[test]
338 fn no_such_field_with_feature_flag_diagnostics() {
339 check_diagnostics(
340 r#"
341//- /lib.rs crate:foo cfg:feature=foo
342struct MyStruct {
343 my_val: usize,
344 #[cfg(feature = "foo")]
345 bar: bool,
346}
347
348impl MyStruct {
349 #[cfg(feature = "foo")]
350 pub(crate) fn new(my_val: usize, bar: bool) -> Self {
351 Self { my_val, bar }
352 }
353 #[cfg(not(feature = "foo"))]
354 pub(crate) fn new(my_val: usize, _bar: bool) -> Self {
355 Self { my_val }
356 }
357}
358"#,
359 );
360 }
361
362 #[test]
363 fn no_such_field_enum_with_feature_flag_diagnostics() {
364 check_diagnostics(
365 r#"
366//- /lib.rs crate:foo cfg:feature=foo
367enum Foo {
368 #[cfg(not(feature = "foo"))]
369 Buz,
370 #[cfg(feature = "foo")]
371 Bar,
372 Baz
373}
374
375fn test_fn(f: Foo) {
376 match f {
377 Foo::Bar => {},
378 Foo::Baz => {},
379 }
380}
381"#,
382 );
383 }
384
385 #[test]
386 fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() {
387 check_diagnostics(
388 r#"
389//- /lib.rs crate:foo cfg:feature=foo
390struct S {
391 #[cfg(feature = "foo")]
392 foo: u32,
393 #[cfg(not(feature = "foo"))]
394 bar: u32,
395}
396
397impl S {
398 #[cfg(feature = "foo")]
399 fn new(foo: u32) -> Self {
400 Self { foo }
401 }
402 #[cfg(not(feature = "foo"))]
403 fn new(bar: u32) -> Self {
404 Self { bar }
405 }
406 fn new2(bar: u32) -> Self {
407 #[cfg(feature = "foo")]
408 { Self { foo: bar } }
409 #[cfg(not(feature = "foo"))]
410 { Self { bar } }
411 }
412 fn new2(val: u32) -> Self {
413 Self {
414 #[cfg(feature = "foo")]
415 foo: val,
416 #[cfg(not(feature = "foo"))]
417 bar: val,
418 }
419 }
420}
421"#,
422 );
423 }
424
425 #[test]
426 fn no_such_field_with_type_macro() {
427 check_diagnostics(
428 r#"
429macro_rules! Type { () => { u32 }; }
430struct Foo { bar: Type![] }
431
432impl Foo {
433 fn new() -> Self {
434 Foo { bar: 0 }
435 }
436}
437"#,
438 );
439 }
440
441 #[test]
442 fn missing_record_pat_field_diagnostic() {
443 check_diagnostics(
444 r#"
445struct S { foo: i32, bar: () }
446fn baz(s: S) {
447 let S { foo: _ } = s;
448 //^^^^^^^^^^ Missing structure fields:
449 // | - bar
450}
451"#,
452 );
453 }
454
455 #[test]
456 fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
457 check_diagnostics(
458 r"
459struct S { foo: i32, bar: () }
460fn baz(s: S) -> i32 {
461 match s {
462 S { foo, .. } => foo,
463 }
464}
465",
466 )
467 }
468
469 #[test]
470 fn break_outside_of_loop() {
471 check_diagnostics(
472 r#"
473fn foo() { break; }
474 //^^^^^ break outside of loop
475"#,
476 );
477 }
478}
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs
index 7db928dde..fd930eab1 100644
--- a/crates/ra_hir_ty/src/expr.rs
+++ b/crates/ra_hir_ty/src/diagnostics/expr.rs
@@ -2,17 +2,19 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{path::path, resolver::HasResolver, AdtId, FunctionId}; 5use hir_def::{path::path, resolver::HasResolver, AdtId, DefWithBodyId};
6use hir_expand::diagnostics::DiagnosticSink; 6use hir_expand::diagnostics::DiagnosticSink;
7use ra_syntax::{ast, AstPtr}; 7use ra_syntax::{ast, AstPtr};
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
9 9
10use crate::{ 10use crate::{
11 db::HirDatabase, 11 db::HirDatabase,
12 diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields}, 12 diagnostics::{
13 match_check::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness},
14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields,
15 },
13 utils::variant_data, 16 utils::variant_data,
14 ApplicationTy, InferenceResult, Ty, TypeCtor, 17 ApplicationTy, InferenceResult, Ty, TypeCtor,
15 _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness},
16}; 18};
17 19
18pub use hir_def::{ 20pub use hir_def::{
@@ -24,26 +26,27 @@ pub use hir_def::{
24 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, 26 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
25 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp, 27 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
26 }, 28 },
27 LocalFieldId, VariantId, 29 src::HasSource,
30 LocalFieldId, Lookup, VariantId,
28}; 31};
29 32
30pub struct ExprValidator<'a, 'b: 'a> { 33pub(super) struct ExprValidator<'a, 'b: 'a> {
31 func: FunctionId, 34 owner: DefWithBodyId,
32 infer: Arc<InferenceResult>, 35 infer: Arc<InferenceResult>,
33 sink: &'a mut DiagnosticSink<'b>, 36 sink: &'a mut DiagnosticSink<'b>,
34} 37}
35 38
36impl<'a, 'b> ExprValidator<'a, 'b> { 39impl<'a, 'b> ExprValidator<'a, 'b> {
37 pub fn new( 40 pub(super) fn new(
38 func: FunctionId, 41 owner: DefWithBodyId,
39 infer: Arc<InferenceResult>, 42 infer: Arc<InferenceResult>,
40 sink: &'a mut DiagnosticSink<'b>, 43 sink: &'a mut DiagnosticSink<'b>,
41 ) -> ExprValidator<'a, 'b> { 44 ) -> ExprValidator<'a, 'b> {
42 ExprValidator { func, infer, sink } 45 ExprValidator { owner, infer, sink }
43 } 46 }
44 47
45 pub fn validate_body(&mut self, db: &dyn HirDatabase) { 48 pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
46 let body = db.body(self.func.into()); 49 let body = db.body(self.owner.into());
47 50
48 for (id, expr) in body.exprs.iter() { 51 for (id, expr) in body.exprs.iter() {
49 if let Some((variant_def, missed_fields, true)) = 52 if let Some((variant_def, missed_fields, true)) =
@@ -56,8 +59,15 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
56 missed_fields, 59 missed_fields,
57 ); 60 );
58 } 61 }
59 if let Expr::Match { expr, arms } = expr { 62
60 self.validate_match(id, *expr, arms, db, self.infer.clone()); 63 match expr {
64 Expr::Match { expr, arms } => {
65 self.validate_match(id, *expr, arms, db, self.infer.clone());
66 }
67 Expr::Call { .. } | Expr::MethodCall { .. } => {
68 self.validate_call(db, id, expr);
69 }
70 _ => {}
61 } 71 }
62 } 72 }
63 for (id, pat) in body.pats.iter() { 73 for (id, pat) in body.pats.iter() {
@@ -86,7 +96,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
86 missed_fields: Vec<LocalFieldId>, 96 missed_fields: Vec<LocalFieldId>,
87 ) { 97 ) {
88 // XXX: only look at source_map if we do have missing fields 98 // XXX: only look at source_map if we do have missing fields
89 let (_, source_map) = db.body_with_source_map(self.func.into()); 99 let (_, source_map) = db.body_with_source_map(self.owner.into());
90 100
91 if let Ok(source_ptr) = source_map.expr_syntax(id) { 101 if let Ok(source_ptr) = source_map.expr_syntax(id) {
92 let root = source_ptr.file_syntax(db.upcast()); 102 let root = source_ptr.file_syntax(db.upcast());
@@ -115,7 +125,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
115 missed_fields: Vec<LocalFieldId>, 125 missed_fields: Vec<LocalFieldId>,
116 ) { 126 ) {
117 // XXX: only look at source_map if we do have missing fields 127 // XXX: only look at source_map if we do have missing fields
118 let (_, source_map) = db.body_with_source_map(self.func.into()); 128 let (_, source_map) = db.body_with_source_map(self.owner.into());
119 129
120 if let Ok(source_ptr) = source_map.pat_syntax(id) { 130 if let Ok(source_ptr) = source_map.pat_syntax(id) {
121 if let Some(expr) = source_ptr.value.as_ref().left() { 131 if let Some(expr) = source_ptr.value.as_ref().left() {
@@ -138,6 +148,65 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
138 } 148 }
139 } 149 }
140 150
151 fn validate_call(&mut self, db: &dyn HirDatabase, call_id: ExprId, expr: &Expr) -> Option<()> {
152 // Check that the number of arguments matches the number of parameters.
153
154 // FIXME: Due to shortcomings in the current type system implementation, only emit this
155 // diagnostic if there are no type mismatches in the containing function.
156 if self.infer.type_mismatches.iter().next().is_some() {
157 return Some(());
158 }
159
160 let is_method_call = matches!(expr, Expr::MethodCall { .. });
161 let (sig, args) = match expr {
162 Expr::Call { callee, args } => {
163 let callee = &self.infer.type_of_expr[*callee];
164 let sig = callee.callable_sig(db)?;
165 (sig, args.clone())
166 }
167 Expr::MethodCall { receiver, args, .. } => {
168 let mut args = args.clone();
169 args.insert(0, *receiver);
170
171 // FIXME: note that we erase information about substs here. This
172 // is not right, but, luckily, doesn't matter as we care only
173 // about the number of params
174 let callee = self.infer.method_resolution(call_id)?;
175 let sig = db.callable_item_signature(callee.into()).value;
176
177 (sig, args)
178 }
179 _ => return None,
180 };
181
182 if sig.is_varargs {
183 return None;
184 }
185
186 let params = sig.params();
187
188 let mut param_count = params.len();
189 let mut arg_count = args.len();
190
191 if arg_count != param_count {
192 let (_, source_map) = db.body_with_source_map(self.owner.into());
193 if let Ok(source_ptr) = source_map.expr_syntax(call_id) {
194 if is_method_call {
195 param_count -= 1;
196 arg_count -= 1;
197 }
198 self.sink.push(MismatchedArgCount {
199 file: source_ptr.file_id,
200 call_expr: source_ptr.value,
201 expected: param_count,
202 found: arg_count,
203 });
204 }
205 }
206
207 None
208 }
209
141 fn validate_match( 210 fn validate_match(
142 &mut self, 211 &mut self,
143 id: ExprId, 212 id: ExprId,
@@ -147,7 +216,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
147 infer: Arc<InferenceResult>, 216 infer: Arc<InferenceResult>,
148 ) { 217 ) {
149 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) = 218 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
150 db.body_with_source_map(self.func.into()); 219 db.body_with_source_map(self.owner.into());
151 220
152 let match_expr_ty = match infer.type_of_expr.get(match_expr) { 221 let match_expr_ty = match infer.type_of_expr.get(match_expr) {
153 Some(ty) => ty, 222 Some(ty) => ty,
@@ -228,7 +297,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
228 297
229 let core_result_path = path![core::result::Result]; 298 let core_result_path = path![core::result::Result];
230 299
231 let resolver = self.func.resolver(db.upcast()); 300 let resolver = self.owner.resolver(db.upcast());
232 let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) { 301 let core_result_enum = match resolver.resolve_known_enum(db.upcast(), &core_result_path) {
233 Some(it) => it, 302 Some(it) => it,
234 _ => return, 303 _ => return,
@@ -243,7 +312,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
243 }; 312 };
244 313
245 if params.len() == 2 && params[0] == mismatch.actual { 314 if params.len() == 2 && params[0] == mismatch.actual {
246 let (_, source_map) = db.body_with_source_map(self.func.into()); 315 let (_, source_map) = db.body_with_source_map(self.owner.into());
247 316
248 if let Ok(source_ptr) = source_map.expr_syntax(id) { 317 if let Ok(source_ptr) = source_map.expr_syntax(id) {
249 self.sink 318 self.sink
@@ -312,3 +381,185 @@ pub fn record_pattern_missing_fields(
312 } 381 }
313 Some((variant_def, missed_fields, exhaustive)) 382 Some((variant_def, missed_fields, exhaustive))
314} 383}
384
385#[cfg(test)]
386mod tests {
387 use crate::diagnostics::tests::check_diagnostics;
388
389 #[test]
390 fn simple_free_fn_zero() {
391 check_diagnostics(
392 r#"
393fn zero() {}
394fn f() { zero(1); }
395 //^^^^^^^ Expected 0 arguments, found 1
396"#,
397 );
398
399 check_diagnostics(
400 r#"
401fn zero() {}
402fn f() { zero(); }
403"#,
404 );
405 }
406
407 #[test]
408 fn simple_free_fn_one() {
409 check_diagnostics(
410 r#"
411fn one(arg: u8) {}
412fn f() { one(); }
413 //^^^^^ Expected 1 argument, found 0
414"#,
415 );
416
417 check_diagnostics(
418 r#"
419fn one(arg: u8) {}
420fn f() { one(1); }
421"#,
422 );
423 }
424
425 #[test]
426 fn method_as_fn() {
427 check_diagnostics(
428 r#"
429struct S;
430impl S { fn method(&self) {} }
431
432fn f() {
433 S::method();
434} //^^^^^^^^^^^ Expected 1 argument, found 0
435"#,
436 );
437
438 check_diagnostics(
439 r#"
440struct S;
441impl S { fn method(&self) {} }
442
443fn f() {
444 S::method(&S);
445 S.method();
446}
447"#,
448 );
449 }
450
451 #[test]
452 fn method_with_arg() {
453 check_diagnostics(
454 r#"
455struct S;
456impl S { fn method(&self, arg: u8) {} }
457
458 fn f() {
459 S.method();
460 } //^^^^^^^^^^ Expected 1 argument, found 0
461 "#,
462 );
463
464 check_diagnostics(
465 r#"
466struct S;
467impl S { fn method(&self, arg: u8) {} }
468
469fn f() {
470 S::method(&S, 0);
471 S.method(1);
472}
473"#,
474 );
475 }
476
477 #[test]
478 fn tuple_struct() {
479 check_diagnostics(
480 r#"
481struct Tup(u8, u16);
482fn f() {
483 Tup(0);
484} //^^^^^^ Expected 2 arguments, found 1
485"#,
486 )
487 }
488
489 #[test]
490 fn enum_variant() {
491 check_diagnostics(
492 r#"
493enum En { Variant(u8, u16), }
494fn f() {
495 En::Variant(0);
496} //^^^^^^^^^^^^^^ Expected 2 arguments, found 1
497"#,
498 )
499 }
500
501 #[test]
502 fn enum_variant_type_macro() {
503 check_diagnostics(
504 r#"
505macro_rules! Type {
506 () => { u32 };
507}
508enum Foo {
509 Bar(Type![])
510}
511impl Foo {
512 fn new() {
513 Foo::Bar(0);
514 Foo::Bar(0, 1);
515 //^^^^^^^^^^^^^^ Expected 1 argument, found 2
516 Foo::Bar();
517 //^^^^^^^^^^ Expected 1 argument, found 0
518 }
519}
520 "#,
521 );
522 }
523
524 #[test]
525 fn varargs() {
526 check_diagnostics(
527 r#"
528extern "C" {
529 fn fixed(fixed: u8);
530 fn varargs(fixed: u8, ...);
531 fn varargs2(...);
532}
533
534fn f() {
535 unsafe {
536 fixed(0);
537 fixed(0, 1);
538 //^^^^^^^^^^^ Expected 1 argument, found 2
539 varargs(0);
540 varargs(0, 1);
541 varargs2();
542 varargs2(0);
543 varargs2(0, 1);
544 }
545}
546 "#,
547 )
548 }
549
550 #[test]
551 fn arg_count_lambda() {
552 check_diagnostics(
553 r#"
554fn main() {
555 let f = |()| ();
556 f();
557 //^^^ Expected 1 argument, found 0
558 f(());
559 f((), ());
560 //^^^^^^^^^ Expected 1 argument, found 2
561}
562"#,
563 )
564 }
565}
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/diagnostics/match_check.rs
index 5495ce284..507edcb7d 100644
--- a/crates/ra_hir_ty/src/_match.rs
+++ b/crates/ra_hir_ty/src/diagnostics/match_check.rs
@@ -41,9 +41,9 @@
41//! ```ignore 41//! ```ignore
42//! // x: (Option<bool>, Result<()>) 42//! // x: (Option<bool>, Result<()>)
43//! match x { 43//! match x {
44//! (Some(true), _) => {} 44//! (Some(true), _) => (),
45//! (None, Err(())) => {} 45//! (None, Err(())) => (),
46//! (None, Err(_)) => {} 46//! (None, Err(_)) => (),
47//! } 47//! }
48//! ``` 48//! ```
49//! 49//!
@@ -218,15 +218,16 @@
218//! ``` 218//! ```
219use std::sync::Arc; 219use std::sync::Arc;
220 220
221use smallvec::{smallvec, SmallVec}; 221use hir_def::{
222 222 adt::VariantData,
223use crate::{ 223 body::Body,
224 db::HirDatabase, 224 expr::{Expr, Literal, Pat, PatId},
225 expr::{Body, Expr, Literal, Pat, PatId}, 225 AdtId, EnumVariantId, VariantId,
226 ApplicationTy, InferenceResult, Ty, TypeCtor,
227}; 226};
228use hir_def::{adt::VariantData, AdtId, EnumVariantId, VariantId};
229use ra_arena::Idx; 227use ra_arena::Idx;
228use smallvec::{smallvec, SmallVec};
229
230use crate::{db::HirDatabase, ApplicationTy, InferenceResult, Ty, TypeCtor};
230 231
231#[derive(Debug, Clone, Copy)] 232#[derive(Debug, Clone, Copy)]
232/// Either a pattern from the source code being analyzed, represented as 233/// Either a pattern from the source code being analyzed, represented as
@@ -271,7 +272,7 @@ impl From<&PatId> for PatIdOrWild {
271} 272}
272 273
273#[derive(Debug, Clone, Copy, PartialEq)] 274#[derive(Debug, Clone, Copy, PartialEq)]
274pub enum MatchCheckErr { 275pub(super) enum MatchCheckErr {
275 NotImplemented, 276 NotImplemented,
276 MalformedMatchArm, 277 MalformedMatchArm,
277 /// Used when type inference cannot resolve the type of 278 /// Used when type inference cannot resolve the type of
@@ -286,21 +287,21 @@ pub enum MatchCheckErr {
286/// 287///
287/// The `std::result::Result` type is used here rather than a custom enum 288/// The `std::result::Result` type is used here rather than a custom enum
288/// to allow the use of `?`. 289/// to allow the use of `?`.
289pub type MatchCheckResult<T> = Result<T, MatchCheckErr>; 290pub(super) type MatchCheckResult<T> = Result<T, MatchCheckErr>;
290 291
291#[derive(Debug)] 292#[derive(Debug)]
292/// A row in a Matrix. 293/// A row in a Matrix.
293/// 294///
294/// This type is modeled from the struct of the same name in `rustc`. 295/// This type is modeled from the struct of the same name in `rustc`.
295pub(crate) struct PatStack(PatStackInner); 296pub(super) struct PatStack(PatStackInner);
296type PatStackInner = SmallVec<[PatIdOrWild; 2]>; 297type PatStackInner = SmallVec<[PatIdOrWild; 2]>;
297 298
298impl PatStack { 299impl PatStack {
299 pub(crate) fn from_pattern(pat_id: PatId) -> PatStack { 300 pub(super) fn from_pattern(pat_id: PatId) -> PatStack {
300 Self(smallvec!(pat_id.into())) 301 Self(smallvec!(pat_id.into()))
301 } 302 }
302 303
303 pub(crate) fn from_wild() -> PatStack { 304 pub(super) fn from_wild() -> PatStack {
304 Self(smallvec!(PatIdOrWild::Wild)) 305 Self(smallvec!(PatIdOrWild::Wild))
305 } 306 }
306 307
@@ -509,14 +510,14 @@ impl PatStack {
509/// A collection of PatStack. 510/// A collection of PatStack.
510/// 511///
511/// This type is modeled from the struct of the same name in `rustc`. 512/// This type is modeled from the struct of the same name in `rustc`.
512pub(crate) struct Matrix(Vec<PatStack>); 513pub(super) struct Matrix(Vec<PatStack>);
513 514
514impl Matrix { 515impl Matrix {
515 pub(crate) fn empty() -> Self { 516 pub(super) fn empty() -> Self {
516 Self(vec![]) 517 Self(vec![])
517 } 518 }
518 519
519 pub(crate) fn push(&mut self, cx: &MatchCheckCtx, row: PatStack) { 520 pub(super) fn push(&mut self, cx: &MatchCheckCtx, row: PatStack) {
520 if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) { 521 if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) {
521 // Or patterns are expanded here 522 // Or patterns are expanded here
522 for pat_id in pat_ids { 523 for pat_id in pat_ids {
@@ -578,16 +579,16 @@ impl Matrix {
578/// not matched by an prior match arms. 579/// not matched by an prior match arms.
579/// 580///
580/// We may eventually need an `Unknown` variant here. 581/// We may eventually need an `Unknown` variant here.
581pub enum Usefulness { 582pub(super) enum Usefulness {
582 Useful, 583 Useful,
583 NotUseful, 584 NotUseful,
584} 585}
585 586
586pub struct MatchCheckCtx<'a> { 587pub(super) struct MatchCheckCtx<'a> {
587 pub match_expr: Idx<Expr>, 588 pub(super) match_expr: Idx<Expr>,
588 pub body: Arc<Body>, 589 pub(super) body: Arc<Body>,
589 pub infer: Arc<InferenceResult>, 590 pub(super) infer: Arc<InferenceResult>,
590 pub db: &'a dyn HirDatabase, 591 pub(super) db: &'a dyn HirDatabase,
591} 592}
592 593
593/// Given a set of patterns `matrix`, and pattern to consider `v`, determines 594/// Given a set of patterns `matrix`, and pattern to consider `v`, determines
@@ -598,7 +599,7 @@ pub struct MatchCheckCtx<'a> {
598/// expected that you have already type checked the match arms. All patterns in 599/// expected that you have already type checked the match arms. All patterns in
599/// matrix should be the same type as v, as well as they should all be the same 600/// matrix should be the same type as v, as well as they should all be the same
600/// type as the match expression. 601/// type as the match expression.
601pub(crate) fn is_useful( 602pub(super) fn is_useful(
602 cx: &MatchCheckCtx, 603 cx: &MatchCheckCtx,
603 matrix: &Matrix, 604 matrix: &Matrix,
604 v: &PatStack, 605 v: &PatStack,
@@ -836,685 +837,251 @@ fn enum_variant_matches(cx: &MatchCheckCtx, pat_id: PatId, enum_variant_id: Enum
836 837
837#[cfg(test)] 838#[cfg(test)]
838mod tests { 839mod tests {
839 pub(super) use insta::assert_snapshot; 840 use crate::diagnostics::tests::check_diagnostics;
840 pub(super) use ra_db::fixture::WithFixture;
841
842 pub(super) use crate::{diagnostics::MissingMatchArms, test_db::TestDB};
843
844 pub(super) fn check_diagnostic_message(ra_fixture: &str) -> String {
845 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().0
846 }
847
848 pub(super) fn check_diagnostic(ra_fixture: &str) {
849 let diagnostic_count =
850 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>().1;
851
852 assert_eq!(1, diagnostic_count, "no diagnostic reported");
853 }
854
855 pub(super) fn check_no_diagnostic(ra_fixture: &str) {
856 let (s, diagnostic_count) =
857 TestDB::with_single_file(ra_fixture).0.diagnostic::<MissingMatchArms>();
858
859 assert_eq!(0, diagnostic_count, "expected no diagnostic, found one: {}", s);
860 }
861
862 #[test]
863 fn empty_tuple_no_arms_diagnostic_message() {
864 assert_snapshot!(
865 check_diagnostic_message(r"
866 fn test_fn() {
867 match () {
868 }
869 }
870 "),
871 @"\"()\": Missing match arm\n"
872 );
873 }
874
875 #[test]
876 fn empty_tuple_no_arms() {
877 check_diagnostic(
878 r"
879 fn test_fn() {
880 match () {
881 }
882 }
883 ",
884 );
885 }
886
887 #[test]
888 fn empty_tuple_wild() {
889 check_no_diagnostic(
890 r"
891 fn test_fn() {
892 match () {
893 _ => {}
894 }
895 }
896 ",
897 );
898 }
899
900 #[test]
901 fn empty_tuple_no_diagnostic() {
902 check_no_diagnostic(
903 r"
904 fn test_fn() {
905 match () {
906 () => {}
907 }
908 }
909 ",
910 );
911 }
912
913 #[test]
914 fn tuple_of_empty_tuple_no_arms() {
915 check_diagnostic(
916 r"
917 fn test_fn() {
918 match (()) {
919 }
920 }
921 ",
922 );
923 }
924
925 #[test]
926 fn tuple_of_empty_tuple_no_diagnostic() {
927 check_no_diagnostic(
928 r"
929 fn test_fn() {
930 match (()) {
931 (()) => {}
932 }
933 }
934 ",
935 );
936 }
937 841
938 #[test] 842 #[test]
939 fn tuple_of_two_empty_tuple_no_arms() { 843 fn empty_tuple() {
940 check_diagnostic( 844 check_diagnostics(
941 r" 845 r#"
942 fn test_fn() { 846fn main() {
943 match ((), ()) { 847 match () { }
944 } 848 //^^ Missing match arm
945 } 849 match (()) { }
946 ", 850 //^^^^ Missing match arm
947 );
948 }
949 851
950 #[test] 852 match () { _ => (), }
951 fn tuple_of_two_empty_tuple_no_diagnostic() { 853 match () { () => (), }
952 check_no_diagnostic( 854 match (()) { (()) => (), }
953 r" 855}
954 fn test_fn() { 856"#,
955 match ((), ()) {
956 ((), ()) => {}
957 }
958 }
959 ",
960 );
961 }
962
963 #[test]
964 fn bool_no_arms() {
965 check_diagnostic(
966 r"
967 fn test_fn() {
968 match false {
969 }
970 }
971 ",
972 );
973 }
974
975 #[test]
976 fn bool_missing_arm() {
977 check_diagnostic(
978 r"
979 fn test_fn() {
980 match false {
981 true => {}
982 }
983 }
984 ",
985 );
986 }
987
988 #[test]
989 fn bool_no_diagnostic() {
990 check_no_diagnostic(
991 r"
992 fn test_fn() {
993 match false {
994 true => {}
995 false => {}
996 }
997 }
998 ",
999 );
1000 }
1001
1002 #[test]
1003 fn tuple_of_bools_no_arms() {
1004 check_diagnostic(
1005 r"
1006 fn test_fn() {
1007 match (false, true) {
1008 }
1009 }
1010 ",
1011 );
1012 }
1013
1014 #[test]
1015 fn tuple_of_bools_missing_arms() {
1016 check_diagnostic(
1017 r"
1018 fn test_fn() {
1019 match (false, true) {
1020 (true, true) => {},
1021 }
1022 }
1023 ",
1024 );
1025 }
1026
1027 #[test]
1028 fn tuple_of_bools_missing_arm() {
1029 check_diagnostic(
1030 r"
1031 fn test_fn() {
1032 match (false, true) {
1033 (false, true) => {},
1034 (false, false) => {},
1035 (true, false) => {},
1036 }
1037 }
1038 ",
1039 );
1040 }
1041
1042 #[test]
1043 fn tuple_of_bools_with_wilds() {
1044 check_no_diagnostic(
1045 r"
1046 fn test_fn() {
1047 match (false, true) {
1048 (false, _) => {},
1049 (true, false) => {},
1050 (_, true) => {},
1051 }
1052 }
1053 ",
1054 ); 857 );
1055 } 858 }
1056 859
1057 #[test] 860 #[test]
1058 fn tuple_of_bools_no_diagnostic() { 861 fn tuple_of_two_empty_tuple() {
1059 check_no_diagnostic( 862 check_diagnostics(
1060 r" 863 r#"
1061 fn test_fn() { 864fn main() {
1062 match (false, true) { 865 match ((), ()) { }
1063 (true, true) => {}, 866 //^^^^^^^^ Missing match arm
1064 (true, false) => {},
1065 (false, true) => {},
1066 (false, false) => {},
1067 }
1068 }
1069 ",
1070 );
1071 }
1072 867
1073 #[test] 868 match ((), ()) { ((), ()) => (), }
1074 fn tuple_of_bools_binding_missing_arms() { 869}
1075 check_diagnostic( 870"#,
1076 r" 871 );
1077 fn test_fn() { 872 }
1078 match (false, true) { 873
1079 (true, _x) => {}, 874 #[test]
1080 } 875 fn boolean() {
1081 } 876 check_diagnostics(
1082 ", 877 r#"
1083 ); 878fn test_main() {
1084 } 879 match false { }
1085 880 //^^^^^ Missing match arm
1086 #[test] 881 match false { true => (), }
1087 fn tuple_of_bools_binding_no_diagnostic() { 882 //^^^^^ Missing match arm
1088 check_no_diagnostic( 883 match (false, true) {}
1089 r" 884 //^^^^^^^^^^^^^ Missing match arm
1090 fn test_fn() { 885 match (false, true) { (true, true) => (), }
1091 match (false, true) { 886 //^^^^^^^^^^^^^ Missing match arm
1092 (true, _x) => {}, 887 match (false, true) {
1093 (false, true) => {}, 888 //^^^^^^^^^^^^^ Missing match arm
1094 (false, false) => {}, 889 (false, true) => (),
1095 } 890 (false, false) => (),
1096 } 891 (true, false) => (),
1097 ", 892 }
893 match (false, true) { (true, _x) => (), }
894 //^^^^^^^^^^^^^ Missing match arm
895
896 match false { true => (), false => (), }
897 match (false, true) {
898 (false, _) => (),
899 (true, false) => (),
900 (_, true) => (),
901 }
902 match (false, true) {
903 (true, true) => (),
904 (true, false) => (),
905 (false, true) => (),
906 (false, false) => (),
907 }
908 match (false, true) {
909 (true, _x) => (),
910 (false, true) => (),
911 (false, false) => (),
912 }
913 match (false, true, false) {
914 (false, ..) => (),
915 (true, ..) => (),
916 }
917 match (false, true, false) {
918 (.., false) => (),
919 (.., true) => (),
920 }
921 match (false, true, false) { (..) => (), }
922}
923"#,
1098 ); 924 );
1099 } 925 }
1100 926
1101 #[test] 927 #[test]
1102 fn tuple_of_bools_with_ellipsis_at_end_no_diagnostic() { 928 fn tuple_of_tuple_and_bools() {
1103 check_no_diagnostic( 929 check_diagnostics(
1104 r" 930 r#"
1105 fn test_fn() { 931fn main() {
1106 match (false, true, false) { 932 match (false, ((), false)) {}
1107 (false, ..) => {}, 933 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1108 (true, ..) => {}, 934 match (false, ((), false)) { (true, ((), true)) => (), }
1109 } 935 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1110 } 936 match (false, ((), false)) { (true, _) => (), }
1111 ", 937 //^^^^^^^^^^^^^^^^^^^^ Missing match arm
1112 );
1113 }
1114 938
1115 #[test] 939 match (false, ((), false)) {
1116 fn tuple_of_bools_with_ellipsis_at_beginning_no_diagnostic() { 940 (true, ((), true)) => (),
1117 check_no_diagnostic( 941 (true, ((), false)) => (),
1118 r" 942 (false, ((), true)) => (),
1119 fn test_fn() { 943 (false, ((), false)) => (),
1120 match (false, true, false) {
1121 (.., false) => {},
1122 (.., true) => {},
1123 }
1124 }
1125 ",
1126 );
1127 } 944 }
1128 945 match (false, ((), false)) {
1129 #[test] 946 (true, ((), true)) => (),
1130 fn tuple_of_bools_with_ellipsis_no_diagnostic() { 947 (true, ((), false)) => (),
1131 check_no_diagnostic( 948 (false, _) => (),
1132 r"
1133 fn test_fn() {
1134 match (false, true, false) {
1135 (..) => {},
1136 }
1137 }
1138 ",
1139 );
1140 } 949 }
1141 950}
1142 #[test] 951"#,
1143 fn tuple_of_tuple_and_bools_no_arms() {
1144 check_diagnostic(
1145 r"
1146 fn test_fn() {
1147 match (false, ((), false)) {
1148 }
1149 }
1150 ",
1151 ); 952 );
1152 } 953 }
1153 954
1154 #[test] 955 #[test]
1155 fn tuple_of_tuple_and_bools_missing_arms() { 956 fn enums() {
1156 check_diagnostic( 957 check_diagnostics(
1157 r" 958 r#"
1158 fn test_fn() { 959enum Either { A, B, }
1159 match (false, ((), false)) {
1160 (true, ((), true)) => {},
1161 }
1162 }
1163 ",
1164 );
1165 }
1166 960
1167 #[test] 961fn main() {
1168 fn tuple_of_tuple_and_bools_no_diagnostic() { 962 match Either::A { }
1169 check_no_diagnostic( 963 //^^^^^^^^^ Missing match arm
1170 r" 964 match Either::B { Either::A => (), }
1171 fn test_fn() { 965 //^^^^^^^^^ Missing match arm
1172 match (false, ((), false)) {
1173 (true, ((), true)) => {},
1174 (true, ((), false)) => {},
1175 (false, ((), true)) => {},
1176 (false, ((), false)) => {},
1177 }
1178 }
1179 ",
1180 );
1181 }
1182 966
1183 #[test] 967 match &Either::B {
1184 fn tuple_of_tuple_and_bools_wildcard_missing_arms() { 968 //^^^^^^^^^^ Missing match arm
1185 check_diagnostic( 969 Either::A => (),
1186 r"
1187 fn test_fn() {
1188 match (false, ((), false)) {
1189 (true, _) => {},
1190 }
1191 }
1192 ",
1193 );
1194 } 970 }
1195 971
1196 #[test] 972 match Either::B {
1197 fn tuple_of_tuple_and_bools_wildcard_no_diagnostic() { 973 Either::A => (), Either::B => (),
1198 check_no_diagnostic(
1199 r"
1200 fn test_fn() {
1201 match (false, ((), false)) {
1202 (true, ((), true)) => {},
1203 (true, ((), false)) => {},
1204 (false, _) => {},
1205 }
1206 }
1207 ",
1208 );
1209 } 974 }
1210 975 match &Either::B {
1211 #[test] 976 Either::A => (), Either::B => (),
1212 fn enum_no_arms() {
1213 check_diagnostic(
1214 r"
1215 enum Either {
1216 A,
1217 B,
1218 }
1219 fn test_fn() {
1220 match Either::A {
1221 }
1222 }
1223 ",
1224 );
1225 } 977 }
1226 978}
1227 #[test] 979"#,
1228 fn enum_missing_arms() {
1229 check_diagnostic(
1230 r"
1231 enum Either {
1232 A,
1233 B,
1234 }
1235 fn test_fn() {
1236 match Either::B {
1237 Either::A => {},
1238 }
1239 }
1240 ",
1241 ); 980 );
1242 } 981 }
1243 982
1244 #[test] 983 #[test]
1245 fn enum_no_diagnostic() { 984 fn enum_containing_bool() {
1246 check_no_diagnostic( 985 check_diagnostics(
1247 r" 986 r#"
1248 enum Either { 987enum Either { A(bool), B }
1249 A,
1250 B,
1251 }
1252 fn test_fn() {
1253 match Either::B {
1254 Either::A => {},
1255 Either::B => {},
1256 }
1257 }
1258 ",
1259 );
1260 }
1261 988
1262 #[test] 989fn main() {
1263 fn enum_ref_missing_arms() { 990 match Either::B { }
1264 check_diagnostic( 991 //^^^^^^^^^ Missing match arm
1265 r" 992 match Either::B {
1266 enum Either { 993 //^^^^^^^^^ Missing match arm
1267 A, 994 Either::A(true) => (), Either::B => ()
1268 B,
1269 }
1270 fn test_fn() {
1271 match &Either::B {
1272 Either::A => {},
1273 }
1274 }
1275 ",
1276 );
1277 } 995 }
1278 996
1279 #[test] 997 match Either::B {
1280 fn enum_ref_no_diagnostic() { 998 Either::A(true) => (),
1281 check_no_diagnostic( 999 Either::A(false) => (),
1282 r" 1000 Either::B => (),
1283 enum Either {
1284 A,
1285 B,
1286 }
1287 fn test_fn() {
1288 match &Either::B {
1289 Either::A => {},
1290 Either::B => {},
1291 }
1292 }
1293 ",
1294 );
1295 } 1001 }
1296 1002 match Either::B {
1297 #[test] 1003 Either::B => (),
1298 fn enum_containing_bool_no_arms() { 1004 _ => (),
1299 check_diagnostic(
1300 r"
1301 enum Either {
1302 A(bool),
1303 B,
1304 }
1305 fn test_fn() {
1306 match Either::B {
1307 }
1308 }
1309 ",
1310 );
1311 } 1005 }
1312 1006 match Either::B {
1313 #[test] 1007 Either::A(_) => (),
1314 fn enum_containing_bool_missing_arms() { 1008 Either::B => (),
1315 check_diagnostic(
1316 r"
1317 enum Either {
1318 A(bool),
1319 B,
1320 }
1321 fn test_fn() {
1322 match Either::B {
1323 Either::A(true) => (),
1324 Either::B => (),
1325 }
1326 }
1327 ",
1328 );
1329 } 1009 }
1330 1010
1331 #[test] 1011}
1332 fn enum_containing_bool_no_diagnostic() { 1012 "#,
1333 check_no_diagnostic(
1334 r"
1335 enum Either {
1336 A(bool),
1337 B,
1338 }
1339 fn test_fn() {
1340 match Either::B {
1341 Either::A(true) => (),
1342 Either::A(false) => (),
1343 Either::B => (),
1344 }
1345 }
1346 ",
1347 ); 1013 );
1348 } 1014 }
1349 1015
1350 #[test] 1016 #[test]
1351 fn enum_containing_bool_with_wild_no_diagnostic() { 1017 fn enum_different_sizes() {
1352 check_no_diagnostic( 1018 check_diagnostics(
1353 r" 1019 r#"
1354 enum Either { 1020enum Either { A(bool), B(bool, bool) }
1355 A(bool),
1356 B,
1357 }
1358 fn test_fn() {
1359 match Either::B {
1360 Either::B => (),
1361 _ => (),
1362 }
1363 }
1364 ",
1365 );
1366 }
1367 1021
1368 #[test] 1022fn main() {
1369 fn enum_containing_bool_with_wild_2_no_diagnostic() { 1023 match Either::A(false) {
1370 check_no_diagnostic( 1024 //^^^^^^^^^^^^^^^^ Missing match arm
1371 r" 1025 Either::A(_) => (),
1372 enum Either { 1026 Either::B(false, _) => (),
1373 A(bool),
1374 B,
1375 }
1376 fn test_fn() {
1377 match Either::B {
1378 Either::A(_) => (),
1379 Either::B => (),
1380 }
1381 }
1382 ",
1383 );
1384 } 1027 }
1385 1028
1386 #[test] 1029 match Either::A(false) {
1387 fn enum_different_sizes_missing_arms() { 1030 Either::A(_) => (),
1388 check_diagnostic( 1031 Either::B(true, _) => (),
1389 r" 1032 Either::B(false, _) => (),
1390 enum Either {
1391 A(bool),
1392 B(bool, bool),
1393 }
1394 fn test_fn() {
1395 match Either::A(false) {
1396 Either::A(_) => (),
1397 Either::B(false, _) => (),
1398 }
1399 }
1400 ",
1401 );
1402 } 1033 }
1403 1034 match Either::A(false) {
1404 #[test] 1035 Either::A(true) | Either::A(false) => (),
1405 fn enum_different_sizes_no_diagnostic() { 1036 Either::B(true, _) => (),
1406 check_no_diagnostic( 1037 Either::B(false, _) => (),
1407 r"
1408 enum Either {
1409 A(bool),
1410 B(bool, bool),
1411 }
1412 fn test_fn() {
1413 match Either::A(false) {
1414 Either::A(_) => (),
1415 Either::B(true, _) => (),
1416 Either::B(false, _) => (),
1417 }
1418 }
1419 ",
1420 );
1421 } 1038 }
1422 1039}
1423 #[test] 1040"#,
1424 fn or_no_diagnostic() {
1425 check_no_diagnostic(
1426 r"
1427 enum Either {
1428 A(bool),
1429 B(bool, bool),
1430 }
1431 fn test_fn() {
1432 match Either::A(false) {
1433 Either::A(true) | Either::A(false) => (),
1434 Either::B(true, _) => (),
1435 Either::B(false, _) => (),
1436 }
1437 }
1438 ",
1439 ); 1041 );
1440 } 1042 }
1441 1043
1442 #[test] 1044 #[test]
1443 fn tuple_of_enum_no_diagnostic() { 1045 fn tuple_of_enum_no_diagnostic() {
1444 check_no_diagnostic( 1046 check_diagnostics(
1445 r" 1047 r#"
1446 enum Either { 1048enum Either { A(bool), B(bool, bool) }
1447 A(bool), 1049enum Either2 { C, D }
1448 B(bool, bool), 1050
1449 } 1051fn main() {
1450 enum Either2 { 1052 match (Either::A(false), Either2::C) {
1451 C, 1053 (Either::A(true), _) | (Either::A(false), _) => (),
1452 D, 1054 (Either::B(true, _), Either2::C) => (),
1453 } 1055 (Either::B(false, _), Either2::C) => (),
1454 fn test_fn() { 1056 (Either::B(_, _), Either2::D) => (),
1455 match (Either::A(false), Either2::C) {
1456 (Either::A(true), _) | (Either::A(false), _) => (),
1457 (Either::B(true, _), Either2::C) => (),
1458 (Either::B(false, _), Either2::C) => (),
1459 (Either::B(_, _), Either2::D) => (),
1460 }
1461 }
1462 ",
1463 );
1464 }
1465
1466 #[test]
1467 fn mismatched_types() {
1468 // Match statements with arms that don't match the
1469 // expression pattern do not fire this diagnostic.
1470 check_no_diagnostic(
1471 r"
1472 enum Either {
1473 A,
1474 B,
1475 }
1476 enum Either2 {
1477 C,
1478 D,
1479 }
1480 fn test_fn() {
1481 match Either::A {
1482 Either2::C => (),
1483 Either2::D => (),
1484 }
1485 }
1486 ",
1487 );
1488 } 1057 }
1489 1058}
1490 #[test] 1059"#,
1491 fn mismatched_types_with_different_arity() {
1492 // Match statements with arms that don't match the
1493 // expression pattern do not fire this diagnostic.
1494 check_no_diagnostic(
1495 r"
1496 fn test_fn() {
1497 match (true, false) {
1498 (true, false, true) => (),
1499 (true) => (),
1500 }
1501 }
1502 ",
1503 ); 1060 );
1504 } 1061 }
1505 1062
1506 #[test] 1063 #[test]
1507 fn malformed_match_arm_tuple_missing_pattern() { 1064 fn mismatched_types() {
1508 // Match statements with arms that don't match the 1065 // Match statements with arms that don't match the
1509 // expression pattern do not fire this diagnostic. 1066 // expression pattern do not fire this diagnostic.
1510 check_no_diagnostic( 1067 check_diagnostics(
1511 r" 1068 r#"
1512 fn test_fn() { 1069enum Either { A, B }
1513 match (0) { 1070enum Either2 { C, D }
1514 () => (), 1071
1515 } 1072fn main() {
1516 } 1073 match Either::A {
1517 ", 1074 Either2::C => (),
1075 Either2::D => (),
1076 }
1077 match (true, false) {
1078 (true, false, true) => (),
1079 (true) => (),
1080 }
1081 match (0) { () => () }
1082 match Unresolved::Bar { Unresolved::Baz => () }
1083}
1084 "#,
1518 ); 1085 );
1519 } 1086 }
1520 1087
@@ -1522,636 +1089,333 @@ mod tests {
1522 fn malformed_match_arm_tuple_enum_missing_pattern() { 1089 fn malformed_match_arm_tuple_enum_missing_pattern() {
1523 // We are testing to be sure we don't panic here when the match 1090 // We are testing to be sure we don't panic here when the match
1524 // arm `Either::B` is missing its pattern. 1091 // arm `Either::B` is missing its pattern.
1525 check_no_diagnostic( 1092 check_diagnostics(
1526 r" 1093 r#"
1527 enum Either { 1094enum Either { A, B(u32) }
1528 A,
1529 B(u32),
1530 }
1531 fn test_fn() {
1532 match Either::A {
1533 Either::A => (),
1534 Either::B() => (),
1535 }
1536 }
1537 ",
1538 );
1539 }
1540 1095
1541 #[test] 1096fn main() {
1542 fn enum_not_in_scope() { 1097 match Either::A {
1543 // The enum is not in scope so we don't perform exhaustiveness 1098 Either::A => (),
1544 // checking, but we want to be sure we don't panic here (and 1099 Either::B() => (),
1545 // we don't create a diagnostic). 1100 }
1546 check_no_diagnostic( 1101}
1547 r" 1102"#,
1548 fn test_fn() {
1549 match Foo::Bar {
1550 Foo::Baz => (),
1551 }
1552 }
1553 ",
1554 ); 1103 );
1555 } 1104 }
1556 1105
1557 #[test] 1106 #[test]
1558 fn expr_diverges() { 1107 fn expr_diverges() {
1559 check_no_diagnostic( 1108 check_diagnostics(
1560 r" 1109 r#"
1561 enum Either { 1110enum Either { A, B }
1562 A,
1563 B,
1564 }
1565 fn test_fn() {
1566 match loop {} {
1567 Either::A => (),
1568 Either::B => (),
1569 }
1570 }
1571 ",
1572 );
1573 }
1574 1111
1575 #[test] 1112fn main() {
1576 fn expr_loop_with_break() { 1113 match loop {} {
1577 check_no_diagnostic( 1114 Either::A => (),
1578 r" 1115 Either::B => (),
1579 enum Either { 1116 }
1580 A, 1117 match loop {} {
1581 B, 1118 Either::A => (),
1582 } 1119 }
1583 fn test_fn() { 1120 match loop { break Foo::A } {
1584 match loop { break Foo::A } { 1121 //^^^^^^^^^^^^^^^^^^^^^ Missing match arm
1585 Either::A => (), 1122 Either::A => (),
1586 Either::B => (), 1123 }
1587 } 1124 match loop { break Foo::A } {
1588 } 1125 Either::A => (),
1589 ", 1126 Either::B => (),
1127 }
1128}
1129"#,
1590 ); 1130 );
1591 } 1131 }
1592 1132
1593 #[test] 1133 #[test]
1594 fn expr_partially_diverges() { 1134 fn expr_partially_diverges() {
1595 check_no_diagnostic( 1135 check_diagnostics(
1596 r" 1136 r#"
1597 enum Either<T> { 1137enum Either<T> { A(T), B }
1598 A(T),
1599 B,
1600 }
1601 fn foo() -> Either<!> {
1602 Either::B
1603 }
1604 fn test_fn() -> u32 {
1605 match foo() {
1606 Either::A(val) => val,
1607 Either::B => 0,
1608 }
1609 }
1610 ",
1611 );
1612 }
1613 1138
1614 #[test] 1139fn foo() -> Either<!> { Either::B }
1615 fn enum_record_no_arms() { 1140fn main() -> u32 {
1616 check_diagnostic( 1141 match foo() {
1617 r" 1142 Either::A(val) => val,
1618 enum Either { 1143 Either::B => 0,
1619 A { foo: bool },
1620 B,
1621 }
1622 fn test_fn() {
1623 let a = Either::A { foo: true };
1624 match a {
1625 }
1626 }
1627 ",
1628 );
1629 } 1144 }
1630 1145}
1631 #[test] 1146"#,
1632 fn enum_record_missing_arms() {
1633 check_diagnostic(
1634 r"
1635 enum Either {
1636 A { foo: bool },
1637 B,
1638 }
1639 fn test_fn() {
1640 let a = Either::A { foo: true };
1641 match a {
1642 Either::A { foo: true } => (),
1643 }
1644 }
1645 ",
1646 ); 1147 );
1647 } 1148 }
1648 1149
1649 #[test] 1150 #[test]
1650 fn enum_record_no_diagnostic() { 1151 fn enum_record() {
1651 check_no_diagnostic( 1152 check_diagnostics(
1652 r" 1153 r#"
1653 enum Either { 1154enum Either { A { foo: bool }, B }
1654 A { foo: bool },
1655 B,
1656 }
1657 fn test_fn() {
1658 let a = Either::A { foo: true };
1659 match a {
1660 Either::A { foo: true } => (),
1661 Either::A { foo: false } => (),
1662 Either::B => (),
1663 }
1664 }
1665 ",
1666 );
1667 }
1668 1155
1669 #[test] 1156fn main() {
1670 fn enum_record_missing_field_no_diagnostic() { 1157 let a = Either::A { foo: true };
1671 // When `Either::A` is missing a struct member, we don't want 1158 match a { }
1672 // to fire the missing match arm diagnostic. This should fire 1159 //^ Missing match arm
1673 // some other diagnostic. 1160 match a { Either::A { foo: true } => () }
1674 check_no_diagnostic( 1161 //^ Missing match arm
1675 r" 1162 match a {
1676 enum Either { 1163 Either::A { } => (),
1677 A { foo: bool }, 1164 //^^^ Missing structure fields:
1678 B, 1165 // | - foo
1679 } 1166 Either::B => (),
1680 fn test_fn() {
1681 let a = Either::B;
1682 match a {
1683 Either::A { } => (),
1684 Either::B => (),
1685 }
1686 }
1687 ",
1688 );
1689 } 1167 }
1168 match a {
1169 //^ Missing match arm
1170 Either::A { } => (),
1171 } //^^^ Missing structure fields:
1172 // | - foo
1690 1173
1691 #[test] 1174 match a {
1692 fn enum_record_missing_field_missing_match_arm() { 1175 Either::A { foo: true } => (),
1693 // Even though `Either::A` is missing fields, we still want to fire 1176 Either::A { foo: false } => (),
1694 // the missing arm diagnostic here, since we know `Either::B` is missing. 1177 Either::B => (),
1695 check_diagnostic(
1696 r"
1697 enum Either {
1698 A { foo: bool },
1699 B,
1700 }
1701 fn test_fn() {
1702 let a = Either::B;
1703 match a {
1704 Either::A { } => (),
1705 }
1706 }
1707 ",
1708 );
1709 } 1178 }
1710 1179 match a {
1711 #[test] 1180 Either::A { foo: _ } => (),
1712 fn enum_record_no_diagnostic_wild() { 1181 Either::B => (),
1713 check_no_diagnostic(
1714 r"
1715 enum Either {
1716 A { foo: bool },
1717 B,
1718 }
1719 fn test_fn() {
1720 let a = Either::A { foo: true };
1721 match a {
1722 Either::A { foo: _ } => (),
1723 Either::B => (),
1724 }
1725 }
1726 ",
1727 );
1728 } 1182 }
1729 1183}
1730 #[test] 1184"#,
1731 fn enum_record_fields_out_of_order_missing_arm() {
1732 check_diagnostic(
1733 r"
1734 enum Either {
1735 A { foo: bool, bar: () },
1736 B,
1737 }
1738 fn test_fn() {
1739 let a = Either::A { foo: true };
1740 match a {
1741 Either::A { bar: (), foo: false } => (),
1742 Either::A { foo: true, bar: () } => (),
1743 }
1744 }
1745 ",
1746 ); 1185 );
1747 } 1186 }
1748 1187
1749 #[test] 1188 #[test]
1750 fn enum_record_fields_out_of_order_no_diagnostic() { 1189 fn enum_record_fields_out_of_order() {
1751 check_no_diagnostic( 1190 check_diagnostics(
1752 r" 1191 r#"
1753 enum Either { 1192enum Either {
1754 A { foo: bool, bar: () }, 1193 A { foo: bool, bar: () },
1755 B, 1194 B,
1756 } 1195}
1757 fn test_fn() {
1758 let a = Either::A { foo: true };
1759 match a {
1760 Either::A { bar: (), foo: false } => (),
1761 Either::A { foo: true, bar: () } => (),
1762 Either::B => (),
1763 }
1764 }
1765 ",
1766 );
1767 }
1768 1196
1769 #[test] 1197fn main() {
1770 fn enum_record_ellipsis_missing_arm() { 1198 let a = Either::A { foo: true, bar: () };
1771 check_diagnostic( 1199 match a {
1772 r" 1200 //^ Missing match arm
1773 enum Either { 1201 Either::A { bar: (), foo: false } => (),
1774 A { foo: bool, bar: bool }, 1202 Either::A { foo: true, bar: () } => (),
1775 B,
1776 }
1777 fn test_fn() {
1778 match Either::B {
1779 Either::A { foo: true, .. } => (),
1780 Either::B => (),
1781 }
1782 }
1783 ",
1784 );
1785 } 1203 }
1786 1204
1787 #[test] 1205 match a {
1788 fn enum_record_ellipsis_no_diagnostic() { 1206 Either::A { bar: (), foo: false } => (),
1789 check_no_diagnostic( 1207 Either::A { foo: true, bar: () } => (),
1790 r" 1208 Either::B => (),
1791 enum Either {
1792 A { foo: bool, bar: bool },
1793 B,
1794 }
1795 fn test_fn() {
1796 let a = Either::A { foo: true };
1797 match a {
1798 Either::A { foo: true, .. } => (),
1799 Either::A { foo: false, .. } => (),
1800 Either::B => (),
1801 }
1802 }
1803 ",
1804 );
1805 } 1209 }
1806 1210}
1807 #[test] 1211"#,
1808 fn enum_record_ellipsis_all_fields_missing_arm() {
1809 check_diagnostic(
1810 r"
1811 enum Either {
1812 A { foo: bool, bar: bool },
1813 B,
1814 }
1815 fn test_fn() {
1816 let a = Either::B;
1817 match a {
1818 Either::A { .. } => (),
1819 }
1820 }
1821 ",
1822 ); 1212 );
1823 } 1213 }
1824 1214
1825 #[test] 1215 #[test]
1826 fn enum_record_ellipsis_all_fields_no_diagnostic() { 1216 fn enum_record_ellipsis() {
1827 check_no_diagnostic( 1217 check_diagnostics(
1828 r" 1218 r#"
1829 enum Either { 1219enum Either {
1830 A { foo: bool, bar: bool }, 1220 A { foo: bool, bar: bool },
1831 B, 1221 B,
1832 } 1222}
1833 fn test_fn() {
1834 let a = Either::B;
1835 match a {
1836 Either::A { .. } => (),
1837 Either::B => (),
1838 }
1839 }
1840 ",
1841 );
1842 }
1843 1223
1844 #[test] 1224fn main() {
1845 fn enum_tuple_partial_ellipsis_no_diagnostic() { 1225 let a = Either::B;
1846 check_no_diagnostic( 1226 match a {
1847 r" 1227 //^ Missing match arm
1848 enum Either { 1228 Either::A { foo: true, .. } => (),
1849 A(bool, bool, bool, bool), 1229 Either::B => (),
1850 B,
1851 }
1852 fn test_fn() {
1853 match Either::B {
1854 Either::A(true, .., true) => {},
1855 Either::A(true, .., false) => {},
1856 Either::A(false, .., true) => {},
1857 Either::A(false, .., false) => {},
1858 Either::B => {},
1859 }
1860 }
1861 ",
1862 );
1863 } 1230 }
1864 1231 match a {
1865 #[test] 1232 //^ Missing match arm
1866 fn enum_tuple_partial_ellipsis_2_no_diagnostic() { 1233 Either::A { .. } => (),
1867 check_no_diagnostic(
1868 r"
1869 enum Either {
1870 A(bool, bool, bool, bool),
1871 B,
1872 }
1873 fn test_fn() {
1874 match Either::B {
1875 Either::A(true, .., true) => {},
1876 Either::A(true, .., false) => {},
1877 Either::A(.., true) => {},
1878 Either::A(.., false) => {},
1879 Either::B => {},
1880 }
1881 }
1882 ",
1883 );
1884 } 1234 }
1885 1235
1886 #[test] 1236 match a {
1887 fn enum_tuple_partial_ellipsis_missing_arm() { 1237 Either::A { foo: true, .. } => (),
1888 check_diagnostic( 1238 Either::A { foo: false, .. } => (),
1889 r" 1239 Either::B => (),
1890 enum Either {
1891 A(bool, bool, bool, bool),
1892 B,
1893 }
1894 fn test_fn() {
1895 match Either::B {
1896 Either::A(true, .., true) => {},
1897 Either::A(true, .., false) => {},
1898 Either::A(false, .., false) => {},
1899 Either::B => {},
1900 }
1901 }
1902 ",
1903 );
1904 } 1240 }
1905 1241
1906 #[test] 1242 match a {
1907 fn enum_tuple_partial_ellipsis_2_missing_arm() { 1243 Either::A { .. } => (),
1908 check_diagnostic( 1244 Either::B => (),
1909 r"
1910 enum Either {
1911 A(bool, bool, bool, bool),
1912 B,
1913 }
1914 fn test_fn() {
1915 match Either::B {
1916 Either::A(true, .., true) => {},
1917 Either::A(true, .., false) => {},
1918 Either::A(.., true) => {},
1919 Either::B => {},
1920 }
1921 }
1922 ",
1923 );
1924 } 1245 }
1925 1246}
1926 #[test] 1247"#,
1927 fn enum_tuple_ellipsis_no_diagnostic() {
1928 check_no_diagnostic(
1929 r"
1930 enum Either {
1931 A(bool, bool, bool, bool),
1932 B,
1933 }
1934 fn test_fn() {
1935 match Either::B {
1936 Either::A(..) => {},
1937 Either::B => {},
1938 }
1939 }
1940 ",
1941 ); 1248 );
1942 } 1249 }
1943 1250
1944 #[test] 1251 #[test]
1945 fn enum_never() { 1252 fn enum_tuple_partial_ellipsis() {
1946 check_no_diagnostic( 1253 check_diagnostics(
1947 r" 1254 r#"
1948 enum Never {} 1255enum Either {
1256 A(bool, bool, bool, bool),
1257 B,
1258}
1949 1259
1950 fn test_fn(never: Never) { 1260fn main() {
1951 match never {} 1261 match Either::B {
1952 } 1262 //^^^^^^^^^ Missing match arm
1953 ", 1263 Either::A(true, .., true) => (),
1954 ); 1264 Either::A(true, .., false) => (),
1265 Either::A(false, .., false) => (),
1266 Either::B => (),
1267 }
1268 match Either::B {
1269 //^^^^^^^^^ Missing match arm
1270 Either::A(true, .., true) => (),
1271 Either::A(true, .., false) => (),
1272 Either::A(.., true) => (),
1273 Either::B => (),
1274 }
1275
1276 match Either::B {
1277 Either::A(true, .., true) => (),
1278 Either::A(true, .., false) => (),
1279 Either::A(false, .., true) => (),
1280 Either::A(false, .., false) => (),
1281 Either::B => (),
1282 }
1283 match Either::B {
1284 Either::A(true, .., true) => (),
1285 Either::A(true, .., false) => (),
1286 Either::A(.., true) => (),
1287 Either::A(.., false) => (),
1288 Either::B => (),
1955 } 1289 }
1956 1290}
1957 #[test] 1291"#,
1958 fn type_never() {
1959 check_no_diagnostic(
1960 r"
1961 fn test_fn(never: !) {
1962 match never {}
1963 }
1964 ",
1965 ); 1292 );
1966 } 1293 }
1967 1294
1968 #[test] 1295 #[test]
1969 fn enum_never_ref() { 1296 fn never() {
1970 check_no_diagnostic( 1297 check_diagnostics(
1971 r" 1298 r#"
1972 enum Never {} 1299enum Never {}
1973 1300
1974 fn test_fn(never: &Never) { 1301fn enum_(never: Never) {
1975 match never {} 1302 match never {}
1976 } 1303}
1977 ", 1304fn enum_ref(never: &Never) {
1978 ); 1305 match never {}
1979 } 1306}
1980 1307fn bang(never: !) {
1981 #[test] 1308 match never {}
1982 fn expr_diverges_missing_arm() { 1309}
1983 check_no_diagnostic( 1310"#,
1984 r"
1985 enum Either {
1986 A,
1987 B,
1988 }
1989 fn test_fn() {
1990 match loop {} {
1991 Either::A => (),
1992 }
1993 }
1994 ",
1995 ); 1311 );
1996 } 1312 }
1997 1313
1998 #[test] 1314 #[test]
1999 fn or_pattern_panic() { 1315 fn or_pattern_panic() {
2000 check_no_diagnostic( 1316 check_diagnostics(
2001 r" 1317 r#"
2002 pub enum Category { 1318pub enum Category { Infinity, Zero }
2003 Infinity,
2004 Zero,
2005 }
2006 1319
2007 fn panic(a: Category, b: Category) { 1320fn panic(a: Category, b: Category) {
2008 match (a, b) { 1321 match (a, b) {
2009 (Category::Zero | Category::Infinity, _) => {} 1322 (Category::Zero | Category::Infinity, _) => (),
2010 (_, Category::Zero | Category::Infinity) => {} 1323 (_, Category::Zero | Category::Infinity) => (),
2011 }
2012 }
2013 ",
2014 );
2015 } 1324 }
2016 1325
2017 #[test] 1326 // FIXME: This is a false positive, but the code used to cause a panic in the match checker,
2018 fn or_pattern_panic_2() { 1327 // so this acts as a regression test for that.
2019 // FIXME: This is a false positive, but the code used to cause a panic in the match checker, 1328 match (a, b) {
2020 // so this acts as a regression test for that. 1329 //^^^^^^ Missing match arm
2021 check_diagnostic( 1330 (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => (),
2022 r" 1331 (Category::Infinity | Category::Zero, _) => (),
2023 pub enum Category {
2024 Infinity,
2025 Zero,
2026 }
2027
2028 fn panic(a: Category, b: Category) {
2029 match (a, b) {
2030 (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => {}
2031
2032 (Category::Infinity | Category::Zero, _) => {}
2033 }
2034 }
2035 ",
2036 );
2037 } 1332 }
2038} 1333}
2039 1334"#,
2040#[cfg(test)] 1335 );
2041mod false_negatives { 1336 }
2042 //! The implementation of match checking here is a work in progress. As we roll this out, we 1337
2043 //! prefer false negatives to false positives (ideally there would be no false positives). This 1338 mod false_negatives {
2044 //! test module should document known false negatives. Eventually we will have a complete 1339 //! The implementation of match checking here is a work in progress. As we roll this out, we
2045 //! implementation of match checking and this module will be empty. 1340 //! prefer false negatives to false positives (ideally there would be no false positives). This
2046 //! 1341 //! test module should document known false negatives. Eventually we will have a complete
2047 //! The reasons for documenting known false negatives: 1342 //! implementation of match checking and this module will be empty.
2048 //! 1343 //!
2049 //! 1. It acts as a backlog of work that can be done to improve the behavior of the system. 1344 //! The reasons for documenting known false negatives:
2050 //! 2. It ensures the code doesn't panic when handling these cases. 1345 //!
2051 1346 //! 1. It acts as a backlog of work that can be done to improve the behavior of the system.
2052 use super::tests::*; 1347 //! 2. It ensures the code doesn't panic when handling these cases.
2053 1348 use super::*;
2054 #[test] 1349
2055 fn integers() { 1350 #[test]
2056 // This is a false negative. 1351 fn integers() {
2057 // We don't currently check integer exhaustiveness. 1352 // We don't currently check integer exhaustiveness.
2058 check_no_diagnostic( 1353 check_diagnostics(
2059 r" 1354 r#"
2060 fn test_fn() { 1355fn main() {
2061 match 5 { 1356 match 5 {
2062 10 => (), 1357 10 => (),
2063 11..20 => (), 1358 11..20 => (),
2064 }
2065 }
2066 ",
2067 );
2068 }
2069
2070 #[test]
2071 fn internal_or() {
2072 // This is a false negative.
2073 // We do not currently handle patterns with internal `or`s.
2074 check_no_diagnostic(
2075 r"
2076 fn test_fn() {
2077 enum Either {
2078 A(bool),
2079 B,
2080 }
2081 match Either::B {
2082 Either::A(true | false) => (),
2083 }
2084 }
2085 ",
2086 );
2087 } 1359 }
1360}
1361"#,
1362 );
1363 }
2088 1364
2089 #[test] 1365 #[test]
2090 fn expr_loop_missing_arm() { 1366 fn internal_or() {
2091 // This is a false negative. 1367 // We do not currently handle patterns with internal `or`s.
2092 // We currently infer the type of `loop { break Foo::A }` to `!`, which 1368 check_diagnostics(
2093 // causes us to skip the diagnostic since `Either::A` doesn't type check 1369 r#"
2094 // with `!`. 1370fn main() {
2095 check_diagnostic( 1371 enum Either { A(bool), B }
2096 r" 1372 match Either::B {
2097 enum Either { 1373 Either::A(true | false) => (),
2098 A,
2099 B,
2100 }
2101 fn test_fn() {
2102 match loop { break Foo::A } {
2103 Either::A => (),
2104 }
2105 }
2106 ",
2107 );
2108 } 1374 }
1375}
1376"#,
1377 );
1378 }
2109 1379
2110 #[test] 1380 #[test]
2111 fn tuple_of_bools_with_ellipsis_at_end_missing_arm() { 1381 fn tuple_of_bools_with_ellipsis_at_end_missing_arm() {
2112 // This is a false negative. 1382 // We don't currently handle tuple patterns with ellipsis.
2113 // We don't currently handle tuple patterns with ellipsis. 1383 check_diagnostics(
2114 check_no_diagnostic( 1384 r#"
2115 r" 1385fn main() {
2116 fn test_fn() { 1386 match (false, true, false) {
2117 match (false, true, false) { 1387 (false, ..) => (),
2118 (false, ..) => {},
2119 }
2120 }
2121 ",
2122 );
2123 } 1388 }
1389}
1390"#,
1391 );
1392 }
2124 1393
2125 #[test] 1394 #[test]
2126 fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() { 1395 fn tuple_of_bools_with_ellipsis_at_beginning_missing_arm() {
2127 // This is a false negative. 1396 // We don't currently handle tuple patterns with ellipsis.
2128 // We don't currently handle tuple patterns with ellipsis. 1397 check_diagnostics(
2129 check_no_diagnostic( 1398 r#"
2130 r" 1399fn main() {
2131 fn test_fn() { 1400 match (false, true, false) {
2132 match (false, true, false) { 1401 (.., false) => (),
2133 (.., false) => {},
2134 }
2135 }
2136 ",
2137 );
2138 } 1402 }
1403}
1404"#,
1405 );
1406 }
2139 1407
2140 #[test] 1408 #[test]
2141 fn struct_missing_arm() { 1409 fn struct_missing_arm() {
2142 // This is a false negative. 1410 // We don't currently handle structs.
2143 // We don't currently handle structs. 1411 check_diagnostics(
2144 check_no_diagnostic( 1412 r#"
2145 r" 1413struct Foo { a: bool }
2146 struct Foo { 1414fn main(f: Foo) {
2147 a: bool, 1415 match f { Foo { a: true } => () }
2148 } 1416}
2149 fn test_fn(f: Foo) { 1417"#,
2150 match f { 1418 );
2151 Foo { a: true } => {}, 1419 }
2152 }
2153 }
2154 ",
2155 );
2156 } 1420 }
2157} 1421}
diff --git a/crates/ra_hir_ty/src/unsafe_validation.rs b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs
index c512c4f8e..5cc76bdce 100644
--- a/crates/ra_hir_ty/src/unsafe_validation.rs
+++ b/crates/ra_hir_ty/src/diagnostics/unsafe_check.rs
@@ -6,35 +6,38 @@ use std::sync::Arc;
6use hir_def::{ 6use hir_def::{
7 body::Body, 7 body::Body,
8 expr::{Expr, ExprId, UnaryOp}, 8 expr::{Expr, ExprId, UnaryOp},
9 DefWithBodyId, FunctionId, 9 DefWithBodyId,
10}; 10};
11use hir_expand::diagnostics::DiagnosticSink; 11use hir_expand::diagnostics::DiagnosticSink;
12 12
13use crate::{ 13use crate::{
14 db::HirDatabase, diagnostics::MissingUnsafe, lower::CallableDef, ApplicationTy, 14 db::HirDatabase, diagnostics::MissingUnsafe, lower::CallableDefId, ApplicationTy,
15 InferenceResult, Ty, TypeCtor, 15 InferenceResult, Ty, TypeCtor,
16}; 16};
17 17
18pub struct UnsafeValidator<'a, 'b: 'a> { 18pub(super) struct UnsafeValidator<'a, 'b: 'a> {
19 func: FunctionId, 19 owner: DefWithBodyId,
20 infer: Arc<InferenceResult>, 20 infer: Arc<InferenceResult>,
21 sink: &'a mut DiagnosticSink<'b>, 21 sink: &'a mut DiagnosticSink<'b>,
22} 22}
23 23
24impl<'a, 'b> UnsafeValidator<'a, 'b> { 24impl<'a, 'b> UnsafeValidator<'a, 'b> {
25 pub fn new( 25 pub(super) fn new(
26 func: FunctionId, 26 owner: DefWithBodyId,
27 infer: Arc<InferenceResult>, 27 infer: Arc<InferenceResult>,
28 sink: &'a mut DiagnosticSink<'b>, 28 sink: &'a mut DiagnosticSink<'b>,
29 ) -> UnsafeValidator<'a, 'b> { 29 ) -> UnsafeValidator<'a, 'b> {
30 UnsafeValidator { func, infer, sink } 30 UnsafeValidator { owner, infer, sink }
31 } 31 }
32 32
33 pub fn validate_body(&mut self, db: &dyn HirDatabase) { 33 pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
34 let def = self.func.into(); 34 let def = self.owner.into();
35 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); 35 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
36 let func_data = db.function_data(self.func); 36 let is_unsafe = match self.owner {
37 if func_data.is_unsafe 37 DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe,
38 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
39 };
40 if is_unsafe
38 || unsafe_expressions 41 || unsafe_expressions
39 .iter() 42 .iter()
40 .filter(|unsafe_expr| !unsafe_expr.inside_unsafe_block) 43 .filter(|unsafe_expr| !unsafe_expr.inside_unsafe_block)
@@ -85,7 +88,7 @@ fn walk_unsafe(
85 Expr::Call { callee, .. } => { 88 Expr::Call { callee, .. } => {
86 let ty = &infer[*callee]; 89 let ty = &infer[*callee];
87 if let &Ty::Apply(ApplicationTy { 90 if let &Ty::Apply(ApplicationTy {
88 ctor: TypeCtor::FnDef(CallableDef::FunctionId(func)), 91 ctor: TypeCtor::FnDef(CallableDefId::FunctionId(func)),
89 .. 92 ..
90 }) = ty 93 }) = ty
91 { 94 {
@@ -118,3 +121,53 @@ fn walk_unsafe(
118 walk_unsafe(unsafe_exprs, db, infer, body, child, inside_unsafe_block); 121 walk_unsafe(unsafe_exprs, db, infer, body, child, inside_unsafe_block);
119 }); 122 });
120} 123}
124
125#[cfg(test)]
126mod tests {
127 use crate::diagnostics::tests::check_diagnostics;
128
129 #[test]
130 fn missing_unsafe_diagnostic_with_raw_ptr() {
131 check_diagnostics(
132 r#"
133fn main() {
134 let x = &5 as *const usize;
135 unsafe { let y = *x; }
136 let z = *x;
137} //^^ This operation is unsafe and requires an unsafe function or block
138"#,
139 )
140 }
141
142 #[test]
143 fn missing_unsafe_diagnostic_with_unsafe_call() {
144 check_diagnostics(
145 r#"
146struct HasUnsafe;
147
148impl HasUnsafe {
149 unsafe fn unsafe_fn(&self) {
150 let x = &5 as *const usize;
151 let y = *x;
152 }
153}
154
155unsafe fn unsafe_fn() {
156 let x = &5 as *const usize;
157 let y = *x;
158}
159
160fn main() {
161 unsafe_fn();
162 //^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
163 HasUnsafe.unsafe_fn();
164 //^^^^^^^^^^^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
165 unsafe {
166 unsafe_fn();
167 HasUnsafe.unsafe_fn();
168 }
169}
170"#,
171 );
172 }
173}
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 23cea1a2a..19770e609 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -3,7 +3,7 @@
3use std::fmt; 3use std::fmt;
4 4
5use crate::{ 5use crate::{
6 db::HirDatabase, utils::generics, ApplicationTy, CallableDef, FnSig, GenericPredicate, 6 db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate,
7 Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 7 Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
8}; 8};
9use hir_def::{ 9use hir_def::{
@@ -243,22 +243,36 @@ impl HirDisplay for ApplicationTy {
243 write!(f, ")")?; 243 write!(f, ")")?;
244 } 244 }
245 } 245 }
246 TypeCtor::FnPtr { .. } => { 246 TypeCtor::FnPtr { is_varargs, .. } => {
247 let sig = FnSig::from_fn_ptr_substs(&self.parameters); 247 let sig = FnSig::from_fn_ptr_substs(&self.parameters, is_varargs);
248 write!(f, "fn(")?; 248 write!(f, "fn(")?;
249 f.write_joined(sig.params(), ", ")?; 249 f.write_joined(sig.params(), ", ")?;
250 if is_varargs {
251 if sig.params().is_empty() {
252 write!(f, "...")?;
253 } else {
254 write!(f, ", ...")?;
255 }
256 }
250 write!(f, ")")?; 257 write!(f, ")")?;
251 let ret = sig.ret(); 258 let ret = sig.ret();
252 if *ret != Ty::unit() { 259 if *ret != Ty::unit() {
253 write!(f, " -> {}", ret.display(f.db))?; 260 let ret_display = if f.omit_verbose_types() {
261 ret.display_truncated(f.db, f.max_size)
262 } else {
263 ret.display(f.db)
264 };
265 write!(f, " -> {}", ret_display)?;
254 } 266 }
255 } 267 }
256 TypeCtor::FnDef(def) => { 268 TypeCtor::FnDef(def) => {
257 let sig = f.db.callable_item_signature(def).subst(&self.parameters); 269 let sig = f.db.callable_item_signature(def).subst(&self.parameters);
258 match def { 270 match def {
259 CallableDef::FunctionId(ff) => write!(f, "fn {}", f.db.function_data(ff).name)?, 271 CallableDefId::FunctionId(ff) => {
260 CallableDef::StructId(s) => write!(f, "{}", f.db.struct_data(s).name)?, 272 write!(f, "fn {}", f.db.function_data(ff).name)?
261 CallableDef::EnumVariantId(e) => { 273 }
274 CallableDefId::StructId(s) => write!(f, "{}", f.db.struct_data(s).name)?,
275 CallableDefId::EnumVariantId(e) => {
262 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? 276 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
263 } 277 }
264 }; 278 };
@@ -279,7 +293,12 @@ impl HirDisplay for ApplicationTy {
279 write!(f, ")")?; 293 write!(f, ")")?;
280 let ret = sig.ret(); 294 let ret = sig.ret();
281 if *ret != Ty::unit() { 295 if *ret != Ty::unit() {
282 write!(f, " -> {}", ret.display(f.db))?; 296 let ret_display = if f.omit_verbose_types() {
297 ret.display_truncated(f.db, f.max_size)
298 } else {
299 ret.display(f.db)
300 };
301 write!(f, " -> {}", ret_display)?;
283 } 302 }
284 } 303 }
285 TypeCtor::Adt(def_id) => { 304 TypeCtor::Adt(def_id) => {
@@ -369,7 +388,7 @@ impl HirDisplay for ApplicationTy {
369 let data = (*datas) 388 let data = (*datas)
370 .as_ref() 389 .as_ref()
371 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 390 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
372 data.clone().subst(&self.parameters) 391 data.subst(&self.parameters)
373 } 392 }
374 }; 393 };
375 write!(f, "impl ")?; 394 write!(f, "impl ")?;
@@ -388,7 +407,13 @@ impl HirDisplay for ApplicationTy {
388 f.write_joined(sig.params(), ", ")?; 407 f.write_joined(sig.params(), ", ")?;
389 write!(f, "|")?; 408 write!(f, "|")?;
390 }; 409 };
391 write!(f, " -> {}", sig.ret().display(f.db))?; 410
411 let ret_display = if f.omit_verbose_types() {
412 sig.ret().display_truncated(f.db, f.max_size)
413 } else {
414 sig.ret().display(f.db)
415 };
416 write!(f, " -> {}", ret_display)?;
392 } else { 417 } else {
393 write!(f, "{{closure}}")?; 418 write!(f, "{{closure}}")?;
394 } 419 }
@@ -456,7 +481,7 @@ impl HirDisplay for Ty {
456 let data = (*datas) 481 let data = (*datas)
457 .as_ref() 482 .as_ref()
458 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 483 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
459 data.clone().subst(&opaque_ty.parameters) 484 data.subst(&opaque_ty.parameters)
460 } 485 }
461 }; 486 };
462 write!(f, "impl ")?; 487 write!(f, "impl ")?;
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 5c56c2eb0..28f32a0a4 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -18,8 +18,6 @@ use std::mem;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use rustc_hash::FxHashMap;
22
23use hir_def::{ 21use hir_def::{
24 body::Body, 22 body::Body,
25 data::{ConstData, FunctionData, StaticData}, 23 data::{ConstData, FunctionData, StaticData},
@@ -35,6 +33,8 @@ use hir_expand::{diagnostics::DiagnosticSink, name::name};
35use ra_arena::map::ArenaMap; 33use ra_arena::map::ArenaMap;
36use ra_prof::profile; 34use ra_prof::profile;
37use ra_syntax::SmolStr; 35use ra_syntax::SmolStr;
36use rustc_hash::FxHashMap;
37use stdx::impl_from;
38 38
39use super::{ 39use super::{
40 primitive::{FloatTy, IntTy}, 40 primitive::{FloatTy, IntTy},
@@ -84,8 +84,7 @@ enum ExprOrPatId {
84 ExprId(ExprId), 84 ExprId(ExprId),
85 PatId(PatId), 85 PatId(PatId),
86} 86}
87 87impl_from!(ExprId, PatId for ExprOrPatId);
88impl_froms!(ExprOrPatId: ExprId, PatId);
89 88
90/// Binding modes inferred for patterns. 89/// Binding modes inferred for patterns.
91/// https://doc.rust-lang.org/reference/patterns.html#binding-modes 90/// https://doc.rust-lang.org/reference/patterns.html#binding-modes
@@ -169,7 +168,7 @@ impl InferenceResult {
169 pub fn add_diagnostics( 168 pub fn add_diagnostics(
170 &self, 169 &self,
171 db: &dyn HirDatabase, 170 db: &dyn HirDatabase,
172 owner: FunctionId, 171 owner: DefWithBodyId,
173 sink: &mut DiagnosticSink, 172 sink: &mut DiagnosticSink,
174 ) { 173 ) {
175 self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) 174 self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink))
@@ -761,7 +760,7 @@ impl std::ops::BitOrAssign for Diverges {
761} 760}
762 761
763mod diagnostics { 762mod diagnostics {
764 use hir_def::{expr::ExprId, FunctionId}; 763 use hir_def::{expr::ExprId, DefWithBodyId};
765 use hir_expand::diagnostics::DiagnosticSink; 764 use hir_expand::diagnostics::DiagnosticSink;
766 765
767 use crate::{ 766 use crate::{
@@ -779,17 +778,17 @@ mod diagnostics {
779 pub(super) fn add_to( 778 pub(super) fn add_to(
780 &self, 779 &self,
781 db: &dyn HirDatabase, 780 db: &dyn HirDatabase,
782 owner: FunctionId, 781 owner: DefWithBodyId,
783 sink: &mut DiagnosticSink, 782 sink: &mut DiagnosticSink,
784 ) { 783 ) {
785 match self { 784 match self {
786 InferenceDiagnostic::NoSuchField { expr, field } => { 785 InferenceDiagnostic::NoSuchField { expr, field } => {
787 let (_, source_map) = db.body_with_source_map(owner.into()); 786 let (_, source_map) = db.body_with_source_map(owner);
788 let field = source_map.field_syntax(*expr, *field); 787 let field = source_map.field_syntax(*expr, *field);
789 sink.push(NoSuchField { file: field.file_id, field: field.value }) 788 sink.push(NoSuchField { file: field.file_id, field: field.value })
790 } 789 }
791 InferenceDiagnostic::BreakOutsideOfLoop { expr } => { 790 InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
792 let (_, source_map) = db.body_with_source_map(owner.into()); 791 let (_, source_map) = db.body_with_source_map(owner);
793 let ptr = source_map 792 let ptr = source_map
794 .expr_syntax(*expr) 793 .expr_syntax(*expr)
795 .expect("break outside of loop in synthetic syntax"); 794 .expect("break outside of loop in synthetic syntax");
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 22884522a..731b062c2 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -17,7 +17,7 @@ use crate::{
17 autoderef, method_resolution, op, 17 autoderef, method_resolution, op,
18 traits::{FnTrait, InEnvironment}, 18 traits::{FnTrait, InEnvironment},
19 utils::{generics, variant_data, Generics}, 19 utils::{generics, variant_data, Generics},
20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, 20 ApplicationTy, Binders, CallableDefId, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
21 TraitRef, Ty, TypeCtor, 21 TraitRef, Ty, TypeCtor,
22}; 22};
23 23
@@ -85,10 +85,8 @@ impl<'a> InferenceContext<'a> {
85 ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, 85 ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
86 parameters, 86 parameters,
87 }); 87 });
88 let substs = Substs::build_for_generics(&generic_params) 88 let substs =
89 .push(ty.clone()) 89 Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
90 .push(arg_ty.clone())
91 .build();
92 90
93 let trait_env = Arc::clone(&self.trait_env); 91 let trait_env = Arc::clone(&self.trait_env);
94 let implements_fn_trait = 92 let implements_fn_trait =
@@ -222,7 +220,7 @@ impl<'a> InferenceContext<'a> {
222 }; 220 };
223 sig_tys.push(ret_ty.clone()); 221 sig_tys.push(ret_ty.clone());
224 let sig_ty = Ty::apply( 222 let sig_ty = Ty::apply(
225 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 223 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false },
226 Substs(sig_tys.clone().into()), 224 Substs(sig_tys.clone().into()),
227 ); 225 );
228 let closure_ty = 226 let closure_ty =
@@ -407,8 +405,15 @@ impl<'a> InferenceContext<'a> {
407 .subst(&a_ty.parameters) 405 .subst(&a_ty.parameters)
408 }) 406 })
409 } 407 }
410 // FIXME: 408 TypeCtor::Adt(AdtId::UnionId(u)) => {
411 TypeCtor::Adt(AdtId::UnionId(_)) => None, 409 self.db.union_data(u).variant_data.field(name).map(|local_id| {
410 let field = FieldId { parent: u.into(), local_id };
411 self.write_field_resolution(tgt_expr, field);
412 self.db.field_types(u.into())[field.local_id]
413 .clone()
414 .subst(&a_ty.parameters)
415 })
416 }
412 _ => None, 417 _ => None,
413 }, 418 },
414 _ => None, 419 _ => None,
@@ -849,7 +854,7 @@ impl<'a> InferenceContext<'a> {
849 } 854 }
850 // add obligation for trait implementation, if this is a trait method 855 // add obligation for trait implementation, if this is a trait method
851 match def { 856 match def {
852 CallableDef::FunctionId(f) => { 857 CallableDefId::FunctionId(f) => {
853 if let AssocContainerId::TraitId(trait_) = 858 if let AssocContainerId::TraitId(trait_) =
854 f.lookup(self.db.upcast()).container 859 f.lookup(self.db.upcast()).container
855 { 860 {
@@ -860,7 +865,7 @@ impl<'a> InferenceContext<'a> {
860 self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); 865 self.obligations.push(Obligation::Trait(TraitRef { trait_, substs }));
861 } 866 }
862 } 867 }
863 CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {} 868 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
864 } 869 }
865 } 870 }
866 } 871 }
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 7f3f5e771..7698cb0d4 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -6,25 +6,6 @@ macro_rules! eprintln {
6 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; 6 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
7} 7}
8 8
9macro_rules! impl_froms {
10 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => {
11 $(
12 impl From<$v> for $e {
13 fn from(it: $v) -> $e {
14 $e::$v(it)
15 }
16 }
17 $($(
18 impl From<$sv> for $e {
19 fn from(it: $sv) -> $e {
20 $e::$v($v::$sv(it))
21 }
22 }
23 )*)?
24 )*
25 }
26}
27
28mod autoderef; 9mod autoderef;
29pub mod primitive; 10pub mod primitive;
30pub mod traits; 11pub mod traits;
@@ -32,22 +13,18 @@ pub mod method_resolution;
32mod op; 13mod op;
33mod lower; 14mod lower;
34pub(crate) mod infer; 15pub(crate) mod infer;
35pub mod display;
36pub(crate) mod utils; 16pub(crate) mod utils;
17
18pub mod display;
37pub mod db; 19pub mod db;
38pub mod diagnostics; 20pub mod diagnostics;
39pub mod expr;
40pub mod unsafe_validation;
41 21
42#[cfg(test)] 22#[cfg(test)]
43mod tests; 23mod tests;
44#[cfg(test)] 24#[cfg(test)]
45mod test_db; 25mod test_db;
46mod _match;
47 26
48use std::ops::Deref; 27use std::{iter, mem, ops::Deref, sync::Arc};
49use std::sync::Arc;
50use std::{iter, mem};
51 28
52use hir_def::{ 29use hir_def::{
53 expr::ExprId, 30 expr::ExprId,
@@ -55,18 +32,19 @@ use hir_def::{
55 AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, 32 AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId,
56 TypeParamId, 33 TypeParamId,
57}; 34};
58use ra_db::{impl_intern_key, salsa, CrateId}; 35use itertools::Itertools;
36use ra_db::{salsa, CrateId};
59 37
60use crate::{ 38use crate::{
61 db::HirDatabase, 39 db::HirDatabase,
40 display::HirDisplay,
62 primitive::{FloatTy, IntTy}, 41 primitive::{FloatTy, IntTy},
63 utils::{generics, make_mut_slice, Generics}, 42 utils::{generics, make_mut_slice, Generics},
64}; 43};
65use display::HirDisplay;
66 44
67pub use autoderef::autoderef; 45pub use autoderef::autoderef;
68pub use infer::{InferTy, InferenceResult}; 46pub use infer::{InferTy, InferenceResult};
69pub use lower::CallableDef; 47pub use lower::CallableDefId;
70pub use lower::{ 48pub use lower::{
71 associated_type_shorthand_candidates, callable_item_sig, ImplTraitLoweringMode, TyDefId, 49 associated_type_shorthand_candidates, callable_item_sig, ImplTraitLoweringMode, TyDefId,
72 TyLoweringContext, ValueTyDefId, 50 TyLoweringContext, ValueTyDefId,
@@ -74,7 +52,6 @@ pub use lower::{
74pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 52pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
75 53
76pub use chalk_ir::{BoundVar, DebruijnIndex}; 54pub use chalk_ir::{BoundVar, DebruijnIndex};
77use itertools::Itertools;
78 55
79/// A type constructor or type name: this might be something like the primitive 56/// A type constructor or type name: this might be something like the primitive
80/// type `bool`, a struct like `Vec`, or things like function pointers or 57/// type `bool`, a struct like `Vec`, or things like function pointers or
@@ -125,7 +102,7 @@ pub enum TypeCtor {
125 /// fn foo() -> i32 { 1 } 102 /// fn foo() -> i32 { 1 }
126 /// let bar = foo; // bar: fn() -> i32 {foo} 103 /// let bar = foo; // bar: fn() -> i32 {foo}
127 /// ``` 104 /// ```
128 FnDef(CallableDef), 105 FnDef(CallableDefId),
129 106
130 /// A pointer to a function. Written as `fn() -> i32`. 107 /// A pointer to a function. Written as `fn() -> i32`.
131 /// 108 ///
@@ -135,7 +112,8 @@ pub enum TypeCtor {
135 /// fn foo() -> i32 { 1 } 112 /// fn foo() -> i32 { 1 }
136 /// let bar: fn() -> i32 = foo; 113 /// let bar: fn() -> i32 = foo;
137 /// ``` 114 /// ```
138 FnPtr { num_args: u16 }, 115 // FIXME make this a Ty variant like in Chalk
116 FnPtr { num_args: u16, is_varargs: bool },
139 117
140 /// The never type `!`. 118 /// The never type `!`.
141 Never, 119 Never,
@@ -162,19 +140,6 @@ pub enum TypeCtor {
162 Closure { def: DefWithBodyId, expr: ExprId }, 140 Closure { def: DefWithBodyId, expr: ExprId },
163} 141}
164 142
165/// This exists just for Chalk, because Chalk just has a single `StructId` where
166/// we have different kinds of ADTs, primitive types and special type
167/// constructors like tuples and function pointers.
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
169pub struct TypeCtorId(salsa::InternId);
170impl_intern_key!(TypeCtorId);
171
172/// This exists just for Chalk, because Chalk just has a single `FnDefId` where
173/// we have different IDs for struct and enum variant constructors.
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
175pub struct CallableDefId(salsa::InternId);
176impl_intern_key!(CallableDefId);
177
178impl TypeCtor { 143impl TypeCtor {
179 pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize { 144 pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize {
180 match self { 145 match self {
@@ -210,7 +175,7 @@ impl TypeCtor {
210 } 175 }
211 } 176 }
212 } 177 }
213 TypeCtor::FnPtr { num_args } => num_args as usize + 1, 178 TypeCtor::FnPtr { num_args, is_varargs: _ } => num_args as usize + 1,
214 TypeCtor::Tuple { cardinality } => cardinality as usize, 179 TypeCtor::Tuple { cardinality } => cardinality as usize,
215 } 180 }
216 } 181 }
@@ -690,19 +655,20 @@ pub enum TyKind {
690#[derive(Clone, PartialEq, Eq, Debug)] 655#[derive(Clone, PartialEq, Eq, Debug)]
691pub struct FnSig { 656pub struct FnSig {
692 params_and_return: Arc<[Ty]>, 657 params_and_return: Arc<[Ty]>,
658 is_varargs: bool,
693} 659}
694 660
695/// A polymorphic function signature. 661/// A polymorphic function signature.
696pub type PolyFnSig = Binders<FnSig>; 662pub type PolyFnSig = Binders<FnSig>;
697 663
698impl FnSig { 664impl FnSig {
699 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { 665 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> FnSig {
700 params.push(ret); 666 params.push(ret);
701 FnSig { params_and_return: params.into() } 667 FnSig { params_and_return: params.into(), is_varargs }
702 } 668 }
703 669
704 pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig { 670 pub fn from_fn_ptr_substs(substs: &Substs, is_varargs: bool) -> FnSig {
705 FnSig { params_and_return: Arc::clone(&substs.0) } 671 FnSig { params_and_return: Arc::clone(&substs.0), is_varargs }
706 } 672 }
707 673
708 pub fn params(&self) -> &[Ty] { 674 pub fn params(&self) -> &[Ty] {
@@ -747,7 +713,7 @@ impl Ty {
747 } 713 }
748 pub fn fn_ptr(sig: FnSig) -> Self { 714 pub fn fn_ptr(sig: FnSig) -> Self {
749 Ty::apply( 715 Ty::apply(
750 TypeCtor::FnPtr { num_args: sig.params().len() as u16 }, 716 TypeCtor::FnPtr { num_args: sig.params().len() as u16, is_varargs: sig.is_varargs },
751 Substs(sig.params_and_return), 717 Substs(sig.params_and_return),
752 ) 718 )
753 } 719 }
@@ -801,15 +767,6 @@ impl Ty {
801 } 767 }
802 } 768 }
803 769
804 pub fn as_callable(&self) -> Option<(CallableDef, &Substs)> {
805 match self {
806 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(callable_def), parameters }) => {
807 Some((*callable_def, parameters))
808 }
809 _ => None,
810 }
811 }
812
813 pub fn is_never(&self) -> bool { 770 pub fn is_never(&self) -> bool {
814 matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. })) 771 matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }))
815 } 772 }
@@ -841,10 +798,12 @@ impl Ty {
841 } 798 }
842 } 799 }
843 800
844 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> { 801 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> {
845 match self { 802 match self {
846 Ty::Apply(a_ty) => match a_ty.ctor { 803 Ty::Apply(a_ty) => match a_ty.ctor {
847 TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)), 804 TypeCtor::FnPtr { is_varargs, .. } => {
805 Some(FnSig::from_fn_ptr_substs(&a_ty.parameters, is_varargs))
806 }
848 TypeCtor::FnDef(def) => { 807 TypeCtor::FnDef(def) => {
849 let sig = db.callable_item_signature(def); 808 let sig = db.callable_item_signature(def);
850 Some(sig.subst(&a_ty.parameters)) 809 Some(sig.subst(&a_ty.parameters))
@@ -891,7 +850,7 @@ impl Ty {
891 let data = (*it) 850 let data = (*it)
892 .as_ref() 851 .as_ref()
893 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 852 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
894 data.clone().subst(&opaque_ty.parameters) 853 data.subst(&opaque_ty.parameters)
895 }) 854 })
896 } 855 }
897 }; 856 };
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 3dc154e92..1eacc6f95 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -5,10 +5,7 @@
5//! - Building the type for an item: This happens through the `type_for_def` query. 5//! - Building the type for an item: This happens through the `type_for_def` query.
6//! 6//!
7//! This usually involves resolving names, collecting generic arguments etc. 7//! This usually involves resolving names, collecting generic arguments etc.
8use std::iter; 8use std::{iter, sync::Arc};
9use std::sync::Arc;
10
11use smallvec::SmallVec;
12 9
13use hir_def::{ 10use hir_def::{
14 adt::StructKind, 11 adt::StructKind,
@@ -24,6 +21,8 @@ use hir_def::{
24use hir_expand::name::Name; 21use hir_expand::name::Name;
25use ra_arena::map::ArenaMap; 22use ra_arena::map::ArenaMap;
26use ra_db::CrateId; 23use ra_db::CrateId;
24use smallvec::SmallVec;
25use stdx::impl_from;
27use test_utils::mark; 26use test_utils::mark;
28 27
29use crate::{ 28use crate::{
@@ -177,9 +176,12 @@ impl Ty {
177 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) 176 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
178 } 177 }
179 TypeRef::Placeholder => Ty::Unknown, 178 TypeRef::Placeholder => Ty::Unknown,
180 TypeRef::Fn(params) => { 179 TypeRef::Fn(params, is_varargs) => {
181 let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); 180 let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect());
182 Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) 181 Ty::apply(
182 TypeCtor::FnPtr { num_args: sig.len() as u16 - 1, is_varargs: *is_varargs },
183 sig,
184 )
183 } 185 }
184 TypeRef::DynTrait(bounds) => { 186 TypeRef::DynTrait(bounds) => {
185 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); 187 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
@@ -339,7 +341,7 @@ impl Ty {
339 let segment = remaining_segments.first().unwrap(); 341 let segment = remaining_segments.first().unwrap();
340 let found = associated_type_by_name_including_super_traits( 342 let found = associated_type_by_name_including_super_traits(
341 ctx.db, 343 ctx.db,
342 trait_ref.clone(), 344 trait_ref,
343 &segment.name, 345 &segment.name,
344 ); 346 );
345 match found { 347 match found {
@@ -720,8 +722,7 @@ fn assoc_type_bindings_from_type_bound<'a>(
720 None => return SmallVec::<[GenericPredicate; 1]>::new(), 722 None => return SmallVec::<[GenericPredicate; 1]>::new(),
721 Some(t) => t, 723 Some(t) => t,
722 }; 724 };
723 let projection_ty = 725 let projection_ty = ProjectionTy { associated_ty, parameters: super_trait_ref.substs };
724 ProjectionTy { associated_ty, parameters: super_trait_ref.substs.clone() };
725 let mut preds = SmallVec::with_capacity( 726 let mut preds = SmallVec::with_capacity(
726 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), 727 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
727 ); 728 );
@@ -767,11 +768,11 @@ fn count_impl_traits(type_ref: &TypeRef) -> usize {
767} 768}
768 769
769/// Build the signature of a callable item (function, struct or enum variant). 770/// Build the signature of a callable item (function, struct or enum variant).
770pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig { 771pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
771 match def { 772 match def {
772 CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), 773 CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
773 CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), 774 CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
774 CallableDef::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e), 775 CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
775 } 776 }
776} 777}
777 778
@@ -998,7 +999,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
998 let ret = Ty::from_hir(&ctx_ret, &data.ret_type); 999 let ret = Ty::from_hir(&ctx_ret, &data.ret_type);
999 let generics = generics(db.upcast(), def.into()); 1000 let generics = generics(db.upcast(), def.into());
1000 let num_binders = generics.len(); 1001 let num_binders = generics.len();
1001 Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) 1002 Binders::new(num_binders, FnSig::from_params_and_return(params, ret, data.is_varargs))
1002} 1003}
1003 1004
1004/// Build the declared type of a function. This should not need to look at the 1005/// Build the declared type of a function. This should not need to look at the
@@ -1049,7 +1050,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
1049 let params = 1050 let params =
1050 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); 1051 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
1051 let ret = type_for_adt(db, def.into()); 1052 let ret = type_for_adt(db, def.into());
1052 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) 1053 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false))
1053} 1054}
1054 1055
1055/// Build the type of a tuple struct constructor. 1056/// Build the type of a tuple struct constructor.
@@ -1073,7 +1074,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
1073 let params = 1074 let params =
1074 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); 1075 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
1075 let ret = type_for_adt(db, def.parent.into()); 1076 let ret = type_for_adt(db, def.parent.into());
1076 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) 1077 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false))
1077} 1078}
1078 1079
1079/// Build the type of a tuple enum variant constructor. 1080/// Build the type of a tuple enum variant constructor.
@@ -1106,31 +1107,31 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
1106} 1107}
1107 1108
1108#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 1109#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1109pub enum CallableDef { 1110pub enum CallableDefId {
1110 FunctionId(FunctionId), 1111 FunctionId(FunctionId),
1111 StructId(StructId), 1112 StructId(StructId),
1112 EnumVariantId(EnumVariantId), 1113 EnumVariantId(EnumVariantId),
1113} 1114}
1114impl_froms!(CallableDef: FunctionId, StructId, EnumVariantId); 1115impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId);
1115 1116
1116impl CallableDef { 1117impl CallableDefId {
1117 pub fn krate(self, db: &dyn HirDatabase) -> CrateId { 1118 pub fn krate(self, db: &dyn HirDatabase) -> CrateId {
1118 let db = db.upcast(); 1119 let db = db.upcast();
1119 match self { 1120 match self {
1120 CallableDef::FunctionId(f) => f.lookup(db).module(db), 1121 CallableDefId::FunctionId(f) => f.lookup(db).module(db),
1121 CallableDef::StructId(s) => s.lookup(db).container.module(db), 1122 CallableDefId::StructId(s) => s.lookup(db).container.module(db),
1122 CallableDef::EnumVariantId(e) => e.parent.lookup(db).container.module(db), 1123 CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container.module(db),
1123 } 1124 }
1124 .krate 1125 .krate
1125 } 1126 }
1126} 1127}
1127 1128
1128impl From<CallableDef> for GenericDefId { 1129impl From<CallableDefId> for GenericDefId {
1129 fn from(def: CallableDef) -> GenericDefId { 1130 fn from(def: CallableDefId) -> GenericDefId {
1130 match def { 1131 match def {
1131 CallableDef::FunctionId(f) => f.into(), 1132 CallableDefId::FunctionId(f) => f.into(),
1132 CallableDef::StructId(s) => s.into(), 1133 CallableDefId::StructId(s) => s.into(),
1133 CallableDef::EnumVariantId(e) => e.into(), 1134 CallableDefId::EnumVariantId(e) => e.into(),
1134 } 1135 }
1135 } 1136 }
1136} 1137}
@@ -1141,7 +1142,7 @@ pub enum TyDefId {
1141 AdtId(AdtId), 1142 AdtId(AdtId),
1142 TypeAliasId(TypeAliasId), 1143 TypeAliasId(TypeAliasId),
1143} 1144}
1144impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId); 1145impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId);
1145 1146
1146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1147pub enum ValueTyDefId { 1148pub enum ValueTyDefId {
@@ -1151,7 +1152,7 @@ pub enum ValueTyDefId {
1151 ConstId(ConstId), 1152 ConstId(ConstId),
1152 StaticId(StaticId), 1153 StaticId(StaticId),
1153} 1154}
1154impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId); 1155impl_from!(FunctionId, StructId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
1155 1156
1156/// Build the declared type of an item. This depends on the namespace; e.g. for 1157/// Build the declared type of an item. This depends on the namespace; e.g. for
1157/// `struct Foo(usize)`, we have two types: The type of the struct itself, and 1158/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
@@ -1216,7 +1217,7 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
1216} 1217}
1217 1218
1218pub(crate) fn return_type_impl_traits( 1219pub(crate) fn return_type_impl_traits(
1219 db: &impl HirDatabase, 1220 db: &dyn HirDatabase,
1220 def: hir_def::FunctionId, 1221 def: hir_def::FunctionId,
1221) -> Option<Arc<Binders<ReturnTypeImplTraits>>> { 1222) -> Option<Arc<Binders<ReturnTypeImplTraits>>> {
1222 // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe 1223 // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index a45febbf7..fb4b30a13 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -6,8 +6,10 @@ use std::{iter, sync::Arc};
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId, 9 builtin_type::{IntBitness, Signedness},
10 HasModule, ImplId, Lookup, TraitId, 10 lang_item::LangItemTarget,
11 type_ref::Mutability,
12 AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
11}; 13};
12use hir_expand::name::Name; 14use hir_expand::name::Name;
13use ra_db::CrateId; 15use ra_db::CrateId;
@@ -16,9 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet};
16 18
17use super::Substs; 19use super::Substs;
18use crate::{ 20use crate::{
19 autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy, 21 autoderef,
20 Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor, 22 db::HirDatabase,
21 TypeWalk, 23 primitive::{FloatBitness, FloatTy, IntTy},
24 utils::all_super_traits,
25 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind,
26 TypeCtor, TypeWalk,
22}; 27};
23 28
24/// This is used as a key for indexing impls. 29/// This is used as a key for indexing impls.
@@ -39,6 +44,62 @@ impl TyFingerprint {
39 } 44 }
40} 45}
41 46
47pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
48 TyFingerprint::Apply(TypeCtor::Int(IntTy {
49 signedness: Signedness::Unsigned,
50 bitness: IntBitness::X8,
51 })),
52 TyFingerprint::Apply(TypeCtor::Int(IntTy {
53 signedness: Signedness::Unsigned,
54 bitness: IntBitness::X16,
55 })),
56 TyFingerprint::Apply(TypeCtor::Int(IntTy {
57 signedness: Signedness::Unsigned,
58 bitness: IntBitness::X32,
59 })),
60 TyFingerprint::Apply(TypeCtor::Int(IntTy {
61 signedness: Signedness::Unsigned,
62 bitness: IntBitness::X64,
63 })),
64 TyFingerprint::Apply(TypeCtor::Int(IntTy {
65 signedness: Signedness::Unsigned,
66 bitness: IntBitness::X128,
67 })),
68 TyFingerprint::Apply(TypeCtor::Int(IntTy {
69 signedness: Signedness::Unsigned,
70 bitness: IntBitness::Xsize,
71 })),
72 TyFingerprint::Apply(TypeCtor::Int(IntTy {
73 signedness: Signedness::Signed,
74 bitness: IntBitness::X8,
75 })),
76 TyFingerprint::Apply(TypeCtor::Int(IntTy {
77 signedness: Signedness::Signed,
78 bitness: IntBitness::X16,
79 })),
80 TyFingerprint::Apply(TypeCtor::Int(IntTy {
81 signedness: Signedness::Signed,
82 bitness: IntBitness::X32,
83 })),
84 TyFingerprint::Apply(TypeCtor::Int(IntTy {
85 signedness: Signedness::Signed,
86 bitness: IntBitness::X64,
87 })),
88 TyFingerprint::Apply(TypeCtor::Int(IntTy {
89 signedness: Signedness::Signed,
90 bitness: IntBitness::X128,
91 })),
92 TyFingerprint::Apply(TypeCtor::Int(IntTy {
93 signedness: Signedness::Signed,
94 bitness: IntBitness::Xsize,
95 })),
96];
97
98pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [
99 TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })),
100 TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })),
101];
102
42/// Trait impls defined or available in some crate. 103/// Trait impls defined or available in some crate.
43#[derive(Debug, Eq, PartialEq)] 104#[derive(Debug, Eq, PartialEq)]
44pub struct TraitImpls { 105pub struct TraitImpls {
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index fddf0604d..a1714ff0f 100644
--- a/crates/ra_hir_ty/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -1,23 +1,17 @@
1//! Database used for testing `hir`. 1//! Database used for testing `hir`.
2 2
3use std::{ 3use std::{
4 panic, 4 fmt, panic,
5 sync::{Arc, Mutex}, 5 sync::{Arc, Mutex},
6}; 6};
7 7
8use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId, ModuleId}; 8use hir_def::{db::DefDatabase, ModuleId};
9use hir_expand::{db::AstDatabase, diagnostics::DiagnosticSink}; 9use hir_expand::db::AstDatabase;
10use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast}; 10use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast};
11use ra_syntax::TextRange; 11use ra_syntax::TextRange;
12use rustc_hash::{FxHashMap, FxHashSet}; 12use rustc_hash::{FxHashMap, FxHashSet};
13use stdx::format_to;
14use test_utils::extract_annotations; 13use test_utils::extract_annotations;
15 14
16use crate::{
17 db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator,
18 unsafe_validation::UnsafeValidator,
19};
20
21#[salsa::database( 15#[salsa::database(
22 ra_db::SourceDatabaseExtStorage, 16 ra_db::SourceDatabaseExtStorage,
23 ra_db::SourceDatabaseStorage, 17 ra_db::SourceDatabaseStorage,
@@ -26,10 +20,15 @@ use crate::{
26 hir_def::db::DefDatabaseStorage, 20 hir_def::db::DefDatabaseStorage,
27 crate::db::HirDatabaseStorage 21 crate::db::HirDatabaseStorage
28)] 22)]
29#[derive(Debug, Default)] 23#[derive(Default)]
30pub struct TestDB { 24pub struct TestDB {
31 events: Mutex<Option<Vec<salsa::Event<TestDB>>>>, 25 storage: salsa::Storage<TestDB>,
32 runtime: salsa::Runtime<TestDB>, 26 events: Mutex<Option<Vec<salsa::Event>>>,
27}
28impl fmt::Debug for TestDB {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.debug_struct("TestDB").finish()
31 }
33} 32}
34 33
35impl Upcast<dyn AstDatabase> for TestDB { 34impl Upcast<dyn AstDatabase> for TestDB {
@@ -45,18 +44,10 @@ impl Upcast<dyn DefDatabase> for TestDB {
45} 44}
46 45
47impl salsa::Database for TestDB { 46impl salsa::Database for TestDB {
48 fn salsa_runtime(&self) -> &salsa::Runtime<TestDB> { 47 fn salsa_event(&self, event: salsa::Event) {
49 &self.runtime
50 }
51
52 fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
53 &mut self.runtime
54 }
55
56 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
57 let mut events = self.events.lock().unwrap(); 48 let mut events = self.events.lock().unwrap();
58 if let Some(events) = &mut *events { 49 if let Some(events) = &mut *events {
59 events.push(event()); 50 events.push(event);
60 } 51 }
61 } 52 }
62} 53}
@@ -64,8 +55,8 @@ impl salsa::Database for TestDB {
64impl salsa::ParallelDatabase for TestDB { 55impl salsa::ParallelDatabase for TestDB {
65 fn snapshot(&self) -> salsa::Snapshot<TestDB> { 56 fn snapshot(&self) -> salsa::Snapshot<TestDB> {
66 salsa::Snapshot::new(TestDB { 57 salsa::Snapshot::new(TestDB {
58 storage: self.storage.snapshot(),
67 events: Default::default(), 59 events: Default::default(),
68 runtime: self.runtime.snapshot(self),
69 }) 60 })
70 } 61 }
71} 62}
@@ -85,7 +76,7 @@ impl FileLoader for TestDB {
85} 76}
86 77
87impl TestDB { 78impl TestDB {
88 pub fn module_for_file(&self, file_id: FileId) -> ModuleId { 79 pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId {
89 for &krate in self.relevant_crates(file_id).iter() { 80 for &krate in self.relevant_crates(file_id).iter() {
90 let crate_def_map = self.crate_def_map(krate); 81 let crate_def_map = self.crate_def_map(krate);
91 for (local_id, data) in crate_def_map.modules.iter() { 82 for (local_id, data) in crate_def_map.modules.iter() {
@@ -97,67 +88,7 @@ impl TestDB {
97 panic!("Can't find module for file") 88 panic!("Can't find module for file")
98 } 89 }
99 90
100 fn diag<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) { 91 pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> {
101 let crate_graph = self.crate_graph();
102 for krate in crate_graph.iter() {
103 let crate_def_map = self.crate_def_map(krate);
104
105 let mut fns = Vec::new();
106 for (module_id, _) in crate_def_map.modules.iter() {
107 for decl in crate_def_map[module_id].scope.declarations() {
108 if let ModuleDefId::FunctionId(f) = decl {
109 fns.push(f)
110 }
111 }
112
113 for impl_id in crate_def_map[module_id].scope.impls() {
114 let impl_data = self.impl_data(impl_id);
115 for item in impl_data.items.iter() {
116 if let AssocItemId::FunctionId(f) = item {
117 fns.push(*f)
118 }
119 }
120 }
121 }
122
123 for f in fns {
124 let infer = self.infer(f.into());
125 let mut sink = DiagnosticSink::new(&mut cb);
126 infer.add_diagnostics(self, f, &mut sink);
127 let mut validator = ExprValidator::new(f, infer.clone(), &mut sink);
128 validator.validate_body(self);
129 let mut validator = UnsafeValidator::new(f, infer, &mut sink);
130 validator.validate_body(self);
131 }
132 }
133 }
134
135 pub fn diagnostics(&self) -> (String, u32) {
136 let mut buf = String::new();
137 let mut count = 0;
138 self.diag(|d| {
139 format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message());
140 count += 1;
141 });
142 (buf, count)
143 }
144
145 /// Like `diagnostics`, but filtered for a single diagnostic.
146 pub fn diagnostic<D: Diagnostic>(&self) -> (String, u32) {
147 let mut buf = String::new();
148 let mut count = 0;
149 self.diag(|d| {
150 // We want to filter diagnostics by the particular one we are testing for, to
151 // avoid surprising results in tests.
152 if d.downcast_ref::<D>().is_some() {
153 format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message());
154 count += 1;
155 };
156 });
157 (buf, count)
158 }
159
160 pub fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> {
161 let mut files = Vec::new(); 92 let mut files = Vec::new();
162 let crate_graph = self.crate_graph(); 93 let crate_graph = self.crate_graph();
163 for krate in crate_graph.iter() { 94 for krate in crate_graph.iter() {
@@ -182,7 +113,7 @@ impl TestDB {
182} 113}
183 114
184impl TestDB { 115impl TestDB {
185 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<TestDB>> { 116 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> {
186 *self.events.lock().unwrap() = Some(Vec::new()); 117 *self.events.lock().unwrap() = Some(Vec::new());
187 f(); 118 f();
188 self.events.lock().unwrap().take().unwrap() 119 self.events.lock().unwrap().take().unwrap()
@@ -196,7 +127,7 @@ impl TestDB {
196 // This pretty horrible, but `Debug` is the only way to inspect 127 // This pretty horrible, but `Debug` is the only way to inspect
197 // QueryDescriptor at the moment. 128 // QueryDescriptor at the moment.
198 salsa::EventKind::WillExecute { database_key } => { 129 salsa::EventKind::WillExecute { database_key } => {
199 Some(format!("{:?}", database_key)) 130 Some(format!("{:?}", database_key.debug(self)))
200 } 131 }
201 _ => None, 132 _ => None,
202 }) 133 })
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index eeac34d14..45bc14c37 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -10,6 +10,7 @@ mod display_source_code;
10 10
11use std::sync::Arc; 11use std::sync::Arc;
12 12
13use expect::Expect;
13use hir_def::{ 14use hir_def::{
14 body::{BodySourceMap, SyntheticSyntax}, 15 body::{BodySourceMap, SyntheticSyntax},
15 child_by_source::ChildBySource, 16 child_by_source::ChildBySource,
@@ -20,8 +21,7 @@ use hir_def::{
20 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, 21 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
21}; 22};
22use hir_expand::{db::AstDatabase, InFile}; 23use hir_expand::{db::AstDatabase, InFile};
23use insta::assert_snapshot; 24use ra_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt};
24use ra_db::{fixture::WithFixture, salsa::Database, FileRange, SourceDatabase};
25use ra_syntax::{ 25use ra_syntax::{
26 algo, 26 algo,
27 ast::{self, AstNode}, 27 ast::{self, AstNode},
@@ -34,8 +34,21 @@ use crate::{
34}; 34};
35 35
36// These tests compare the inference results for all expressions in a file 36// These tests compare the inference results for all expressions in a file
37// against snapshots of the expected results using insta. Use cargo-insta to 37// against snapshots of the expected results using expect. Use
38// update the snapshots. 38// `env UPDATE_EXPECT=1 cargo test -p ra_hir_ty` to update the snapshots.
39
40fn setup_tracing() -> tracing::subscriber::DefaultGuard {
41 use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
42 use tracing_tree::HierarchicalLayer;
43 let filter = EnvFilter::from_env("CHALK_DEBUG");
44 let layer = HierarchicalLayer::default()
45 .with_indent_lines(true)
46 .with_ansi(false)
47 .with_indent_amount(2)
48 .with_writer(std::io::stderr);
49 let subscriber = Registry::default().with(filter).with(layer);
50 tracing::subscriber::set_default(subscriber)
51}
39 52
40fn check_types(ra_fixture: &str) { 53fn check_types(ra_fixture: &str) {
41 check_types_impl(ra_fixture, false) 54 check_types_impl(ra_fixture, false)
@@ -46,6 +59,7 @@ fn check_types_source_code(ra_fixture: &str) {
46} 59}
47 60
48fn check_types_impl(ra_fixture: &str, display_source: bool) { 61fn check_types_impl(ra_fixture: &str, display_source: bool) {
62 let _tracing = setup_tracing();
49 let db = TestDB::with_files(ra_fixture); 63 let db = TestDB::with_files(ra_fixture);
50 let mut checked_one = false; 64 let mut checked_one = false;
51 for (file_id, annotations) in db.extract_annotations() { 65 for (file_id, annotations) in db.extract_annotations() {
@@ -86,6 +100,7 @@ fn infer(ra_fixture: &str) -> String {
86} 100}
87 101
88fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { 102fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
103 let _tracing = setup_tracing();
89 let (db, file_id) = TestDB::with_single_file(content); 104 let (db, file_id) = TestDB::with_single_file(content);
90 105
91 let mut buf = String::new(); 106 let mut buf = String::new();
@@ -317,7 +332,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
317 " 332 "
318 .to_string(); 333 .to_string();
319 334
320 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text)); 335 db.set_file_text(pos.file_id, Arc::new(new_text));
321 336
322 { 337 {
323 let events = db.log_executed(|| { 338 let events = db.log_executed(|| {
@@ -331,409 +346,14 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
331 } 346 }
332} 347}
333 348
334#[test] 349fn check_infer(ra_fixture: &str, expect: Expect) {
335fn no_such_field_diagnostics() { 350 let mut actual = infer(ra_fixture);
336 let diagnostics = TestDB::with_files( 351 actual.push('\n');
337 r" 352 expect.assert_eq(&actual);
338 //- /lib.rs
339 struct S { foo: i32, bar: () }
340 impl S {
341 fn new() -> S {
342 S {
343 foo: 92,
344 baz: 62,
345 }
346 }
347 }
348 ",
349 )
350 .diagnostics()
351 .0;
352
353 assert_snapshot!(diagnostics, @r###"
354 "baz: 62": no such field
355 "{\n foo: 92,\n baz: 62,\n }": Missing structure fields:
356 - bar
357 "###
358 );
359}
360
361#[test]
362fn no_such_field_with_feature_flag_diagnostics() {
363 let diagnostics = TestDB::with_files(
364 r#"
365 //- /lib.rs crate:foo cfg:feature=foo
366 struct MyStruct {
367 my_val: usize,
368 #[cfg(feature = "foo")]
369 bar: bool,
370 }
371
372 impl MyStruct {
373 #[cfg(feature = "foo")]
374 pub(crate) fn new(my_val: usize, bar: bool) -> Self {
375 Self { my_val, bar }
376 }
377
378 #[cfg(not(feature = "foo"))]
379 pub(crate) fn new(my_val: usize, _bar: bool) -> Self {
380 Self { my_val }
381 }
382 }
383 "#,
384 )
385 .diagnostics()
386 .0;
387
388 assert_snapshot!(diagnostics, @r###""###);
389}
390
391#[test]
392fn no_such_field_enum_with_feature_flag_diagnostics() {
393 let diagnostics = TestDB::with_files(
394 r#"
395 //- /lib.rs crate:foo cfg:feature=foo
396 enum Foo {
397 #[cfg(not(feature = "foo"))]
398 Buz,
399 #[cfg(feature = "foo")]
400 Bar,
401 Baz
402 }
403
404 fn test_fn(f: Foo) {
405 match f {
406 Foo::Bar => {},
407 Foo::Baz => {},
408 }
409 }
410 "#,
411 )
412 .diagnostics()
413 .0;
414
415 assert_snapshot!(diagnostics, @r###""###);
416}
417
418#[test]
419fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() {
420 let diagnostics = TestDB::with_files(
421 r#"
422 //- /lib.rs crate:foo cfg:feature=foo
423 struct S {
424 #[cfg(feature = "foo")]
425 foo: u32,
426 #[cfg(not(feature = "foo"))]
427 bar: u32,
428 }
429
430 impl S {
431 #[cfg(feature = "foo")]
432 fn new(foo: u32) -> Self {
433 Self { foo }
434 }
435 #[cfg(not(feature = "foo"))]
436 fn new(bar: u32) -> Self {
437 Self { bar }
438 }
439 }
440 "#,
441 )
442 .diagnostics()
443 .0;
444
445 assert_snapshot!(diagnostics, @r###""###);
446}
447
448#[test]
449fn no_such_field_with_feature_flag_diagnostics_on_block_expr() {
450 let diagnostics = TestDB::with_files(
451 r#"
452 //- /lib.rs crate:foo cfg:feature=foo
453 struct S {
454 #[cfg(feature = "foo")]
455 foo: u32,
456 #[cfg(not(feature = "foo"))]
457 bar: u32,
458 }
459
460 impl S {
461 fn new(bar: u32) -> Self {
462 #[cfg(feature = "foo")]
463 {
464 Self { foo: bar }
465 }
466 #[cfg(not(feature = "foo"))]
467 {
468 Self { bar }
469 }
470 }
471 }
472 "#,
473 )
474 .diagnostics()
475 .0;
476
477 assert_snapshot!(diagnostics, @r###""###);
478}
479
480#[test]
481fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() {
482 let diagnostics = TestDB::with_files(
483 r#"
484 //- /lib.rs crate:foo cfg:feature=foo
485 struct S {
486 #[cfg(feature = "foo")]
487 foo: u32,
488 #[cfg(not(feature = "foo"))]
489 bar: u32,
490 }
491
492 impl S {
493 fn new(val: u32) -> Self {
494 Self {
495 #[cfg(feature = "foo")]
496 foo: val,
497 #[cfg(not(feature = "foo"))]
498 bar: val,
499 }
500 }
501 }
502 "#,
503 )
504 .diagnostics()
505 .0;
506
507 assert_snapshot!(diagnostics, @r###""###);
508}
509
510#[test]
511fn no_such_field_with_type_macro() {
512 let diagnostics = TestDB::with_files(
513 r"
514 macro_rules! Type {
515 () => { u32 };
516 }
517
518 struct Foo {
519 bar: Type![],
520 }
521 impl Foo {
522 fn new() -> Self {
523 Foo { bar: 0 }
524 }
525 }
526 ",
527 )
528 .diagnostics()
529 .0;
530
531 assert_snapshot!(diagnostics, @r###""###);
532} 353}
533 354
534#[test] 355fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) {
535fn missing_record_pat_field_diagnostic() { 356 let mut actual = infer_with_mismatches(ra_fixture, true);
536 let diagnostics = TestDB::with_files( 357 actual.push('\n');
537 r" 358 expect.assert_eq(&actual);
538 //- /lib.rs
539 struct S { foo: i32, bar: () }
540 fn baz(s: S) {
541 let S { foo: _ } = s;
542 }
543 ",
544 )
545 .diagnostics()
546 .0;
547
548 assert_snapshot!(diagnostics, @r###"
549 "{ foo: _ }": Missing structure fields:
550 - bar
551 "###
552 );
553}
554
555#[test]
556fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
557 let diagnostics = TestDB::with_files(
558 r"
559 //- /lib.rs
560 struct S { foo: i32, bar: () }
561 fn baz(s: S) -> i32 {
562 match s {
563 S { foo, .. } => foo,
564 }
565 }
566 ",
567 )
568 .diagnostics()
569 .0;
570
571 assert_snapshot!(diagnostics, @"");
572}
573
574#[test]
575fn missing_unsafe_diagnostic_with_raw_ptr() {
576 let diagnostics = TestDB::with_files(
577 r"
578//- /lib.rs
579fn missing_unsafe() {
580 let x = &5 as *const usize;
581 let y = *x;
582}
583",
584 )
585 .diagnostics()
586 .0;
587
588 assert_snapshot!(diagnostics, @r#""*x": This operation is unsafe and requires an unsafe function or block"#);
589}
590
591#[test]
592fn missing_unsafe_diagnostic_with_unsafe_call() {
593 let diagnostics = TestDB::with_files(
594 r"
595//- /lib.rs
596unsafe fn unsafe_fn() {
597 let x = &5 as *const usize;
598 let y = *x;
599}
600
601fn missing_unsafe() {
602 unsafe_fn();
603}
604",
605 )
606 .diagnostics()
607 .0;
608
609 assert_snapshot!(diagnostics, @r#""unsafe_fn()": This operation is unsafe and requires an unsafe function or block"#);
610}
611
612#[test]
613fn missing_unsafe_diagnostic_with_unsafe_method_call() {
614 let diagnostics = TestDB::with_files(
615 r"
616struct HasUnsafe;
617
618impl HasUnsafe {
619 unsafe fn unsafe_fn(&self) {
620 let x = &5 as *const usize;
621 let y = *x;
622 }
623}
624
625fn missing_unsafe() {
626 HasUnsafe.unsafe_fn();
627}
628
629",
630 )
631 .diagnostics()
632 .0;
633
634 assert_snapshot!(diagnostics, @r#""HasUnsafe.unsafe_fn()": This operation is unsafe and requires an unsafe function or block"#);
635}
636
637#[test]
638fn no_missing_unsafe_diagnostic_with_raw_ptr_in_unsafe_block() {
639 let diagnostics = TestDB::with_files(
640 r"
641fn nothing_to_see_move_along() {
642 let x = &5 as *const usize;
643 unsafe {
644 let y = *x;
645 }
646}
647",
648 )
649 .diagnostics()
650 .0;
651
652 assert_snapshot!(diagnostics, @"");
653}
654
655#[test]
656fn missing_unsafe_diagnostic_with_raw_ptr_outside_unsafe_block() {
657 let diagnostics = TestDB::with_files(
658 r"
659fn nothing_to_see_move_along() {
660 let x = &5 as *const usize;
661 unsafe {
662 let y = *x;
663 }
664 let z = *x;
665}
666",
667 )
668 .diagnostics()
669 .0;
670
671 assert_snapshot!(diagnostics, @r#""*x": This operation is unsafe and requires an unsafe function or block"#);
672}
673
674#[test]
675fn no_missing_unsafe_diagnostic_with_unsafe_call_in_unsafe_block() {
676 let diagnostics = TestDB::with_files(
677 r"
678unsafe fn unsafe_fn() {
679 let x = &5 as *const usize;
680 let y = *x;
681}
682
683fn nothing_to_see_move_along() {
684 unsafe {
685 unsafe_fn();
686 }
687}
688",
689 )
690 .diagnostics()
691 .0;
692
693 assert_snapshot!(diagnostics, @"");
694}
695
696#[test]
697fn no_missing_unsafe_diagnostic_with_unsafe_method_call_in_unsafe_block() {
698 let diagnostics = TestDB::with_files(
699 r"
700struct HasUnsafe;
701
702impl HasUnsafe {
703 unsafe fn unsafe_fn() {
704 let x = &5 as *const usize;
705 let y = *x;
706 }
707}
708
709fn nothing_to_see_move_along() {
710 unsafe {
711 HasUnsafe.unsafe_fn();
712 }
713}
714
715",
716 )
717 .diagnostics()
718 .0;
719
720 assert_snapshot!(diagnostics, @"");
721}
722
723#[test]
724fn break_outside_of_loop() {
725 let diagnostics = TestDB::with_files(
726 r"
727 //- /lib.rs
728 fn foo() {
729 break;
730 }
731 ",
732 )
733 .diagnostics()
734 .0;
735
736 assert_snapshot!(diagnostics, @r###""break": break outside of loop
737 "###
738 );
739} 359}
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index 136d28a91..17efd75cb 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -1,345 +1,381 @@
1use insta::assert_snapshot; 1use expect::expect;
2use test_utils::mark; 2use test_utils::mark;
3 3
4use super::infer_with_mismatches; 4use super::{check_infer, check_infer_with_mismatches};
5
6// Infer with some common definitions and impls.
7fn infer(source: &str) -> String {
8 let defs = r#"
9 #[lang = "sized"]
10 pub trait Sized {}
11 #[lang = "unsize"]
12 pub trait Unsize<T: ?Sized> {}
13 #[lang = "coerce_unsized"]
14 pub trait CoerceUnsized<T> {}
15
16 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
17 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
18 "#;
19
20 // Append to the end to keep positions unchanged.
21 super::infer(&format!("{}{}", source, defs))
22}
23 5
24#[test] 6#[test]
25fn infer_block_expr_type_mismatch() { 7fn infer_block_expr_type_mismatch() {
26 assert_snapshot!( 8 check_infer(
27 infer(r#" 9 r"
28fn test() { 10 fn test() {
29 let a: i32 = { 1i64 }; 11 let a: i32 = { 1i64 };
30} 12 }
31"#), 13 ",
32 @r###" 14 expect![[r"
33 10..40 '{ ...4 }; }': () 15 10..40 '{ ...4 }; }': ()
34 20..21 'a': i32 16 20..21 'a': i32
35 29..37 '{ 1i64 }': i64 17 29..37 '{ 1i64 }': i64
36 31..35 '1i64': i64 18 31..35 '1i64': i64
37 "###); 19 "]],
20 );
38} 21}
39 22
40#[test] 23#[test]
41fn coerce_places() { 24fn coerce_places() {
42 assert_snapshot!( 25 check_infer(
43 infer(r#" 26 r#"
44struct S<T> { a: T } 27 struct S<T> { a: T }
45 28
46fn f<T>(_: &[T]) -> T { loop {} } 29 fn f<T>(_: &[T]) -> T { loop {} }
47fn g<T>(_: S<&[T]>) -> T { loop {} } 30 fn g<T>(_: S<&[T]>) -> T { loop {} }
48 31
49fn gen<T>() -> *mut [T; 2] { loop {} } 32 fn gen<T>() -> *mut [T; 2] { loop {} }
50fn test1<U>() -> *mut [U] { 33 fn test1<U>() -> *mut [U] {
51 gen() 34 gen()
52} 35 }
53 36
54fn test2() { 37 fn test2() {
55 let arr: &[u8; 1] = &[1]; 38 let arr: &[u8; 1] = &[1];
56 39
57 let a: &[_] = arr; 40 let a: &[_] = arr;
58 let b = f(arr); 41 let b = f(arr);
59 let c: &[_] = { arr }; 42 let c: &[_] = { arr };
60 let d = g(S { a: arr }); 43 let d = g(S { a: arr });
61 let e: [&[_]; 1] = [arr]; 44 let e: [&[_]; 1] = [arr];
62 let f: [&[_]; 2] = [arr; 2]; 45 let f: [&[_]; 2] = [arr; 2];
63 let g: (&[_], &[_]) = (arr, arr); 46 let g: (&[_], &[_]) = (arr, arr);
64} 47 }
65"#), 48
66 @r###" 49 #[lang = "sized"]
67 30..31 '_': &[T] 50 pub trait Sized {}
68 44..55 '{ loop {} }': T 51 #[lang = "unsize"]
69 46..53 'loop {}': ! 52 pub trait Unsize<T: ?Sized> {}
70 51..53 '{}': () 53 #[lang = "coerce_unsized"]
71 64..65 '_': S<&[T]> 54 pub trait CoerceUnsized<T> {}
72 81..92 '{ loop {} }': T 55
73 83..90 'loop {}': ! 56 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
74 88..90 '{}': () 57 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
75 121..132 '{ loop {} }': *mut [T; _] 58 "#,
76 123..130 'loop {}': ! 59 expect![[r"
77 128..130 '{}': () 60 30..31 '_': &[T]
78 159..172 '{ gen() }': *mut [U] 61 44..55 '{ loop {} }': T
79 165..168 'gen': fn gen<U>() -> *mut [U; _] 62 46..53 'loop {}': !
80 165..170 'gen()': *mut [U; _] 63 51..53 '{}': ()
81 185..419 '{ ...rr); }': () 64 64..65 '_': S<&[T]>
82 195..198 'arr': &[u8; _] 65 81..92 '{ loop {} }': T
83 211..215 '&[1]': &[u8; _] 66 83..90 'loop {}': !
84 212..215 '[1]': [u8; _] 67 88..90 '{}': ()
85 213..214 '1': u8 68 121..132 '{ loop {} }': *mut [T; _]
86 226..227 'a': &[u8] 69 123..130 'loop {}': !
87 236..239 'arr': &[u8; _] 70 128..130 '{}': ()
88 249..250 'b': u8 71 159..172 '{ gen() }': *mut [U]
89 253..254 'f': fn f<u8>(&[u8]) -> u8 72 165..168 'gen': fn gen<U>() -> *mut [U; _]
90 253..259 'f(arr)': u8 73 165..170 'gen()': *mut [U; _]
91 255..258 'arr': &[u8; _] 74 185..419 '{ ...rr); }': ()
92 269..270 'c': &[u8] 75 195..198 'arr': &[u8; _]
93 279..286 '{ arr }': &[u8] 76 211..215 '&[1]': &[u8; _]
94 281..284 'arr': &[u8; _] 77 212..215 '[1]': [u8; _]
95 296..297 'd': u8 78 213..214 '1': u8
96 300..301 'g': fn g<u8>(S<&[u8]>) -> u8 79 226..227 'a': &[u8]
97 300..315 'g(S { a: arr })': u8 80 236..239 'arr': &[u8; _]
98 302..314 'S { a: arr }': S<&[u8]> 81 249..250 'b': u8
99 309..312 'arr': &[u8; _] 82 253..254 'f': fn f<u8>(&[u8]) -> u8
100 325..326 'e': [&[u8]; _] 83 253..259 'f(arr)': u8
101 340..345 '[arr]': [&[u8]; _] 84 255..258 'arr': &[u8; _]
102 341..344 'arr': &[u8; _] 85 269..270 'c': &[u8]
103 355..356 'f': [&[u8]; _] 86 279..286 '{ arr }': &[u8]
104 370..378 '[arr; 2]': [&[u8]; _] 87 281..284 'arr': &[u8; _]
105 371..374 'arr': &[u8; _] 88 296..297 'd': u8
106 376..377 '2': usize 89 300..301 'g': fn g<u8>(S<&[u8]>) -> u8
107 388..389 'g': (&[u8], &[u8]) 90 300..315 'g(S { a: arr })': u8
108 406..416 '(arr, arr)': (&[u8], &[u8]) 91 302..314 'S { a: arr }': S<&[u8]>
109 407..410 'arr': &[u8; _] 92 309..312 'arr': &[u8; _]
110 412..415 'arr': &[u8; _] 93 325..326 'e': [&[u8]; _]
111 "### 94 340..345 '[arr]': [&[u8]; _]
95 341..344 'arr': &[u8; _]
96 355..356 'f': [&[u8]; _]
97 370..378 '[arr; 2]': [&[u8]; _]
98 371..374 'arr': &[u8; _]
99 376..377 '2': usize
100 388..389 'g': (&[u8], &[u8])
101 406..416 '(arr, arr)': (&[u8], &[u8])
102 407..410 'arr': &[u8; _]
103 412..415 'arr': &[u8; _]
104 "]],
112 ); 105 );
113} 106}
114 107
115#[test] 108#[test]
116fn infer_let_stmt_coerce() { 109fn infer_let_stmt_coerce() {
117 assert_snapshot!( 110 check_infer(
118 infer(r#" 111 r"
119fn test() { 112 fn test() {
120 let x: &[isize] = &[1]; 113 let x: &[isize] = &[1];
121 let x: *const [isize] = &[1]; 114 let x: *const [isize] = &[1];
122} 115 }
123"#), 116 ",
124 @r###" 117 expect![[r"
125 10..75 '{ ...[1]; }': () 118 10..75 '{ ...[1]; }': ()
126 20..21 'x': &[isize] 119 20..21 'x': &[isize]
127 34..38 '&[1]': &[isize; _] 120 34..38 '&[1]': &[isize; _]
128 35..38 '[1]': [isize; _] 121 35..38 '[1]': [isize; _]
129 36..37 '1': isize 122 36..37 '1': isize
130 48..49 'x': *const [isize] 123 48..49 'x': *const [isize]
131 68..72 '&[1]': &[isize; _] 124 68..72 '&[1]': &[isize; _]
132 69..72 '[1]': [isize; _] 125 69..72 '[1]': [isize; _]
133 70..71 '1': isize 126 70..71 '1': isize
134 "###); 127 "]],
128 );
135} 129}
136 130
137#[test] 131#[test]
138fn infer_custom_coerce_unsized() { 132fn infer_custom_coerce_unsized() {
139 assert_snapshot!( 133 check_infer(
140 infer(r#" 134 r#"
141struct A<T: ?Sized>(*const T); 135 struct A<T: ?Sized>(*const T);
142struct B<T: ?Sized>(*const T); 136 struct B<T: ?Sized>(*const T);
143struct C<T: ?Sized> { inner: *const T } 137 struct C<T: ?Sized> { inner: *const T }
144 138
145impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} 139 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
146impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {} 140 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
147 141
148fn foo1<T>(x: A<[T]>) -> A<[T]> { x } 142 fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
149fn foo2<T>(x: B<[T]>) -> B<[T]> { x } 143 fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
150fn foo3<T>(x: C<[T]>) -> C<[T]> { x } 144 fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
151 145
152fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { 146 fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
153 let d = foo1(a); 147 let d = foo1(a);
154 let e = foo2(b); 148 let e = foo2(b);
155 let f = foo3(c); 149 let f = foo3(c);
156} 150 }
157"#), 151
158 @r###" 152
159 257..258 'x': A<[T]> 153 #[lang = "sized"]
160 278..283 '{ x }': A<[T]> 154 pub trait Sized {}
161 280..281 'x': A<[T]> 155 #[lang = "unsize"]
162 295..296 'x': B<[T]> 156 pub trait Unsize<T: ?Sized> {}
163 316..321 '{ x }': B<[T]> 157 #[lang = "coerce_unsized"]
164 318..319 'x': B<[T]> 158 pub trait CoerceUnsized<T> {}
165 333..334 'x': C<[T]> 159
166 354..359 '{ x }': C<[T]> 160 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
167 356..357 'x': C<[T]> 161 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
168 369..370 'a': A<[u8; _]> 162 "#,
169 384..385 'b': B<[u8; _]> 163 expect![[r"
170 399..400 'c': C<[u8; _]> 164 257..258 'x': A<[T]>
171 414..480 '{ ...(c); }': () 165 278..283 '{ x }': A<[T]>
172 424..425 'd': A<[{unknown}]> 166 280..281 'x': A<[T]>
173 428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]> 167 295..296 'x': B<[T]>
174 428..435 'foo1(a)': A<[{unknown}]> 168 316..321 '{ x }': B<[T]>
175 433..434 'a': A<[u8; _]> 169 318..319 'x': B<[T]>
176 445..446 'e': B<[u8]> 170 333..334 'x': C<[T]>
177 449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]> 171 354..359 '{ x }': C<[T]>
178 449..456 'foo2(b)': B<[u8]> 172 356..357 'x': C<[T]>
179 454..455 'b': B<[u8; _]> 173 369..370 'a': A<[u8; _]>
180 466..467 'f': C<[u8]> 174 384..385 'b': B<[u8; _]>
181 470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]> 175 399..400 'c': C<[u8; _]>
182 470..477 'foo3(c)': C<[u8]> 176 414..480 '{ ...(c); }': ()
183 475..476 'c': C<[u8; _]> 177 424..425 'd': A<[{unknown}]>
184 "### 178 428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
179 428..435 'foo1(a)': A<[{unknown}]>
180 433..434 'a': A<[u8; _]>
181 445..446 'e': B<[u8]>
182 449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
183 449..456 'foo2(b)': B<[u8]>
184 454..455 'b': B<[u8; _]>
185 466..467 'f': C<[u8]>
186 470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
187 470..477 'foo3(c)': C<[u8]>
188 475..476 'c': C<[u8; _]>
189 "]],
185 ); 190 );
186} 191}
187 192
188#[test] 193#[test]
189fn infer_if_coerce() { 194fn infer_if_coerce() {
190 assert_snapshot!( 195 check_infer(
191 infer(r#" 196 r#"
192fn foo<T>(x: &[T]) -> &[T] { loop {} } 197 fn foo<T>(x: &[T]) -> &[T] { loop {} }
193fn test() { 198 fn test() {
194 let x = if true { 199 let x = if true {
195 foo(&[1]) 200 foo(&[1])
196 } else { 201 } else {
197 &[1] 202 &[1]
198 }; 203 };
199} 204 }
200"#), 205
201 @r###" 206
202 10..11 'x': &[T] 207 #[lang = "sized"]
203 27..38 '{ loop {} }': &[T] 208 pub trait Sized {}
204 29..36 'loop {}': ! 209 #[lang = "unsize"]
205 34..36 '{}': () 210 pub trait Unsize<T: ?Sized> {}
206 49..125 '{ ... }; }': () 211 "#,
207 59..60 'x': &[i32] 212 expect![[r"
208 63..122 'if tru... }': &[i32] 213 10..11 'x': &[T]
209 66..70 'true': bool 214 27..38 '{ loop {} }': &[T]
210 71..96 '{ ... }': &[i32] 215 29..36 'loop {}': !
211 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32] 216 34..36 '{}': ()
212 81..90 'foo(&[1])': &[i32] 217 49..125 '{ ... }; }': ()
213 85..89 '&[1]': &[i32; _] 218 59..60 'x': &[i32]
214 86..89 '[1]': [i32; _] 219 63..122 'if tru... }': &[i32]
215 87..88 '1': i32 220 66..70 'true': bool
216 102..122 '{ ... }': &[i32; _] 221 71..96 '{ ... }': &[i32]
217 112..116 '&[1]': &[i32; _] 222 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32]
218 113..116 '[1]': [i32; _] 223 81..90 'foo(&[1])': &[i32]
219 114..115 '1': i32 224 85..89 '&[1]': &[i32; _]
220 "### 225 86..89 '[1]': [i32; _]
226 87..88 '1': i32
227 102..122 '{ ... }': &[i32; _]
228 112..116 '&[1]': &[i32; _]
229 113..116 '[1]': [i32; _]
230 114..115 '1': i32
231 "]],
221 ); 232 );
222} 233}
223 234
224#[test] 235#[test]
225fn infer_if_else_coerce() { 236fn infer_if_else_coerce() {
226 assert_snapshot!( 237 check_infer(
227 infer(r#" 238 r#"
228fn foo<T>(x: &[T]) -> &[T] { loop {} } 239 fn foo<T>(x: &[T]) -> &[T] { loop {} }
229fn test() { 240 fn test() {
230 let x = if true { 241 let x = if true {
231 &[1] 242 &[1]
232 } else { 243 } else {
233 foo(&[1]) 244 foo(&[1])
234 }; 245 };
235} 246 }
236"#), 247
237 @r###" 248 #[lang = "sized"]
238 10..11 'x': &[T] 249 pub trait Sized {}
239 27..38 '{ loop {} }': &[T] 250 #[lang = "unsize"]
240 29..36 'loop {}': ! 251 pub trait Unsize<T: ?Sized> {}
241 34..36 '{}': () 252 #[lang = "coerce_unsized"]
242 49..125 '{ ... }; }': () 253 pub trait CoerceUnsized<T> {}
243 59..60 'x': &[i32] 254
244 63..122 'if tru... }': &[i32] 255 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
245 66..70 'true': bool 256 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
246 71..91 '{ ... }': &[i32; _] 257 "#,
247 81..85 '&[1]': &[i32; _] 258 expect![[r"
248 82..85 '[1]': [i32; _] 259 10..11 'x': &[T]
249 83..84 '1': i32 260 27..38 '{ loop {} }': &[T]
250 97..122 '{ ... }': &[i32] 261 29..36 'loop {}': !
251 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32] 262 34..36 '{}': ()
252 107..116 'foo(&[1])': &[i32] 263 49..125 '{ ... }; }': ()
253 111..115 '&[1]': &[i32; _] 264 59..60 'x': &[i32]
254 112..115 '[1]': [i32; _] 265 63..122 'if tru... }': &[i32]
255 113..114 '1': i32 266 66..70 'true': bool
256 "### 267 71..91 '{ ... }': &[i32; _]
257 ); 268 81..85 '&[1]': &[i32; _]
269 82..85 '[1]': [i32; _]
270 83..84 '1': i32
271 97..122 '{ ... }': &[i32]
272 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32]
273 107..116 'foo(&[1])': &[i32]
274 111..115 '&[1]': &[i32; _]
275 112..115 '[1]': [i32; _]
276 113..114 '1': i32
277 "]],
278 )
258} 279}
259 280
260#[test] 281#[test]
261fn infer_match_first_coerce() { 282fn infer_match_first_coerce() {
262 assert_snapshot!( 283 check_infer(
263 infer(r#" 284 r#"
264fn foo<T>(x: &[T]) -> &[T] { loop {} } 285 fn foo<T>(x: &[T]) -> &[T] { loop {} }
265fn test(i: i32) { 286 fn test(i: i32) {
266 let x = match i { 287 let x = match i {
267 2 => foo(&[2]), 288 2 => foo(&[2]),
268 1 => &[1], 289 1 => &[1],
269 _ => &[3], 290 _ => &[3],
270 }; 291 };
271} 292 }
272"#), 293
273 @r###" 294 #[lang = "sized"]
274 10..11 'x': &[T] 295 pub trait Sized {}
275 27..38 '{ loop {} }': &[T] 296 #[lang = "unsize"]
276 29..36 'loop {}': ! 297 pub trait Unsize<T: ?Sized> {}
277 34..36 '{}': () 298 "#,
278 47..48 'i': i32 299 expect![[r"
279 55..149 '{ ... }; }': () 300 10..11 'x': &[T]
280 65..66 'x': &[i32] 301 27..38 '{ loop {} }': &[T]
281 69..146 'match ... }': &[i32] 302 29..36 'loop {}': !
282 75..76 'i': i32 303 34..36 '{}': ()
283 87..88 '2': i32 304 47..48 'i': i32
284 87..88 '2': i32 305 55..149 '{ ... }; }': ()
285 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32] 306 65..66 'x': &[i32]
286 92..101 'foo(&[2])': &[i32] 307 69..146 'match ... }': &[i32]
287 96..100 '&[2]': &[i32; _] 308 75..76 'i': i32
288 97..100 '[2]': [i32; _] 309 87..88 '2': i32
289 98..99 '2': i32 310 87..88 '2': i32
290 111..112 '1': i32 311 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32]
291 111..112 '1': i32 312 92..101 'foo(&[2])': &[i32]
292 116..120 '&[1]': &[i32; _] 313 96..100 '&[2]': &[i32; _]
293 117..120 '[1]': [i32; _] 314 97..100 '[2]': [i32; _]
294 118..119 '1': i32 315 98..99 '2': i32
295 130..131 '_': i32 316 111..112 '1': i32
296 135..139 '&[3]': &[i32; _] 317 111..112 '1': i32
297 136..139 '[3]': [i32; _] 318 116..120 '&[1]': &[i32; _]
298 137..138 '3': i32 319 117..120 '[1]': [i32; _]
299 "### 320 118..119 '1': i32
321 130..131 '_': i32
322 135..139 '&[3]': &[i32; _]
323 136..139 '[3]': [i32; _]
324 137..138 '3': i32
325 "]],
300 ); 326 );
301} 327}
302 328
303#[test] 329#[test]
304fn infer_match_second_coerce() { 330fn infer_match_second_coerce() {
305 assert_snapshot!( 331 check_infer(
306 infer(r#" 332 r#"
307fn foo<T>(x: &[T]) -> &[T] { loop {} } 333 fn foo<T>(x: &[T]) -> &[T] { loop {} }
308fn test(i: i32) { 334 fn test(i: i32) {
309 let x = match i { 335 let x = match i {
310 1 => &[1], 336 1 => &[1],
311 2 => foo(&[2]), 337 2 => foo(&[2]),
312 _ => &[3], 338 _ => &[3],
313 }; 339 };
314} 340 }
315"#), 341
316 @r###" 342 #[lang = "sized"]
317 10..11 'x': &[T] 343 pub trait Sized {}
318 27..38 '{ loop {} }': &[T] 344 #[lang = "unsize"]
319 29..36 'loop {}': ! 345 pub trait Unsize<T: ?Sized> {}
320 34..36 '{}': () 346 #[lang = "coerce_unsized"]
321 47..48 'i': i32 347 pub trait CoerceUnsized<T> {}
322 55..149 '{ ... }; }': () 348
323 65..66 'x': &[i32] 349 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
324 69..146 'match ... }': &[i32] 350 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
325 75..76 'i': i32 351 "#,
326 87..88 '1': i32 352 expect![[r"
327 87..88 '1': i32 353 10..11 'x': &[T]
328 92..96 '&[1]': &[i32; _] 354 27..38 '{ loop {} }': &[T]
329 93..96 '[1]': [i32; _] 355 29..36 'loop {}': !
330 94..95 '1': i32 356 34..36 '{}': ()
331 106..107 '2': i32 357 47..48 'i': i32
332 106..107 '2': i32 358 55..149 '{ ... }; }': ()
333 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32] 359 65..66 'x': &[i32]
334 111..120 'foo(&[2])': &[i32] 360 69..146 'match ... }': &[i32]
335 115..119 '&[2]': &[i32; _] 361 75..76 'i': i32
336 116..119 '[2]': [i32; _] 362 87..88 '1': i32
337 117..118 '2': i32 363 87..88 '1': i32
338 130..131 '_': i32 364 92..96 '&[1]': &[i32; _]
339 135..139 '&[3]': &[i32; _] 365 93..96 '[1]': [i32; _]
340 136..139 '[3]': [i32; _] 366 94..95 '1': i32
341 137..138 '3': i32 367 106..107 '2': i32
342 "### 368 106..107 '2': i32
369 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32]
370 111..120 'foo(&[2])': &[i32]
371 115..119 '&[2]': &[i32; _]
372 116..119 '[2]': [i32; _]
373 117..118 '2': i32
374 130..131 '_': i32
375 135..139 '&[3]': &[i32; _]
376 136..139 '[3]': [i32; _]
377 137..138 '3': i32
378 "]],
343 ); 379 );
344} 380}
345 381
@@ -347,405 +383,453 @@ fn test(i: i32) {
347fn coerce_merge_one_by_one1() { 383fn coerce_merge_one_by_one1() {
348 mark::check!(coerce_merge_fail_fallback); 384 mark::check!(coerce_merge_fail_fallback);
349 385
350 assert_snapshot!( 386 check_infer(
351 infer(r#" 387 r"
352fn test() { 388 fn test() {
353 let t = &mut 1; 389 let t = &mut 1;
354 let x = match 1 { 390 let x = match 1 {
355 1 => t as *mut i32, 391 1 => t as *mut i32,
356 2 => t as &i32, 392 2 => t as &i32,
357 _ => t as *const i32, 393 _ => t as *const i32,
358 }; 394 };
359} 395 }
360"#), 396 ",
361 @r###" 397 expect![[r"
362 10..144 '{ ... }; }': () 398 10..144 '{ ... }; }': ()
363 20..21 't': &mut i32 399 20..21 't': &mut i32
364 24..30 '&mut 1': &mut i32 400 24..30 '&mut 1': &mut i32
365 29..30 '1': i32 401 29..30 '1': i32
366 40..41 'x': *const i32 402 40..41 'x': *const i32
367 44..141 'match ... }': *const i32 403 44..141 'match ... }': *const i32
368 50..51 '1': i32 404 50..51 '1': i32
369 62..63 '1': i32 405 62..63 '1': i32
370 62..63 '1': i32 406 62..63 '1': i32
371 67..68 't': &mut i32 407 67..68 't': &mut i32
372 67..80 't as *mut i32': *mut i32 408 67..80 't as *mut i32': *mut i32
373 90..91 '2': i32 409 90..91 '2': i32
374 90..91 '2': i32 410 90..91 '2': i32
375 95..96 't': &mut i32 411 95..96 't': &mut i32
376 95..104 't as &i32': &i32 412 95..104 't as &i32': &i32
377 114..115 '_': i32 413 114..115 '_': i32
378 119..120 't': &mut i32 414 119..120 't': &mut i32
379 119..134 't as *const i32': *const i32 415 119..134 't as *const i32': *const i32
380 "### 416 "]],
381 ); 417 );
382} 418}
383 419
384#[test] 420#[test]
385fn return_coerce_unknown() { 421fn return_coerce_unknown() {
386 assert_snapshot!( 422 check_infer_with_mismatches(
387 infer_with_mismatches(r#" 423 r"
388fn foo() -> u32 { 424 fn foo() -> u32 {
389 return unknown; 425 return unknown;
390} 426 }
391"#, true), 427 ",
392 @r###" 428 expect![[r"
393 16..39 '{ ...own; }': u32 429 16..39 '{ ...own; }': u32
394 22..36 'return unknown': ! 430 22..36 'return unknown': !
395 29..36 'unknown': u32 431 29..36 'unknown': u32
396 "### 432 "]],
397 ); 433 );
398} 434}
399 435
400#[test] 436#[test]
401fn coerce_autoderef() { 437fn coerce_autoderef() {
402 assert_snapshot!( 438 check_infer_with_mismatches(
403 infer_with_mismatches(r#" 439 r"
404struct Foo; 440 struct Foo;
405fn takes_ref_foo(x: &Foo) {} 441 fn takes_ref_foo(x: &Foo) {}
406fn test() { 442 fn test() {
407 takes_ref_foo(&Foo); 443 takes_ref_foo(&Foo);
408 takes_ref_foo(&&Foo); 444 takes_ref_foo(&&Foo);
409 takes_ref_foo(&&&Foo); 445 takes_ref_foo(&&&Foo);
410} 446 }
411"#, true), 447 ",
412 @r###" 448 expect![[r"
413 29..30 'x': &Foo 449 29..30 'x': &Foo
414 38..40 '{}': () 450 38..40 '{}': ()
415 51..132 '{ ...oo); }': () 451 51..132 '{ ...oo); }': ()
416 57..70 'takes_ref_foo': fn takes_ref_foo(&Foo) 452 57..70 'takes_ref_foo': fn takes_ref_foo(&Foo)
417 57..76 'takes_...(&Foo)': () 453 57..76 'takes_...(&Foo)': ()
418 71..75 '&Foo': &Foo 454 71..75 '&Foo': &Foo
419 72..75 'Foo': Foo 455 72..75 'Foo': Foo
420 82..95 'takes_ref_foo': fn takes_ref_foo(&Foo) 456 82..95 'takes_ref_foo': fn takes_ref_foo(&Foo)
421 82..102 'takes_...&&Foo)': () 457 82..102 'takes_...&&Foo)': ()
422 96..101 '&&Foo': &&Foo 458 96..101 '&&Foo': &&Foo
423 97..101 '&Foo': &Foo 459 97..101 '&Foo': &Foo
424 98..101 'Foo': Foo 460 98..101 'Foo': Foo
425 108..121 'takes_ref_foo': fn takes_ref_foo(&Foo) 461 108..121 'takes_ref_foo': fn takes_ref_foo(&Foo)
426 108..129 'takes_...&&Foo)': () 462 108..129 'takes_...&&Foo)': ()
427 122..128 '&&&Foo': &&&Foo 463 122..128 '&&&Foo': &&&Foo
428 123..128 '&&Foo': &&Foo 464 123..128 '&&Foo': &&Foo
429 124..128 '&Foo': &Foo 465 124..128 '&Foo': &Foo
430 125..128 'Foo': Foo 466 125..128 'Foo': Foo
431 "### 467 "]],
432 ); 468 );
433} 469}
434 470
435#[test] 471#[test]
436fn coerce_autoderef_generic() { 472fn coerce_autoderef_generic() {
437 assert_snapshot!( 473 check_infer_with_mismatches(
438 infer_with_mismatches(r#" 474 r"
439struct Foo; 475 struct Foo;
440fn takes_ref<T>(x: &T) -> T { *x } 476 fn takes_ref<T>(x: &T) -> T { *x }
441fn test() { 477 fn test() {
442 takes_ref(&Foo); 478 takes_ref(&Foo);
443 takes_ref(&&Foo); 479 takes_ref(&&Foo);
444 takes_ref(&&&Foo); 480 takes_ref(&&&Foo);
445} 481 }
446"#, true), 482 ",
447 @r###" 483 expect![[r"
448 28..29 'x': &T 484 28..29 'x': &T
449 40..46 '{ *x }': T 485 40..46 '{ *x }': T
450 42..44 '*x': T 486 42..44 '*x': T
451 43..44 'x': &T 487 43..44 'x': &T
452 57..126 '{ ...oo); }': () 488 57..126 '{ ...oo); }': ()
453 63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo 489 63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo
454 63..78 'takes_ref(&Foo)': Foo 490 63..78 'takes_ref(&Foo)': Foo
455 73..77 '&Foo': &Foo 491 73..77 '&Foo': &Foo
456 74..77 'Foo': Foo 492 74..77 'Foo': Foo
457 84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo 493 84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo
458 84..100 'takes_...&&Foo)': &Foo 494 84..100 'takes_...&&Foo)': &Foo
459 94..99 '&&Foo': &&Foo 495 94..99 '&&Foo': &&Foo
460 95..99 '&Foo': &Foo 496 95..99 '&Foo': &Foo
461 96..99 'Foo': Foo 497 96..99 'Foo': Foo
462 106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo 498 106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo
463 106..123 'takes_...&&Foo)': &&Foo 499 106..123 'takes_...&&Foo)': &&Foo
464 116..122 '&&&Foo': &&&Foo 500 116..122 '&&&Foo': &&&Foo
465 117..122 '&&Foo': &&Foo 501 117..122 '&&Foo': &&Foo
466 118..122 '&Foo': &Foo 502 118..122 '&Foo': &Foo
467 119..122 'Foo': Foo 503 119..122 'Foo': Foo
468 "### 504 "]],
469 ); 505 );
470} 506}
471 507
472#[test] 508#[test]
473fn coerce_autoderef_block() { 509fn coerce_autoderef_block() {
474 assert_snapshot!( 510 check_infer_with_mismatches(
475 infer_with_mismatches(r#" 511 r#"
476struct String {} 512 struct String {}
477#[lang = "deref"] 513 #[lang = "deref"]
478trait Deref { type Target; } 514 trait Deref { type Target; }
479impl Deref for String { type Target = str; } 515 impl Deref for String { type Target = str; }
480fn takes_ref_str(x: &str) {} 516 fn takes_ref_str(x: &str) {}
481fn returns_string() -> String { loop {} } 517 fn returns_string() -> String { loop {} }
482fn test() { 518 fn test() {
483 takes_ref_str(&{ returns_string() }); 519 takes_ref_str(&{ returns_string() });
484} 520 }
485"#, true), 521 "#,
486 @r###" 522 expect![[r"
487 126..127 'x': &str 523 126..127 'x': &str
488 135..137 '{}': () 524 135..137 '{}': ()
489 168..179 '{ loop {} }': String 525 168..179 '{ loop {} }': String
490 170..177 'loop {}': ! 526 170..177 'loop {}': !
491 175..177 '{}': () 527 175..177 '{}': ()
492 190..235 '{ ... }); }': () 528 190..235 '{ ... }); }': ()
493 196..209 'takes_ref_str': fn takes_ref_str(&str) 529 196..209 'takes_ref_str': fn takes_ref_str(&str)
494 196..232 'takes_...g() })': () 530 196..232 'takes_...g() })': ()
495 210..231 '&{ ret...ng() }': &String 531 210..231 '&{ ret...ng() }': &String
496 211..231 '{ retu...ng() }': String 532 211..231 '{ retu...ng() }': String
497 213..227 'returns_string': fn returns_string() -> String 533 213..227 'returns_string': fn returns_string() -> String
498 213..229 'return...ring()': String 534 213..229 'return...ring()': String
499 "### 535 "]],
500 ); 536 );
501} 537}
502 538
503#[test] 539#[test]
504fn closure_return_coerce() { 540fn closure_return_coerce() {
505 assert_snapshot!( 541 check_infer_with_mismatches(
506 infer_with_mismatches(r#" 542 r"
507fn foo() { 543 fn foo() {
508 let x = || { 544 let x = || {
509 if true { 545 if true {
510 return &1u32; 546 return &1u32;
547 }
548 &&1u32
549 };
511 } 550 }
512 &&1u32 551 ",
513 }; 552 expect![[r"
514} 553 9..105 '{ ... }; }': ()
515"#, true), 554 19..20 'x': || -> &u32
516 @r###" 555 23..102 '|| { ... }': || -> &u32
517 9..105 '{ ... }; }': () 556 26..102 '{ ... }': &u32
518 19..20 'x': || -> &u32 557 36..81 'if tru... }': ()
519 23..102 '|| { ... }': || -> &u32 558 39..43 'true': bool
520 26..102 '{ ... }': &u32 559 44..81 '{ ... }': ()
521 36..81 'if tru... }': () 560 58..70 'return &1u32': !
522 39..43 'true': bool 561 65..70 '&1u32': &u32
523 44..81 '{ ... }': () 562 66..70 '1u32': u32
524 58..70 'return &1u32': ! 563 90..96 '&&1u32': &&u32
525 65..70 '&1u32': &u32 564 91..96 '&1u32': &u32
526 66..70 '1u32': u32 565 92..96 '1u32': u32
527 90..96 '&&1u32': &&u32 566 "]],
528 91..96 '&1u32': &u32
529 92..96 '1u32': u32
530 "###
531 ); 567 );
532} 568}
533 569
534#[test] 570#[test]
535fn coerce_fn_item_to_fn_ptr() { 571fn coerce_fn_item_to_fn_ptr() {
536 assert_snapshot!( 572 check_infer_with_mismatches(
537 infer_with_mismatches(r#" 573 r"
538fn foo(x: u32) -> isize { 1 } 574 fn foo(x: u32) -> isize { 1 }
539fn test() { 575 fn test() {
540 let f: fn(u32) -> isize = foo; 576 let f: fn(u32) -> isize = foo;
541} 577 }
542"#, true), 578 ",
543 @r###" 579 expect![[r"
544 7..8 'x': u32 580 7..8 'x': u32
545 24..29 '{ 1 }': isize 581 24..29 '{ 1 }': isize
546 26..27 '1': isize 582 26..27 '1': isize
547 40..78 '{ ...foo; }': () 583 40..78 '{ ...foo; }': ()
548 50..51 'f': fn(u32) -> isize 584 50..51 'f': fn(u32) -> isize
549 72..75 'foo': fn foo(u32) -> isize 585 72..75 'foo': fn foo(u32) -> isize
550 "### 586 "]],
551 ); 587 );
552} 588}
553 589
554#[test] 590#[test]
555fn coerce_fn_items_in_match_arms() { 591fn coerce_fn_items_in_match_arms() {
556 mark::check!(coerce_fn_reification); 592 mark::check!(coerce_fn_reification);
557 assert_snapshot!( 593
558 infer_with_mismatches(r#" 594 check_infer_with_mismatches(
559fn foo1(x: u32) -> isize { 1 } 595 r"
560fn foo2(x: u32) -> isize { 2 } 596 fn foo1(x: u32) -> isize { 1 }
561fn foo3(x: u32) -> isize { 3 } 597 fn foo2(x: u32) -> isize { 2 }
562fn test() { 598 fn foo3(x: u32) -> isize { 3 }
563 let x = match 1 { 599 fn test() {
564 1 => foo1, 600 let x = match 1 {
565 2 => foo2, 601 1 => foo1,
566 _ => foo3, 602 2 => foo2,
567 }; 603 _ => foo3,
568} 604 };
569"#, true), 605 }
570 @r###" 606 ",
571 8..9 'x': u32 607 expect![[r"
572 25..30 '{ 1 }': isize 608 8..9 'x': u32
573 27..28 '1': isize 609 25..30 '{ 1 }': isize
574 39..40 'x': u32 610 27..28 '1': isize
575 56..61 '{ 2 }': isize 611 39..40 'x': u32
576 58..59 '2': isize 612 56..61 '{ 2 }': isize
577 70..71 'x': u32 613 58..59 '2': isize
578 87..92 '{ 3 }': isize 614 70..71 'x': u32
579 89..90 '3': isize 615 87..92 '{ 3 }': isize
580 103..192 '{ ... }; }': () 616 89..90 '3': isize
581 113..114 'x': fn(u32) -> isize 617 103..192 '{ ... }; }': ()
582 117..189 'match ... }': fn(u32) -> isize 618 113..114 'x': fn(u32) -> isize
583 123..124 '1': i32 619 117..189 'match ... }': fn(u32) -> isize
584 135..136 '1': i32 620 123..124 '1': i32
585 135..136 '1': i32 621 135..136 '1': i32
586 140..144 'foo1': fn foo1(u32) -> isize 622 135..136 '1': i32
587 154..155 '2': i32 623 140..144 'foo1': fn foo1(u32) -> isize
588 154..155 '2': i32 624 154..155 '2': i32
589 159..163 'foo2': fn foo2(u32) -> isize 625 154..155 '2': i32
590 173..174 '_': i32 626 159..163 'foo2': fn foo2(u32) -> isize
591 178..182 'foo3': fn foo3(u32) -> isize 627 173..174 '_': i32
592 "### 628 178..182 'foo3': fn foo3(u32) -> isize
629 "]],
593 ); 630 );
594} 631}
595 632
596#[test] 633#[test]
597fn coerce_closure_to_fn_ptr() { 634fn coerce_closure_to_fn_ptr() {
598 assert_snapshot!( 635 check_infer_with_mismatches(
599 infer_with_mismatches(r#" 636 r"
600fn test() { 637 fn test() {
601 let f: fn(u32) -> isize = |x| { 1 }; 638 let f: fn(u32) -> isize = |x| { 1 };
602} 639 }
603"#, true), 640 ",
604 @r###" 641 expect![[r"
605 10..54 '{ ...1 }; }': () 642 10..54 '{ ...1 }; }': ()
606 20..21 'f': fn(u32) -> isize 643 20..21 'f': fn(u32) -> isize
607 42..51 '|x| { 1 }': |u32| -> isize 644 42..51 '|x| { 1 }': |u32| -> isize
608 43..44 'x': u32 645 43..44 'x': u32
609 46..51 '{ 1 }': isize 646 46..51 '{ 1 }': isize
610 48..49 '1': isize 647 48..49 '1': isize
611 "### 648 "]],
612 ); 649 );
613} 650}
614 651
615#[test] 652#[test]
616fn coerce_placeholder_ref() { 653fn coerce_placeholder_ref() {
617 // placeholders should unify, even behind references 654 // placeholders should unify, even behind references
618 assert_snapshot!( 655 check_infer_with_mismatches(
619 infer_with_mismatches(r#" 656 r"
620struct S<T> { t: T } 657 struct S<T> { t: T }
621impl<TT> S<TT> { 658 impl<TT> S<TT> {
622 fn get(&self) -> &TT { 659 fn get(&self) -> &TT {
623 &self.t 660 &self.t
624 } 661 }
625} 662 }
626"#, true), 663 ",
627 @r###" 664 expect![[r"
628 50..54 'self': &S<TT> 665 50..54 'self': &S<TT>
629 63..86 '{ ... }': &TT 666 63..86 '{ ... }': &TT
630 73..80 '&self.t': &TT 667 73..80 '&self.t': &TT
631 74..78 'self': &S<TT> 668 74..78 'self': &S<TT>
632 74..80 'self.t': TT 669 74..80 'self.t': TT
633 "### 670 "]],
634 ); 671 );
635} 672}
636 673
637#[test] 674#[test]
638fn coerce_unsize_array() { 675fn coerce_unsize_array() {
639 assert_snapshot!( 676 check_infer_with_mismatches(
640 infer_with_mismatches(r#" 677 r#"
641#[lang = "unsize"] 678 #[lang = "unsize"]
642pub trait Unsize<T> {} 679 pub trait Unsize<T> {}
643#[lang = "coerce_unsized"] 680 #[lang = "coerce_unsized"]
644pub trait CoerceUnsized<T> {} 681 pub trait CoerceUnsized<T> {}
645 682
646impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} 683 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
647 684
648fn test() { 685 fn test() {
649 let f: &[usize] = &[1, 2, 3]; 686 let f: &[usize] = &[1, 2, 3];
650} 687 }
651"#, true), 688 "#,
652 @r###" 689 expect![[r"
653 161..198 '{ ... 3]; }': () 690 161..198 '{ ... 3]; }': ()
654 171..172 'f': &[usize] 691 171..172 'f': &[usize]
655 185..195 '&[1, 2, 3]': &[usize; _] 692 185..195 '&[1, 2, 3]': &[usize; _]
656 186..195 '[1, 2, 3]': [usize; _] 693 186..195 '[1, 2, 3]': [usize; _]
657 187..188 '1': usize 694 187..188 '1': usize
658 190..191 '2': usize 695 190..191 '2': usize
659 193..194 '3': usize 696 193..194 '3': usize
660 "### 697 "]],
661 ); 698 );
662} 699}
663 700
664#[test] 701#[test]
665fn coerce_unsize_trait_object() { 702fn coerce_unsize_trait_object_simple() {
666 assert_snapshot!( 703 check_infer_with_mismatches(
667 infer_with_mismatches(r#" 704 r#"
668#[lang = "sized"] 705 #[lang = "sized"]
669pub trait Sized {} 706 pub trait Sized {}
670#[lang = "unsize"] 707 #[lang = "unsize"]
671pub trait Unsize<T> {} 708 pub trait Unsize<T> {}
672#[lang = "coerce_unsized"] 709 #[lang = "coerce_unsized"]
673pub trait CoerceUnsized<T> {} 710 pub trait CoerceUnsized<T> {}
674 711
675impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} 712 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
676 713
677trait Foo<T, U> {} 714 trait Foo<T, U> {}
678trait Bar<U, T, X>: Foo<T, U> {} 715 trait Bar<U, T, X>: Foo<T, U> {}
679trait Baz<T, X>: Bar<usize, T, X> {} 716 trait Baz<T, X>: Bar<usize, T, X> {}
680 717
681struct S<T, X>; 718 struct S<T, X>;
682impl<T, X> Foo<T, usize> for S<T, X> {} 719 impl<T, X> Foo<T, usize> for S<T, X> {}
683impl<T, X> Bar<usize, T, X> for S<T, X> {} 720 impl<T, X> Bar<usize, T, X> for S<T, X> {}
684impl<T, X> Baz<T, X> for S<T, X> {} 721 impl<T, X> Baz<T, X> for S<T, X> {}
685 722
686fn test() { 723 fn test() {
687 let obj: &dyn Baz<i8, i16> = &S; 724 let obj: &dyn Baz<i8, i16> = &S;
688 let obj: &dyn Bar<_, _, _> = obj; 725 let obj: &dyn Bar<_, i8, i16> = &S;
689 let obj: &dyn Foo<_, _> = obj; 726 let obj: &dyn Foo<i8, _> = &S;
690 let obj2: &dyn Baz<i8, i16> = &S; 727 }
691 let _: &dyn Foo<_, _> = obj2; 728 "#,
729 expect![[r"
730 424..539 '{ ... &S; }': ()
731 434..437 'obj': &dyn Baz<i8, i16>
732 459..461 '&S': &S<i8, i16>
733 460..461 'S': S<i8, i16>
734 471..474 'obj': &dyn Bar<usize, i8, i16>
735 499..501 '&S': &S<i8, i16>
736 500..501 'S': S<i8, i16>
737 511..514 'obj': &dyn Foo<i8, usize>
738 534..536 '&S': &S<i8, {unknown}>
739 535..536 'S': S<i8, {unknown}>
740 "]],
741 );
692} 742}
693"#, true), 743
694 @r###" 744#[test]
695 424..609 '{ ...bj2; }': () 745// The rust reference says this should be possible, but rustc doesn't implement
696 434..437 'obj': &dyn Baz<i8, i16> 746// it. We used to support it, but Chalk doesn't.
697 459..461 '&S': &S<i8, i16> 747#[ignore]
698 460..461 'S': S<i8, i16> 748fn coerce_unsize_trait_object_to_trait_object() {
699 471..474 'obj': &dyn Bar<usize, i8, i16> 749 check_infer_with_mismatches(
700 496..499 'obj': &dyn Baz<i8, i16> 750 r#"
701 509..512 'obj': &dyn Foo<i8, usize> 751 #[lang = "sized"]
702 531..534 'obj': &dyn Bar<usize, i8, i16> 752 pub trait Sized {}
703 544..548 'obj2': &dyn Baz<i8, i16> 753 #[lang = "unsize"]
704 570..572 '&S': &S<i8, i16> 754 pub trait Unsize<T> {}
705 571..572 'S': S<i8, i16> 755 #[lang = "coerce_unsized"]
706 582..583 '_': &dyn Foo<i8, usize> 756 pub trait CoerceUnsized<T> {}
707 602..606 'obj2': &dyn Baz<i8, i16> 757
708 "### 758 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
759
760 trait Foo<T, U> {}
761 trait Bar<U, T, X>: Foo<T, U> {}
762 trait Baz<T, X>: Bar<usize, T, X> {}
763
764 struct S<T, X>;
765 impl<T, X> Foo<T, usize> for S<T, X> {}
766 impl<T, X> Bar<usize, T, X> for S<T, X> {}
767 impl<T, X> Baz<T, X> for S<T, X> {}
768
769 fn test() {
770 let obj: &dyn Baz<i8, i16> = &S;
771 let obj: &dyn Bar<_, _, _> = obj;
772 let obj: &dyn Foo<_, _> = obj;
773 let obj2: &dyn Baz<i8, i16> = &S;
774 let _: &dyn Foo<_, _> = obj2;
775 }
776 "#,
777 expect![[r"
778 424..609 '{ ...bj2; }': ()
779 434..437 'obj': &dyn Baz<i8, i16>
780 459..461 '&S': &S<i8, i16>
781 460..461 'S': S<i8, i16>
782 471..474 'obj': &dyn Bar<usize, i8, i16>
783 496..499 'obj': &dyn Baz<i8, i16>
784 509..512 'obj': &dyn Foo<i8, usize>
785 531..534 'obj': &dyn Bar<usize, i8, i16>
786 544..548 'obj2': &dyn Baz<i8, i16>
787 570..572 '&S': &S<i8, i16>
788 571..572 'S': S<i8, i16>
789 582..583 '_': &dyn Foo<i8, usize>
790 602..606 'obj2': &dyn Baz<i8, i16>
791 "]],
709 ); 792 );
710} 793}
711 794
712#[test] 795#[test]
713fn coerce_unsize_super_trait_cycle() { 796fn coerce_unsize_super_trait_cycle() {
714 assert_snapshot!( 797 check_infer_with_mismatches(
715 infer_with_mismatches(r#" 798 r#"
716#[lang = "sized"] 799 #[lang = "sized"]
717pub trait Sized {} 800 pub trait Sized {}
718#[lang = "unsize"] 801 #[lang = "unsize"]
719pub trait Unsize<T> {} 802 pub trait Unsize<T> {}
720#[lang = "coerce_unsized"] 803 #[lang = "coerce_unsized"]
721pub trait CoerceUnsized<T> {} 804 pub trait CoerceUnsized<T> {}
722 805
723impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} 806 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
724 807
725trait A {} 808 trait A {}
726trait B: C + A {} 809 trait B: C + A {}
727trait C: B {} 810 trait C: B {}
728trait D: C 811 trait D: C
729 812
730struct S; 813 struct S;
731impl A for S {} 814 impl A for S {}
732impl B for S {} 815 impl B for S {}
733impl C for S {} 816 impl C for S {}
734impl D for S {} 817 impl D for S {}
735 818
736fn test() { 819 fn test() {
737 let obj: &dyn D = &S; 820 let obj: &dyn D = &S;
738 let obj: &dyn A = obj; 821 let obj: &dyn A = &S;
739} 822 }
740"#, true), 823 "#,
741 @r###" 824 expect![[r"
742 328..384 '{ ...obj; }': () 825 328..383 '{ ... &S; }': ()
743 338..341 'obj': &dyn D 826 338..341 'obj': &dyn D
744 352..354 '&S': &S 827 352..354 '&S': &S
745 353..354 'S': S 828 353..354 'S': S
746 364..367 'obj': &dyn A 829 364..367 'obj': &dyn A
747 378..381 'obj': &dyn D 830 378..380 '&S': &S
748 "### 831 379..380 'S': S
832 "]],
749 ); 833 );
750} 834}
751 835
@@ -754,24 +838,24 @@ fn test() {
754fn coerce_unsize_generic() { 838fn coerce_unsize_generic() {
755 // FIXME: Implement this 839 // FIXME: Implement this
756 // https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions 840 // https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions
757 assert_snapshot!( 841 check_infer_with_mismatches(
758 infer_with_mismatches(r#" 842 r#"
759#[lang = "unsize"] 843 #[lang = "unsize"]
760pub trait Unsize<T> {} 844 pub trait Unsize<T> {}
761#[lang = "coerce_unsized"] 845 #[lang = "coerce_unsized"]
762pub trait CoerceUnsized<T> {} 846 pub trait CoerceUnsized<T> {}
763 847
764impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} 848 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
765 849
766struct Foo<T> { t: T }; 850 struct Foo<T> { t: T };
767struct Bar<T>(Foo<T>); 851 struct Bar<T>(Foo<T>);
768 852
769fn test() { 853 fn test() {
770 let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; 854 let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
771 let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); 855 let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
772} 856 }
773"#, true), 857 "#,
774 @r###" 858 expect![[r"
775 "### 859 "]],
776 ); 860 );
777} 861}
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index 45c4e309e..24c53eb02 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -1,9 +1,9 @@
1use std::fs; 1use std::fs;
2 2
3use insta::assert_snapshot; 3use expect::expect;
4use test_utils::project_dir; 4use test_utils::project_dir;
5 5
6use super::{check_types, infer}; 6use super::{check_infer, check_types};
7 7
8#[test] 8#[test]
9fn cfg_impl_def() { 9fn cfg_impl_def() {
@@ -46,204 +46,204 @@ impl S {
46 46
47#[test] 47#[test]
48fn infer_macros_expanded() { 48fn infer_macros_expanded() {
49 assert_snapshot!( 49 check_infer(
50 infer(r#" 50 r#"
51struct Foo(Vec<i32>); 51 struct Foo(Vec<i32>);
52 52
53macro_rules! foo { 53 macro_rules! foo {
54 ($($item:expr),*) => { 54 ($($item:expr),*) => {
55 { 55 {
56 Foo(vec![$($item,)*]) 56 Foo(vec![$($item,)*])
57 } 57 }
58 }; 58 };
59} 59 }
60 60
61fn main() { 61 fn main() {
62 let x = foo!(1,2); 62 let x = foo!(1,2);
63} 63 }
64"#), 64 "#,
65 @r###" 65 expect![[r#"
66 !0..17 '{Foo(v...,2,])}': Foo 66 !0..17 '{Foo(v...,2,])}': Foo
67 !1..4 'Foo': Foo({unknown}) -> Foo 67 !1..4 'Foo': Foo({unknown}) -> Foo
68 !1..16 'Foo(vec![1,2,])': Foo 68 !1..16 'Foo(vec![1,2,])': Foo
69 !5..15 'vec![1,2,]': {unknown} 69 !5..15 'vec![1,2,]': {unknown}
70 155..181 '{ ...,2); }': () 70 155..181 '{ ...,2); }': ()
71 165..166 'x': Foo 71 165..166 'x': Foo
72 "### 72 "#]],
73 ); 73 );
74} 74}
75 75
76#[test] 76#[test]
77fn infer_legacy_textual_scoped_macros_expanded() { 77fn infer_legacy_textual_scoped_macros_expanded() {
78 assert_snapshot!( 78 check_infer(
79 infer(r#" 79 r#"
80struct Foo(Vec<i32>); 80 struct Foo(Vec<i32>);
81 81
82#[macro_use] 82 #[macro_use]
83mod m { 83 mod m {
84 macro_rules! foo { 84 macro_rules! foo {
85 ($($item:expr),*) => { 85 ($($item:expr),*) => {
86 { 86 {
87 Foo(vec![$($item,)*]) 87 Foo(vec![$($item,)*])
88 }
89 };
88 } 90 }
89 }; 91 }
90 }
91}
92 92
93fn main() { 93 fn main() {
94 let x = foo!(1,2); 94 let x = foo!(1,2);
95 let y = crate::foo!(1,2); 95 let y = crate::foo!(1,2);
96} 96 }
97"#), 97 "#,
98 @r###" 98 expect![[r#"
99 !0..17 '{Foo(v...,2,])}': Foo 99 !0..17 '{Foo(v...,2,])}': Foo
100 !1..4 'Foo': Foo({unknown}) -> Foo 100 !1..4 'Foo': Foo({unknown}) -> Foo
101 !1..16 'Foo(vec![1,2,])': Foo 101 !1..16 'Foo(vec![1,2,])': Foo
102 !5..15 'vec![1,2,]': {unknown} 102 !5..15 'vec![1,2,]': {unknown}
103 194..250 '{ ...,2); }': () 103 194..250 '{ ...,2); }': ()
104 204..205 'x': Foo 104 204..205 'x': Foo
105 227..228 'y': {unknown} 105 227..228 'y': {unknown}
106 231..247 'crate:...!(1,2)': {unknown} 106 231..247 'crate:...!(1,2)': {unknown}
107 "### 107 "#]],
108 ); 108 );
109} 109}
110 110
111#[test] 111#[test]
112fn infer_path_qualified_macros_expanded() { 112fn infer_path_qualified_macros_expanded() {
113 assert_snapshot!( 113 check_infer(
114 infer(r#" 114 r#"
115#[macro_export] 115 #[macro_export]
116macro_rules! foo { 116 macro_rules! foo {
117 () => { 42i32 } 117 () => { 42i32 }
118} 118 }
119 119
120mod m { 120 mod m {
121 pub use super::foo as bar; 121 pub use super::foo as bar;
122} 122 }
123 123
124fn main() { 124 fn main() {
125 let x = crate::foo!(); 125 let x = crate::foo!();
126 let y = m::bar!(); 126 let y = m::bar!();
127} 127 }
128"#), 128 "#,
129 @r###" 129 expect![[r#"
130 !0..5 '42i32': i32 130 !0..5 '42i32': i32
131 !0..5 '42i32': i32 131 !0..5 '42i32': i32
132 110..163 '{ ...!(); }': () 132 110..163 '{ ...!(); }': ()
133 120..121 'x': i32 133 120..121 'x': i32
134 147..148 'y': i32 134 147..148 'y': i32
135 "### 135 "#]],
136 ); 136 );
137} 137}
138 138
139#[test] 139#[test]
140fn expr_macro_expanded_in_various_places() { 140fn expr_macro_expanded_in_various_places() {
141 assert_snapshot!( 141 check_infer(
142 infer(r#" 142 r#"
143macro_rules! spam { 143 macro_rules! spam {
144 () => (1isize); 144 () => (1isize);
145} 145 }
146 146
147fn spam() { 147 fn spam() {
148 spam!(); 148 spam!();
149 (spam!()); 149 (spam!());
150 spam!().spam(spam!()); 150 spam!().spam(spam!());
151 for _ in spam!() {} 151 for _ in spam!() {}
152 || spam!(); 152 || spam!();
153 while spam!() {} 153 while spam!() {}
154 break spam!(); 154 break spam!();
155 return spam!(); 155 return spam!();
156 match spam!() { 156 match spam!() {
157 _ if spam!() => spam!(), 157 _ if spam!() => spam!(),
158 } 158 }
159 spam!()(spam!()); 159 spam!()(spam!());
160 Spam { spam: spam!() }; 160 Spam { spam: spam!() };
161 spam!()[spam!()]; 161 spam!()[spam!()];
162 await spam!(); 162 await spam!();
163 spam!() as usize; 163 spam!() as usize;
164 &spam!(); 164 &spam!();
165 -spam!(); 165 -spam!();
166 spam!()..spam!(); 166 spam!()..spam!();
167 spam!() + spam!(); 167 spam!() + spam!();
168} 168 }
169"#), 169 "#,
170 @r###" 170 expect![[r#"
171 !0..6 '1isize': isize 171 !0..6 '1isize': isize
172 !0..6 '1isize': isize 172 !0..6 '1isize': isize
173 !0..6 '1isize': isize 173 !0..6 '1isize': isize
174 !0..6 '1isize': isize 174 !0..6 '1isize': isize
175 !0..6 '1isize': isize 175 !0..6 '1isize': isize
176 !0..6 '1isize': isize 176 !0..6 '1isize': isize
177 !0..6 '1isize': isize 177 !0..6 '1isize': isize
178 !0..6 '1isize': isize 178 !0..6 '1isize': isize
179 !0..6 '1isize': isize 179 !0..6 '1isize': isize
180 !0..6 '1isize': isize 180 !0..6 '1isize': isize
181 !0..6 '1isize': isize 181 !0..6 '1isize': isize
182 !0..6 '1isize': isize 182 !0..6 '1isize': isize
183 !0..6 '1isize': isize 183 !0..6 '1isize': isize
184 !0..6 '1isize': isize 184 !0..6 '1isize': isize
185 !0..6 '1isize': isize 185 !0..6 '1isize': isize
186 !0..6 '1isize': isize 186 !0..6 '1isize': isize
187 !0..6 '1isize': isize 187 !0..6 '1isize': isize
188 !0..6 '1isize': isize 188 !0..6 '1isize': isize
189 !0..6 '1isize': isize 189 !0..6 '1isize': isize
190 !0..6 '1isize': isize 190 !0..6 '1isize': isize
191 !0..6 '1isize': isize 191 !0..6 '1isize': isize
192 !0..6 '1isize': isize 192 !0..6 '1isize': isize
193 !0..6 '1isize': isize 193 !0..6 '1isize': isize
194 !0..6 '1isize': isize 194 !0..6 '1isize': isize
195 !0..6 '1isize': isize 195 !0..6 '1isize': isize
196 53..456 '{ ...!(); }': () 196 53..456 '{ ...!(); }': ()
197 87..108 'spam!(...am!())': {unknown} 197 87..108 'spam!(...am!())': {unknown}
198 114..133 'for _ ...!() {}': () 198 114..133 'for _ ...!() {}': ()
199 118..119 '_': {unknown} 199 118..119 '_': {unknown}
200 131..133 '{}': () 200 131..133 '{}': ()
201 138..148 '|| spam!()': || -> isize 201 138..148 '|| spam!()': || -> isize
202 154..170 'while ...!() {}': () 202 154..170 'while ...!() {}': ()
203 168..170 '{}': () 203 168..170 '{}': ()
204 175..188 'break spam!()': ! 204 175..188 'break spam!()': !
205 194..208 'return spam!()': ! 205 194..208 'return spam!()': !
206 214..268 'match ... }': isize 206 214..268 'match ... }': isize
207 238..239 '_': isize 207 238..239 '_': isize
208 273..289 'spam!(...am!())': {unknown} 208 273..289 'spam!(...am!())': {unknown}
209 295..317 'Spam {...m!() }': {unknown} 209 295..317 'Spam {...m!() }': {unknown}
210 323..339 'spam!(...am!()]': {unknown} 210 323..339 'spam!(...am!()]': {unknown}
211 364..380 'spam!(... usize': usize 211 364..380 'spam!(... usize': usize
212 386..394 '&spam!()': &isize 212 386..394 '&spam!()': &isize
213 400..408 '-spam!()': isize 213 400..408 '-spam!()': isize
214 414..430 'spam!(...pam!()': {unknown} 214 414..430 'spam!(...pam!()': {unknown}
215 436..453 'spam!(...pam!()': isize 215 436..453 'spam!(...pam!()': isize
216 "### 216 "#]],
217 ); 217 );
218} 218}
219 219
220#[test] 220#[test]
221fn infer_type_value_macro_having_same_name() { 221fn infer_type_value_macro_having_same_name() {
222 assert_snapshot!( 222 check_infer(
223 infer(r#" 223 r#"
224#[macro_export] 224 #[macro_export]
225macro_rules! foo { 225 macro_rules! foo {
226 () => { 226 () => {
227 mod foo { 227 mod foo {
228 pub use super::foo; 228 pub use super::foo;
229 }
230 };
231 ($x:tt) => {
232 $x
233 };
229 } 234 }
230 };
231 ($x:tt) => {
232 $x
233 };
234}
235 235
236foo!(); 236 foo!();
237 237
238fn foo() { 238 fn foo() {
239 let foo = foo::foo!(42i32); 239 let foo = foo::foo!(42i32);
240} 240 }
241"#), 241 "#,
242 @r###" 242 expect![[r#"
243 !0..5 '42i32': i32 243 !0..5 '42i32': i32
244 170..205 '{ ...32); }': () 244 170..205 '{ ...32); }': ()
245 180..183 'foo': i32 245 180..183 'foo': i32
246 "### 246 "#]],
247 ); 247 );
248} 248}
249 249
@@ -372,50 +372,50 @@ expand!();
372 372
373#[test] 373#[test]
374fn infer_type_value_non_legacy_macro_use_as() { 374fn infer_type_value_non_legacy_macro_use_as() {
375 assert_snapshot!( 375 check_infer(
376 infer(r#" 376 r#"
377mod m { 377 mod m {
378 macro_rules! _foo { 378 macro_rules! _foo {
379 ($x:ident) => { type $x = u64; } 379 ($x:ident) => { type $x = u64; }
380 } 380 }
381 pub(crate) use _foo as foo; 381 pub(crate) use _foo as foo;
382} 382 }
383 383
384m::foo!(foo); 384 m::foo!(foo);
385use foo as bar; 385 use foo as bar;
386fn f() -> bar { 0 } 386 fn f() -> bar { 0 }
387fn main() { 387 fn main() {
388 let _a = f(); 388 let _a = f();
389} 389 }
390"#), 390 "#,
391 @r###" 391 expect![[r#"
392 158..163 '{ 0 }': u64 392 158..163 '{ 0 }': u64
393 160..161 '0': u64 393 160..161 '0': u64
394 174..196 '{ ...f(); }': () 394 174..196 '{ ...f(); }': ()
395 184..186 '_a': u64 395 184..186 '_a': u64
396 190..191 'f': fn f() -> u64 396 190..191 'f': fn f() -> u64
397 190..193 'f()': u64 397 190..193 'f()': u64
398 "### 398 "#]],
399 ); 399 );
400} 400}
401 401
402#[test] 402#[test]
403fn infer_local_macro() { 403fn infer_local_macro() {
404 assert_snapshot!( 404 check_infer(
405 infer(r#" 405 r#"
406fn main() { 406 fn main() {
407 macro_rules! foo { 407 macro_rules! foo {
408 () => { 1usize } 408 () => { 1usize }
409 } 409 }
410 let _a = foo!(); 410 let _a = foo!();
411} 411 }
412"#), 412 "#,
413 @r###" 413 expect![[r#"
414 !0..6 '1usize': usize 414 !0..6 '1usize': usize
415 10..89 '{ ...!(); }': () 415 10..89 '{ ...!(); }': ()
416 16..65 'macro_... }': {unknown} 416 16..65 'macro_... }': {unknown}
417 74..76 '_a': usize 417 74..76 '_a': usize
418 "### 418 "#]],
419 ); 419 );
420} 420}
421 421
@@ -446,77 +446,77 @@ macro_rules! bar {
446 446
447#[test] 447#[test]
448fn infer_builtin_macros_line() { 448fn infer_builtin_macros_line() {
449 assert_snapshot!( 449 check_infer(
450 infer(r#" 450 r#"
451#[rustc_builtin_macro] 451 #[rustc_builtin_macro]
452macro_rules! line {() => {}} 452 macro_rules! line {() => {}}
453 453
454fn main() { 454 fn main() {
455 let x = line!(); 455 let x = line!();
456} 456 }
457"#), 457 "#,
458 @r###" 458 expect![[r#"
459 !0..1 '0': i32 459 !0..1 '0': i32
460 63..87 '{ ...!(); }': () 460 63..87 '{ ...!(); }': ()
461 73..74 'x': i32 461 73..74 'x': i32
462 "### 462 "#]],
463 ); 463 );
464} 464}
465 465
466#[test] 466#[test]
467fn infer_builtin_macros_file() { 467fn infer_builtin_macros_file() {
468 assert_snapshot!( 468 check_infer(
469 infer(r#" 469 r#"
470#[rustc_builtin_macro] 470 #[rustc_builtin_macro]
471macro_rules! file {() => {}} 471 macro_rules! file {() => {}}
472 472
473fn main() { 473 fn main() {
474 let x = file!(); 474 let x = file!();
475} 475 }
476"#), 476 "#,
477 @r###" 477 expect![[r#"
478 !0..2 '""': &str 478 !0..2 '""': &str
479 63..87 '{ ...!(); }': () 479 63..87 '{ ...!(); }': ()
480 73..74 'x': &str 480 73..74 'x': &str
481 "### 481 "#]],
482 ); 482 );
483} 483}
484 484
485#[test] 485#[test]
486fn infer_builtin_macros_column() { 486fn infer_builtin_macros_column() {
487 assert_snapshot!( 487 check_infer(
488 infer(r#" 488 r#"
489#[rustc_builtin_macro] 489 #[rustc_builtin_macro]
490macro_rules! column {() => {}} 490 macro_rules! column {() => {}}
491 491
492fn main() { 492 fn main() {
493 let x = column!(); 493 let x = column!();
494} 494 }
495"#), 495 "#,
496 @r###" 496 expect![[r#"
497 !0..1 '0': i32 497 !0..1 '0': i32
498 65..91 '{ ...!(); }': () 498 65..91 '{ ...!(); }': ()
499 75..76 'x': i32 499 75..76 'x': i32
500 "### 500 "#]],
501 ); 501 );
502} 502}
503 503
504#[test] 504#[test]
505fn infer_builtin_macros_concat() { 505fn infer_builtin_macros_concat() {
506 assert_snapshot!( 506 check_infer(
507 infer(r#" 507 r#"
508#[rustc_builtin_macro] 508 #[rustc_builtin_macro]
509macro_rules! concat {() => {}} 509 macro_rules! concat {() => {}}
510 510
511fn main() { 511 fn main() {
512 let x = concat!("hello", concat!("world", "!")); 512 let x = concat!("hello", concat!("world", "!"));
513} 513 }
514"#), 514 "#,
515 @r###" 515 expect![[r#"
516 !0..13 '"helloworld!"': &str 516 !0..13 '"helloworld!"': &str
517 65..121 '{ ...")); }': () 517 65..121 '{ ...")); }': ()
518 75..76 'x': &str 518 75..76 'x': &str
519 "### 519 "#]],
520 ); 520 );
521} 521}
522 522
@@ -622,7 +622,7 @@ macro_rules! include {() => {}}
622include!("main.rs"); 622include!("main.rs");
623 623
624fn main() { 624fn main() {
625 0 625 0
626} //^ i32 626} //^ i32
627"#, 627"#,
628 ); 628 );
@@ -630,42 +630,42 @@ fn main() {
630 630
631#[test] 631#[test]
632fn infer_builtin_macros_concat_with_lazy() { 632fn infer_builtin_macros_concat_with_lazy() {
633 assert_snapshot!( 633 check_infer(
634 infer(r#" 634 r#"
635macro_rules! hello {() => {"hello"}} 635 macro_rules! hello {() => {"hello"}}
636 636
637#[rustc_builtin_macro] 637 #[rustc_builtin_macro]
638macro_rules! concat {() => {}} 638 macro_rules! concat {() => {}}
639 639
640fn main() { 640 fn main() {
641 let x = concat!(hello!(), concat!("world", "!")); 641 let x = concat!(hello!(), concat!("world", "!"));
642} 642 }
643"#), 643 "#,
644 @r###" 644 expect![[r#"
645 !0..13 '"helloworld!"': &str 645 !0..13 '"helloworld!"': &str
646 103..160 '{ ...")); }': () 646 103..160 '{ ...")); }': ()
647 113..114 'x': &str 647 113..114 'x': &str
648 "### 648 "#]],
649 ); 649 );
650} 650}
651 651
652#[test] 652#[test]
653fn infer_builtin_macros_env() { 653fn infer_builtin_macros_env() {
654 assert_snapshot!( 654 check_infer(
655 infer(r#" 655 r#"
656//- /main.rs env:foo=bar 656 //- /main.rs env:foo=bar
657#[rustc_builtin_macro] 657 #[rustc_builtin_macro]
658macro_rules! env {() => {}} 658 macro_rules! env {() => {}}
659 659
660fn main() { 660 fn main() {
661 let x = env!("foo"); 661 let x = env!("foo");
662} 662 }
663"#), 663 "#,
664 @r###" 664 expect![[r#"
665 !0..22 '"__RA_...TED__"': &str 665 !0..22 '"__RA_...TED__"': &str
666 62..90 '{ ...o"); }': () 666 62..90 '{ ...o"); }': ()
667 72..73 'x': &str 667 72..73 'x': &str
668 "### 668 "#]],
669 ); 669 );
670} 670}
671 671
@@ -763,25 +763,25 @@ fn test() {
763 763
764#[test] 764#[test]
765fn macro_in_arm() { 765fn macro_in_arm() {
766 assert_snapshot!( 766 check_infer(
767 infer(r#" 767 r#"
768macro_rules! unit { 768 macro_rules! unit {
769 () => { () }; 769 () => { () };
770} 770 }
771 771
772fn main() { 772 fn main() {
773 let x = match () { 773 let x = match () {
774 unit!() => 92u32, 774 unit!() => 92u32,
775 }; 775 };
776} 776 }
777"#), 777 "#,
778 @r###" 778 expect![[r#"
779 51..110 '{ ... }; }': () 779 51..110 '{ ... }; }': ()
780 61..62 'x': u32 780 61..62 'x': u32
781 65..107 'match ... }': u32 781 65..107 'match ... }': u32
782 71..73 '()': () 782 71..73 '()': ()
783 84..91 'unit!()': () 783 84..91 'unit!()': ()
784 95..100 '92u32': u32 784 95..100 '92u32': u32
785 "### 785 "#]],
786 ); 786 );
787} 787}
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index 9c8f22314..fa68355aa 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -1,245 +1,245 @@
1use insta::assert_snapshot; 1use expect::expect;
2 2
3use super::{check_types, infer}; 3use super::{check_infer, check_types};
4 4
5#[test] 5#[test]
6fn infer_slice_method() { 6fn infer_slice_method() {
7 assert_snapshot!( 7 check_infer(
8 infer(r#" 8 r#"
9#[lang = "slice"] 9 #[lang = "slice"]
10impl<T> [T] { 10 impl<T> [T] {
11 fn foo(&self) -> T { 11 fn foo(&self) -> T {
12 loop {} 12 loop {}
13 } 13 }
14} 14 }
15 15
16#[lang = "slice_alloc"] 16 #[lang = "slice_alloc"]
17impl<T> [T] {} 17 impl<T> [T] {}
18 18
19fn test(x: &[u8]) { 19 fn test(x: &[u8]) {
20 <[_]>::foo(x); 20 <[_]>::foo(x);
21} 21 }
22"#), 22 "#,
23 @r###" 23 expect![[r#"
24 44..48 'self': &[T] 24 44..48 'self': &[T]
25 55..78 '{ ... }': T 25 55..78 '{ ... }': T
26 65..72 'loop {}': ! 26 65..72 'loop {}': !
27 70..72 '{}': () 27 70..72 '{}': ()
28 130..131 'x': &[u8] 28 130..131 'x': &[u8]
29 140..162 '{ ...(x); }': () 29 140..162 '{ ...(x); }': ()
30 146..156 '<[_]>::foo': fn foo<u8>(&[u8]) -> u8 30 146..156 '<[_]>::foo': fn foo<u8>(&[u8]) -> u8
31 146..159 '<[_]>::foo(x)': u8 31 146..159 '<[_]>::foo(x)': u8
32 157..158 'x': &[u8] 32 157..158 'x': &[u8]
33 "### 33 "#]],
34 ); 34 );
35} 35}
36 36
37#[test] 37#[test]
38fn infer_associated_method_struct() { 38fn infer_associated_method_struct() {
39 assert_snapshot!( 39 check_infer(
40 infer(r#" 40 r#"
41struct A { x: u32 } 41 struct A { x: u32 }
42 42
43impl A { 43 impl A {
44 fn new() -> A { 44 fn new() -> A {
45 A { x: 0 } 45 A { x: 0 }
46 } 46 }
47} 47 }
48fn test() { 48 fn test() {
49 let a = A::new(); 49 let a = A::new();
50 a.x; 50 a.x;
51} 51 }
52"#), 52 "#,
53 @r###" 53 expect![[r#"
54 48..74 '{ ... }': A 54 48..74 '{ ... }': A
55 58..68 'A { x: 0 }': A 55 58..68 'A { x: 0 }': A
56 65..66 '0': u32 56 65..66 '0': u32
57 87..121 '{ ...a.x; }': () 57 87..121 '{ ...a.x; }': ()
58 97..98 'a': A 58 97..98 'a': A
59 101..107 'A::new': fn new() -> A 59 101..107 'A::new': fn new() -> A
60 101..109 'A::new()': A 60 101..109 'A::new()': A
61 115..116 'a': A 61 115..116 'a': A
62 115..118 'a.x': u32 62 115..118 'a.x': u32
63 "### 63 "#]],
64 ); 64 );
65} 65}
66 66
67#[test] 67#[test]
68fn infer_associated_method_enum() { 68fn infer_associated_method_enum() {
69 assert_snapshot!( 69 check_infer(
70 infer(r#" 70 r#"
71enum A { B, C } 71 enum A { B, C }
72 72
73impl A { 73 impl A {
74 pub fn b() -> A { 74 pub fn b() -> A {
75 A::B 75 A::B
76 } 76 }
77 pub fn c() -> A { 77 pub fn c() -> A {
78 A::C 78 A::C
79 } 79 }
80} 80 }
81fn test() { 81 fn test() {
82 let a = A::b(); 82 let a = A::b();
83 a; 83 a;
84 let c = A::c(); 84 let c = A::c();
85 c; 85 c;
86} 86 }
87"#), 87 "#,
88 @r###" 88 expect![[r#"
89 46..66 '{ ... }': A 89 46..66 '{ ... }': A
90 56..60 'A::B': A 90 56..60 'A::B': A
91 87..107 '{ ... }': A 91 87..107 '{ ... }': A
92 97..101 'A::C': A 92 97..101 'A::C': A
93 120..177 '{ ... c; }': () 93 120..177 '{ ... c; }': ()
94 130..131 'a': A 94 130..131 'a': A
95 134..138 'A::b': fn b() -> A 95 134..138 'A::b': fn b() -> A
96 134..140 'A::b()': A 96 134..140 'A::b()': A
97 146..147 'a': A 97 146..147 'a': A
98 157..158 'c': A 98 157..158 'c': A
99 161..165 'A::c': fn c() -> A 99 161..165 'A::c': fn c() -> A
100 161..167 'A::c()': A 100 161..167 'A::c()': A
101 173..174 'c': A 101 173..174 'c': A
102 "### 102 "#]],
103 ); 103 );
104} 104}
105 105
106#[test] 106#[test]
107fn infer_associated_method_with_modules() { 107fn infer_associated_method_with_modules() {
108 assert_snapshot!( 108 check_infer(
109 infer(r#" 109 r#"
110mod a { 110 mod a {
111 struct A; 111 struct A;
112 impl A { pub fn thing() -> A { A {} }} 112 impl A { pub fn thing() -> A { A {} }}
113} 113 }
114 114
115mod b { 115 mod b {
116 struct B; 116 struct B;
117 impl B { pub fn thing() -> u32 { 99 }} 117 impl B { pub fn thing() -> u32 { 99 }}
118 118
119 mod c { 119 mod c {
120 struct C; 120 struct C;
121 impl C { pub fn thing() -> C { C {} }} 121 impl C { pub fn thing() -> C { C {} }}
122 } 122 }
123} 123 }
124use b::c; 124 use b::c;
125 125
126fn test() { 126 fn test() {
127 let x = a::A::thing(); 127 let x = a::A::thing();
128 let y = b::B::thing(); 128 let y = b::B::thing();
129 let z = c::C::thing(); 129 let z = c::C::thing();
130} 130 }
131"#), 131 "#,
132 @r###" 132 expect![[r#"
133 55..63 '{ A {} }': A 133 55..63 '{ A {} }': A
134 57..61 'A {}': A 134 57..61 'A {}': A
135 125..131 '{ 99 }': u32 135 125..131 '{ 99 }': u32
136 127..129 '99': u32 136 127..129 '99': u32
137 201..209 '{ C {} }': C 137 201..209 '{ C {} }': C
138 203..207 'C {}': C 138 203..207 'C {}': C
139 240..324 '{ ...g(); }': () 139 240..324 '{ ...g(); }': ()
140 250..251 'x': A 140 250..251 'x': A
141 254..265 'a::A::thing': fn thing() -> A 141 254..265 'a::A::thing': fn thing() -> A
142 254..267 'a::A::thing()': A 142 254..267 'a::A::thing()': A
143 277..278 'y': u32 143 277..278 'y': u32
144 281..292 'b::B::thing': fn thing() -> u32 144 281..292 'b::B::thing': fn thing() -> u32
145 281..294 'b::B::thing()': u32 145 281..294 'b::B::thing()': u32
146 304..305 'z': C 146 304..305 'z': C
147 308..319 'c::C::thing': fn thing() -> C 147 308..319 'c::C::thing': fn thing() -> C
148 308..321 'c::C::thing()': C 148 308..321 'c::C::thing()': C
149 "### 149 "#]],
150 ); 150 );
151} 151}
152 152
153#[test] 153#[test]
154fn infer_associated_method_generics() { 154fn infer_associated_method_generics() {
155 assert_snapshot!( 155 check_infer(
156 infer(r#" 156 r#"
157struct Gen<T> { 157 struct Gen<T> {
158 val: T 158 val: T
159} 159 }
160 160
161impl<T> Gen<T> { 161 impl<T> Gen<T> {
162 pub fn make(val: T) -> Gen<T> { 162 pub fn make(val: T) -> Gen<T> {
163 Gen { val } 163 Gen { val }
164 } 164 }
165} 165 }
166 166
167fn test() { 167 fn test() {
168 let a = Gen::make(0u32); 168 let a = Gen::make(0u32);
169} 169 }
170"#), 170 "#,
171 @r###" 171 expect![[r#"
172 63..66 'val': T 172 63..66 'val': T
173 81..108 '{ ... }': Gen<T> 173 81..108 '{ ... }': Gen<T>
174 91..102 'Gen { val }': Gen<T> 174 91..102 'Gen { val }': Gen<T>
175 97..100 'val': T 175 97..100 'val': T
176 122..154 '{ ...32); }': () 176 122..154 '{ ...32); }': ()
177 132..133 'a': Gen<u32> 177 132..133 'a': Gen<u32>
178 136..145 'Gen::make': fn make<u32>(u32) -> Gen<u32> 178 136..145 'Gen::make': fn make<u32>(u32) -> Gen<u32>
179 136..151 'Gen::make(0u32)': Gen<u32> 179 136..151 'Gen::make(0u32)': Gen<u32>
180 146..150 '0u32': u32 180 146..150 '0u32': u32
181 "### 181 "#]],
182 ); 182 );
183} 183}
184 184
185#[test] 185#[test]
186fn infer_associated_method_generics_without_args() { 186fn infer_associated_method_generics_without_args() {
187 assert_snapshot!( 187 check_infer(
188 infer(r#" 188 r#"
189struct Gen<T> { 189 struct Gen<T> {
190 val: T 190 val: T
191} 191 }
192 192
193impl<T> Gen<T> { 193 impl<T> Gen<T> {
194 pub fn make() -> Gen<T> { 194 pub fn make() -> Gen<T> {
195 loop { } 195 loop { }
196 } 196 }
197} 197 }
198 198
199fn test() { 199 fn test() {
200 let a = Gen::<u32>::make(); 200 let a = Gen::<u32>::make();
201} 201 }
202"#), 202 "#,
203 @r###" 203 expect![[r#"
204 75..99 '{ ... }': Gen<T> 204 75..99 '{ ... }': Gen<T>
205 85..93 'loop { }': ! 205 85..93 'loop { }': !
206 90..93 '{ }': () 206 90..93 '{ }': ()
207 113..148 '{ ...e(); }': () 207 113..148 '{ ...e(); }': ()
208 123..124 'a': Gen<u32> 208 123..124 'a': Gen<u32>
209 127..143 'Gen::<...::make': fn make<u32>() -> Gen<u32> 209 127..143 'Gen::<...::make': fn make<u32>() -> Gen<u32>
210 127..145 'Gen::<...make()': Gen<u32> 210 127..145 'Gen::<...make()': Gen<u32>
211 "### 211 "#]],
212 ); 212 );
213} 213}
214 214
215#[test] 215#[test]
216fn infer_associated_method_generics_2_type_params_without_args() { 216fn infer_associated_method_generics_2_type_params_without_args() {
217 assert_snapshot!( 217 check_infer(
218 infer(r#" 218 r#"
219struct Gen<T, U> { 219 struct Gen<T, U> {
220 val: T, 220 val: T,
221 val2: U, 221 val2: U,
222} 222 }
223 223
224impl<T> Gen<u32, T> { 224 impl<T> Gen<u32, T> {
225 pub fn make() -> Gen<u32,T> { 225 pub fn make() -> Gen<u32,T> {
226 loop { } 226 loop { }
227 } 227 }
228} 228 }
229 229
230fn test() { 230 fn test() {
231 let a = Gen::<u32, u64>::make(); 231 let a = Gen::<u32, u64>::make();
232} 232 }
233"#), 233 "#,
234 @r###" 234 expect![[r#"
235 101..125 '{ ... }': Gen<u32, T> 235 101..125 '{ ... }': Gen<u32, T>
236 111..119 'loop { }': ! 236 111..119 'loop { }': !
237 116..119 '{ }': () 237 116..119 '{ }': ()
238 139..179 '{ ...e(); }': () 238 139..179 '{ ...e(); }': ()
239 149..150 'a': Gen<u32, u64> 239 149..150 'a': Gen<u32, u64>
240 153..174 'Gen::<...::make': fn make<u64>() -> Gen<u32, u64> 240 153..174 'Gen::<...::make': fn make<u64>() -> Gen<u32, u64>
241 153..176 'Gen::<...make()': Gen<u32, u64> 241 153..176 'Gen::<...make()': Gen<u32, u64>
242 "### 242 "#]],
243 ); 243 );
244} 244}
245 245
@@ -267,416 +267,416 @@ mod foo {
267#[test] 267#[test]
268fn infer_trait_method_simple() { 268fn 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 assert_snapshot!( 270 check_infer(
271 infer(r#" 271 r#"
272trait Trait1 { 272 trait Trait1 {
273 fn method(&self) -> u32; 273 fn method(&self) -> u32;
274} 274 }
275struct S1; 275 struct S1;
276impl Trait1 for S1 {} 276 impl Trait1 for S1 {}
277trait Trait2 { 277 trait Trait2 {
278 fn method(&self) -> i128; 278 fn method(&self) -> i128;
279} 279 }
280struct S2; 280 struct S2;
281impl Trait2 for S2 {} 281 impl Trait2 for S2 {}
282fn test() { 282 fn test() {
283 S1.method(); // -> u32 283 S1.method(); // -> u32
284 S2.method(); // -> i128 284 S2.method(); // -> i128
285} 285 }
286"#), 286 "#,
287 @r###" 287 expect![[r#"
288 30..34 'self': &Self 288 30..34 'self': &Self
289 109..113 'self': &Self 289 109..113 'self': &Self
290 169..227 '{ ...i128 }': () 290 169..227 '{ ...i128 }': ()
291 175..177 'S1': S1 291 175..177 'S1': S1
292 175..186 'S1.method()': u32 292 175..186 'S1.method()': u32
293 202..204 'S2': S2 293 202..204 'S2': S2
294 202..213 'S2.method()': i128 294 202..213 'S2.method()': i128
295 "### 295 "#]],
296 ); 296 );
297} 297}
298 298
299#[test] 299#[test]
300fn infer_trait_method_scoped() { 300fn infer_trait_method_scoped() {
301 // the trait implementation is intentionally incomplete -- it shouldn't matter 301 // the trait implementation is intentionally incomplete -- it shouldn't matter
302 assert_snapshot!( 302 check_infer(
303 infer(r#" 303 r#"
304struct S; 304 struct S;
305mod foo { 305 mod foo {
306 pub trait Trait1 { 306 pub trait Trait1 {
307 fn method(&self) -> u32; 307 fn method(&self) -> u32;
308 } 308 }
309 impl Trait1 for super::S {} 309 impl Trait1 for super::S {}
310} 310 }
311mod bar { 311 mod bar {
312 pub trait Trait2 { 312 pub trait Trait2 {
313 fn method(&self) -> i128; 313 fn method(&self) -> i128;
314 } 314 }
315 impl Trait2 for super::S {} 315 impl Trait2 for super::S {}
316} 316 }
317 317
318mod foo_test { 318 mod foo_test {
319 use super::S; 319 use super::S;
320 use super::foo::Trait1; 320 use super::foo::Trait1;
321 fn test() { 321 fn test() {
322 S.method(); // -> u32 322 S.method(); // -> u32
323 } 323 }
324} 324 }
325 325
326mod bar_test { 326 mod bar_test {
327 use super::S; 327 use super::S;
328 use super::bar::Trait2; 328 use super::bar::Trait2;
329 fn test() { 329 fn test() {
330 S.method(); // -> i128 330 S.method(); // -> i128
331 } 331 }
332} 332 }
333"#), 333 "#,
334 @r###" 334 expect![[r#"
335 62..66 'self': &Self 335 62..66 'self': &Self
336 168..172 'self': &Self 336 168..172 'self': &Self
337 299..336 '{ ... }': () 337 299..336 '{ ... }': ()
338 309..310 'S': S 338 309..310 'S': S
339 309..319 'S.method()': u32 339 309..319 'S.method()': u32
340 415..453 '{ ... }': () 340 415..453 '{ ... }': ()
341 425..426 'S': S 341 425..426 'S': S
342 425..435 'S.method()': i128 342 425..435 'S.method()': i128
343 "### 343 "#]],
344 ); 344 );
345} 345}
346 346
347#[test] 347#[test]
348fn infer_trait_method_generic_1() { 348fn infer_trait_method_generic_1() {
349 // the trait implementation is intentionally incomplete -- it shouldn't matter 349 // the trait implementation is intentionally incomplete -- it shouldn't matter
350 assert_snapshot!( 350 check_infer(
351 infer(r#" 351 r#"
352trait Trait<T> { 352 trait Trait<T> {
353 fn method(&self) -> T; 353 fn method(&self) -> T;
354} 354 }
355struct S; 355 struct S;
356impl Trait<u32> for S {} 356 impl Trait<u32> for S {}
357fn test() { 357 fn test() {
358 S.method(); 358 S.method();
359} 359 }
360"#), 360 "#,
361 @r###" 361 expect![[r#"
362 32..36 'self': &Self 362 32..36 'self': &Self
363 91..110 '{ ...d(); }': () 363 91..110 '{ ...d(); }': ()
364 97..98 'S': S 364 97..98 'S': S
365 97..107 'S.method()': u32 365 97..107 'S.method()': u32
366 "### 366 "#]],
367 ); 367 );
368} 368}
369 369
370#[test] 370#[test]
371fn infer_trait_method_generic_more_params() { 371fn infer_trait_method_generic_more_params() {
372 // the trait implementation is intentionally incomplete -- it shouldn't matter 372 // the trait implementation is intentionally incomplete -- it shouldn't matter
373 assert_snapshot!( 373 check_infer(
374 infer(r#" 374 r#"
375trait Trait<T1, T2, T3> { 375 trait Trait<T1, T2, T3> {
376 fn method1(&self) -> (T1, T2, T3); 376 fn method1(&self) -> (T1, T2, T3);
377 fn method2(&self) -> (T3, T2, T1); 377 fn method2(&self) -> (T3, T2, T1);
378} 378 }
379struct S1; 379 struct S1;
380impl Trait<u8, u16, u32> for S1 {} 380 impl Trait<u8, u16, u32> for S1 {}
381struct S2; 381 struct S2;
382impl<T> Trait<i8, i16, T> for S2 {} 382 impl<T> Trait<i8, i16, T> for S2 {}
383fn test() { 383 fn test() {
384 S1.method1(); // u8, u16, u32 384 S1.method1(); // u8, u16, u32
385 S1.method2(); // u32, u16, u8 385 S1.method2(); // u32, u16, u8
386 S2.method1(); // i8, i16, {unknown} 386 S2.method1(); // i8, i16, {unknown}
387 S2.method2(); // {unknown}, i16, i8 387 S2.method2(); // {unknown}, i16, i8
388} 388 }
389"#), 389 "#,
390 @r###" 390 expect![[r#"
391 42..46 'self': &Self 391 42..46 'self': &Self
392 81..85 'self': &Self 392 81..85 'self': &Self
393 209..360 '{ ..., i8 }': () 393 209..360 '{ ..., i8 }': ()
394 215..217 'S1': S1 394 215..217 'S1': S1
395 215..227 'S1.method1()': (u8, u16, u32) 395 215..227 'S1.method1()': (u8, u16, u32)
396 249..251 'S1': S1 396 249..251 'S1': S1
397 249..261 'S1.method2()': (u32, u16, u8) 397 249..261 'S1.method2()': (u32, u16, u8)
398 283..285 'S2': S2 398 283..285 'S2': S2
399 283..295 'S2.method1()': (i8, i16, {unknown}) 399 283..295 'S2.method1()': (i8, i16, {unknown})
400 323..325 'S2': S2 400 323..325 'S2': S2
401 323..335 'S2.method2()': ({unknown}, i16, i8) 401 323..335 'S2.method2()': ({unknown}, i16, i8)
402 "### 402 "#]],
403 ); 403 );
404} 404}
405 405
406#[test] 406#[test]
407fn infer_trait_method_generic_2() { 407fn infer_trait_method_generic_2() {
408 // the trait implementation is intentionally incomplete -- it shouldn't matter 408 // the trait implementation is intentionally incomplete -- it shouldn't matter
409 assert_snapshot!( 409 check_infer(
410 infer(r#" 410 r#"
411trait Trait<T> { 411 trait Trait<T> {
412 fn method(&self) -> T; 412 fn method(&self) -> T;
413} 413 }
414struct S<T>(T); 414 struct S<T>(T);
415impl<U> Trait<U> for S<U> {} 415 impl<U> Trait<U> for S<U> {}
416fn test() { 416 fn test() {
417 S(1u32).method(); 417 S(1u32).method();
418} 418 }
419"#), 419 "#,
420 @r###" 420 expect![[r#"
421 32..36 'self': &Self 421 32..36 'self': &Self
422 101..126 '{ ...d(); }': () 422 101..126 '{ ...d(); }': ()
423 107..108 'S': S<u32>(u32) -> S<u32> 423 107..108 'S': S<u32>(u32) -> S<u32>
424 107..114 'S(1u32)': S<u32> 424 107..114 'S(1u32)': S<u32>
425 107..123 'S(1u32...thod()': u32 425 107..123 'S(1u32...thod()': u32
426 109..113 '1u32': u32 426 109..113 '1u32': u32
427 "### 427 "#]],
428 ); 428 );
429} 429}
430 430
431#[test] 431#[test]
432fn infer_trait_assoc_method() { 432fn infer_trait_assoc_method() {
433 assert_snapshot!( 433 check_infer(
434 infer(r#" 434 r#"
435trait Default { 435 trait Default {
436 fn default() -> Self; 436 fn default() -> Self;
437} 437 }
438struct S; 438 struct S;
439impl Default for S {} 439 impl Default for S {}
440fn test() { 440 fn test() {
441 let s1: S = Default::default(); 441 let s1: S = Default::default();
442 let s2 = S::default(); 442 let s2 = S::default();
443 let s3 = <S as Default>::default(); 443 let s3 = <S as Default>::default();
444} 444 }
445"#), 445 "#,
446 @r###" 446 expect![[r#"
447 86..192 '{ ...t(); }': () 447 86..192 '{ ...t(); }': ()
448 96..98 's1': S 448 96..98 's1': S
449 104..120 'Defaul...efault': fn default<S>() -> S 449 104..120 'Defaul...efault': fn default<S>() -> S
450 104..122 'Defaul...ault()': S 450 104..122 'Defaul...ault()': S
451 132..134 's2': S 451 132..134 's2': S
452 137..147 'S::default': fn default<S>() -> S 452 137..147 'S::default': fn default<S>() -> S
453 137..149 'S::default()': S 453 137..149 'S::default()': S
454 159..161 's3': S 454 159..161 's3': S
455 164..187 '<S as ...efault': fn default<S>() -> S 455 164..187 '<S as ...efault': fn default<S>() -> S
456 164..189 '<S as ...ault()': S 456 164..189 '<S as ...ault()': S
457 "### 457 "#]],
458 ); 458 );
459} 459}
460 460
461#[test] 461#[test]
462fn infer_trait_assoc_method_generics_1() { 462fn infer_trait_assoc_method_generics_1() {
463 assert_snapshot!( 463 check_infer(
464 infer(r#" 464 r#"
465trait Trait<T> { 465 trait Trait<T> {
466 fn make() -> T; 466 fn make() -> T;
467} 467 }
468struct S; 468 struct S;
469impl Trait<u32> for S {} 469 impl Trait<u32> for S {}
470struct G<T>; 470 struct G<T>;
471impl<T> Trait<T> for G<T> {} 471 impl<T> Trait<T> for G<T> {}
472fn test() { 472 fn test() {
473 let a = S::make(); 473 let a = S::make();
474 let b = G::<u64>::make(); 474 let b = G::<u64>::make();
475 let c: f64 = G::make(); 475 let c: f64 = G::make();
476} 476 }
477"#), 477 "#,
478 @r###" 478 expect![[r#"
479 126..210 '{ ...e(); }': () 479 126..210 '{ ...e(); }': ()
480 136..137 'a': u32 480 136..137 'a': u32
481 140..147 'S::make': fn make<S, u32>() -> u32 481 140..147 'S::make': fn make<S, u32>() -> u32
482 140..149 'S::make()': u32 482 140..149 'S::make()': u32
483 159..160 'b': u64 483 159..160 'b': u64
484 163..177 'G::<u64>::make': fn make<G<u64>, u64>() -> u64 484 163..177 'G::<u64>::make': fn make<G<u64>, u64>() -> u64
485 163..179 'G::<u6...make()': u64 485 163..179 'G::<u6...make()': u64
486 189..190 'c': f64 486 189..190 'c': f64
487 198..205 'G::make': fn make<G<f64>, f64>() -> f64 487 198..205 'G::make': fn make<G<f64>, f64>() -> f64
488 198..207 'G::make()': f64 488 198..207 'G::make()': f64
489 "### 489 "#]],
490 ); 490 );
491} 491}
492 492
493#[test] 493#[test]
494fn infer_trait_assoc_method_generics_2() { 494fn infer_trait_assoc_method_generics_2() {
495 assert_snapshot!( 495 check_infer(
496 infer(r#" 496 r#"
497trait Trait<T> { 497 trait Trait<T> {
498 fn make<U>() -> (T, U); 498 fn make<U>() -> (T, U);
499} 499 }
500struct S; 500 struct S;
501impl Trait<u32> for S {} 501 impl Trait<u32> for S {}
502struct G<T>; 502 struct G<T>;
503impl<T> Trait<T> for G<T> {} 503 impl<T> Trait<T> for G<T> {}
504fn test() { 504 fn test() {
505 let a = S::make::<i64>(); 505 let a = S::make::<i64>();
506 let b: (_, i64) = S::make(); 506 let b: (_, i64) = S::make();
507 let c = G::<u32>::make::<i64>(); 507 let c = G::<u32>::make::<i64>();
508 let d: (u32, _) = G::make::<i64>(); 508 let d: (u32, _) = G::make::<i64>();
509 let e: (u32, i64) = G::make(); 509 let e: (u32, i64) = G::make();
510} 510 }
511"#), 511 "#,
512 @r###" 512 expect![[r#"
513 134..312 '{ ...e(); }': () 513 134..312 '{ ...e(); }': ()
514 144..145 'a': (u32, i64) 514 144..145 'a': (u32, i64)
515 148..162 'S::make::<i64>': fn make<S, u32, i64>() -> (u32, i64) 515 148..162 'S::make::<i64>': fn make<S, u32, i64>() -> (u32, i64)
516 148..164 'S::mak...i64>()': (u32, i64) 516 148..164 'S::mak...i64>()': (u32, i64)
517 174..175 'b': (u32, i64) 517 174..175 'b': (u32, i64)
518 188..195 'S::make': fn make<S, u32, i64>() -> (u32, i64) 518 188..195 'S::make': fn make<S, u32, i64>() -> (u32, i64)
519 188..197 'S::make()': (u32, i64) 519 188..197 'S::make()': (u32, i64)
520 207..208 'c': (u32, i64) 520 207..208 'c': (u32, i64)
521 211..232 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) 521 211..232 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64)
522 211..234 'G::<u3...i64>()': (u32, i64) 522 211..234 'G::<u3...i64>()': (u32, i64)
523 244..245 'd': (u32, i64) 523 244..245 'd': (u32, i64)
524 258..272 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) 524 258..272 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64)
525 258..274 'G::mak...i64>()': (u32, i64) 525 258..274 'G::mak...i64>()': (u32, i64)
526 284..285 'e': (u32, i64) 526 284..285 'e': (u32, i64)
527 300..307 'G::make': fn make<G<u32>, u32, i64>() -> (u32, i64) 527 300..307 'G::make': fn make<G<u32>, u32, i64>() -> (u32, i64)
528 300..309 'G::make()': (u32, i64) 528 300..309 'G::make()': (u32, i64)
529 "### 529 "#]],
530 ); 530 );
531} 531}
532 532
533#[test] 533#[test]
534fn infer_trait_assoc_method_generics_3() { 534fn infer_trait_assoc_method_generics_3() {
535 assert_snapshot!( 535 check_infer(
536 infer(r#" 536 r#"
537trait Trait<T> { 537 trait Trait<T> {
538 fn make() -> (Self, T); 538 fn make() -> (Self, T);
539} 539 }
540struct S<T>; 540 struct S<T>;
541impl Trait<i64> for S<i32> {} 541 impl Trait<i64> for S<i32> {}
542fn test() { 542 fn test() {
543 let a = S::make(); 543 let a = S::make();
544} 544 }
545"#), 545 "#,
546 @r###" 546 expect![[r#"
547 100..126 '{ ...e(); }': () 547 100..126 '{ ...e(); }': ()
548 110..111 'a': (S<i32>, i64) 548 110..111 'a': (S<i32>, i64)
549 114..121 'S::make': fn make<S<i32>, i64>() -> (S<i32>, i64) 549 114..121 'S::make': fn make<S<i32>, i64>() -> (S<i32>, i64)
550 114..123 'S::make()': (S<i32>, i64) 550 114..123 'S::make()': (S<i32>, i64)
551 "### 551 "#]],
552 ); 552 );
553} 553}
554 554
555#[test] 555#[test]
556fn infer_trait_assoc_method_generics_4() { 556fn infer_trait_assoc_method_generics_4() {
557 assert_snapshot!( 557 check_infer(
558 infer(r#" 558 r#"
559trait Trait<T> { 559 trait Trait<T> {
560 fn make() -> (Self, T); 560 fn make() -> (Self, T);
561} 561 }
562struct S<T>; 562 struct S<T>;
563impl Trait<i64> for S<u64> {} 563 impl Trait<i64> for S<u64> {}
564impl Trait<i32> for S<u32> {} 564 impl Trait<i32> for S<u32> {}
565fn test() { 565 fn test() {
566 let a: (S<u64>, _) = S::make(); 566 let a: (S<u64>, _) = S::make();
567 let b: (_, i32) = S::make(); 567 let b: (_, i32) = S::make();
568} 568 }
569"#), 569 "#,
570 @r###" 570 expect![[r#"
571 130..202 '{ ...e(); }': () 571 130..202 '{ ...e(); }': ()
572 140..141 'a': (S<u64>, i64) 572 140..141 'a': (S<u64>, i64)
573 157..164 'S::make': fn make<S<u64>, i64>() -> (S<u64>, i64) 573 157..164 'S::make': fn make<S<u64>, i64>() -> (S<u64>, i64)
574 157..166 'S::make()': (S<u64>, i64) 574 157..166 'S::make()': (S<u64>, i64)
575 176..177 'b': (S<u32>, i32) 575 176..177 'b': (S<u32>, i32)
576 190..197 'S::make': fn make<S<u32>, i32>() -> (S<u32>, i32) 576 190..197 'S::make': fn make<S<u32>, i32>() -> (S<u32>, i32)
577 190..199 'S::make()': (S<u32>, i32) 577 190..199 'S::make()': (S<u32>, i32)
578 "### 578 "#]],
579 ); 579 );
580} 580}
581 581
582#[test] 582#[test]
583fn infer_trait_assoc_method_generics_5() { 583fn infer_trait_assoc_method_generics_5() {
584 assert_snapshot!( 584 check_infer(
585 infer(r#" 585 r#"
586trait Trait<T> { 586 trait Trait<T> {
587 fn make<U>() -> (Self, T, U); 587 fn make<U>() -> (Self, T, U);
588} 588 }
589struct S<T>; 589 struct S<T>;
590impl Trait<i64> for S<u64> {} 590 impl Trait<i64> for S<u64> {}
591fn test() { 591 fn test() {
592 let a = <S as Trait<i64>>::make::<u8>(); 592 let a = <S as Trait<i64>>::make::<u8>();
593 let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>(); 593 let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>();
594} 594 }
595"#), 595 "#,
596 @r###" 596 expect![[r#"
597 106..210 '{ ...>(); }': () 597 106..210 '{ ...>(); }': ()
598 116..117 'a': (S<u64>, i64, u8) 598 116..117 'a': (S<u64>, i64, u8)
599 120..149 '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) 599 120..149 '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8)
600 120..151 '<S as ...<u8>()': (S<u64>, i64, u8) 600 120..151 '<S as ...<u8>()': (S<u64>, i64, u8)
601 161..162 'b': (S<u64>, i64, u8) 601 161..162 'b': (S<u64>, i64, u8)
602 181..205 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) 602 181..205 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8)
603 181..207 'Trait:...<u8>()': (S<u64>, i64, u8) 603 181..207 'Trait:...<u8>()': (S<u64>, i64, u8)
604 "### 604 "#]],
605 ); 605 );
606} 606}
607 607
608#[test] 608#[test]
609fn infer_call_trait_method_on_generic_param_1() { 609fn infer_call_trait_method_on_generic_param_1() {
610 assert_snapshot!( 610 check_infer(
611 infer(r#" 611 r#"
612trait Trait { 612 trait Trait {
613 fn method(&self) -> u32; 613 fn method(&self) -> u32;
614} 614 }
615fn test<T: Trait>(t: T) { 615 fn test<T: Trait>(t: T) {
616 t.method(); 616 t.method();
617} 617 }
618"#), 618 "#,
619 @r###" 619 expect![[r#"
620 29..33 'self': &Self 620 29..33 'self': &Self
621 63..64 't': T 621 63..64 't': T
622 69..88 '{ ...d(); }': () 622 69..88 '{ ...d(); }': ()
623 75..76 't': T 623 75..76 't': T
624 75..85 't.method()': u32 624 75..85 't.method()': u32
625 "### 625 "#]],
626 ); 626 );
627} 627}
628 628
629#[test] 629#[test]
630fn infer_call_trait_method_on_generic_param_2() { 630fn infer_call_trait_method_on_generic_param_2() {
631 assert_snapshot!( 631 check_infer(
632 infer(r#" 632 r#"
633trait Trait<T> { 633 trait Trait<T> {
634 fn method(&self) -> T; 634 fn method(&self) -> T;
635} 635 }
636fn test<U, T: Trait<U>>(t: T) { 636 fn test<U, T: Trait<U>>(t: T) {
637 t.method(); 637 t.method();
638} 638 }
639"#), 639 "#,
640 @r###" 640 expect![[r#"
641 32..36 'self': &Self 641 32..36 'self': &Self
642 70..71 't': T 642 70..71 't': T
643 76..95 '{ ...d(); }': () 643 76..95 '{ ...d(); }': ()
644 82..83 't': T 644 82..83 't': T
645 82..92 't.method()': U 645 82..92 't.method()': U
646 "### 646 "#]],
647 ); 647 );
648} 648}
649 649
650#[test] 650#[test]
651fn infer_with_multiple_trait_impls() { 651fn infer_with_multiple_trait_impls() {
652 assert_snapshot!( 652 check_infer(
653 infer(r#" 653 r#"
654trait Into<T> { 654 trait Into<T> {
655 fn into(self) -> T; 655 fn into(self) -> T;
656} 656 }
657struct S; 657 struct S;
658impl Into<u32> for S {} 658 impl Into<u32> for S {}
659impl Into<u64> for S {} 659 impl Into<u64> for S {}
660fn test() { 660 fn test() {
661 let x: u32 = S.into(); 661 let x: u32 = S.into();
662 let y: u64 = S.into(); 662 let y: u64 = S.into();
663 let z = Into::<u64>::into(S); 663 let z = Into::<u64>::into(S);
664} 664 }
665"#), 665 "#,
666 @r###" 666 expect![[r#"
667 28..32 'self': Self 667 28..32 'self': Self
668 110..201 '{ ...(S); }': () 668 110..201 '{ ...(S); }': ()
669 120..121 'x': u32 669 120..121 'x': u32
670 129..130 'S': S 670 129..130 'S': S
671 129..137 'S.into()': u32 671 129..137 'S.into()': u32
672 147..148 'y': u64 672 147..148 'y': u64
673 156..157 'S': S 673 156..157 'S': S
674 156..164 'S.into()': u64 674 156..164 'S.into()': u64
675 174..175 'z': u64 675 174..175 'z': u64
676 178..195 'Into::...::into': fn into<S, u64>(S) -> u64 676 178..195 'Into::...::into': fn into<S, u64>(S) -> u64
677 178..198 'Into::...nto(S)': u64 677 178..198 'Into::...nto(S)': u64
678 196..197 'S': S 678 196..197 'S': S
679 "### 679 "#]],
680 ); 680 );
681} 681}
682 682
@@ -1023,31 +1023,31 @@ fn test() { (S {}).method(); }
1023 1023
1024#[test] 1024#[test]
1025fn dyn_trait_super_trait_not_in_scope() { 1025fn dyn_trait_super_trait_not_in_scope() {
1026 assert_snapshot!( 1026 check_infer(
1027 infer(r#" 1027 r#"
1028mod m { 1028 mod m {
1029 pub trait SuperTrait { 1029 pub trait SuperTrait {
1030 fn foo(&self) -> u32 { 0 } 1030 fn foo(&self) -> u32 { 0 }
1031 } 1031 }
1032} 1032 }
1033trait Trait: m::SuperTrait {} 1033 trait Trait: m::SuperTrait {}
1034 1034
1035struct S; 1035 struct S;
1036impl m::SuperTrait for S {} 1036 impl m::SuperTrait for S {}
1037impl Trait for S {} 1037 impl Trait for S {}
1038 1038
1039fn test(d: &dyn Trait) { 1039 fn test(d: &dyn Trait) {
1040 d.foo(); 1040 d.foo();
1041} 1041 }
1042"#), 1042 "#,
1043 @r###" 1043 expect![[r#"
1044 51..55 'self': &Self 1044 51..55 'self': &Self
1045 64..69 '{ 0 }': u32 1045 64..69 '{ 0 }': u32
1046 66..67 '0': u32 1046 66..67 '0': u32
1047 176..177 'd': &dyn Trait 1047 176..177 'd': &dyn Trait
1048 191..207 '{ ...o(); }': () 1048 191..207 '{ ...o(); }': ()
1049 197..198 'd': &dyn Trait 1049 197..198 'd': &dyn Trait
1050 197..204 'd.foo()': u32 1050 197..204 'd.foo()': u32
1051 "### 1051 "#]],
1052 ); 1052 );
1053} 1053}
diff --git a/crates/ra_hir_ty/src/tests/never_type.rs b/crates/ra_hir_ty/src/tests/never_type.rs
index 64d421d40..49538b572 100644
--- a/crates/ra_hir_ty/src/tests/never_type.rs
+++ b/crates/ra_hir_ty/src/tests/never_type.rs
@@ -1,6 +1,6 @@
1use insta::assert_snapshot; 1use expect::expect;
2 2
3use super::{check_types, infer_with_mismatches}; 3use super::{check_infer_with_mismatches, check_types};
4 4
5#[test] 5#[test]
6fn infer_never1() { 6fn infer_never1() {
@@ -240,173 +240,170 @@ fn test(a: i32) {
240 240
241#[test] 241#[test]
242fn diverging_expression_1() { 242fn diverging_expression_1() {
243 let t = infer_with_mismatches( 243 check_infer_with_mismatches(
244 r#" 244 r"
245//- /main.rs 245 //- /main.rs
246fn test1() { 246 fn test1() {
247 let x: u32 = return; 247 let x: u32 = return;
248} 248 }
249fn test2() { 249 fn test2() {
250 let x: u32 = { return; }; 250 let x: u32 = { return; };
251} 251 }
252fn test3() { 252 fn test3() {
253 let x: u32 = loop {}; 253 let x: u32 = loop {};
254} 254 }
255fn test4() { 255 fn test4() {
256 let x: u32 = { loop {} }; 256 let x: u32 = { loop {} };
257} 257 }
258fn test5() { 258 fn test5() {
259 let x: u32 = { if true { loop {}; } else { loop {}; } }; 259 let x: u32 = { if true { loop {}; } else { loop {}; } };
260} 260 }
261fn test6() { 261 fn test6() {
262 let x: u32 = { let y: u32 = { loop {}; }; }; 262 let x: u32 = { let y: u32 = { loop {}; }; };
263} 263 }
264"#, 264 ",
265 true, 265 expect![[r"
266 11..39 '{ ...urn; }': ()
267 21..22 'x': u32
268 30..36 'return': !
269 51..84 '{ ...; }; }': ()
270 61..62 'x': u32
271 70..81 '{ return; }': u32
272 72..78 'return': !
273 96..125 '{ ... {}; }': ()
274 106..107 'x': u32
275 115..122 'loop {}': !
276 120..122 '{}': ()
277 137..170 '{ ...} }; }': ()
278 147..148 'x': u32
279 156..167 '{ loop {} }': u32
280 158..165 'loop {}': !
281 163..165 '{}': ()
282 182..246 '{ ...} }; }': ()
283 192..193 'x': u32
284 201..243 '{ if t...}; } }': u32
285 203..241 'if tru... {}; }': u32
286 206..210 'true': bool
287 211..223 '{ loop {}; }': u32
288 213..220 'loop {}': !
289 218..220 '{}': ()
290 229..241 '{ loop {}; }': u32
291 231..238 'loop {}': !
292 236..238 '{}': ()
293 258..310 '{ ...; }; }': ()
294 268..269 'x': u32
295 277..307 '{ let ...; }; }': u32
296 283..284 'y': u32
297 292..304 '{ loop {}; }': u32
298 294..301 'loop {}': !
299 299..301 '{}': ()
300 "]],
266 ); 301 );
267 assert_snapshot!(t, @r###"
268 11..39 '{ ...urn; }': ()
269 21..22 'x': u32
270 30..36 'return': !
271 51..84 '{ ...; }; }': ()
272 61..62 'x': u32
273 70..81 '{ return; }': u32
274 72..78 'return': !
275 96..125 '{ ... {}; }': ()
276 106..107 'x': u32
277 115..122 'loop {}': !
278 120..122 '{}': ()
279 137..170 '{ ...} }; }': ()
280 147..148 'x': u32
281 156..167 '{ loop {} }': u32
282 158..165 'loop {}': !
283 163..165 '{}': ()
284 182..246 '{ ...} }; }': ()
285 192..193 'x': u32
286 201..243 '{ if t...}; } }': u32
287 203..241 'if tru... {}; }': u32
288 206..210 'true': bool
289 211..223 '{ loop {}; }': u32
290 213..220 'loop {}': !
291 218..220 '{}': ()
292 229..241 '{ loop {}; }': u32
293 231..238 'loop {}': !
294 236..238 '{}': ()
295 258..310 '{ ...; }; }': ()
296 268..269 'x': u32
297 277..307 '{ let ...; }; }': u32
298 283..284 'y': u32
299 292..304 '{ loop {}; }': u32
300 294..301 'loop {}': !
301 299..301 '{}': ()
302 "###);
303} 302}
304 303
305#[test] 304#[test]
306fn diverging_expression_2() { 305fn diverging_expression_2() {
307 let t = infer_with_mismatches( 306 check_infer_with_mismatches(
308 r#" 307 r#"
309//- /main.rs 308 //- /main.rs
310fn test1() { 309 fn test1() {
311 // should give type mismatch 310 // should give type mismatch
312 let x: u32 = { loop {}; "foo" }; 311 let x: u32 = { loop {}; "foo" };
313} 312 }
314"#, 313 "#,
315 true, 314 expect![[r#"
315 11..84 '{ ..." }; }': ()
316 54..55 'x': u32
317 63..81 '{ loop...foo" }': &str
318 65..72 'loop {}': !
319 70..72 '{}': ()
320 74..79 '"foo"': &str
321 63..81: expected u32, got &str
322 74..79: expected u32, got &str
323 "#]],
316 ); 324 );
317 assert_snapshot!(t, @r###"
318 11..84 '{ ..." }; }': ()
319 54..55 'x': u32
320 63..81 '{ loop...foo" }': &str
321 65..72 'loop {}': !
322 70..72 '{}': ()
323 74..79 '"foo"': &str
324 63..81: expected u32, got &str
325 74..79: expected u32, got &str
326 "###);
327} 325}
328 326
329#[test] 327#[test]
330fn diverging_expression_3_break() { 328fn diverging_expression_3_break() {
331 let t = infer_with_mismatches( 329 check_infer_with_mismatches(
332 r#" 330 r"
333//- /main.rs 331 //- /main.rs
334fn test1() { 332 fn test1() {
335 // should give type mismatch 333 // should give type mismatch
336 let x: u32 = { loop { break; } }; 334 let x: u32 = { loop { break; } };
337} 335 }
338fn test2() { 336 fn test2() {
339 // should give type mismatch 337 // should give type mismatch
340 let x: u32 = { for a in b { break; }; }; 338 let x: u32 = { for a in b { break; }; };
341 // should give type mismatch as well 339 // should give type mismatch as well
342 let x: u32 = { for a in b {}; }; 340 let x: u32 = { for a in b {}; };
343 // should give type mismatch as well 341 // should give type mismatch as well
344 let x: u32 = { for a in b { return; }; }; 342 let x: u32 = { for a in b { return; }; };
345} 343 }
346fn test3() { 344 fn test3() {
347 // should give type mismatch 345 // should give type mismatch
348 let x: u32 = { while true { break; }; }; 346 let x: u32 = { while true { break; }; };
349 // should give type mismatch as well -- there's an implicit break, even if it's never hit 347 // should give type mismatch as well -- there's an implicit break, even if it's never hit
350 let x: u32 = { while true {}; }; 348 let x: u32 = { while true {}; };
351 // should give type mismatch as well 349 // should give type mismatch as well
352 let x: u32 = { while true { return; }; }; 350 let x: u32 = { while true { return; }; };
353} 351 }
354"#, 352 ",
355 true, 353 expect![[r"
354 11..85 '{ ...} }; }': ()
355 54..55 'x': u32
356 63..82 '{ loop...k; } }': ()
357 65..80 'loop { break; }': ()
358 70..80 '{ break; }': ()
359 72..77 'break': !
360 63..82: expected u32, got ()
361 65..80: expected u32, got ()
362 97..343 '{ ...; }; }': ()
363 140..141 'x': u32
364 149..175 '{ for ...; }; }': ()
365 151..172 'for a ...eak; }': ()
366 155..156 'a': {unknown}
367 160..161 'b': {unknown}
368 162..172 '{ break; }': ()
369 164..169 'break': !
370 226..227 'x': u32
371 235..253 '{ for ... {}; }': ()
372 237..250 'for a in b {}': ()
373 241..242 'a': {unknown}
374 246..247 'b': {unknown}
375 248..250 '{}': ()
376 304..305 'x': u32
377 313..340 '{ for ...; }; }': ()
378 315..337 'for a ...urn; }': ()
379 319..320 'a': {unknown}
380 324..325 'b': {unknown}
381 326..337 '{ return; }': ()
382 328..334 'return': !
383 149..175: expected u32, got ()
384 235..253: expected u32, got ()
385 313..340: expected u32, got ()
386 355..654 '{ ...; }; }': ()
387 398..399 'x': u32
388 407..433 '{ whil...; }; }': ()
389 409..430 'while ...eak; }': ()
390 415..419 'true': bool
391 420..430 '{ break; }': ()
392 422..427 'break': !
393 537..538 'x': u32
394 546..564 '{ whil... {}; }': ()
395 548..561 'while true {}': ()
396 554..558 'true': bool
397 559..561 '{}': ()
398 615..616 'x': u32
399 624..651 '{ whil...; }; }': ()
400 626..648 'while ...urn; }': ()
401 632..636 'true': bool
402 637..648 '{ return; }': ()
403 639..645 'return': !
404 407..433: expected u32, got ()
405 546..564: expected u32, got ()
406 624..651: expected u32, got ()
407 "]],
356 ); 408 );
357 assert_snapshot!(t, @r###"
358 11..85 '{ ...} }; }': ()
359 54..55 'x': u32
360 63..82 '{ loop...k; } }': ()
361 65..80 'loop { break; }': ()
362 70..80 '{ break; }': ()
363 72..77 'break': !
364 63..82: expected u32, got ()
365 65..80: expected u32, got ()
366 97..343 '{ ...; }; }': ()
367 140..141 'x': u32
368 149..175 '{ for ...; }; }': ()
369 151..172 'for a ...eak; }': ()
370 155..156 'a': {unknown}
371 160..161 'b': {unknown}
372 162..172 '{ break; }': ()
373 164..169 'break': !
374 226..227 'x': u32
375 235..253 '{ for ... {}; }': ()
376 237..250 'for a in b {}': ()
377 241..242 'a': {unknown}
378 246..247 'b': {unknown}
379 248..250 '{}': ()
380 304..305 'x': u32
381 313..340 '{ for ...; }; }': ()
382 315..337 'for a ...urn; }': ()
383 319..320 'a': {unknown}
384 324..325 'b': {unknown}
385 326..337 '{ return; }': ()
386 328..334 'return': !
387 149..175: expected u32, got ()
388 235..253: expected u32, got ()
389 313..340: expected u32, got ()
390 355..654 '{ ...; }; }': ()
391 398..399 'x': u32
392 407..433 '{ whil...; }; }': ()
393 409..430 'while ...eak; }': ()
394 415..419 'true': bool
395 420..430 '{ break; }': ()
396 422..427 'break': !
397 537..538 'x': u32
398 546..564 '{ whil... {}; }': ()
399 548..561 'while true {}': ()
400 554..558 'true': bool
401 559..561 '{}': ()
402 615..616 'x': u32
403 624..651 '{ whil...; }; }': ()
404 626..648 'while ...urn; }': ()
405 632..636 'true': bool
406 637..648 '{ return; }': ()
407 639..645 'return': !
408 407..433: expected u32, got ()
409 546..564: expected u32, got ()
410 624..651: expected u32, got ()
411 "###);
412} 409}
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index f937426bd..39fabf7eb 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -1,561 +1,561 @@
1use insta::assert_snapshot; 1use expect::expect;
2use test_utils::mark; 2use test_utils::mark;
3 3
4use super::{infer, infer_with_mismatches}; 4use super::{check_infer, check_infer_with_mismatches};
5 5
6#[test] 6#[test]
7fn infer_pattern() { 7fn infer_pattern() {
8 assert_snapshot!( 8 check_infer(
9 infer(r#" 9 r#"
10fn test(x: &i32) { 10 fn test(x: &i32) {
11 let y = x; 11 let y = x;
12 let &z = x; 12 let &z = x;
13 let a = z; 13 let a = z;
14 let (c, d) = (1, "hello"); 14 let (c, d) = (1, "hello");
15 15
16 for (e, f) in some_iter { 16 for (e, f) in some_iter {
17 let g = e; 17 let g = e;
18 } 18 }
19 19
20 if let [val] = opt { 20 if let [val] = opt {
21 let h = val; 21 let h = val;
22 } 22 }
23 23
24 let lambda = |a: u64, b, c: i32| { a + b; c }; 24 let lambda = |a: u64, b, c: i32| { a + b; c };
25 25
26 let ref ref_to_x = x; 26 let ref ref_to_x = x;
27 let mut mut_x = x; 27 let mut mut_x = x;
28 let ref mut mut_ref_to_x = x; 28 let ref mut mut_ref_to_x = x;
29 let k = mut_ref_to_x; 29 let k = mut_ref_to_x;
30} 30 }
31"#), 31 "#,
32 @r###" 32 expect![[r#"
33 8..9 'x': &i32 33 8..9 'x': &i32
34 17..368 '{ ...o_x; }': () 34 17..368 '{ ...o_x; }': ()
35 27..28 'y': &i32 35 27..28 'y': &i32
36 31..32 'x': &i32 36 31..32 'x': &i32
37 42..44 '&z': &i32 37 42..44 '&z': &i32
38 43..44 'z': i32 38 43..44 'z': i32
39 47..48 'x': &i32 39 47..48 'x': &i32
40 58..59 'a': i32 40 58..59 'a': i32
41 62..63 'z': i32 41 62..63 'z': i32
42 73..79 '(c, d)': (i32, &str) 42 73..79 '(c, d)': (i32, &str)
43 74..75 'c': i32 43 74..75 'c': i32
44 77..78 'd': &str 44 77..78 'd': &str
45 82..94 '(1, "hello")': (i32, &str) 45 82..94 '(1, "hello")': (i32, &str)
46 83..84 '1': i32 46 83..84 '1': i32
47 86..93 '"hello"': &str 47 86..93 '"hello"': &str
48 101..151 'for (e... }': () 48 101..151 'for (e... }': ()
49 105..111 '(e, f)': ({unknown}, {unknown}) 49 105..111 '(e, f)': ({unknown}, {unknown})
50 106..107 'e': {unknown} 50 106..107 'e': {unknown}
51 109..110 'f': {unknown} 51 109..110 'f': {unknown}
52 115..124 'some_iter': {unknown} 52 115..124 'some_iter': {unknown}
53 125..151 '{ ... }': () 53 125..151 '{ ... }': ()
54 139..140 'g': {unknown} 54 139..140 'g': {unknown}
55 143..144 'e': {unknown} 55 143..144 'e': {unknown}
56 157..204 'if let... }': () 56 157..204 'if let... }': ()
57 164..169 '[val]': [{unknown}] 57 164..169 '[val]': [{unknown}]
58 165..168 'val': {unknown} 58 165..168 'val': {unknown}
59 172..175 'opt': [{unknown}] 59 172..175 'opt': [{unknown}]
60 176..204 '{ ... }': () 60 176..204 '{ ... }': ()
61 190..191 'h': {unknown} 61 190..191 'h': {unknown}
62 194..197 'val': {unknown} 62 194..197 'val': {unknown}
63 214..220 'lambda': |u64, u64, i32| -> i32 63 214..220 'lambda': |u64, u64, i32| -> i32
64 223..255 '|a: u6...b; c }': |u64, u64, i32| -> i32 64 223..255 '|a: u6...b; c }': |u64, u64, i32| -> i32
65 224..225 'a': u64 65 224..225 'a': u64
66 232..233 'b': u64 66 232..233 'b': u64
67 235..236 'c': i32 67 235..236 'c': i32
68 243..255 '{ a + b; c }': i32 68 243..255 '{ a + b; c }': i32
69 245..246 'a': u64 69 245..246 'a': u64
70 245..250 'a + b': u64 70 245..250 'a + b': u64
71 249..250 'b': u64 71 249..250 'b': u64
72 252..253 'c': i32 72 252..253 'c': i32
73 266..278 'ref ref_to_x': &&i32 73 266..278 'ref ref_to_x': &&i32
74 281..282 'x': &i32 74 281..282 'x': &i32
75 292..301 'mut mut_x': &i32 75 292..301 'mut mut_x': &i32
76 304..305 'x': &i32 76 304..305 'x': &i32
77 315..335 'ref mu...f_to_x': &mut &i32 77 315..335 'ref mu...f_to_x': &mut &i32
78 338..339 'x': &i32 78 338..339 'x': &i32
79 349..350 'k': &mut &i32 79 349..350 'k': &mut &i32
80 353..365 'mut_ref_to_x': &mut &i32 80 353..365 'mut_ref_to_x': &mut &i32
81 "### 81 "#]],
82 ); 82 );
83} 83}
84 84
85#[test] 85#[test]
86fn infer_literal_pattern() { 86fn infer_literal_pattern() {
87 assert_snapshot!( 87 check_infer_with_mismatches(
88 infer_with_mismatches(r#" 88 r#"
89fn any<T>() -> T { loop {} } 89 fn any<T>() -> T { loop {} }
90fn test(x: &i32) {