8799: Add basic support for array lengths in types r=flodiebold a=lf-

This recognizes `let a = [1u8, 2, 3]` as having type `[u8; 3]` instead
of the previous `[u8; _]`. Byte strings and `[0u8; 2]` kinds of range
array declarations are unsupported as before.

I don't know why a bunch of our rustc tests had single quotes inside
strings un-escaped by `UPDATE_EXPECT=1 cargo t`, but I don't think it's
bad? Maybe something in a nightly?

Co-authored-by: Jade <software@lfcode.ca>
This commit is contained in:
bors[bot] 2021-05-12 14:49:43 +00:00 committed by GitHub
commit 312f1fe20a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 156 additions and 110 deletions

View file

@ -0,0 +1,21 @@
//! Handling of concrete const values
/// A concrete constant value
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ConstScalar {
// for now, we only support the trivial case of constant evaluating the length of an array
// Note that this is u64 because the target usize may be bigger than our usize
Usize(u64),
/// Case of an unknown value that rustc might know but we don't
Unknown,
}
impl std::fmt::Display for ConstScalar {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
ConstScalar::Usize(us) => write!(fmt, "{}", us),
ConstScalar::Unknown => write!(fmt, "_"),
}
}
}

View file

@ -308,7 +308,7 @@ impl HirDisplay for Const {
let param_data = &generics.params.consts[id.local_id]; let param_data = &generics.params.consts[id.local_id];
write!(f, "{}", param_data.name) write!(f, "{}", param_data.name)
} }
ConstValue::Concrete(_) => write!(f, "_"), ConstValue::Concrete(c) => write!(f, "{}", c.interned),
} }
} }
} }

View file

@ -3,7 +3,7 @@
use std::iter::{repeat, repeat_with}; use std::iter::{repeat, repeat_with};
use std::{mem, sync::Arc}; use std::{mem, sync::Arc};
use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind}; use chalk_ir::{cast::Cast, fold::Shift, ConstData, Mutability, TyVariableKind};
use hir_def::{ use hir_def::{
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
path::{GenericArg, GenericArgs}, path::{GenericArg, GenericArgs},
@ -15,7 +15,9 @@ use stdx::always;
use syntax::ast::RangeOp; use syntax::ast::RangeOp;
use crate::{ use crate::{
autoderef, dummy_usize_const, autoderef,
consts::ConstScalar,
dummy_usize_const,
lower::lower_to_chalk_mutability, lower::lower_to_chalk_mutability,
mapping::from_chalk, mapping::from_chalk,
method_resolution, op, method_resolution, op,
@ -23,7 +25,7 @@ use crate::{
static_lifetime, to_chalk_trait_id, static_lifetime, to_chalk_trait_id,
traits::FnTrait, traits::FnTrait,
utils::{generics, Generics}, utils::{generics, Generics},
AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, AdtId, Binders, CallableDefId, ConstValue, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
}; };
@ -717,11 +719,12 @@ impl<'a> InferenceContext<'a> {
_ => self.table.new_type_var(), _ => self.table.new_type_var(),
}; };
match array { let len = match array {
Array::ElementList(items) => { Array::ElementList(items) => {
for expr in items.iter() { for expr in items.iter() {
self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone())); self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone()));
} }
Some(items.len())
} }
Array::Repeat { initializer, repeat } => { Array::Repeat { initializer, repeat } => {
self.infer_expr_coerce( self.infer_expr_coerce(
@ -734,10 +737,20 @@ impl<'a> InferenceContext<'a> {
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
), ),
); );
// FIXME: support length for Repeat array expressions
None
} }
} };
TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner) let cd = ConstData {
ty: TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner),
value: ConstValue::Concrete(chalk_ir::ConcreteConst {
interned: len
.map(|len| ConstScalar::Usize(len as u64))
.unwrap_or(ConstScalar::Unknown),
}),
};
TyKind::Array(elem_ty, cd.intern(&Interner)).intern(&Interner)
} }
Expr::Literal(lit) => match lit { Expr::Literal(lit) => match lit {
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
@ -747,6 +760,7 @@ impl<'a> InferenceContext<'a> {
} }
Literal::ByteString(..) => { Literal::ByteString(..) => {
let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
let array_type = let array_type =
TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner); TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner) TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)

View file

