diff options
author | Benjamin Coenen <[email protected]> | 2020-05-21 09:53:29 +0100 |
---|---|---|
committer | Benjamin Coenen <[email protected]> | 2020-05-21 09:53:29 +0100 |
commit | a7c8aa7c60c05db66ba4e89ae9e05c82e62507a5 (patch) | |
tree | e848f47bdf5d031c408df94222f595d2efcb2070 /crates/ra_hir_ty | |
parent | c6143742bd4e625d391ac3ea860be7578ab9f53f (diff) | |
parent | a4e6963a2313971fe7bbec97d03bc67266ef68a9 (diff) |
add support of feature flag for runnables #4464
Signed-off-by: Benjamin Coenen <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/_match.rs | 39 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/coerce.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/pat.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/unify.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/marks.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/coercion.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/method_resolution.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/patterns.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/regression.rs | 46 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 63 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 140 |
16 files changed, 337 insertions, 87 deletions
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs index 149f65042..3e6e1e333 100644 --- a/crates/ra_hir_ty/src/_match.rs +++ b/crates/ra_hir_ty/src/_match.rs | |||
@@ -1946,6 +1946,23 @@ mod tests { | |||
1946 | 1946 | ||
1947 | check_no_diagnostic(content); | 1947 | check_no_diagnostic(content); |
1948 | } | 1948 | } |
1949 | |||
1950 | #[test] | ||
1951 | fn expr_diverges_missing_arm() { | ||
1952 | let content = r" | ||
1953 | enum Either { | ||
1954 | A, | ||
1955 | B, | ||
1956 | } | ||
1957 | fn test_fn() { | ||
1958 | match loop {} { | ||
1959 | Either::A => (), | ||
1960 | } | ||
1961 | } | ||
1962 | "; | ||
1963 | |||
1964 | check_no_diagnostic(content); | ||
1965 | } | ||
1949 | } | 1966 | } |
1950 | 1967 | ||
1951 | #[cfg(test)] | 1968 | #[cfg(test)] |
@@ -1998,26 +2015,6 @@ mod false_negatives { | |||
1998 | } | 2015 | } |
1999 | 2016 | ||
2000 | #[test] | 2017 | #[test] |
2001 | fn expr_diverges_missing_arm() { | ||
2002 | let content = r" | ||
2003 | enum Either { | ||
2004 | A, | ||
2005 | B, | ||
2006 | } | ||
2007 | fn test_fn() { | ||
2008 | match loop {} { | ||
2009 | Either::A => (), | ||
2010 | } | ||
2011 | } | ||
2012 | "; | ||
2013 | |||
2014 | // This is a false negative. | ||
2015 | // Even though the match expression diverges, rustc fails | ||
2016 | // to compile here since `Either::B` is missing. | ||
2017 | check_no_diagnostic(content); | ||
2018 | } | ||
2019 | |||
2020 | #[test] | ||
2021 | fn expr_loop_missing_arm() { | 2018 | fn expr_loop_missing_arm() { |
2022 | let content = r" | 2019 | let content = r" |
2023 | enum Either { | 2020 | enum Either { |
@@ -2035,7 +2032,7 @@ mod false_negatives { | |||
2035 | // We currently infer the type of `loop { break Foo::A }` to `!`, which | 2032 | // We currently infer the type of `loop { break Foo::A }` to `!`, which |
2036 | // causes us to skip the diagnostic since `Either::A` doesn't type check | 2033 | // causes us to skip the diagnostic since `Either::A` doesn't type check |
2037 | // with `!`. | 2034 | // with `!`. |
2038 | check_no_diagnostic(content); | 2035 | check_diagnostic(content); |
2039 | } | 2036 | } |
2040 | 2037 | ||
2041 | #[test] | 2038 | #[test] |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 2876cb141..957d6e0b5 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -218,6 +218,7 @@ struct InferenceContext<'a> { | |||
218 | #[derive(Clone, Debug)] | 218 | #[derive(Clone, Debug)] |
219 | struct BreakableContext { | 219 | struct BreakableContext { |
220 | pub may_break: bool, | 220 | pub may_break: bool, |
221 | pub break_ty: Ty, | ||
221 | } | 222 | } |
222 | 223 | ||
223 | impl<'a> InferenceContext<'a> { | 224 | impl<'a> InferenceContext<'a> { |
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 173ec59ed..2ee9adb16 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; | 7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; |
8 | use test_utils::tested_by; | 8 | use test_utils::mark; |
9 | 9 | ||
10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; | 10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; |
11 | 11 | ||
@@ -34,7 +34,7 @@ impl<'a> InferenceContext<'a> { | |||
34 | ty1.clone() | 34 | ty1.clone() |
35 | } else { | 35 | } else { |
36 | if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { | 36 | if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { |
37 | tested_by!(coerce_fn_reification); | 37 | mark::hit!(coerce_fn_reification); |
38 | // Special case: two function types. Try to coerce both to | 38 | // Special case: two function types. Try to coerce both to |
39 | // pointers to have a chance at getting a match. See | 39 | // pointers to have a chance at getting a match. See |
40 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 | 40 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 |
@@ -44,7 +44,7 @@ impl<'a> InferenceContext<'a> { | |||
44 | let ptr_ty2 = Ty::fn_ptr(sig2); | 44 | let ptr_ty2 = Ty::fn_ptr(sig2); |
45 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) | 45 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) |
46 | } else { | 46 | } else { |
47 | tested_by!(coerce_merge_fail_fallback); | 47 | mark::hit!(coerce_merge_fail_fallback); |
48 | // For incompatible types, we use the latter one as result | 48 | // For incompatible types, we use the latter one as result |
49 | // to be better recovery for `if` without `else`. | 49 | // to be better recovery for `if` without `else`. |
50 | ty2.clone() | 50 | ty2.clone() |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 0b67d216a..b28724f0e 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -93,22 +93,25 @@ impl<'a> InferenceContext<'a> { | |||
93 | Ty::Unknown | 93 | Ty::Unknown |
94 | } | 94 | } |
95 | Expr::Loop { body } => { | 95 | Expr::Loop { body } => { |
96 | self.breakables.push(BreakableContext { may_break: false }); | 96 | self.breakables.push(BreakableContext { |
97 | may_break: false, | ||
98 | break_ty: self.table.new_type_var(), | ||
99 | }); | ||
97 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 100 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
98 | 101 | ||
99 | let ctxt = self.breakables.pop().expect("breakable stack broken"); | 102 | let ctxt = self.breakables.pop().expect("breakable stack broken"); |
100 | if ctxt.may_break { | 103 | if ctxt.may_break { |
101 | self.diverges = Diverges::Maybe; | 104 | self.diverges = Diverges::Maybe; |
102 | } | 105 | } |
103 | // FIXME handle break with value | 106 | |
104 | if ctxt.may_break { | 107 | if ctxt.may_break { |
105 | Ty::unit() | 108 | ctxt.break_ty |
106 | } else { | 109 | } else { |
107 | Ty::simple(TypeCtor::Never) | 110 | Ty::simple(TypeCtor::Never) |
108 | } | 111 | } |
109 | } | 112 | } |
110 | Expr::While { condition, body } => { | 113 | Expr::While { condition, body } => { |
111 | self.breakables.push(BreakableContext { may_break: false }); | 114 | self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); |
112 | // while let is desugared to a match loop, so this is always simple while | 115 | // while let is desugared to a match loop, so this is always simple while |
113 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 116 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
114 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 117 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
@@ -120,7 +123,7 @@ impl<'a> InferenceContext<'a> { | |||
120 | Expr::For { iterable, body, pat } => { | 123 | Expr::For { iterable, body, pat } => { |
121 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); | 124 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); |
122 | 125 | ||
123 | self.breakables.push(BreakableContext { may_break: false }); | 126 | self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); |
124 | let pat_ty = | 127 | let pat_ty = |
125 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); | 128 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); |
126 | 129 | ||
@@ -229,17 +232,29 @@ impl<'a> InferenceContext<'a> { | |||
229 | } | 232 | } |
230 | Expr::Continue => Ty::simple(TypeCtor::Never), | 233 | Expr::Continue => Ty::simple(TypeCtor::Never), |
231 | Expr::Break { expr } => { | 234 | Expr::Break { expr } => { |
232 | if let Some(expr) = expr { | 235 | let val_ty = if let Some(expr) = expr { |
233 | // FIXME handle break with value | 236 | self.infer_expr(*expr, &Expectation::none()) |
234 | self.infer_expr(*expr, &Expectation::none()); | 237 | } else { |
235 | } | 238 | Ty::unit() |
239 | }; | ||
240 | |||
241 | let last_ty = if let Some(ctxt) = self.breakables.last() { | ||
242 | ctxt.break_ty.clone() | ||
243 | } else { | ||
244 | Ty::Unknown | ||
245 | }; | ||
246 | |||
247 | let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); | ||
248 | |||
236 | if let Some(ctxt) = self.breakables.last_mut() { | 249 | if let Some(ctxt) = self.breakables.last_mut() { |
250 | ctxt.break_ty = merged_type; | ||
237 | ctxt.may_break = true; | 251 | ctxt.may_break = true; |
238 | } else { | 252 | } else { |
239 | self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { | 253 | self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { |
240 | expr: tgt_expr, | 254 | expr: tgt_expr, |
241 | }); | 255 | }); |
242 | } | 256 | } |
257 | |||
243 | Ty::simple(TypeCtor::Never) | 258 | Ty::simple(TypeCtor::Never) |
244 | } | 259 | } |
245 | Expr::Return { expr } => { | 260 | Expr::Return { expr } => { |
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index 54ec870df..4006f595d 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -10,7 +10,7 @@ use hir_def::{ | |||
10 | FieldId, | 10 | FieldId, |
11 | }; | 11 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use test_utils::tested_by; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 15 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; | 16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; |
@@ -111,7 +111,7 @@ impl<'a> InferenceContext<'a> { | |||
111 | } | 111 | } |
112 | } | 112 | } |
113 | } else if let Pat::Ref { .. } = &body[pat] { | 113 | } else if let Pat::Ref { .. } = &body[pat] { |
114 | tested_by!(match_ergonomics_ref); | 114 | mark::hit!(match_ergonomics_ref); |
115 | // When you encounter a `&pat` pattern, reset to Move. | 115 | // When you encounter a `&pat` pattern, reset to Move. |
116 | // This is so that `w` is by value: `let (_, &w) = &(1, &2);` | 116 | // This is so that `w` is by value: `let (_, &w) = &(1, &2);` |
117 | default_bm = BindingMode::Move; | 117 | default_bm = BindingMode::Move; |
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs index ab0bc8b70..269495ca0 100644 --- a/crates/ra_hir_ty/src/infer/unify.rs +++ b/crates/ra_hir_ty/src/infer/unify.rs | |||
@@ -4,7 +4,7 @@ use std::borrow::Cow; | |||
4 | 4 | ||
5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
6 | 6 | ||
7 | use test_utils::tested_by; | 7 | use test_utils::mark; |
8 | 8 | ||
9 | use super::{InferenceContext, Obligation}; | 9 | use super::{InferenceContext, Obligation}; |
10 | use crate::{ | 10 | use crate::{ |
@@ -313,7 +313,7 @@ impl InferenceTable { | |||
313 | // more than once | 313 | // more than once |
314 | for i in 0..3 { | 314 | for i in 0..3 { |
315 | if i > 0 { | 315 | if i > 0 { |
316 | tested_by!(type_var_resolves_to_int_var); | 316 | mark::hit!(type_var_resolves_to_int_var); |
317 | } | 317 | } |
318 | match &*ty { | 318 | match &*ty { |
319 | Ty::Infer(tv) => { | 319 | Ty::Infer(tv) => { |
@@ -342,7 +342,7 @@ impl InferenceTable { | |||
342 | Ty::Infer(tv) => { | 342 | Ty::Infer(tv) => { |
343 | let inner = tv.to_inner(); | 343 | let inner = tv.to_inner(); |
344 | if tv_stack.contains(&inner) { | 344 | if tv_stack.contains(&inner) { |
345 | tested_by!(type_var_cycles_resolve_as_possible); | 345 | mark::hit!(type_var_cycles_resolve_as_possible); |
346 | // recursive type | 346 | // recursive type |
347 | return tv.fallback_value(); | 347 | return tv.fallback_value(); |
348 | } | 348 | } |
@@ -369,7 +369,7 @@ impl InferenceTable { | |||
369 | Ty::Infer(tv) => { | 369 | Ty::Infer(tv) => { |
370 | let inner = tv.to_inner(); | 370 | let inner = tv.to_inner(); |
371 | if tv_stack.contains(&inner) { | 371 | if tv_stack.contains(&inner) { |
372 | tested_by!(type_var_cycles_resolve_completely); | 372 | mark::hit!(type_var_cycles_resolve_completely); |
373 | // recursive type | 373 | // recursive type |
374 | return tv.fallback_value(); | 374 | return tv.fallback_value(); |
375 | } | 375 | } |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index ccc4348f4..c87ee06ce 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -42,7 +42,6 @@ pub mod expr; | |||
42 | mod tests; | 42 | mod tests; |
43 | #[cfg(test)] | 43 | #[cfg(test)] |
44 | mod test_db; | 44 | mod test_db; |
45 | mod marks; | ||
46 | mod _match; | 45 | mod _match; |
47 | 46 | ||
48 | use std::ops::Deref; | 47 | use std::ops::Deref; |
@@ -808,15 +807,13 @@ impl Ty { | |||
808 | } | 807 | } |
809 | } | 808 | } |
810 | 809 | ||
811 | /// If this is an `impl Trait` or `dyn Trait`, returns that trait. | 810 | /// If this is a `dyn Trait`, returns that trait. |
812 | pub fn inherent_trait(&self) -> Option<TraitId> { | 811 | pub fn dyn_trait(&self) -> Option<TraitId> { |
813 | match self { | 812 | match self { |
814 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 813 | Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred { |
815 | predicates.iter().find_map(|pred| match pred { | 814 | GenericPredicate::Implemented(tr) => Some(tr.trait_), |
816 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | 815 | _ => None, |
817 | _ => None, | 816 | }), |
818 | }) | ||
819 | } | ||
820 | _ => None, | 817 | _ => None, |
821 | } | 818 | } |
822 | } | 819 | } |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 9ad6dbe07..35ac86a46 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -812,7 +812,7 @@ impl TraitEnvironment { | |||
812 | // add `Self: Trait<T1, T2, ...>` to the environment in trait | 812 | // add `Self: Trait<T1, T2, ...>` to the environment in trait |
813 | // function default implementations (and hypothetical code | 813 | // function default implementations (and hypothetical code |
814 | // inside consts or type aliases) | 814 | // inside consts or type aliases) |
815 | test_utils::tested_by!(trait_self_implements_self); | 815 | test_utils::mark::hit!(trait_self_implements_self); |
816 | let substs = Substs::type_params(db, trait_id); | 816 | let substs = Substs::type_params(db, trait_id); |
817 | let trait_ref = TraitRef { trait_: trait_id, substs }; | 817 | let trait_ref = TraitRef { trait_: trait_id, substs }; |
818 | let pred = GenericPredicate::Implemented(trait_ref); | 818 | let pred = GenericPredicate::Implemented(trait_ref); |
diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs deleted file mode 100644 index a39740143..000000000 --- a/crates/ra_hir_ty/src/marks.rs +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | //! See test_utils/src/marks.rs | ||
2 | |||
3 | test_utils::marks!( | ||
4 | type_var_cycles_resolve_completely | ||
5 | type_var_cycles_resolve_as_possible | ||
6 | type_var_resolves_to_int_var | ||
7 | impl_self_type_match_without_receiver | ||
8 | match_ergonomics_ref | ||
9 | coerce_merge_fail_fallback | ||
10 | coerce_fn_reification | ||
11 | trait_self_implements_self | ||
12 | ); | ||
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 657284fd0..e19628fdf 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -408,8 +408,9 @@ fn iterate_trait_method_candidates<T>( | |||
408 | receiver_ty: Option<&Canonical<Ty>>, | 408 | receiver_ty: Option<&Canonical<Ty>>, |
409 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 409 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
410 | ) -> Option<T> { | 410 | ) -> Option<T> { |
411 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope | 411 | // if ty is `dyn Trait`, the trait doesn't need to be in scope |
412 | let inherent_trait = self_ty.value.inherent_trait().into_iter(); | 412 | let inherent_trait = |
413 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); | ||
413 | let env_traits = if let Ty::Placeholder(_) = self_ty.value { | 414 | let env_traits = if let Ty::Placeholder(_) = self_ty.value { |
414 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 415 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope |
415 | env.trait_predicates_for_self_ty(&self_ty.value) | 416 | env.trait_predicates_for_self_ty(&self_ty.value) |
@@ -468,7 +469,7 @@ fn iterate_inherent_methods<T>( | |||
468 | // already happens in `is_valid_candidate` above; if not, we | 469 | // already happens in `is_valid_candidate` above; if not, we |
469 | // check it here | 470 | // check it here |
470 | if receiver_ty.is_none() && inherent_impl_substs(db, impl_def, self_ty).is_none() { | 471 | if receiver_ty.is_none() && inherent_impl_substs(db, impl_def, self_ty).is_none() { |
471 | test_utils::tested_by!(impl_self_type_match_without_receiver); | 472 | test_utils::mark::hit!(impl_self_type_match_without_receiver); |
472 | continue; | 473 | continue; |
473 | } | 474 | } |
474 | if let Some(result) = callback(&self_ty.value, item) { | 475 | if let Some(result) = callback(&self_ty.value, item) { |
@@ -601,11 +602,6 @@ pub fn implements_trait( | |||
601 | krate: CrateId, | 602 | krate: CrateId, |
602 | trait_: TraitId, | 603 | trait_: TraitId, |
603 | ) -> bool { | 604 | ) -> bool { |
604 | if ty.value.inherent_trait() == Some(trait_) { | ||
605 | // FIXME this is a bit of a hack, since Chalk should say the same thing | ||
606 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | ||
607 | return true; | ||
608 | } | ||
609 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 605 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
610 | let solution = db.trait_solve(krate, goal); | 606 | let solution = db.trait_solve(krate, goal); |
611 | 607 | ||
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 6dc4b2cd1..2cc4f4bf9 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use super::infer_with_mismatches; | 1 | use super::infer_with_mismatches; |
2 | use insta::assert_snapshot; | 2 | use insta::assert_snapshot; |
3 | use test_utils::covers; | 3 | use test_utils::mark; |
4 | 4 | ||
5 | // Infer with some common definitions and impls. | 5 | // Infer with some common definitions and impls. |
6 | fn infer(source: &str) -> String { | 6 | fn infer(source: &str) -> String { |
@@ -339,7 +339,7 @@ fn test(i: i32) { | |||
339 | 339 | ||
340 | #[test] | 340 | #[test] |
341 | fn coerce_merge_one_by_one1() { | 341 | fn coerce_merge_one_by_one1() { |
342 | covers!(coerce_merge_fail_fallback); | 342 | mark::check!(coerce_merge_fail_fallback); |
343 | 343 | ||
344 | assert_snapshot!( | 344 | assert_snapshot!( |
345 | infer(r#" | 345 | infer(r#" |
@@ -547,7 +547,7 @@ fn test() { | |||
547 | 547 | ||
548 | #[test] | 548 | #[test] |
549 | fn coerce_fn_items_in_match_arms() { | 549 | fn coerce_fn_items_in_match_arms() { |
550 | covers!(coerce_fn_reification); | 550 | mark::check!(coerce_fn_reification); |
551 | assert_snapshot!( | 551 | assert_snapshot!( |
552 | infer_with_mismatches(r#" | 552 | infer_with_mismatches(r#" |
553 | fn foo1(x: u32) -> isize { 1 } | 553 | fn foo1(x: u32) -> isize { 1 } |
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 67f964ab5..558a70022 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -984,7 +984,7 @@ fn test() { S2.into()<|>; } | |||
984 | 984 | ||
985 | #[test] | 985 | #[test] |
986 | fn method_resolution_overloaded_method() { | 986 | fn method_resolution_overloaded_method() { |
987 | test_utils::covers!(impl_self_type_match_without_receiver); | 987 | test_utils::mark::check!(impl_self_type_match_without_receiver); |
988 | let t = type_at( | 988 | let t = type_at( |
989 | r#" | 989 | r#" |
990 | //- main.rs | 990 | //- main.rs |
@@ -1096,3 +1096,34 @@ fn test() { (S {}).method()<|>; } | |||
1096 | ); | 1096 | ); |
1097 | assert_eq!(t, "()"); | 1097 | assert_eq!(t, "()"); |
1098 | } | 1098 | } |
1099 | |||
1100 | #[test] | ||
1101 | fn dyn_trait_super_trait_not_in_scope() { | ||
1102 | assert_snapshot!( | ||
1103 | infer(r#" | ||
1104 | mod m { | ||
1105 | pub trait SuperTrait { | ||
1106 | fn foo(&self) -> u32 { 0 } | ||
1107 | } | ||
1108 | } | ||
1109 | trait Trait: m::SuperTrait {} | ||
1110 | |||
1111 | struct S; | ||
1112 | impl m::SuperTrait for S {} | ||
1113 | impl Trait for S {} | ||
1114 | |||
1115 | fn test(d: &dyn Trait) { | ||
1116 | d.foo(); | ||
1117 | } | ||
1118 | "#), | ||
1119 | @r###" | ||
1120 | 52..56 'self': &Self | ||
1121 | 65..70 '{ 0 }': u32 | ||
1122 | 67..68 '0': u32 | ||
1123 | 177..178 'd': &dyn Trait | ||
1124 | 192..208 '{ ...o(); }': () | ||
1125 | 198..199 'd': &dyn Trait | ||
1126 | 198..205 'd.foo()': u32 | ||
1127 | "### | ||
1128 | ); | ||
1129 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index d83ff5e0e..0c5f972a2 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | use test_utils::covers; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{infer, infer_with_mismatches}; | 4 | use super::{infer, infer_with_mismatches}; |
5 | 5 | ||
@@ -197,7 +197,7 @@ fn test() { | |||
197 | 197 | ||
198 | #[test] | 198 | #[test] |
199 | fn infer_pattern_match_ergonomics_ref() { | 199 | fn infer_pattern_match_ergonomics_ref() { |
200 | covers!(match_ergonomics_ref); | 200 | mark::check!(match_ergonomics_ref); |
201 | assert_snapshot!( | 201 | assert_snapshot!( |
202 | infer(r#" | 202 | infer(r#" |
203 | fn test() { | 203 | fn test() { |
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 115ad8328..1f004bd63 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -1,9 +1,10 @@ | |||
1 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | use test_utils::covers; | 2 | use ra_db::fixture::WithFixture; |
3 | use test_utils::mark; | ||
3 | 4 | ||
4 | use super::infer; | ||
5 | use crate::test_db::TestDB; | 5 | use crate::test_db::TestDB; |
6 | use ra_db::fixture::WithFixture; | 6 | |
7 | use super::infer; | ||
7 | 8 | ||
8 | #[test] | 9 | #[test] |
9 | fn bug_484() { | 10 | fn bug_484() { |
@@ -89,8 +90,8 @@ fn quux() { | |||
89 | 90 | ||
90 | #[test] | 91 | #[test] |
91 | fn recursive_vars() { | 92 | fn recursive_vars() { |
92 | covers!(type_var_cycles_resolve_completely); | 93 | mark::check!(type_var_cycles_resolve_completely); |
93 | covers!(type_var_cycles_resolve_as_possible); | 94 | mark::check!(type_var_cycles_resolve_as_possible); |
94 | assert_snapshot!( | 95 | assert_snapshot!( |
95 | infer(r#" | 96 | infer(r#" |
96 | fn test() { | 97 | fn test() { |
@@ -112,8 +113,6 @@ fn test() { | |||
112 | 113 | ||
113 | #[test] | 114 | #[test] |
114 | fn recursive_vars_2() { | 115 | fn recursive_vars_2() { |
115 | covers!(type_var_cycles_resolve_completely); | ||
116 | covers!(type_var_cycles_resolve_as_possible); | ||
117 | assert_snapshot!( | 116 | assert_snapshot!( |
118 | infer(r#" | 117 | infer(r#" |
119 | fn test() { | 118 | fn test() { |
@@ -170,7 +169,7 @@ fn write() { | |||
170 | 169 | ||
171 | #[test] | 170 | #[test] |
172 | fn infer_std_crash_2() { | 171 | fn infer_std_crash_2() { |
173 | covers!(type_var_resolves_to_int_var); | 172 | mark::check!(type_var_resolves_to_int_var); |
174 | // caused "equating two type variables, ...", taken from std | 173 | // caused "equating two type variables, ...", taken from std |
175 | assert_snapshot!( | 174 | assert_snapshot!( |
176 | infer(r#" | 175 | infer(r#" |
@@ -564,6 +563,37 @@ fn main() { | |||
564 | } | 563 | } |
565 | 564 | ||
566 | #[test] | 565 | #[test] |
566 | fn issue_4465_dollar_crate_at_type() { | ||
567 | assert_snapshot!( | ||
568 | infer(r#" | ||
569 | pub struct Foo {} | ||
570 | pub fn anything<T>() -> T { | ||
571 | loop {} | ||
572 | } | ||
573 | macro_rules! foo { | ||
574 | () => {{ | ||
575 | let r: $crate::Foo = anything(); | ||
576 | r | ||
577 | }}; | ||
578 | } | ||
579 | fn main() { | ||
580 | let _a = foo!(); | ||
581 | } | ||
582 | "#), @r###" | ||
583 | 45..60 '{ loop {} }': T | ||
584 | 51..58 'loop {}': ! | ||
585 | 56..58 '{}': () | ||
586 | !0..31 '{letr:...g();r}': Foo | ||
587 | !4..5 'r': Foo | ||
588 | !18..26 'anything': fn anything<Foo>() -> Foo | ||
589 | !18..28 'anything()': Foo | ||
590 | !29..30 'r': Foo | ||
591 | 164..188 '{ ...!(); }': () | ||
592 | 174..176 '_a': Foo | ||
593 | "###); | ||
594 | } | ||
595 | |||
596 | #[test] | ||
567 | fn issue_4053_diesel_where_clauses() { | 597 | fn issue_4053_diesel_where_clauses() { |
568 | assert_snapshot!( | 598 | assert_snapshot!( |
569 | infer(r#" | 599 | infer(r#" |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 72122c070..fd2208af2 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -1860,3 +1860,66 @@ fn test() { | |||
1860 | "### | 1860 | "### |
1861 | ); | 1861 | ); |
1862 | } | 1862 | } |
1863 | |||
1864 | #[test] | ||
1865 | fn infer_loop_break_with_val() { | ||
1866 | assert_snapshot!( | ||
1867 | infer(r#" | ||
1868 | enum Option<T> { Some(T), None } | ||
1869 | use Option::*; | ||
1870 | |||
1871 | fn test() { | ||
1872 | let x = loop { | ||
1873 | if false { | ||
1874 | break None; | ||
1875 | } | ||
1876 | |||
1877 | break Some(true); | ||
1878 | }; | ||
1879 | } | ||
1880 | "#), | ||
1881 | @r###" | ||
1882 | 60..169 '{ ... }; }': () | ||
1883 | 70..71 'x': Option<bool> | ||
1884 | 74..166 'loop {... }': Option<bool> | ||
1885 | 79..166 '{ ... }': () | ||
1886 | 89..133 'if fal... }': () | ||
1887 | 92..97 'false': bool | ||
1888 | 98..133 '{ ... }': () | ||
1889 | 112..122 'break None': ! | ||
1890 | 118..122 'None': Option<bool> | ||
1891 | 143..159 'break ...(true)': ! | ||
1892 | 149..153 'Some': Some<bool>(bool) -> Option<bool> | ||
1893 | 149..159 'Some(true)': Option<bool> | ||
1894 | 154..158 'true': bool | ||
1895 | "### | ||
1896 | ); | ||
1897 | } | ||
1898 | |||
1899 | #[test] | ||
1900 | fn infer_loop_break_without_val() { | ||
1901 | assert_snapshot!( | ||
1902 | infer(r#" | ||
1903 | enum Option<T> { Some(T), None } | ||
1904 | use Option::*; | ||
1905 | |||
1906 | fn test() { | ||
1907 | let x = loop { | ||
1908 | if false { | ||
1909 | break; | ||
1910 | } | ||
1911 | }; | ||
1912 | } | ||
1913 | "#), | ||
1914 | @r###" | ||
1915 | 60..137 '{ ... }; }': () | ||
1916 | 70..71 'x': () | ||
1917 | 74..134 'loop {... }': () | ||
1918 | 79..134 '{ ... }': () | ||
1919 | 89..128 'if fal... }': () | ||
1920 | 92..97 'false': bool | ||
1921 | 98..128 '{ ... }': () | ||
1922 | 112..117 'break': ! | ||
1923 | "### | ||
1924 | ); | ||
1925 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 9d32cbc7a..34f4b9039 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | |||
3 | use ra_db::fixture::WithFixture; | 2 | use ra_db::fixture::WithFixture; |
3 | use test_utils::mark; | ||
4 | 4 | ||
5 | use super::{infer, infer_with_mismatches, type_at, type_at_pos}; | ||
6 | use crate::test_db::TestDB; | 5 | use crate::test_db::TestDB; |
7 | 6 | ||
7 | use super::{infer, infer_with_mismatches, type_at, type_at_pos}; | ||
8 | |||
8 | #[test] | 9 | #[test] |
9 | fn infer_await() { | 10 | fn infer_await() { |
10 | let (db, pos) = TestDB::with_position( | 11 | let (db, pos) = TestDB::with_position( |
@@ -301,7 +302,7 @@ fn test() { | |||
301 | 302 | ||
302 | #[test] | 303 | #[test] |
303 | fn trait_default_method_self_bound_implements_trait() { | 304 | fn trait_default_method_self_bound_implements_trait() { |
304 | test_utils::covers!(trait_self_implements_self); | 305 | mark::check!(trait_self_implements_self); |
305 | assert_snapshot!( | 306 | assert_snapshot!( |
306 | infer(r#" | 307 | infer(r#" |
307 | trait Trait { | 308 | trait Trait { |
@@ -324,7 +325,6 @@ trait Trait { | |||
324 | 325 | ||
325 | #[test] | 326 | #[test] |
326 | fn trait_default_method_self_bound_implements_super_trait() { | 327 | fn trait_default_method_self_bound_implements_super_trait() { |
327 | test_utils::covers!(trait_self_implements_self); | ||
328 | assert_snapshot!( | 328 | assert_snapshot!( |
329 | infer(r#" | 329 | infer(r#" |
330 | trait SuperTrait { | 330 | trait SuperTrait { |
@@ -1617,6 +1617,138 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) { | |||
1617 | } | 1617 | } |
1618 | 1618 | ||
1619 | #[test] | 1619 | #[test] |
1620 | fn fn_ptr_and_item() { | ||
1621 | assert_snapshot!( | ||
1622 | infer(r#" | ||
1623 | #[lang="fn_once"] | ||
1624 | trait FnOnce<Args> { | ||
1625 | type Output; | ||
1626 | |||
1627 | fn call_once(self, args: Args) -> Self::Output; | ||
1628 | } | ||
1629 | |||
1630 | trait Foo<T> { | ||
1631 | fn foo(&self) -> T; | ||
1632 | } | ||
1633 | |||
1634 | struct Bar<T>(T); | ||
1635 | |||
1636 | impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> { | ||
1637 | fn foo(&self) -> (A1, R) {} | ||
1638 | } | ||
1639 | |||
1640 | enum Opt<T> { None, Some(T) } | ||
1641 | impl<T> Opt<T> { | ||
1642 | fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {} | ||
1643 | } | ||
1644 | |||
1645 | fn test() { | ||
1646 | let bar: Bar<fn(u8) -> u32>; | ||
1647 | bar.foo(); | ||
1648 | |||
1649 | let opt: Opt<u8>; | ||
1650 | let f: fn(u8) -> u32; | ||
1651 | opt.map(f); | ||
1652 | } | ||
1653 | "#), | ||
1654 | @r###" | ||
1655 | 75..79 'self': Self | ||
1656 | 81..85 'args': Args | ||
1657 | 140..144 'self': &Self | ||
1658 | 244..248 'self': &Bar<F> | ||
1659 | 261..263 '{}': () | ||
1660 | 347..351 'self': Opt<T> | ||
1661 | 353..354 'f': F | ||
1662 | 369..371 '{}': () | ||
1663 | 385..501 '{ ...(f); }': () | ||
1664 | 395..398 'bar': Bar<fn(u8) -> u32> | ||
1665 | 424..427 'bar': Bar<fn(u8) -> u32> | ||
1666 | 424..433 'bar.foo()': {unknown} | ||
1667 | 444..447 'opt': Opt<u8> | ||
1668 | 466..467 'f': fn(u8) -> u32 | ||
1669 | 488..491 'opt': Opt<u8> | ||
1670 | 488..498 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>> | ||
1671 | 496..497 'f': fn(u8) -> u32 | ||
1672 | "### | ||
1673 | ); | ||
1674 | } | ||
1675 | |||
1676 | #[test] | ||
1677 | fn fn_trait_deref_with_ty_default() { | ||
1678 | assert_snapshot!( | ||
1679 | infer(r#" | ||
1680 | #[lang = "deref"] | ||
1681 | trait Deref { | ||
1682 | type Target; | ||
1683 | |||
1684 | fn deref(&self) -> &Self::Target; | ||
1685 | } | ||
1686 | |||
1687 | #[lang="fn_once"] | ||
1688 | trait FnOnce<Args> { | ||
1689 | type Output; | ||
1690 | |||
1691 | fn call_once(self, args: Args) -> Self::Output; | ||
1692 | } | ||
1693 | |||
1694 | struct Foo; | ||
1695 | |||
1696 | impl Foo { | ||
1697 | fn foo(&self) -> usize {} | ||
1698 | } | ||
1699 | |||
1700 | struct Lazy<T, F = fn() -> T>(F); | ||
1701 | |||
1702 | impl<T, F> Lazy<T, F> { | ||
1703 | pub fn new(f: F) -> Lazy<T, F> {} | ||
1704 | } | ||
1705 | |||
1706 | impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { | ||
1707 | type Target = T; | ||
1708 | } | ||
1709 | |||
1710 | fn test() { | ||
1711 | let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo); | ||
1712 | let r1 = lazy1.foo(); | ||
1713 | |||
1714 | fn make_foo_fn() -> Foo {} | ||
1715 | let make_foo_fn_ptr: fn() -> Foo = make_foo_fn; | ||
1716 | let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr); | ||
1717 | let r2 = lazy2.foo(); | ||
1718 | } | ||
1719 | "#), | ||
1720 | @r###" | ||
1721 | 65..69 'self': &Self | ||
1722 | 166..170 'self': Self | ||
1723 | 172..176 'args': Args | ||
1724 | 240..244 'self': &Foo | ||
1725 | 255..257 '{}': () | ||
1726 | 335..336 'f': F | ||
1727 | 355..357 '{}': () | ||
1728 | 444..690 '{ ...o(); }': () | ||
1729 | 454..459 'lazy1': Lazy<Foo, fn() -> T> | ||
1730 | 476..485 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T> | ||
1731 | 476..493 'Lazy::...| Foo)': Lazy<Foo, fn() -> T> | ||
1732 | 486..492 '|| Foo': || -> T | ||
1733 | 489..492 'Foo': Foo | ||
1734 | 503..505 'r1': {unknown} | ||
1735 | 508..513 'lazy1': Lazy<Foo, fn() -> T> | ||
1736 | 508..519 'lazy1.foo()': {unknown} | ||
1737 | 561..576 'make_foo_fn_ptr': fn() -> Foo | ||
1738 | 592..603 'make_foo_fn': fn make_foo_fn() -> Foo | ||
1739 | 613..618 'lazy2': Lazy<Foo, fn() -> T> | ||
1740 | 635..644 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T> | ||
1741 | 635..661 'Lazy::...n_ptr)': Lazy<Foo, fn() -> T> | ||
1742 | 645..660 'make_foo_fn_ptr': fn() -> Foo | ||
1743 | 671..673 'r2': {unknown} | ||
1744 | 676..681 'lazy2': Lazy<Foo, fn() -> T> | ||
1745 | 676..687 'lazy2.foo()': {unknown} | ||
1746 | 550..552 '{}': () | ||
1747 | "### | ||
1748 | ); | ||
1749 | } | ||
1750 | |||
1751 | #[test] | ||
1620 | fn closure_1() { | 1752 | fn closure_1() { |
1621 | assert_snapshot!( | 1753 | assert_snapshot!( |
1622 | infer(r#" | 1754 | infer(r#" |