aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/chalk_ext.rs36
-rw-r--r--crates/hir_ty/src/consteval.rs56
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs1
-rw-r--r--crates/hir_ty/src/display.rs7
-rw-r--r--crates/hir_ty/src/infer/expr.rs22
-rw-r--r--crates/hir_ty/src/infer/pat.rs9
-rw-r--r--crates/hir_ty/src/interner.rs15
-rw-r--r--crates/hir_ty/src/lib.rs11
-rw-r--r--crates/hir_ty/src/lower.rs9
-rw-r--r--crates/hir_ty/src/tests/coercion.rs136
-rw-r--r--crates/hir_ty/src/tests/patterns.rs16
-rw-r--r--crates/hir_ty/src/tests/regression.rs61
-rw-r--r--crates/hir_ty/src/tests/simple.rs145
-rw-r--r--crates/hir_ty/src/tests/traits.rs99
15 files changed, 451 insertions, 174 deletions
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
index 8c4542956..5232a7d80 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -1,8 +1,10 @@
1//! Various extensions traits for Chalk types. 1//! Various extensions traits for Chalk types.
2 2
3use chalk_ir::Mutability; 3use chalk_ir::{FloatTy, IntTy, Mutability, Scalar, UintTy};
4use hir_def::{ 4use hir_def::{
5 type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId, 5 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint},
6 type_ref::Rawness,
7 AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId,
6}; 8};
7 9
8use crate::{ 10use crate::{
@@ -18,6 +20,7 @@ pub trait TyExt {
18 fn is_unknown(&self) -> bool; 20 fn is_unknown(&self) -> bool;
19 21
20 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>; 22 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
23 fn as_builtin(&self) -> Option<BuiltinType>;
21 fn as_tuple(&self) -> Option<&Substitution>; 24 fn as_tuple(&self) -> Option<&Substitution>;
22 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>; 25 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
23 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>; 26 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
@@ -59,6 +62,35 @@ impl TyExt for Ty {
59 } 62 }
60 } 63 }
61 64
65 fn as_builtin(&self) -> Option<BuiltinType> {
66 match self.kind(&Interner) {
67 TyKind::Str => Some(BuiltinType::Str),
68 TyKind::Scalar(Scalar::Bool) => Some(BuiltinType::Bool),
69 TyKind::Scalar(Scalar::Char) => Some(BuiltinType::Char),
70 TyKind::Scalar(Scalar::Float(fty)) => Some(BuiltinType::Float(match fty {
71 FloatTy::F64 => BuiltinFloat::F64,
72 FloatTy::F32 => BuiltinFloat::F32,
73 })),
74 TyKind::Scalar(Scalar::Int(ity)) => Some(BuiltinType::Int(match ity {
75 IntTy::Isize => BuiltinInt::Isize,
76 IntTy::I8 => BuiltinInt::I8,
77 IntTy::I16 => BuiltinInt::I16,
78 IntTy::I32 => BuiltinInt::I32,
79 IntTy::I64 => BuiltinInt::I64,
80 IntTy::I128 => BuiltinInt::I128,
81 })),
82 TyKind::Scalar(Scalar::Uint(ity)) => Some(BuiltinType::Uint(match ity {
83 UintTy::Usize => BuiltinUint::Usize,
84 UintTy::U8 => BuiltinUint::U8,
85 UintTy::U16 => BuiltinUint::U16,
86 UintTy::U32 => BuiltinUint::U32,
87 UintTy::U64 => BuiltinUint::U64,
88 UintTy::U128 => BuiltinUint::U128,
89 })),
90 _ => None,
91 }
92 }
93
62 fn as_tuple(&self) -> Option<&Substitution> { 94 fn as_tuple(&self) -> Option<&Substitution> {
63 match self.kind(&Interner) { 95 match self.kind(&Interner) {
64 TyKind::Tuple(_, substs) => Some(substs), 96 TyKind::Tuple(_, substs) => Some(substs),
diff --git a/crates/hir_ty/src/consteval.rs b/crates/hir_ty/src/consteval.rs
new file mode 100644
index 000000000..e3ceb3d62
--- /dev/null
+++ b/crates/hir_ty/src/consteval.rs
@@ -0,0 +1,56 @@
1//! Constant evaluation details
2
3use std::convert::TryInto;
4
5use hir_def::{
6 builtin_type::BuiltinUint,
7 expr::{Expr, Literal},
8 type_ref::ConstScalar,
9};
10
11use crate::{Const, ConstData, ConstValue, Interner, TyKind};
12
13/// Extension trait for [`Const`]
14pub trait ConstExt {
15 /// Is a [`Const`] unknown?
16 fn is_unknown(&self) -> bool;
17}
18
19impl ConstExt for Const {
20 fn is_unknown(&self) -> bool {
21 match self.data(&Interner).value {
22 // interned Unknown
23 chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
24 interned: ConstScalar::Unknown,
25 }) => true,
26
27 // interned concrete anything else
28 chalk_ir::ConstValue::Concrete(..) => false,
29
30 _ => {
31 log::error!("is_unknown was called on a non-concrete constant value! {:?}", self);
32 true
33 }
34 }
35 }
36}
37
38// FIXME: support more than just evaluating literals
39pub fn eval_usize(expr: &Expr) -> Option<u64> {
40 match expr {
41 Expr::Literal(Literal::Uint(v, None))
42 | Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => (*v).try_into().ok(),
43 _ => None,
44 }
45}
46
47/// Interns a possibly-unknown target usize
48pub fn usize_const(value: Option<u64>) -> Const {
49 ConstData {
50 ty: TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(&Interner),
51 value: ConstValue::Concrete(chalk_ir::ConcreteConst {
52 interned: value.map(|value| ConstScalar::Usize(value)).unwrap_or(ConstScalar::Unknown),
53 }),
54 }
55 .intern(&Interner)
56}
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 79602c3dd..47709c1e8 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -83,7 +83,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
83 if let Expr::Block { statements, tail, .. } = body_expr { 83 if let Expr::Block { statements, tail, .. } = body_expr {
84 if let Some(t) = tail { 84 if let Some(t) = tail {
85 self.validate_results_in_tail_expr(body.body_expr, *t, db); 85 self.validate_results_in_tail_expr(body.body_expr, *t, db);
86 } else if let Some(Statement::Expr(id)) = statements.last() { 86 } else if let Some(Statement::Expr { expr: id, .. }) = statements.last() {
87 self.validate_missing_tail_expr(body.body_expr, *id, db); 87 self.validate_missing_tail_expr(body.body_expr, *id, db);
88 } 88 }
89 } 89 }
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index e9762622f..6ee0529c6 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -1119,6 +1119,7 @@ fn main() {
1119 (true, false, true) => (), 1119 (true, false, true) => (),
1120 (true) => (), 1120 (true) => (),
1121 } 1121 }
1122 match (true, false) { (true,) => {} }
1122 match (0) { () => () } 1123 match (0) { () => () }
1123 match Unresolved::Bar { Unresolved::Baz => () } 1124 match Unresolved::Bar { Unresolved::Baz => () }
1124} 1125}
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 1f6edf7a2..7bbd1a1f7 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -308,7 +308,7 @@ impl HirDisplay for Const {
308 let param_data = &generics.params.consts[id.local_id]; 308 let param_data = &generics.params.consts[id.local_id];
309 write!(f, "{}", param_data.name) 309 write!(f, "{}", param_data.name)
310 } 310 }
311 ConstValue::Concrete(_) => write!(f, "_"), 311 ConstValue::Concrete(c) => write!(f, "{}", c.interned),
312 } 312 }
313 } 313 }
314} 314}
@@ -962,11 +962,10 @@ impl HirDisplay for TypeRef {
962 write!(f, "{}", mutability)?; 962 write!(f, "{}", mutability)?;
963 inner.hir_fmt(f)?; 963 inner.hir_fmt(f)?;
964 } 964 }
965 TypeRef::Array(inner) => { 965 TypeRef::Array(inner, len) => {
966 write!(f, "[")?; 966 write!(f, "[")?;
967 inner.hir_fmt(f)?; 967 inner.hir_fmt(f)?;
968 // FIXME: Array length? 968 write!(f, "; {}]", len)?;
969 write!(f, "; _]")?;
970 } 969 }
971 TypeRef::Slice(inner) => { 970 TypeRef::Slice(inner) => {
972 write!(f, "[")?; 971 write!(f, "[")?;
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 50497eecb..b6b5a1b75 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -15,7 +15,7 @@ use stdx::always;
15use syntax::ast::RangeOp; 15use syntax::ast::RangeOp;
16 16
17use crate::{ 17use crate::{
18 autoderef, dummy_usize_const, 18 autoderef, consteval,
19 lower::lower_to_chalk_mutability, 19 lower::lower_to_chalk_mutability,
20 mapping::from_chalk, 20 mapping::from_chalk,
21 method_resolution, op, 21 method_resolution, op,
@@ -717,11 +717,12 @@ impl<'a> InferenceContext<'a> {
717 _ => self.table.new_type_var(), 717 _ => self.table.new_type_var(),
718 }; 718 };
719 719
720 match array { 720 let len = match array {
721 Array::ElementList(items) => { 721 Array::ElementList(items) => {
722 for expr in items.iter() { 722 for expr in items.iter() {
723 self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone())); 723 self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
724 } 724 }
725 Some(items.len() as u64)
725 } 726 }
726 Array::Repeat { initializer, repeat } => { 727 Array::Repeat { initializer, repeat } => {
727 self.infer_expr_coerce( 728 self.infer_expr_coerce(
@@ -734,10 +735,13 @@ impl<'a> InferenceContext<'a> {
734 TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), 735 TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
735 ), 736 ),
736 ); 737 );
738
739 let repeat_expr = &self.body.exprs[*repeat];
740 consteval::eval_usize(repeat_expr)
737 } 741 }
738 } 742 };
739 743
740 TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner) 744 TyKind::Array(elem_ty, consteval::usize_const(len)).intern(&Interner)
741 } 745 }
742 Expr::Literal(lit) => match lit { 746 Expr::Literal(lit) => match lit {
743 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 747 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
@@ -745,10 +749,12 @@ impl<'a> InferenceContext<'a> {
745 TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner)) 749 TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner))
746 .intern(&Interner) 750 .intern(&Interner)
747 } 751 }
748 Literal::ByteString(..) => { 752 Literal::ByteString(bs) => {
749 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); 753 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
750 let array_type = 754
751 TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner); 755 let len = consteval::usize_const(Some(bs.len() as u64));
756
757 let array_type = TyKind::Array(byte_type, len).intern(&Interner);
752 TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner) 758 TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)
753 } 759 }
754 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), 760 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
@@ -809,7 +815,7 @@ impl<'a> InferenceContext<'a> {
809 let ty = self.resolve_ty_as_possible(ty); 815 let ty = self.resolve_ty_as_possible(ty);
810 self.infer_pat(*pat, &ty, BindingMode::default()); 816 self.infer_pat(*pat, &ty, BindingMode::default());
811 } 817 }
812 Statement::Expr(expr) => { 818 Statement::Expr { expr, .. } => {
813 self.infer_expr(*expr, &Expectation::none()); 819 self.infer_expr(*expr, &Expectation::none());
814 } 820 }
815 } 821 }
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index aea354cde..60b94a642 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -126,11 +126,12 @@ impl<'a> InferenceContext<'a> {
126 _ => &[], 126 _ => &[],
127 }; 127 };
128 128
129 let (pre, post) = match ellipsis { 129 let ((pre, post), n_uncovered_patterns) = match ellipsis {
130 Some(idx) => args.split_at(idx), 130 Some(idx) => {
131 None => (&args[..], &[][..]), 131 (args.split_at(idx), expectations.len().saturating_sub(args.len()))
132 }
133 None => ((&args[..], &[][..]), 0),
132 }; 134 };
133 let n_uncovered_patterns = expectations.len().saturating_sub(args.len());
134 let err_ty = self.err_ty(); 135 let err_ty = self.err_ty();
135 let mut expectations_iter = 136 let mut expectations_iter =
136 expectations.iter().map(|a| a.assert_ty_ref(&Interner)).chain(repeat(&err_ty)); 137 expectations.iter().map(|a| a.assert_ty_ref(&Interner)).chain(repeat(&err_ty));
diff --git a/crates/hir_ty/src/interner.rs b/crates/hir_ty/src/interner.rs
index a1656115d..7b4119747 100644
--- a/crates/hir_ty/src/interner.rs
+++ b/crates/hir_ty/src/interner.rs
@@ -6,6 +6,7 @@ use base_db::salsa::InternId;
6use chalk_ir::{Goal, GoalData}; 6use chalk_ir::{Goal, GoalData};
7use hir_def::{ 7use hir_def::{
8 intern::{impl_internable, InternStorage, Internable, Interned}, 8 intern::{impl_internable, InternStorage, Internable, Interned},
9 type_ref::ConstScalar,
9 TypeAliasId, 10 TypeAliasId,
10}; 11};
11use smallvec::SmallVec; 12use smallvec::SmallVec;
@@ -31,6 +32,7 @@ impl_internable!(
31 InternedWrapper<chalk_ir::TyData<Interner>>, 32 InternedWrapper<chalk_ir::TyData<Interner>>,
32 InternedWrapper<chalk_ir::LifetimeData<Interner>>, 33 InternedWrapper<chalk_ir::LifetimeData<Interner>>,
33 InternedWrapper<chalk_ir::ConstData<Interner>>, 34 InternedWrapper<chalk_ir::ConstData<Interner>>,
35 InternedWrapper<ConstScalar>,
34 InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>, 36 InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
35 InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>, 37 InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
36 InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>, 38 InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
@@ -41,7 +43,7 @@ impl chalk_ir::interner::Interner for Interner {
41 type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>; 43 type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
42 type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>; 44 type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
43 type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>; 45 type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
44 type InternedConcreteConst = (); 46 type InternedConcreteConst = ConstScalar;
45 type InternedGenericArg = chalk_ir::GenericArgData<Self>; 47 type InternedGenericArg = chalk_ir::GenericArgData<Self>;
46 type InternedGoal = Arc<GoalData<Self>>; 48 type InternedGoal = Arc<GoalData<Self>>;
47 type InternedGoals = Vec<Goal<Self>>; 49 type InternedGoals = Vec<Goal<Self>>;
@@ -245,10 +247,15 @@ impl chalk_ir::interner::Interner for Interner {
245 fn const_eq( 247 fn const_eq(
246 &self, 248 &self,
247 _ty: &Self::InternedType, 249 _ty: &Self::InternedType,
248 _c1: &Self::InternedConcreteConst, 250 c1: &Self::InternedConcreteConst,
249 _c2: &Self::InternedConcreteConst, 251 c2: &Self::InternedConcreteConst,
250 ) -> bool { 252 ) -> bool {
251 true 253 match (c1, c2) {
254 (&ConstScalar::Usize(a), &ConstScalar::Usize(b)) => a == b,
255 // we were previously assuming this to be true, I'm not whether true or false on
256 // unknown values is safer.
257 (_, _) => true,
258 }
252 } 259 }
253 260
254 fn intern_generic_arg( 261 fn intern_generic_arg(
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 0505fa4ae..15b61bedc 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -10,6 +10,7 @@ mod autoderef;
10mod builder; 10mod builder;
11mod chalk_db; 11mod chalk_db;
12mod chalk_ext; 12mod chalk_ext;
13pub mod consteval;
13mod infer; 14mod infer;
14mod interner; 15mod interner;
15mod lower; 16mod lower;
@@ -37,7 +38,11 @@ use chalk_ir::{
37 interner::HasInterner, 38 interner::HasInterner,
38 UintTy, 39 UintTy,
39}; 40};
40use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId}; 41use hir_def::{
42 expr::ExprId,
43 type_ref::{ConstScalar, Rawness},
44 TypeParamId,
45};
41 46
42use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; 47use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
43 48
@@ -250,7 +255,9 @@ pub fn dummy_usize_const() -> Const {
250 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner); 255 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
251 chalk_ir::ConstData { 256 chalk_ir::ConstData {
252 ty: usize_ty, 257 ty: usize_ty,
253 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }), 258 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
259 interned: ConstScalar::Unknown,
260 }),
254 } 261 }
255 .intern(&Interner) 262 .intern(&Interner)
256} 263}
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index c99dd8d0a..bd8bb6028 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -29,8 +29,8 @@ use stdx::impl_from;
29use syntax::ast; 29use syntax::ast;
30 30
31use crate::{ 31use crate::{
32 consteval,
32 db::HirDatabase, 33 db::HirDatabase,
33 dummy_usize_const,
34 mapping::ToChalk, 34 mapping::ToChalk,
35 static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, 35 static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
36 utils::{ 36 utils::{
@@ -172,9 +172,12 @@ impl<'a> TyLoweringContext<'a> {
172 let inner_ty = self.lower_ty(inner); 172 let inner_ty = self.lower_ty(inner);
173 TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner) 173 TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
174 } 174 }
175 TypeRef::Array(inner) => { 175 TypeRef::Array(inner, len) => {
176 let inner_ty = self.lower_ty(inner); 176 let inner_ty = self.lower_ty(inner);
177 TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner) 177
178 let const_len = consteval::usize_const(len.as_usize());
179
180 TyKind::Array(inner_ty, const_len).intern(&Interner)
178 } 181 }
179 TypeRef::Slice(inner) => { 182 TypeRef::Slice(inner) => {
180 let inner_ty = self.lower_ty(inner); 183 let inner_ty = self.lower_ty(inner);
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs
index 63d9d4e0b..190471069 100644
--- a/crates/hir_ty/src/tests/coercion.rs
+++ b/crates/hir_ty/src/tests/coercion.rs
@@ -55,7 +55,7 @@ fn coerce_places() {
55 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} 55 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
56 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} 56 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
57 "#, 57 "#,
58 expect![[r" 58 expect![[r#"
59 30..31 '_': &[T] 59 30..31 '_': &[T]
60 44..55 '{ loop {} }': T 60 44..55 '{ loop {} }': T
61 46..53 'loop {}': ! 61 46..53 'loop {}': !
@@ -64,43 +64,43 @@ fn coerce_places() {
64 81..92 '{ loop {} }': T 64 81..92 '{ loop {} }': T
65 83..90 'loop {}': ! 65 83..90 'loop {}': !
66 88..90 '{}': () 66 88..90 '{}': ()
67 121..132 '{ loop {} }': *mut [T; _] 67 121..132 '{ loop {} }': *mut [T; 2]
68 123..130 'loop {}': ! 68 123..130 'loop {}': !
69 128..130 '{}': () 69 128..130 '{}': ()
70 159..172 '{ gen() }': *mut [U] 70 159..172 '{ gen() }': *mut [U]
71 165..168 'gen': fn gen<U>() -> *mut [U; _] 71 165..168 'gen': fn gen<U>() -> *mut [U; 2]
72 165..170 'gen()': *mut [U; _] 72 165..170 'gen()': *mut [U; 2]
73 185..419 '{ ...rr); }': () 73 185..419 '{ ...rr); }': ()
74 195..198 'arr': &[u8; _] 74 195..198 'arr': &[u8; 1]
75 211..215 '&[1]': &[u8; _] 75 211..215 '&[1]': &[u8; 1]
76 212..215 '[1]': [u8; _] 76 212..215 '[1]': [u8; 1]
77 213..214 '1': u8 77 213..214 '1': u8
78 226..227 'a': &[u8] 78 226..227 'a': &[u8]
79 236..239 'arr': &[u8; _] 79 236..239 'arr': &[u8; 1]
80 249..250 'b': u8 80 249..250 'b': u8
81 253..254 'f': fn f<u8>(&[u8]) -> u8 81 253..254 'f': fn f<u8>(&[u8]) -> u8
82 253..259 'f(arr)': u8 82 253..259 'f(arr)': u8
83 255..258 'arr': &[u8; _] 83 255..258 'arr': &[u8; 1]
84 269..270 'c': &[u8] 84 269..270 'c': &[u8]
85 279..286 '{ arr }': &[u8] 85 279..286 '{ arr }': &[u8]
86 281..284 'arr': &[u8; _] 86 281..284 'arr': &[u8; 1]
87 296..297 'd': u8 87 296..297 'd': u8
88 300..301 'g': fn g<u8>(S<&[u8]>) -> u8 88 300..301 'g': fn g<u8>(S<&[u8]>) -> u8
89 300..315 'g(S { a: arr })': u8 89 300..315 'g(S { a: arr })': u8
90 302..314 'S { a: arr }': S<&[u8]> 90 302..314 'S { a: arr }': S<&[u8]>
91 309..312 'arr': &[u8; _] 91 309..312 'arr': &[u8; 1]
92 325..326 'e': [&[u8]; _] 92 325..326 'e': [&[u8]; 1]
93 340..345 '[arr]': [&[u8]; _] 93 340..345 '[arr]': [&[u8]; 1]
94 341..344 'arr': &[u8; _] 94 341..344 'arr': &[u8; 1]
95 355..356 'f': [&[u8]; _] 95 355..356 'f': [&[u8]; 2]
96 370..378 '[arr; 2]': [&[u8]; _] 96 370..378 '[arr; 2]': [&[u8]; 2]
97 371..374 'arr': &[u8; _] 97 371..374 'arr': &[u8; 1]
98 376..377 '2': usize 98 376..377 '2': usize
99 388..389 'g': (&[u8], &[u8]) 99 388..389 'g': (&[u8], &[u8])
100 406..416 '(arr, arr)': (&[u8], &[u8]) 100 406..416 '(arr, arr)': (&[u8], &[u8])
101 407..410 'arr': &[u8; _] 101 407..410 'arr': &[u8; 1]
102 412..415 'arr': &[u8; _] 102 412..415 'arr': &[u8; 1]
103 "]], 103 "#]],
104 ); 104 );
105} 105}
106 106
@@ -113,17 +113,17 @@ fn infer_let_stmt_coerce() {
113 let x: *const [isize] = &[1]; 113 let x: *const [isize] = &[1];
114 } 114 }
115 ", 115 ",
116 expect![[r" 116 expect![[r#"
117 10..75 '{ ...[1]; }': () 117 10..75 '{ ...[1]; }': ()
118 20..21 'x': &[isize] 118 20..21 'x': &[isize]
119 34..38 '&[1]': &[isize; _] 119 34..38 '&[1]': &[isize; 1]
120 35..38 '[1]': [isize; _] 120 35..38 '[1]': [isize; 1]
121 36..37 '1': isize 121 36..37 '1': isize
122 48..49 'x': *const [isize] 122 48..49 'x': *const [isize]
123 68..72 '&[1]': &[isize; _] 123 68..72 '&[1]': &[isize; 1]
124 69..72 '[1]': [isize; _] 124 69..72 '[1]': [isize; 1]
125 70..71 '1': isize 125 70..71 '1': isize
126 "]], 126 "#]],
127 ); 127 );
128} 128}
129 129
@@ -159,7 +159,7 @@ fn infer_custom_coerce_unsized() {
159 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} 159 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
160 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} 160 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
161 "#, 161 "#,
162 expect![[r" 162 expect![[r#"
163 257..258 'x': A<[T]> 163 257..258 'x': A<[T]>
164 278..283 '{ x }': A<[T]> 164 278..283 '{ x }': A<[T]>
165 280..281 'x': A<[T]> 165 280..281 'x': A<[T]>
@@ -169,23 +169,23 @@ fn infer_custom_coerce_unsized() {
169 333..334 'x': C<[T]> 169 333..334 'x': C<[T]>
170 354..359 '{ x }': C<[T]> 170 354..359 '{ x }': C<[T]>
171 356..357 'x': C<[T]> 171 356..357 'x': C<[T]>
172 369..370 'a': A<[u8; _]> 172 369..370 'a': A<[u8; 2]>
173 384..385 'b': B<[u8; _]> 173 384..385 'b': B<[u8; 2]>
174 399..400 'c': C<[u8; _]> 174 399..400 'c': C<[u8; 2]>
175 414..480 '{ ...(c); }': () 175 414..480 '{ ...(c); }': ()
176 424..425 'd': A<[{unknown}]> 176 424..425 'd': A<[{unknown}]>
177 428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]> 177 428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
178 428..435 'foo1(a)': A<[{unknown}]> 178 428..435 'foo1(a)': A<[{unknown}]>
179 433..434 'a': A<[u8; _]> 179 433..434 'a': A<[u8; 2]>
180 445..446 'e': B<[u8]> 180 445..446 'e': B<[u8]>
181 449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]> 181 449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
182 449..456 'foo2(b)': B<[u8]> 182 449..456 'foo2(b)': B<[u8]>
183 454..455 'b': B<[u8; _]> 183 454..455 'b': B<[u8; 2]>
184 466..467 'f': C<[u8]> 184 466..467 'f': C<[u8]>
185 470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]> 185 470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
186 470..477 'foo3(c)': C<[u8]> 186 470..477 'foo3(c)': C<[u8]>
187 475..476 'c': C<[u8; _]> 187 475..476 'c': C<[u8; 2]>
188 "]], 188 "#]],
189 ); 189 );
190} 190}
191 191
@@ -208,7 +208,7 @@ fn infer_if_coerce() {
208 #[lang = "unsize"] 208 #[lang = "unsize"]
209 pub trait Unsize<T: ?Sized> {} 209 pub trait Unsize<T: ?Sized> {}
210 "#, 210 "#,
211 expect![[r" 211 expect![[r#"
212 10..11 'x': &[T] 212 10..11 'x': &[T]
213 27..38 '{ loop {} }': &[T] 213 27..38 '{ loop {} }': &[T]
214 29..36 'loop {}': ! 214 29..36 'loop {}': !
@@ -220,14 +220,14 @@ fn infer_if_coerce() {
220 71..96 '{ ... }': &[i32] 220 71..96 '{ ... }': &[i32]
221 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32] 221 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32]
222 81..90 'foo(&[1])': &[i32] 222 81..90 'foo(&[1])': &[i32]
223 85..89 '&[1]': &[i32; _] 223 85..89 '&[1]': &[i32; 1]
224 86..89 '[1]': [i32; _] 224 86..89 '[1]': [i32; 1]
225 87..88 '1': i32 225 87..88 '1': i32
226 102..122 '{ ... }': &[i32; _] 226 102..122 '{ ... }': &[i32; 1]
227 112..116 '&[1]': &[i32; _] 227 112..116 '&[1]': &[i32; 1]
228 113..116 '[1]': [i32; _] 228 113..116 '[1]': [i32; 1]
229 114..115 '1': i32 229 114..115 '1': i32
230 "]], 230 "#]],
231 ); 231 );
232} 232}
233 233
@@ -254,7 +254,7 @@ fn infer_if_else_coerce() {
254 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} 254 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
255 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} 255 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
256 "#, 256 "#,
257 expect![[r" 257 expect![[r#"
258 10..11 'x': &[T] 258 10..11 'x': &[T]
259 27..38 '{ loop {} }': &[T] 259 27..38 '{ loop {} }': &[T]
260 29..36 'loop {}': ! 260 29..36 'loop {}': !
@@ -263,17 +263,17 @@ fn infer_if_else_coerce() {
263 59..60 'x': &[i32] 263 59..60 'x': &[i32]
264 63..122 'if tru... }': &[i32] 264 63..122 'if tru... }': &[i32]
265 66..70 'true': bool 265 66..70 'true': bool
266 71..91 '{ ... }': &[i32; _] 266 71..91 '{ ... }': &[i32; 1]
267 81..85 '&[1]': &[i32; _] 267 81..85 '&[1]': &[i32; 1]
268 82..85 '[1]': [i32; _] 268 82..85 '[1]': [i32; 1]
269 83..84 '1': i32 269 83..84 '1': i32
270 97..122 '{ ... }': &[i32] 270 97..122 '{ ... }': &[i32]
271 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32] 271 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32]
272 107..116 'foo(&[1])': &[i32] 272 107..116 'foo(&[1])': &[i32]
273 111..115 '&[1]': &[i32; _] 273 111..115 '&[1]': &[i32; 1]
274 112..115 '[1]': [i32; _] 274 112..115 '[1]': [i32; 1]
275 113..114 '1': i32 275 113..114 '1': i32
276 "]], 276 "#]],
277 ) 277 )
278} 278}
279 279
@@ -295,7 +295,7 @@ fn infer_match_first_coerce() {
295 #[lang = "unsize"] 295 #[lang = "unsize"]
296 pub trait Unsize<T: ?Sized> {} 296 pub trait Unsize<T: ?Sized> {}
297 "#, 297 "#,
298 expect![[r" 298 expect![[r#"
299 10..11 'x': &[T] 299 10..11 'x': &[T]
300 27..38 '{ loop {} }': &[T] 300 27..38 '{ loop {} }': &[T]
301 29..36 'loop {}': ! 301 29..36 'loop {}': !
@@ -309,19 +309,19 @@ fn infer_match_first_coerce() {
309 87..88 '2': i32 309 87..88 '2': i32
310 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32] 310 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32]
311 92..101 'foo(&[2])': &[i32] 311 92..101 'foo(&[2])': &[i32]
312 96..100 '&[2]': &[i32; _] 312 96..100 '&[2]': &[i32; 1]
313 97..100 '[2]': [i32; _] 313 97..100 '[2]': [i32; 1]
314 98..99 '2': i32 314 98..99 '2': i32
315 111..112 '1': i32 315 111..112 '1': i32
316 111..112 '1': i32 316 111..112 '1': i32
317 116..120 '&[1]': &[i32; _] 317 116..120 '&[1]': &[i32; 1]
318 117..120 '[1]': [i32; _] 318 117..120 '[1]': [i32; 1]
319 118..119 '1': i32 319 118..119 '1': i32
320 130..131 '_': i32 320 130..131 '_': i32
321 135..139 '&[3]': &[i32; _] 321 135..139 '&[3]': &[i32; 1]
322 136..139 '[3]': [i32; _] 322 136..139 '[3]': [i32; 1]
323 137..138 '3': i32 323 137..138 '3': i32
324 "]], 324 "#]],
325 ); 325 );
326} 326}
327 327
@@ -348,7 +348,7 @@ fn infer_match_second_coerce() {
348 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} 348 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
349 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} 349 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
350 "#, 350 "#,
351 expect![[r" 351 expect![[r#"
352 10..11 'x': &[T] 352 10..11 'x': &[T]
353 27..38 '{ loop {} }': &[T] 353 27..38 '{ loop {} }': &[T]
354 29..36 'loop {}': ! 354 29..36 'loop {}': !
@@ -360,21 +360,21 @@ fn infer_match_second_coerce() {
360 75..76 'i': i32 360 75..76 'i': i32
361 87..88 '1': i32 361 87..88 '1': i32
362 87..88 '1': i32 362 87..88 '1': i32
363 92..96 '&[1]': &[i32; _] 363 92..96 '&[1]': &[i32; 1]
364 93..96 '[1]': [i32; _] 364 93..96 '[1]': [i32; 1]
365 94..95 '1': i32 365 94..95 '1': i32
366 106..107 '2': i32 366 106..107 '2': i32
367 106..107 '2': i32 367 106..107 '2': i32
368 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32] 368 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32]
369 111..120 'foo(&[2])': &[i32] 369 111..120 'foo(&[2])': &[i32]
370 115..119 '&[2]': &[i32; _] 370 115..119 '&[2]': &[i32; 1]
371 116..119 '[2]': [i32; _] 371 116..119 '[2]': [i32; 1]
372 117..118 '2': i32 372 117..118 '2': i32
373 130..131 '_': i32 373 130..131 '_': i32
374 135..139 '&[3]': &[i32; _] 374 135..139 '&[3]': &[i32; 1]
375 136..139 '[3]': [i32; _] 375 136..139 '[3]': [i32; 1]
376 137..138 '3': i32 376 137..138 '3': i32
377 "]], 377 "#]],
378 ); 378 );
379} 379}
380 380
@@ -685,15 +685,15 @@ fn coerce_unsize_array() {
685 let f: &[usize] = &[1, 2, 3]; 685 let f: &[usize] = &[1, 2, 3];
686 } 686 }
687 "#, 687 "#,
688 expect![[r" 688 expect![[r#"
689 161..198 '{ ... 3]; }': () 689 161..198 '{ ... 3]; }': ()
690 171..172 'f': &[usize] 690 171..172 'f': &[usize]
691 185..195 '&[1, 2, 3]': &[usize; _] 691 185..195 '&[1, 2, 3]': &[usize; 3]
692 186..195 '[1, 2, 3]': [usize; _] 692 186..195 '[1, 2, 3]': [usize; 3]
693 187..188 '1': usize 693 187..188 '1': usize
694 190..191 '2': usize 694 190..191 '2': usize
695 193..194 '3': usize 695 193..194 '3': usize
696 "]], 696 "#]],
697 ); 697 );
698} 698}
699 699
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
index f514b3efe..787647e9f 100644
--- a/crates/hir_ty/src/tests/patterns.rs
+++ b/crates/hir_ty/src/tests/patterns.rs
@@ -243,8 +243,8 @@ fn infer_pattern_match_slice() {
243 expect![[r#" 243 expect![[r#"
244 10..209 '{ ... } }': () 244 10..209 '{ ... } }': ()
245 20..25 'slice': &[f64] 245 20..25 'slice': &[f64]
246 36..42 '&[0.0]': &[f64; _] 246 36..42 '&[0.0]': &[f64; 1]
247 37..42 '[0.0]': [f64; _] 247 37..42 '[0.0]': [f64; 1]
248 38..41 '0.0': f64 248 38..41 '0.0': f64
249 48..207 'match ... }': () 249 48..207 'match ... }': ()
250 54..59 'slice': &[f64] 250 54..59 'slice': &[f64]
@@ -345,19 +345,19 @@ fn infer_pattern_match_arr() {
345 "#, 345 "#,
346 expect![[r#" 346 expect![[r#"
347 10..179 '{ ... } }': () 347 10..179 '{ ... } }': ()
348 20..23 'arr': [f64; _] 348 20..23 'arr': [f64; 2]
349 36..46 '[0.0, 1.0]': [f64; _] 349 36..46 '[0.0, 1.0]': [f64; 2]
350 37..40 '0.0': f64 350 37..40 '0.0': f64
351 42..45 '1.0': f64 351 42..45 '1.0': f64
352 52..177 'match ... }': () 352 52..177 'match ... }': ()
353 58..61 'arr': [f64; _] 353 58..61 'arr': [f64; 2]
354 72..80 '[1.0, a]': [f64; _] 354 72..80 '[1.0, a]': [f64; 2]
355 73..76 '1.0': f64 355 73..76 '1.0': f64
356 73..76 '1.0': f64 356 73..76 '1.0': f64
357 78..79 'a': f64 357 78..79 'a': f64
358 84..110 '{ ... }': () 358 84..110 '{ ... }': ()
359 98..99 'a': f64 359 98..99 'a': f64
360 120..126 '[b, c]': [f64; _] 360 120..126 '[b, c]': [f64; 2]
361 121..122 'b': f64 361 121..122 'b': f64
362 124..125 'c': f64 362 124..125 'c': f64
363 130..171 '{ ... }': () 363 130..171 '{ ... }': ()
@@ -732,7 +732,7 @@ fn foo(tuple: (u8, i16, f32)) {
732 111..112 'a': u8 732 111..112 'a': u8
733 114..115 'b': i16 733 114..115 'b': i16
734 124..126 '{}': () 734 124..126 '{}': ()
735 136..142 '(a, b)': (u8, i16, f32) 735 136..142 '(a, b)': (u8, i16)
736 137..138 'a': u8 736 137..138 'a': u8
737 140..141 'b': i16 737 140..141 'b': i16
738 146..161 '{/*too short*/}': () 738 146..161 '{/*too short*/}': ()
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index d14f5c9bb..431861712 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -99,7 +99,7 @@ fn recursive_vars() {
99 10..47 '{ ...&y]; }': () 99 10..47 '{ ...&y]; }': ()
100 20..21 'y': &{unknown} 100 20..21 'y': &{unknown}
101 24..31 'unknown': &{unknown} 101 24..31 'unknown': &{unknown}
102 37..44 '[y, &y]': [&&{unknown}; _] 102 37..44 '[y, &y]': [&&{unknown}; 2]
103 38..39 'y': &{unknown} 103 38..39 'y': &{unknown}
104 41..43 '&y': &&{unknown} 104 41..43 '&y': &&{unknown}
105 42..43 'y': &{unknown} 105 42..43 'y': &{unknown}
@@ -123,7 +123,7 @@ fn recursive_vars_2() {
123 24..31 'unknown': &&{unknown} 123 24..31 'unknown': &&{unknown}
124 41..42 'y': &&{unknown} 124 41..42 'y': &&{unknown}
125 45..52 'unknown': &&{unknown} 125 45..52 'unknown': &&{unknown}
126 58..76 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _] 126 58..76 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); 2]
127 59..65 '(x, y)': (&&&{unknown}, &&&{unknown}) 127 59..65 '(x, y)': (&&&{unknown}, &&&{unknown})
128 60..61 'x': &&{unknown} 128 60..61 'x': &&{unknown}
129 63..64 'y': &&{unknown} 129 63..64 'y': &&{unknown}
@@ -175,8 +175,8 @@ fn infer_std_crash_2() {
175 "#, 175 "#,
176 expect![[r#" 176 expect![[r#"
177 22..52 '{ ...n']; }': () 177 22..52 '{ ...n']; }': ()
178 28..49 '&[0, b...b'\n']': &[u8; _] 178 28..49 '&[0, b...b'\n']': &[u8; 4]
179 29..49 '[0, b'...b'\n']': [u8; _] 179 29..49 '[0, b'...b'\n']': [u8; 4]
180 30..31 '0': u8 180 30..31 '0': u8
181 33..38 'b'\n'': u8 181 33..38 'b'\n'': u8
182 40..41 '1': u8 182 40..41 '1': u8
@@ -336,8 +336,8 @@ fn infer_array_macro_call() {
336 expect![[r#" 336 expect![[r#"
337 !0..4 '0u32': u32 337 !0..4 '0u32': u32
338 44..69 '{ ...()]; }': () 338 44..69 '{ ...()]; }': ()
339 54..55 'a': [u32; _] 339 54..55 'a': [u32; 1]
340 58..66 '[bar!()]': [u32; _] 340 58..66 '[bar!()]': [u32; 1]
341 "#]], 341 "#]],
342 ); 342 );
343} 343}
@@ -1050,3 +1050,52 @@ fn test() {
1050 "#]], 1050 "#]],
1051 ); 1051 );
1052} 1052}
1053
1054#[test]
1055fn cfg_tail() {
1056 // https://github.com/rust-analyzer/rust-analyzer/issues/8378
1057 check_infer(
1058 r#"
1059 fn fake_tail(){
1060 { "first" }
1061 #[cfg(never)] 9
1062 }
1063 fn multiple_fake(){
1064 { "fake" }
1065 { "fake" }
1066 { "second" }
1067 #[cfg(never)] { 11 }
1068 #[cfg(never)] 12;
1069 #[cfg(never)] 13
1070 }
1071 fn no_normal_tail(){
1072 { "third" }
1073 #[cfg(never)] 14;
1074 #[cfg(never)] 15;
1075 }
1076 fn no_actual_tail(){
1077 { "fourth" };
1078 #[cfg(never)] 14;
1079 #[cfg(never)] 15
1080 }
1081 "#,
1082 expect![[r#"
1083 14..53 '{ ...)] 9 }': &str
1084 20..31 '{ "first" }': &str
1085 22..29 '"first"': &str
1086 72..190 '{ ...] 13 }': &str
1087 78..88 '{ "fake" }': &str
1088 80..86 '"fake"': &str
1089 93..103 '{ "fake" }': &str
1090 95..101 '"fake"': &str
1091 108..120 '{ "second" }': &str
1092 110..118 '"second"': &str
1093 210..273 '{ ... 15; }': &str
1094 216..227 '{ "third" }': &str
1095 218..225 '"third"': &str
1096 293..357 '{ ...] 15 }': ()
1097 299..311 '{ "fourth" }': &str
1098 301..309 '"fourth"': &str
1099 "#]],
1100 )
1101}
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 0eefd70f2..a9cd42186 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -11,7 +11,7 @@ fn test() {
11 let x = box 1; 11 let x = box 1;
12 let t = (x, box x, box &1, box [1]); 12 let t = (x, box x, box &1, box [1]);
13 t; 13 t;
14} //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>) 14} //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; 1]>)
15 15
16//- /std.rs crate:std 16//- /std.rs crate:std
17#[prelude_import] use prelude::*; 17#[prelude_import] use prelude::*;
@@ -36,7 +36,7 @@ fn test() {
36 let x = box 1; 36 let x = box 1;
37 let t = (x, box x, box &1, box [1]); 37 let t = (x, box x, box &1, box [1]);
38 t; 38 t;
39} //^ (Box<i32, {unknown}>, Box<Box<i32, {unknown}>, {unknown}>, Box<&i32, {unknown}>, Box<[i32; _], {unknown}>) 39} //^ (Box<i32, {unknown}>, Box<Box<i32, {unknown}>, {unknown}>, Box<&i32, {unknown}>, Box<[i32; 1], {unknown}>)
40 40
41//- /std.rs crate:std 41//- /std.rs crate:std
42#[prelude_import] use prelude::*; 42#[prelude_import] use prelude::*;
@@ -488,23 +488,34 @@ fn infer_literals() {
488 mod foo {} 488 mod foo {}
489 "#; 489 "#;
490 br#"yolo"#; 490 br#"yolo"#;
491 let a = b"a\x20b\
492 c";
493 let b = br"g\
494h";
495 let c = br#"x"\"yb"#;
491 } 496 }
492 "##, 497 "##,
493 expect![[r##" 498 expect![[r##"
494 10..216 '{ ...o"#; }': () 499 18..478 '{ ... }': ()
495 16..20 '5i32': i32 500 32..36 '5i32': i32
496 26..30 '5f32': f32 501 50..54 '5f32': f32
497 36..40 '5f64': f64 502 68..72 '5f64': f64
498 46..53 '"hello"': &str 503 86..93 '"hello"': &str
499 59..67 'b"bytes"': &[u8; _] 504 107..115 'b"bytes"': &[u8; 5]
500 73..76 ''c'': char 505 129..132 ''c'': char
501 82..86 'b'b'': u8 506 146..150 'b'b'': u8
502 92..96 '3.14': f64 507 164..168 '3.14': f64
503 102..106 '5000': i32 508 182..186 '5000': i32
504 112..117 'false': bool 509 200..205 'false': bool
505 123..127 'true': bool 510 219..223 'true': bool
506 133..197 'r#" ... "#': &str 511 237..333 'r#" ... "#': &str
507 203..213 'br#"yolo"#': &[u8; _] 512 347..357 'br#"yolo"#': &[u8; 4]
513 375..376 'a': &[u8; 4]
514 379..403 'b"a\x2... c"': &[u8; 4]
515 421..422 'b': &[u8; 4]
516 425..433 'br"g\ h"': &[u8; 4]
517 451..452 'c': &[u8; 6]
518 455..467 'br#"x"\"yb"#': &[u8; 6]
508 "##]], 519 "##]],
509 ); 520 );
510} 521}
@@ -1260,61 +1271,69 @@ fn infer_array() {
1260 1271
1261 let b = [a, ["b"]]; 1272 let b = [a, ["b"]];
1262 let x: [u8; 0] = []; 1273 let x: [u8; 0] = [];
1274 // FIXME: requires const evaluation/taking type from rhs somehow
1275 let y: [u8; 2+2] = [1,2,3,4];
1263 } 1276 }
1264 "#, 1277 "#,
1265 expect![[r#" 1278 expect![[r#"
1266 8..9 'x': &str 1279 8..9 'x': &str
1267 17..18 'y': isize 1280 17..18 'y': isize
1268 27..292 '{ ... []; }': () 1281 27..395 '{ ...,4]; }': ()
1269 37..38 'a': [&str; _] 1282 37..38 'a': [&str; 1]
1270 41..44 '[x]': [&str; _] 1283 41..44 '[x]': [&str; 1]
1271 42..43 'x': &str 1284 42..43 'x': &str
1272 54..55 'b': [[&str; _]; _] 1285 54..55 'b': [[&str; 1]; 2]
1273 58..64 '[a, a]': [[&str; _]; _] 1286 58..64 '[a, a]': [[&str; 1]; 2]
1274 59..60 'a': [&str; _] 1287 59..60 'a': [&str; 1]
1275 62..63 'a': [&str; _] 1288 62..63 'a': [&str; 1]
1276 74..75 'c': [[[&str; _]; _]; _] 1289 74..75 'c': [[[&str; 1]; 2]; 2]
1277 78..84 '[b, b]': [[[&str; _]; _]; _] 1290 78..84 '[b, b]': [[[&str; 1]; 2]; 2]
1278 79..80 'b': [[&str; _]; _] 1291 79..80 'b': [[&str; 1]; 2]
1279 82..83 'b': [[&str; _]; _] 1292 82..83 'b': [[&str; 1]; 2]
1280 95..96 'd': [isize; _] 1293 95..96 'd': [isize; 4]
1281 99..111 '[y, 1, 2, 3]': [isize; _] 1294 99..111 '[y, 1, 2, 3]': [isize; 4]
1282 100..101 'y': isize 1295 100..101 'y': isize
1283 103..104 '1': isize 1296 103..104 '1': isize
1284 106..107 '2': isize 1297 106..107 '2': isize
1285 109..110 '3': isize 1298 109..110 '3': isize
1286 121..122 'd': [isize; _] 1299 121..122 'd': [isize; 4]
1287 125..137 '[1, y, 2, 3]': [isize; _] 1300 125..137 '[1, y, 2, 3]': [isize; 4]
1288 126..127 '1': isize 1301 126..127 '1': isize
1289 129..130 'y': isize 1302 129..130 'y': isize
1290 132..133 '2': isize 1303 132..133 '2': isize
1291 135..136 '3': isize 1304 135..136 '3': isize
1292 147..148 'e': [isize; _] 1305 147..148 'e': [isize; 1]
1293 151..154 '[y]': [isize; _] 1306 151..154 '[y]': [isize; 1]
1294 152..153 'y': isize 1307 152..153 'y': isize
1295 164..165 'f': [[isize; _]; _] 1308 164..165 'f': [[isize; 4]; 2]
1296 168..174 '[d, d]': [[isize; _]; _] 1309 168..174 '[d, d]': [[isize; 4]; 2]
1297 169..170 'd': [isize; _] 1310 169..170 'd': [isize; 4]
1298 172..173 'd': [isize; _] 1311 172..173 'd': [isize; 4]
1299 184..185 'g': [[isize; _]; _] 1312 184..185 'g': [[isize; 1]; 2]
1300 188..194 '[e, e]': [[isize; _]; _] 1313 188..194 '[e, e]': [[isize; 1]; 2]
1301 189..190 'e': [isize; _] 1314 189..190 'e': [isize; 1]
1302 192..193 'e': [isize; _] 1315 192..193 'e': [isize; 1]
1303 205..206 'h': [i32; _] 1316 205..206 'h': [i32; 2]
1304 209..215 '[1, 2]': [i32; _] 1317 209..215 '[1, 2]': [i32; 2]
1305 210..211 '1': i32 1318 210..211 '1': i32
1306 213..214 '2': i32 1319 213..214 '2': i32
1307 225..226 'i': [&str; _] 1320 225..226 'i': [&str; 2]
1308 229..239 '["a", "b"]': [&str; _] 1321 229..239 '["a", "b"]': [&str; 2]
1309 230..233 '"a"': &str 1322 230..233 '"a"': &str
1310 235..238 '"b"': &str 1323 235..238 '"b"': &str
1311 250..251 'b': [[&str; _]; _] 1324 250..251 'b': [[&str; 1]; 2]
1312 254..264 '[a, ["b"]]': [[&str; _]; _] 1325 254..264 '[a, ["b"]]': [[&str; 1]; 2]
1313 255..256 'a': [&str; _] 1326 255..256 'a': [&str; 1]
1314 258..263 '["b"]': [&str; _] 1327 258..263 '["b"]': [&str; 1]
1315 259..262 '"b"': &str 1328 259..262 '"b"': &str
1316 274..275 'x': [u8; _] 1329 274..275 'x': [u8; 0]
1317 287..289 '[]': [u8; _] 1330 287..289 '[]': [u8; 0]
1331 368..369 'y': [u8; _]
1332 383..392 '[1,2,3,4]': [u8; 4]
1333 384..385 '1': u8
1334 386..387 '2': u8
1335 388..389 '3': u8
1336 390..391 '4': u8
1318 "#]], 1337 "#]],
1319 ); 1338 );
1320} 1339}
@@ -2409,40 +2428,40 @@ fn infer_operator_overload() {
2409 320..422 '{ ... }': V2 2428 320..422 '{ ... }': V2
2410 334..335 'x': f32 2429 334..335 'x': f32
2411 338..342 'self': V2 2430 338..342 'self': V2
2412 338..344 'self.0': [f32; _] 2431 338..344 'self.0': [f32; 2]
2413 338..347 'self.0[0]': {unknown} 2432 338..347 'self.0[0]': {unknown}
2414 338..358 'self.0...s.0[0]': f32 2433 338..358 'self.0...s.0[0]': f32
2415 345..346 '0': i32 2434 345..346 '0': i32
2416 350..353 'rhs': V2 2435 350..353 'rhs': V2
2417 350..355 'rhs.0': [f32; _] 2436 350..355 'rhs.0': [f32; 2]
2418 350..358 'rhs.0[0]': {unknown} 2437 350..358 'rhs.0[0]': {unknown}
2419 356..357 '0': i32 2438 356..357 '0': i32
2420 372..373 'y': f32 2439 372..373 'y': f32
2421 376..380 'self': V2 2440 376..380 'self': V2
2422 376..382 'self.0': [f32; _] 2441 376..382 'self.0': [f32; 2]
2423 376..385 'self.0[1]': {unknown} 2442 376..385 'self.0[1]': {unknown}
2424 376..396 'self.0...s.0[1]': f32 2443 376..396 'self.0...s.0[1]': f32
2425 383..384 '1': i32 2444 383..384 '1': i32
2426 388..391 'rhs': V2 2445 388..391 'rhs': V2
2427 388..393 'rhs.0': [f32; _] 2446 388..393 'rhs.0': [f32; 2]
2428 388..396 'rhs.0[1]': {unknown} 2447 388..396 'rhs.0[1]': {unknown}
2429 394..395 '1': i32 2448 394..395 '1': i32
2430 406..408 'V2': V2([f32; _]) -> V2 2449 406..408 'V2': V2([f32; 2]) -> V2
2431 406..416 'V2([x, y])': V2 2450 406..416 'V2([x, y])': V2
2432 409..415 '[x, y]': [f32; _] 2451 409..415 '[x, y]': [f32; 2]
2433 410..411 'x': f32 2452 410..411 'x': f32
2434 413..414 'y': f32 2453 413..414 'y': f32
2435 436..519 '{ ... vb; }': () 2454 436..519 '{ ... vb; }': ()
2436 446..448 'va': V2 2455 446..448 'va': V2
2437 451..453 'V2': V2([f32; _]) -> V2 2456 451..453 'V2': V2([f32; 2]) -> V2
2438 451..465 'V2([0.0, 1.0])': V2 2457 451..465 'V2([0.0, 1.0])': V2
2439 454..464 '[0.0, 1.0]': [f32; _] 2458 454..464 '[0.0, 1.0]': [f32; 2]
2440 455..458 '0.0': f32 2459 455..458 '0.0': f32
2441 460..463 '1.0': f32 2460 460..463 '1.0': f32
2442 475..477 'vb': V2 2461 475..477 'vb': V2
2443 480..482 'V2': V2([f32; _]) -> V2 2462 480..482 'V2': V2([f32; 2]) -> V2
2444 480..494 'V2([0.0, 1.0])': V2 2463 480..494 'V2([0.0, 1.0])': V2
2445 483..493 '[0.0, 1.0]': [f32; _] 2464 483..493 '[0.0, 1.0]': [f32; 2]
2446 484..487 '0.0': f32 2465 484..487 '0.0': f32
2447 489..492 '1.0': f32 2466 489..492 '1.0': f32
2448 505..506 'r': V2 2467 505..506 'r': V2
@@ -2593,8 +2612,8 @@ fn test() {
2593 658..661 'vec': Vec<i32, Global> 2612 658..661 'vec': Vec<i32, Global>
2594 664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global> 2613 664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global>
2595 664..691 '<[_]>:...1i32])': Vec<i32, Global> 2614 664..691 '<[_]>:...1i32])': Vec<i32, Global>
2596 680..690 'box [1i32]': Box<[i32; _], Global> 2615 680..690 'box [1i32]': Box<[i32; 1], Global>
2597 684..690 '[1i32]': [i32; _] 2616 684..690 '[1i32]': [i32; 1]
2598 685..689 '1i32': i32 2617 685..689 '1i32': i32
2599 "#]], 2618 "#]],
2600 ) 2619 )
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index ffc7c8ef4..f80cf9879 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -531,7 +531,7 @@ fn indexing_arrays() {
531 expect![[r#" 531 expect![[r#"
532 10..26 '{ &mut...[2]; }': () 532 10..26 '{ &mut...[2]; }': ()
533 12..23 '&mut [9][2]': &mut {unknown} 533 12..23 '&mut [9][2]': &mut {unknown}
534 17..20 '[9]': [i32; _] 534 17..20 '[9]': [i32; 1]
535 17..23 '[9][2]': {unknown} 535 17..23 '[9][2]': {unknown}
536 18..19 '9': i32 536 18..19 '9': i32
537 21..22 '2': i32 537 21..22 '2': i32
@@ -3474,3 +3474,100 @@ fn main(){
3474 "#]], 3474 "#]],
3475 ) 3475 )
3476} 3476}
3477
3478#[test]
3479fn array_length() {
3480 check_infer(
3481 r#"
3482trait T {
3483 type Output;
3484 fn do_thing(&self) -> Self::Output;
3485}
3486
3487impl T for [u8; 4] {
3488 type Output = usize;
3489 fn do_thing(&self) -> Self::Output {
3490 2
3491 }
3492}
3493
3494impl T for [u8; 2] {
3495 type Output = u8;
3496 fn do_thing(&self) -> Self::Output {
3497 2
3498 }
3499}
3500
3501fn main() {
3502 let v = [0u8; 2];
3503 let v2 = v.do_thing();
3504 let v3 = [0u8; 4];
3505 let v4 = v3.do_thing();
3506}
3507"#,
3508 expect![[r#"
3509 44..48 'self': &Self
3510 133..137 'self': &[u8; 4]
3511 155..172 '{ ... }': usize
3512 165..166 '2': usize
3513 236..240 'self': &[u8; 2]
3514 258..275 '{ ... }': u8
3515 268..269 '2': u8
3516 289..392 '{ ...g(); }': ()
3517 299..300 'v': [u8; 2]
3518 303..311 '[0u8; 2]': [u8; 2]
3519 304..307 '0u8': u8
3520 309..310 '2': usize
3521 321..323 'v2': u8
3522 326..327 'v': [u8; 2]
3523 326..338 'v.do_thing()': u8
3524 348..350 'v3': [u8; 4]
3525 353..361 '[0u8; 4]': [u8; 4]
3526 354..357 '0u8': u8
3527 359..360 '4': usize
3528 371..373 'v4': usize
3529 376..378 'v3': [u8; 4]
3530 376..389 'v3.do_thing()': usize
3531 "#]],
3532 )
3533}
3534
3535// FIXME: We should infer the length of the returned array :)
3536#[test]
3537fn const_generics() {
3538 check_infer(
3539 r#"
3540trait T {
3541 type Output;
3542 fn do_thing(&self) -> Self::Output;
3543}
3544
3545impl<const L: usize> T for [u8; L] {
3546 type Output = [u8; L];
3547 fn do_thing(&self) -> Self::Output {
3548 *self
3549 }
3550}
3551
3552fn main() {
3553 let v = [0u8; 2];
3554 let v2 = v.do_thing();
3555}
3556"#,
3557 expect![[r#"
3558 44..48 'self': &Self
3559 151..155 'self': &[u8; _]
3560 173..194 '{ ... }': [u8; _]
3561 183..188 '*self': [u8; _]
3562 184..188 'self': &[u8; _]
3563 208..260 '{ ...g(); }': ()
3564 218..219 'v': [u8; 2]
3565 222..230 '[0u8; 2]': [u8; 2]
3566 223..226 '0u8': u8
3567 228..229 '2': usize
3568 240..242 'v2': [u8; _]
3569 245..246 'v': [u8; 2]
3570 245..257 'v.do_thing()': [u8; _]
3571 "#]],
3572 )
3573}