@ -1,7 +1,7 @@
//! Implementation of the Chalk `Interner` trait, which allows customizing the //! Implementation of the Chalk `Interner` trait, which allows customizing the
//! representation of the various objects Chalk deals with (types, goals etc.). //! representation of the various objects Chalk deals with (types, goals etc.).
use crate::{chalk_db, tls, GenericArg}; use crate::{chalk_db, consts::ConstScalar, tls, GenericArg};
use base_db::salsa::InternId; use base_db::salsa::InternId;
use chalk_ir::{Goal, GoalData}; use chalk_ir::{Goal, GoalData};
use hir_def::{ use hir_def::{
@ -31,6 +31,7 @@ impl_internable!(
InternedWrapper<chalk_ir::TyData<Interner>>, InternedWrapper<chalk_ir::TyData<Interner>>,
InternedWrapper<chalk_ir::LifetimeData<Interner>>, InternedWrapper<chalk_ir::LifetimeData<Interner>>,
InternedWrapper<chalk_ir::ConstData<Interner>>, InternedWrapper<chalk_ir::ConstData<Interner>>,
InternedWrapper<ConstScalar>,
InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>, InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>, InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>, InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
@ -41,7 +42,7 @@ impl chalk_ir::interner::Interner for Interner {
type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>; type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>; type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>; type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
type InternedConcreteConst = (); type InternedConcreteConst = ConstScalar;
type InternedGenericArg = chalk_ir::GenericArgData<Self>; type InternedGenericArg = chalk_ir::GenericArgData<Self>;
type InternedGoal = Arc<GoalData<Self>>; type InternedGoal = Arc<GoalData<Self>>;
type InternedGoals = Vec<Goal<Self>>; type InternedGoals = Vec<Goal<Self>>;
@ -245,10 +246,15 @@ impl chalk_ir::interner::Interner for Interner {
fn const_eq( fn const_eq(
&self, &self,
_ty: &Self::InternedType, _ty: &Self::InternedType,
_c1: &Self::InternedConcreteConst, c1: &Self::InternedConcreteConst,
_c2: &Self::InternedConcreteConst, c2: &Self::InternedConcreteConst,
) -> bool { ) -> bool {
true match (c1, c2) {
(&ConstScalar::Usize(a), &ConstScalar::Usize(b)) => a == b,
// we were previously assuming this to be true, I'm not whether true or false on
// unknown values is safer.
(_, _) => true,
}
} }
fn intern_generic_arg( fn intern_generic_arg(

View file

@ -12,6 +12,7 @@ mod chalk_db;
mod chalk_ext; mod chalk_ext;
mod infer; mod infer;
mod interner; mod interner;
mod consts;
mod lower; mod lower;
mod mapping; mod mapping;
mod op; mod op;
@ -39,7 +40,7 @@ use chalk_ir::{
}; };
use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId}; use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId};
use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; use crate::{consts::ConstScalar, db::HirDatabase, display::HirDisplay, utils::generics};
pub use autoderef::autoderef; pub use autoderef::autoderef;
pub use builder::TyBuilder; pub use builder::TyBuilder;
@ -250,7 +251,9 @@ pub fn dummy_usize_const() -> Const {
let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner); let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
chalk_ir::ConstData { chalk_ir::ConstData {
ty: usize_ty, ty: usize_ty,
value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }), value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
interned: ConstScalar::Unknown,
}),
} }
.intern(&Interner) .intern(&Interner)
} }

View file

@ -174,6 +174,8 @@ impl<'a> TyLoweringContext<'a> {
} }
TypeRef::Array(inner) => { TypeRef::Array(inner) => {
let inner_ty = self.lower_ty(inner); let inner_ty = self.lower_ty(inner);
// FIXME: we don't have length info here because we don't store an expression for
// the length
TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner) TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner)
} }
TypeRef::Slice(inner) => { TypeRef::Slice(inner) => {

View file

@ -55,7 +55,7 @@ fn coerce_places() {
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
"#, "#,
expect![[r" expect![[r#"
30..31 '_': &[T] 30..31 '_': &[T]
44..55 '{ loop {} }': T 44..55 '{ loop {} }': T
46..53 'loop {}': ! 46..53 'loop {}': !
@ -72,8 +72,8 @@ fn coerce_places() {
165..170 'gen()': *mut [U; _] 165..170 'gen()': *mut [U; _]
185..419 '{ ...rr); }': () 185..419 '{ ...rr); }': ()
195..198 'arr': &[u8; _] 195..198 'arr': &[u8; _]
211..215 '&[1]': &[u8; _] 211..215 '&[1]': &[u8; 1]
212..215 '[1]': [u8; _] 212..215 '[1]': [u8; 1]
213..214 '1': u8 213..214 '1': u8
226..227 'a': &[u8] 226..227 'a': &[u8]
236..239 'arr': &[u8; _] 236..239 'arr': &[u8; _]
@ -90,7 +90,7 @@ fn coerce_places() {
302..314 'S { a: arr }': S<&[u8]> 302..314 'S { a: arr }': S<&[u8]>
309..312 'arr': &[u8; _] 309..312 'arr': &[u8; _]
325..326 'e': [&[u8]; _] 325..326 'e': [&[u8]; _]
340..345 '[arr]': [&[u8]; _] 340..345 '[arr]': [&[u8]; 1]
341..344 'arr': &[u8; _] 341..344 'arr': &[u8; _]
355..356 'f': [&[u8]; _] 355..356 'f': [&[u8]; _]
370..378 '[arr; 2]': [&[u8]; _] 370..378 '[arr; 2]': [&[u8]; _]
@ -100,7 +100,7 @@ fn coerce_places() {
406..416 '(arr, arr)': (&[u8], &[u8]) 406..416 '(arr, arr)': (&[u8], &[u8])
407..410 'arr': &[u8; _] 407..410 'arr': &[u8; _]
412..415 'arr': &[u8; _] 412..415 'arr': &[u8; _]
"]], "#]],
); );
} }
@ -113,17 +113,17 @@ fn infer_let_stmt_coerce() {
let x: *const [isize] = &[1]; let x: *const [isize] = &[1];
} }
", ",
expect![[r" expect![[r#"
10..75 '{ ...[1]; }': () 10..75 '{ ...[1]; }': ()
20..21 'x': &[isize] 20..21 'x': &[isize]
34..38 '&[1]': &[isize; _] 34..38 '&[1]': &[isize; 1]
35..38 '[1]': [isize; _] 35..38 '[1]': [isize; 1]
36..37 '1': isize 36..37 '1': isize
48..49 'x': *const [isize] 48..49 'x': *const [isize]
68..72 '&[1]': &[isize; _] 68..72 '&[1]': &[isize; 1]
69..72 '[1]': [isize; _] 69..72 '[1]': [isize; 1]
70..71 '1': isize 70..71 '1': isize
"]], "#]],
); );
} }
@ -208,7 +208,7 @@ fn infer_if_coerce() {
#[lang = "unsize"] #[lang = "unsize"]
pub trait Unsize<T: ?Sized> {} pub trait Unsize<T: ?Sized> {}
"#, "#,
expect![[r" expect![[r#"
10..11 'x': &[T] 10..11 'x': &[T]
27..38 '{ loop {} }': &[T] 27..38 '{ loop {} }': &[T]
29..36 'loop {}': ! 29..36 'loop {}': !
@ -220,14 +220,14 @@ fn infer_if_coerce() {
71..96 '{ ... }': &[i32] 71..96 '{ ... }': &[i32]
81..84 'foo': fn foo<i32>(&[i32]) -> &[i32] 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32]
81..90 'foo(&[1])': &[i32] 81..90 'foo(&[1])': &[i32]
85..89 '&[1]': &[i32; _] 85..89 '&[1]': &[i32; 1]
86..89 '[1]': [i32; _] 86..89 '[1]': [i32; 1]
87..88 '1': i32 87..88 '1': i32
102..122 '{ ... }': &[i32; _] 102..122 '{ ... }': &[i32; 1]
112..116 '&[1]': &[i32; _] 112..116 '&[1]': &[i32; 1]
113..116 '[1]': [i32; _] 113..116 '[1]': [i32; 1]
114..115 '1': i32 114..115 '1': i32
"]], "#]],
); );
} }
@ -254,7 +254,7 @@ fn infer_if_else_coerce() {
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
"#, "#,
expect![[r" expect![[r#"
10..11 'x': &[T] 10..11 'x': &[T]
27..38 '{ loop {} }': &[T] 27..38 '{ loop {} }': &[T]
29..36 'loop {}': ! 29..36 'loop {}': !
@ -263,17 +263,17 @@ fn infer_if_else_coerce() {
59..60 'x': &[i32] 59..60 'x': &[i32]
63..122 'if tru... }': &[i32] 63..122 'if tru... }': &[i32]
66..70 'true': bool 66..70 'true': bool
71..91 '{ ... }': &[i32; _] 71..91 '{ ... }': &[i32; 1]
81..85 '&[1]': &[i32; _] 81..85 '&[1]': &[i32; 1]
82..85 '[1]': [i32; _] 82..85 '[1]': [i32; 1]
83..84 '1': i32 83..84 '1': i32
97..122 '{ ... }': &[i32] 97..122 '{ ... }': &[i32]
107..110 'foo': fn foo<i32>(&[i32]) -> &[i32] 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32]
107..116 'foo(&[1])': &[i32] 107..116 'foo(&[1])': &[i32]
111..115 '&[1]': &[i32; _] 111..115 '&[1]': &[i32; 1]
112..115 '[1]': [i32; _] 112..115 '[1]': [i32; 1]
113..114 '1': i32 113..114 '1': i32
"]], "#]],
) )
} }
@ -295,7 +295,7 @@ fn infer_match_first_coerce() {
#[lang = "unsize"] #[lang = "unsize"]
pub trait Unsize<T: ?Sized> {} pub trait Unsize<T: ?Sized> {}
"#, "#,
expect![[r" expect![[r#"
10..11 'x': &[T] 10..11 'x': &[T]
27..38 '{ loop {} }': &[T] 27..38 '{ loop {} }': &[T]
29..36 'loop {}': ! 29..36 'loop {}': !
@ -309,19 +309,19 @@ fn infer_match_first_coerce() {
87..88 '2': i32 87..88 '2': i32
92..95 'foo': fn foo<i32>(&[i32]) -> &[i32] 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32]
92..101 'foo(&[2])': &[i32] 92..101 'foo(&[2])': &[i32]
96..100 '&[2]': &[i32; _] 96..100 '&[2]': &[i32; 1]
97..100 '[2]': [i32; _] 97..100 '[2]': [i32; 1]
98..99 '2': i32 98..99 '2': i32
111..112 '1': i32 111..112 '1': i32
111..112 '1': i32 111..112 '1': i32
116..120 '&[1]': &[i32; _] 116..120 '&[1]': &[i32; 1]
117..120 '[1]': [i32; _] 117..120 '[1]': [i32; 1]
118..119 '1': i32 118..119 '1': i32
130..131 '_': i32 130..131 '_': i32
135..139 '&[3]': &[i32; _] 135..139 '&[3]': &[i32; 1]
136..139 '[3]': [i32; _] 136..139 '[3]': [i32; 1]
137..138 '3': i32 137..138 '3': i32
"]], "#]],
); );
} }
@ -348,7 +348,7 @@ fn infer_match_second_coerce() {
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
"#, "#,
expect![[r" expect![[r#"
10..11 'x': &[T] 10..11 'x': &[T]
27..38 '{ loop {} }': &[T] 27..38 '{ loop {} }': &[T]
29..36 'loop {}': ! 29..36 'loop {}': !
@ -360,21 +360,21 @@ fn infer_match_second_coerce() {
75..76 'i': i32 75..76 'i': i32
87..88 '1': i32 87..88 '1': i32
87..88 '1': i32 87..88 '1': i32
92..96 '&[1]': &[i32; _] 92..96 '&[1]': &[i32; 1]
93..96 '[1]': [i32; _] 93..96 '[1]': [i32; 1]
94..95 '1': i32 94..95 '1': i32
106..107 '2': i32 106..107 '2': i32
106..107 '2': i32 106..107 '2': i32
111..114 'foo': fn foo<i32>(&[i32]) -> &[i32] 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32]
111..120 'foo(&[2])': &[i32] 111..120 'foo(&[2])': &[i32]
115..119 '&[2]': &[i32; _] 115..119 '&[2]': &[i32; 1]
116..119 '[2]': [i32; _] 116..119 '[2]': [i32; 1]
117..118 '2': i32 117..118 '2': i32
130..131 '_': i32 130..131 '_': i32
135..139 '&[3]': &[i32; _] 135..139 '&[3]': &[i32; 1]
136..139 '[3]': [i32; _] 136..139 '[3]': [i32; 1]
137..138 '3': i32 137..138 '3': i32
"]], "#]],
); );
} }
@ -685,15 +685,15 @@ fn coerce_unsize_array() {
let f: &[usize] = &[1, 2, 3]; let f: &[usize] = &[1, 2, 3];
} }
"#, "#,
expect![[r" expect![[r#"
161..198 '{ ... 3]; }': () 161..198 '{ ... 3]; }': ()
171..172 'f': &[usize] 171..172 'f': &[usize]
185..195 '&[1, 2, 3]': &[usize; _] 185..195 '&[1, 2, 3]': &[usize; 3]
186..195 '[1, 2, 3]': [usize; _] 186..195 '[1, 2, 3]': [usize; 3]
187..188 '1': usize 187..188 '1': usize
190..191 '2': usize 190..191 '2': usize
193..194 '3': usize 193..194 '3': usize
"]], "#]],
); );
} }

View file

@ -243,8 +243,8 @@ fn infer_pattern_match_slice() {
expect![[r#" expect![[r#"
10..209 '{ ... } }': () 10..209 '{ ... } }': ()
20..25 'slice': &[f64] 20..25 'slice': &[f64]
36..42 '&[0.0]': &[f64; _] 36..42 '&[0.0]': &[f64; 1]
37..42 '[0.0]': [f64; _] 37..42 '[0.0]': [f64; 1]
38..41 '0.0': f64 38..41 '0.0': f64
48..207 'match ... }': () 48..207 'match ... }': ()
54..59 'slice': &[f64] 54..59 'slice': &[f64]
@ -346,7 +346,7 @@ fn infer_pattern_match_arr() {
expect![[r#" expect![[r#"
10..179 '{ ... } }': () 10..179 '{ ... } }': ()
20..23 'arr': [f64; _] 20..23 'arr': [f64; _]
36..46 '[0.0, 1.0]': [f64; _] 36..46 '[0.0, 1.0]': [f64; 2]
37..40 '0.0': f64 37..40 '0.0': f64
42..45 '1.0': f64 42..45 '1.0': f64
52..177 'match ... }': () 52..177 'match ... }': ()

View file

@ -99,7 +99,7 @@ fn recursive_vars() {
10..47 '{ ...&y]; }': () 10..47 '{ ...&y]; }': ()
20..21 'y': &{unknown} 20..21 'y': &{unknown}
24..31 'unknown': &{unknown} 24..31 'unknown': &{unknown}
37..44 '[y, &y]': [&&{unknown}; _] 37..44 '[y, &y]': [&&{unknown}; 2]
38..39 'y': &{unknown} 38..39 'y': &{unknown}
41..43 '&y': &&{unknown} 41..43 '&y': &&{unknown}
42..43 'y': &{unknown} 42..43 'y': &{unknown}
@ -123,7 +123,7 @@ fn recursive_vars_2() {
24..31 'unknown': &&{unknown} 24..31 'unknown': &&{unknown}
41..42 'y': &&{unknown} 41..42 'y': &&{unknown}
45..52 'unknown': &&{unknown} 45..52 'unknown': &&{unknown}
58..76 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _] 58..76 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); 2]
59..65 '(x, y)': (&&&{unknown}, &&&{unknown}) 59..65 '(x, y)': (&&&{unknown}, &&&{unknown})
60..61 'x': &&{unknown} 60..61 'x': &&{unknown}
63..64 'y': &&{unknown} 63..64 'y': &&{unknown}
@ -175,8 +175,8 @@ fn infer_std_crash_2() {
"#, "#,
expect![[r#" expect![[r#"
22..52 '{ ...n']; }': () 22..52 '{ ...n']; }': ()
28..49 '&[0, b...b'\n']': &[u8; _] 28..49 '&[0, b...b'\n']': &[u8; 4]
29..49 '[0, b'...b'\n']': [u8; _] 29..49 '[0, b'...b'\n']': [u8; 4]
30..31 '0': u8 30..31 '0': u8
33..38 'b'\n'': u8 33..38 'b'\n'': u8
40..41 '1': u8 40..41 '1': u8
@ -336,8 +336,8 @@ fn infer_array_macro_call() {
expect![[r#" expect![[r#"
!0..4 '0u32': u32 !0..4 '0u32': u32
44..69 '{ ...()]; }': () 44..69 '{ ...()]; }': ()
54..55 'a': [u32; _] 54..55 'a': [u32; 1]
58..66 '[bar!()]': [u32; _] 58..66 '[bar!()]': [u32; 1]
"#]], "#]],
); );
} }

View file

@ -11,7 +11,7 @@ fn test() {
let x = box 1; let x = box 1;
let t = (x, box x, box &1, box [1]); let t = (x, box x, box &1, box [1]);
t; t;
} //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>) } //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; 1]>)
//- /std.rs crate:std //- /std.rs crate:std
#[prelude_import] use prelude::*; #[prelude_import] use prelude::*;
@ -36,7 +36,7 @@ fn test() {
let x = box 1; let x = box 1;
let t = (x, box x, box &1, box [1]); let t = (x, box x, box &1, box [1]);
t; t;
} //^ (Box<i32, {unknown}>, Box<Box<i32, {unknown}>, {unknown}>, Box<&i32, {unknown}>, Box<[i32; _], {unknown}>) } //^ (Box<i32, {unknown}>, Box<Box<i32, {unknown}>, {unknown}>, Box<&i32, {unknown}>, Box<[i32; 1], {unknown}>)
//- /std.rs crate:std //- /std.rs crate:std
#[prelude_import] use prelude::*; #[prelude_import] use prelude::*;
@ -1266,55 +1266,55 @@ fn infer_array() {
8..9 'x': &str 8..9 'x': &str
17..18 'y': isize 17..18 'y': isize
27..292 '{ ... []; }': () 27..292 '{ ... []; }': ()
37..38 'a': [&str; _] 37..38 'a': [&str; 1]
41..44 '[x]': [&str; _] 41..44 '[x]': [&str; 1]
42..43 'x': &str 42..43 'x': &str
54..55 'b': [[&str; _]; _] 54..55 'b': [[&str; 1]; 2]
58..64 '[a, a]': [[&str; _]; _] 58..64 '[a, a]': [[&str; 1]; 2]
59..60 'a': [&str; _] 59..60 'a': [&str; 1]
62..63 'a': [&str; _] 62..63 'a': [&str; 1]
74..75 'c': [[[&str; _]; _]; _] 74..75 'c': [[[&str; 1]; 2]; 2]
78..84 '[b, b]': [[[&str; _]; _]; _] 78..84 '[b, b]': [[[&str; 1]; 2]; 2]
79..80 'b': [[&str; _]; _] 79..80 'b': [[&str; 1]; 2]
82..83 'b': [[&str; _]; _] 82..83 'b': [[&str; 1]; 2]
95..96 'd': [isize; _] 95..96 'd': [isize; 4]
99..111 '[y, 1, 2, 3]': [isize; _] 99..111 '[y, 1, 2, 3]': [isize; 4]
100..101 'y': isize 100..101 'y': isize
103..104 '1': isize 103..104 '1': isize
106..107 '2': isize 106..107 '2': isize
109..110 '3': isize 109..110 '3': isize
121..122 'd': [isize; _] 121..122 'd': [isize; 4]
125..137 '[1, y, 2, 3]': [isize; _] 125..137 '[1, y, 2, 3]': [isize; 4]
126..127 '1': isize 126..127 '1': isize
129..130 'y': isize 129..130 'y': isize
132..133 '2': isize 132..133 '2': isize
135..136 '3': isize 135..136 '3': isize
147..148 'e': [isize; _] 147..148 'e': [isize; 1]
151..154 '[y]': [isize; _] 151..154 '[y]': [isize; 1]
152..153 'y': isize 152..153 'y': isize
164..165 'f': [[isize; _]; _] 164..165 'f': [[isize; 4]; 2]
168..174 '[d, d]': [[isize; _]; _] 168..174 '[d, d]': [[isize; 4]; 2]
169..170 'd': [isize; _] 169..170 'd': [isize; 4]
172..173 'd': [isize; _] 172..173 'd': [isize; 4]
184..185 'g': [[isize; _]; _] 184..185 'g': [[isize; 1]; 2]
188..194 '[e, e]': [[isize; _]; _] 188..194 '[e, e]': [[isize; 1]; 2]
189..190 'e': [isize; _] 189..190 'e': [isize; 1]
192..193 'e': [isize; _] 192..193 'e': [isize; 1]
205..206 'h': [i32; _] 205..206 'h': [i32; 2]
209..215 '[1, 2]': [i32; _] 209..215 '[1, 2]': [i32; 2]
210..211 '1': i32 210..211 '1': i32
213..214 '2': i32 213..214 '2': i32
225..226 'i': [&str; _] 225..226 'i': [&str; 2]
229..239 '["a", "b"]': [&str; _] 229..239 '["a", "b"]': [&str; 2]
230..233 '"a"': &str 230..233 '"a"': &str
235..238 '"b"': &str 235..238 '"b"': &str
250..251 'b': [[&str; _]; _] 250..251 'b': [[&str; 1]; 2]
254..264 '[a, ["b"]]': [[&str; _]; _] 254..264 '[a, ["b"]]': [[&str; 1]; 2]
255..256 'a': [&str; _] 255..256 'a': [&str; 1]
258..263 '["b"]': [&str; _] 258..263 '["b"]': [&str; 1]
259..262 '"b"': &str 259..262 '"b"': &str
274..275 'x': [u8; _] 274..275 'x': [u8; _]
287..289 '[]': [u8; _] 287..289 '[]': [u8; 0]
"#]], "#]],
); );
} }
@ -2429,20 +2429,20 @@ fn infer_operator_overload() {
394..395 '1': i32 394..395 '1': i32
406..408 'V2': V2([f32; _]) -> V2 406..408 'V2': V2([f32; _]) -> V2
406..416 'V2([x, y])': V2 406..416 'V2([x, y])': V2
409..415 '[x, y]': [f32; _] 409..415 '[x, y]': [f32; 2]
410..411 'x': f32 410..411 'x': f32
413..414 'y': f32 413..414 'y': f32
436..519 '{ ... vb; }': () 436..519 '{ ... vb; }': ()
446..448 'va': V2 446..448 'va': V2
451..453 'V2': V2([f32; _]) -> V2 451..453 'V2': V2([f32; _]) -> V2
451..465 'V2([0.0, 1.0])': V2 451..465 'V2([0.0, 1.0])': V2
454..464 '[0.0, 1.0]': [f32; _] 454..464 '[0.0, 1.0]': [f32; 2]
455..458 '0.0': f32 455..458 '0.0': f32
460..463 '1.0': f32 460..463 '1.0': f32
475..477 'vb': V2 475..477 'vb': V2
480..482 'V2': V2([f32; _]) -> V2 480..482 'V2': V2([f32; _]) -> V2
480..494 'V2([0.0, 1.0])': V2 480..494 'V2([0.0, 1.0])': V2
483..493 '[0.0, 1.0]': [f32; _] 483..493 '[0.0, 1.0]': [f32; 2]
484..487 '0.0': f32 484..487 '0.0': f32
489..492 '1.0': f32 489..492 '1.0': f32
505..506 'r': V2 505..506 'r': V2
@ -2593,8 +2593,8 @@ fn test() {
658..661 'vec': Vec<i32, Global> 658..661 'vec': Vec<i32, Global>
664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global> 664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global>
664..691 '<[_]>:...1i32])': Vec<i32, Global> 664..691 '<[_]>:...1i32])': Vec<i32, Global>
680..690 'box [1i32]': Box<[i32; _], Global> 680..690 'box [1i32]': Box<[i32; 1], Global>
684..690 '[1i32]': [i32; _] 684..690 '[1i32]': [i32; 1]
685..689 '1i32': i32 685..689 '1i32': i32
"#]], "#]],
) )

View file

@ -531,7 +531,7 @@ fn indexing_arrays() {
expect![[r#" expect![[r#"
10..26 '{ &mut...[2]; }': () 10..26 '{ &mut...[2]; }': ()
12..23 '&mut [9][2]': &mut {unknown} 12..23 '&mut [9][2]': &mut {unknown}
17..20 '[9]': [i32; _] 17..20 '[9]': [i32; 1]
17..23 '[9][2]': {unknown} 17..23 '[9][2]': {unknown}
18..19 '9': i32 18..19 '9': i32
21..22 '2': i32 21..22 '2': i32

View file

@ -1126,7 +1126,7 @@ fn main() {
r#" r#"
fn main() { fn main() {
let data = &[1i32, 2, 3]; let data = &[1i32, 2, 3];
//^^^^ &[i32; _] //^^^^ &[i32; 3]
for i for i
}"#, }"#,
); );