mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
Get rid of resolve_ty_as_possible
Instead use shallow resolving where necessary.
This commit is contained in:
parent
a78f0076ab
commit
4bd446f5b3
8 changed files with 56 additions and 88 deletions
|
@ -273,7 +273,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn err_ty(&self) -> Ty {
|
fn err_ty(&self) -> Ty {
|
||||||
TyKind::Error.intern(&Interner)
|
self.result.standard_types.unknown.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_all(mut self) -> InferenceResult {
|
fn resolve_all(mut self) -> InferenceResult {
|
||||||
|
@ -284,12 +284,14 @@ impl<'a> InferenceContext<'a> {
|
||||||
self.table.propagate_diverging_flag();
|
self.table.propagate_diverging_flag();
|
||||||
let mut result = std::mem::take(&mut self.result);
|
let mut result = std::mem::take(&mut self.result);
|
||||||
for ty in result.type_of_expr.values_mut() {
|
for ty in result.type_of_expr.values_mut() {
|
||||||
let resolved = self.table.resolve_ty_completely(ty.clone());
|
*ty = self.table.resolve_ty_completely(ty.clone());
|
||||||
*ty = resolved;
|
|
||||||
}
|
}
|
||||||
for ty in result.type_of_pat.values_mut() {
|
for ty in result.type_of_pat.values_mut() {
|
||||||
let resolved = self.table.resolve_ty_completely(ty.clone());
|
*ty = self.table.resolve_ty_completely(ty.clone());
|
||||||
*ty = resolved;
|
}
|
||||||
|
for mismatch in result.type_mismatches.values_mut() {
|
||||||
|
mismatch.expected = self.table.resolve_ty_completely(mismatch.expected.clone());
|
||||||
|
mismatch.actual = self.table.resolve_ty_completely(mismatch.actual.clone());
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -343,6 +345,14 @@ impl<'a> InferenceContext<'a> {
|
||||||
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
|
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
|
||||||
match ty.kind(&Interner) {
|
match ty.kind(&Interner) {
|
||||||
TyKind::Error => self.table.new_type_var(),
|
TyKind::Error => self.table.new_type_var(),
|
||||||
|
TyKind::InferenceVar(..) => {
|
||||||
|
let ty_resolved = self.resolve_ty_shallow(&ty);
|
||||||
|
if ty_resolved.is_unknown() {
|
||||||
|
self.table.new_type_var()
|
||||||
|
} else {
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => ty,
|
_ => ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,18 +381,8 @@ impl<'a> InferenceContext<'a> {
|
||||||
self.table.unify_inner(ty1, ty2)
|
self.table.unify_inner(ty1, ty2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME get rid of this, instead resolve shallowly where necessary
|
|
||||||
/// Resolves the type as far as currently possible, replacing type variables
|
|
||||||
/// by their known types. All types returned by the infer_* functions should
|
|
||||||
/// be resolved as far as possible, i.e. contain no type variables with
|
|
||||||
/// known type.
|
|
||||||
fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
|
|
||||||
self.resolve_obligations_as_possible();
|
|
||||||
|
|
||||||
self.table.resolve_ty_as_possible(ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
|
fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
|
||||||
|
self.resolve_obligations_as_possible();
|
||||||
self.table.resolve_ty_shallow(ty)
|
self.table.resolve_ty_shallow(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,7 +416,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
};
|
};
|
||||||
self.push_obligation(trait_ref.cast(&Interner));
|
self.push_obligation(trait_ref.cast(&Interner));
|
||||||
self.push_obligation(alias_eq.cast(&Interner));
|
self.push_obligation(alias_eq.cast(&Interner));
|
||||||
self.resolve_ty_as_possible(ty)
|
ty
|
||||||
}
|
}
|
||||||
None => self.err_ty(),
|
None => self.err_ty(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,12 @@ impl<'a> InferenceContext<'a> {
|
||||||
/// Unify two types, but may coerce the first one to the second one
|
/// Unify two types, but may coerce the first one to the second one
|
||||||
/// using "implicit coercion rules" if needed.
|
/// using "implicit coercion rules" if needed.
|
||||||
pub(super) fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool {
|
pub(super) fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool {
|
||||||
|
let from_ty = self.resolve_ty_shallow(from_ty);
|
||||||
|
let to_ty = self.resolve_ty_shallow(to_ty);
|
||||||
// TODO handle expectations properly
|
// TODO handle expectations properly
|
||||||
if to_ty.is_unknown() {
|
if to_ty.is_unknown() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let from_ty = self.resolve_ty_shallow(from_ty);
|
|
||||||
let to_ty = self.resolve_ty_shallow(to_ty);
|
|
||||||
match self.coerce_inner(from_ty, &to_ty) {
|
match self.coerce_inner(from_ty, &to_ty) {
|
||||||
Ok(_result) => {
|
Ok(_result) => {
|
||||||
// TODO deal with goals
|
// TODO deal with goals
|
||||||
|
|
|
@ -35,7 +35,7 @@ use super::{
|
||||||
impl<'a> InferenceContext<'a> {
|
impl<'a> InferenceContext<'a> {
|
||||||
pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||||
let ty = self.infer_expr_inner(tgt_expr, expected);
|
let ty = self.infer_expr_inner(tgt_expr, expected);
|
||||||
if ty.is_never() {
|
if self.resolve_ty_shallow(&ty).is_never() {
|
||||||
// Any expression that produces a value of type `!` must have diverged
|
// Any expression that produces a value of type `!` must have diverged
|
||||||
self.diverges = Diverges::Always;
|
self.diverges = Diverges::Always;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
|
TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.resolve_ty_as_possible(ty)
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Infer type of expression with possibly implicit coerce to the expected type.
|
/// Infer type of expression with possibly implicit coerce to the expected type.
|
||||||
|
@ -67,7 +67,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
expected.ty.clone()
|
expected.ty.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
self.resolve_ty_as_possible(ty)
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
|
fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
|
||||||
|
@ -284,8 +284,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
|
|
||||||
// Now go through the argument patterns
|
// Now go through the argument patterns
|
||||||
for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
|
for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
|
||||||
let resolved = self.resolve_ty_as_possible(arg_ty);
|
self.infer_pat(*arg_pat, &arg_ty, BindingMode::default());
|
||||||
self.infer_pat(*arg_pat, &resolved, BindingMode::default());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||||
|
@ -525,14 +524,14 @@ impl<'a> InferenceContext<'a> {
|
||||||
Expr::Ref { expr, rawness, mutability } => {
|
Expr::Ref { expr, rawness, mutability } => {
|
||||||
let mutability = lower_to_chalk_mutability(*mutability);
|
let mutability = lower_to_chalk_mutability(*mutability);
|
||||||
let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) =
|
let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) =
|
||||||
&expected.ty.as_reference_or_ptr()
|
&self.resolve_ty_shallow(&expected.ty).as_reference_or_ptr()
|
||||||
{
|
{
|
||||||
if *exp_mutability == Mutability::Mut && mutability == Mutability::Not {
|
if *exp_mutability == Mutability::Mut && mutability == Mutability::Not {
|
||||||
// FIXME: throw type error - expected mut reference but found shared ref,
|
// FIXME: record type error - expected mut reference but found shared ref,
|
||||||
// which cannot be coerced
|
// which cannot be coerced
|
||||||
}
|
}
|
||||||
if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr {
|
if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr {
|
||||||
// FIXME: throw type error - expected reference but found ptr,
|
// FIXME: record type error - expected reference but found ptr,
|
||||||
// which cannot be coerced
|
// which cannot be coerced
|
||||||
}
|
}
|
||||||
Expectation::rvalue_hint(Ty::clone(exp_inner))
|
Expectation::rvalue_hint(Ty::clone(exp_inner))
|
||||||
|
@ -559,6 +558,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
Expr::UnaryOp { expr, op } => {
|
Expr::UnaryOp { expr, op } => {
|
||||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||||
|
let inner_ty = self.resolve_ty_shallow(&inner_ty);
|
||||||
match op {
|
match op {
|
||||||
UnaryOp::Deref => match self.resolver.krate() {
|
UnaryOp::Deref => match self.resolver.krate() {
|
||||||
Some(krate) => {
|
Some(krate) => {
|
||||||
|
@ -615,8 +615,10 @@ impl<'a> InferenceContext<'a> {
|
||||||
_ => Expectation::none(),
|
_ => Expectation::none(),
|
||||||
};
|
};
|
||||||
let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
|
let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
|
||||||
|
let lhs_ty = self.resolve_ty_shallow(&lhs_ty);
|
||||||
let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty.clone());
|
let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty.clone());
|
||||||
let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation));
|
let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation));
|
||||||
|
let rhs_ty = self.resolve_ty_shallow(&rhs_ty);
|
||||||
|
|
||||||
let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone());
|
let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone());
|
||||||
|
|
||||||
|
@ -699,7 +701,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Tuple { exprs } => {
|
Expr::Tuple { exprs } => {
|
||||||
let mut tys = match expected.ty.kind(&Interner) {
|
let mut tys = match self.resolve_ty_shallow(&expected.ty).kind(&Interner) {
|
||||||
TyKind::Tuple(_, substs) => substs
|
TyKind::Tuple(_, substs) => substs
|
||||||
.iter(&Interner)
|
.iter(&Interner)
|
||||||
.map(|a| a.assert_ty_ref(&Interner).clone())
|
.map(|a| a.assert_ty_ref(&Interner).clone())
|
||||||
|
@ -716,7 +718,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner)
|
TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner)
|
||||||
}
|
}
|
||||||
Expr::Array(array) => {
|
Expr::Array(array) => {
|
||||||
let elem_ty = match expected.ty.kind(&Interner) {
|
let elem_ty = match self.resolve_ty_shallow(&expected.ty).kind(&Interner) {
|
||||||
TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
|
TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
|
||||||
_ => self.table.new_type_var(),
|
_ => self.table.new_type_var(),
|
||||||
};
|
};
|
||||||
|
@ -788,7 +790,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
};
|
};
|
||||||
// use a new type variable if we got unknown here
|
// use a new type variable if we got unknown here
|
||||||
let ty = self.insert_type_vars_shallow(ty);
|
let ty = self.insert_type_vars_shallow(ty);
|
||||||
let ty = self.resolve_ty_as_possible(ty);
|
|
||||||
self.write_expr_ty(tgt_expr, ty.clone());
|
self.write_expr_ty(tgt_expr, ty.clone());
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
@ -816,7 +817,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty = self.resolve_ty_as_possible(ty);
|
|
||||||
self.infer_pat(*pat, &ty, BindingMode::default());
|
self.infer_pat(*pat, &ty, BindingMode::default());
|
||||||
}
|
}
|
||||||
Statement::Expr { expr, .. } => {
|
Statement::Expr { expr, .. } => {
|
||||||
|
@ -894,7 +894,8 @@ impl<'a> InferenceContext<'a> {
|
||||||
};
|
};
|
||||||
// Apply autoref so the below unification works correctly
|
// Apply autoref so the below unification works correctly
|
||||||
// FIXME: return correct autorefs from lookup_method
|
// FIXME: return correct autorefs from lookup_method
|
||||||
let actual_receiver_ty = match expected_receiver_ty.as_reference() {
|
let actual_receiver_ty = match self.resolve_ty_shallow(&expected_receiver_ty).as_reference()
|
||||||
|
{
|
||||||
Some((_, lifetime, mutability)) => {
|
Some((_, lifetime, mutability)) => {
|
||||||
TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner)
|
TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner)
|
||||||
}
|
}
|
||||||
|
@ -974,6 +975,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
|
fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
|
||||||
|
let callable_ty = self.resolve_ty_shallow(&callable_ty);
|
||||||
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(&Interner) {
|
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(&Interner) {
|
||||||
let def: CallableDefId = from_chalk(self.db, *fn_def);
|
let def: CallableDefId = from_chalk(self.db, *fn_def);
|
||||||
let generic_predicates = self.db.generic_predicates(def.into());
|
let generic_predicates = self.db.generic_predicates(def.into());
|
||||||
|
|
|
@ -94,14 +94,15 @@ impl<'a> InferenceContext<'a> {
|
||||||
pub(super) fn infer_pat(
|
pub(super) fn infer_pat(
|
||||||
&mut self,
|
&mut self,
|
||||||
pat: PatId,
|
pat: PatId,
|
||||||
mut expected: &Ty,
|
expected: &Ty,
|
||||||
mut default_bm: BindingMode,
|
mut default_bm: BindingMode,
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||||
|
let mut expected = self.resolve_ty_shallow(expected);
|
||||||
|
|
||||||
if is_non_ref_pat(&body, pat) {
|
if is_non_ref_pat(&body, pat) {
|
||||||
while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
|
while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
|
||||||
expected = inner;
|
expected = self.resolve_ty_shallow(inner);
|
||||||
default_bm = match default_bm {
|
default_bm = match default_bm {
|
||||||
BindingMode::Move => BindingMode::Ref(mutability),
|
BindingMode::Move => BindingMode::Ref(mutability),
|
||||||
BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
|
BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
|
||||||
|
@ -147,9 +148,9 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
Pat::Or(ref pats) => {
|
Pat::Or(ref pats) => {
|
||||||
if let Some((first_pat, rest)) = pats.split_first() {
|
if let Some((first_pat, rest)) = pats.split_first() {
|
||||||
let ty = self.infer_pat(*first_pat, expected, default_bm);
|
let ty = self.infer_pat(*first_pat, &expected, default_bm);
|
||||||
for pat in rest {
|
for pat in rest {
|
||||||
self.infer_pat(*pat, expected, default_bm);
|
self.infer_pat(*pat, &expected, default_bm);
|
||||||
}
|
}
|
||||||
ty
|
ty
|
||||||
} else {
|
} else {
|
||||||
|
@ -173,13 +174,13 @@ impl<'a> InferenceContext<'a> {
|
||||||
Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
|
Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
|
||||||
p.as_deref(),
|
p.as_deref(),
|
||||||
subpats,
|
subpats,
|
||||||
expected,
|
&expected,
|
||||||
default_bm,
|
default_bm,
|
||||||
pat,
|
pat,
|
||||||
*ellipsis,
|
*ellipsis,
|
||||||
),
|
),
|
||||||
Pat::Record { path: p, args: fields, ellipsis: _ } => {
|
Pat::Record { path: p, args: fields, ellipsis: _ } => {
|
||||||
self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat)
|
self.infer_record_pat(p.as_deref(), fields, &expected, default_bm, pat)
|
||||||
}
|
}
|
||||||
Pat::Path(path) => {
|
Pat::Path(path) => {
|
||||||
// FIXME use correct resolver for the surrounding expression
|
// FIXME use correct resolver for the surrounding expression
|
||||||
|
@ -193,7 +194,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
BindingMode::convert(*mode)
|
BindingMode::convert(*mode)
|
||||||
};
|
};
|
||||||
let inner_ty = if let Some(subpat) = subpat {
|
let inner_ty = if let Some(subpat) = subpat {
|
||||||
self.infer_pat(*subpat, expected, default_bm)
|
self.infer_pat(*subpat, &expected, default_bm)
|
||||||
} else {
|
} else {
|
||||||
expected.clone()
|
expected.clone()
|
||||||
};
|
};
|
||||||
|
@ -206,7 +207,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
BindingMode::Move => inner_ty.clone(),
|
BindingMode::Move => inner_ty.clone(),
|
||||||
};
|
};
|
||||||
let bound_ty = self.resolve_ty_as_possible(bound_ty);
|
|
||||||
self.write_pat_ty(pat, bound_ty);
|
self.write_pat_ty(pat, bound_ty);
|
||||||
return inner_ty;
|
return inner_ty;
|
||||||
}
|
}
|
||||||
|
@ -265,13 +265,12 @@ impl<'a> InferenceContext<'a> {
|
||||||
};
|
};
|
||||||
// use a new type variable if we got error type here
|
// use a new type variable if we got error type here
|
||||||
let ty = self.insert_type_vars_shallow(ty);
|
let ty = self.insert_type_vars_shallow(ty);
|
||||||
if !self.unify(&ty, expected) {
|
if !self.unify(&ty, &expected) {
|
||||||
self.result.type_mismatches.insert(
|
self.result.type_mismatches.insert(
|
||||||
pat.into(),
|
pat.into(),
|
||||||
TypeMismatch { expected: expected.clone(), actual: ty.clone() },
|
TypeMismatch { expected: expected.clone(), actual: ty.clone() },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let ty = self.resolve_ty_as_possible(ty);
|
|
||||||
self.write_pat_ty(pat, ty.clone());
|
self.write_pat_ty(pat, ty.clone());
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
let typable: ValueTyDefId = match value {
|
let typable: ValueTyDefId = match value {
|
||||||
ValueNs::LocalBinding(pat) => {
|
ValueNs::LocalBinding(pat) => {
|
||||||
let ty = self.result.type_of_pat.get(pat)?.clone();
|
let ty = self.result.type_of_pat.get(pat)?.clone();
|
||||||
let ty = self.resolve_ty_as_possible(ty);
|
|
||||||
return Some(ty);
|
return Some(ty);
|
||||||
}
|
}
|
||||||
ValueNs::FunctionId(it) => it.into(),
|
ValueNs::FunctionId(it) => it.into(),
|
||||||
|
@ -275,6 +274,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
name: &Name,
|
name: &Name,
|
||||||
id: ExprOrPatId,
|
id: ExprOrPatId,
|
||||||
) -> Option<(ValueNs, Option<Substitution>)> {
|
) -> Option<(ValueNs, Option<Substitution>)> {
|
||||||
|
let ty = self.resolve_ty_shallow(ty);
|
||||||
let (enum_id, subst) = match ty.as_adt() {
|
let (enum_id, subst) = match ty.as_adt() {
|
||||||
Some((AdtId::EnumId(e), subst)) => (e, subst),
|
Some((AdtId::EnumId(e), subst)) => (e, subst),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
|
|
@ -24,6 +24,9 @@ impl<'a> InferenceContext<'a> {
|
||||||
where
|
where
|
||||||
T::Result: HasInterner<Interner = Interner>,
|
T::Result: HasInterner<Interner = Interner>,
|
||||||
{
|
{
|
||||||
|
// try to resolve obligations before canonicalizing, since this might
|
||||||
|
// result in new knowledge about variables
|
||||||
|
self.resolve_obligations_as_possible();
|
||||||
self.table.canonicalize(t)
|
self.table.canonicalize(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +219,6 @@ impl<'a> InferenceTable<'a> {
|
||||||
/// call). `make_ty` handles this already, but e.g. for field types we need
|
/// call). `make_ty` handles this already, but e.g. for field types we need
|
||||||
/// to do it as well.
|
/// to do it as well.
|
||||||
pub(super) fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
|
pub(super) fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
|
||||||
let ty = self.resolve_ty_as_possible(ty);
|
|
||||||
fold_tys(
|
fold_tys(
|
||||||
ty,
|
ty,
|
||||||
|ty, _| match ty.kind(&Interner) {
|
|ty, _| match ty.kind(&Interner) {
|
||||||
|
@ -302,11 +304,6 @@ impl<'a> InferenceTable<'a> {
|
||||||
self.resolve_with_fallback(ty, |_, _, d, _| d)
|
self.resolve_with_fallback(ty, |_, _, d, _| d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME get rid of this, instead resolve shallowly where necessary
|
|
||||||
pub(crate) fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
|
|
||||||
self.resolve_ty_as_possible_inner(&mut Vec::new(), ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unify two types and register new trait goals that arise from that.
|
/// Unify two types and register new trait goals that arise from that.
|
||||||
// TODO give these two functions better names
|
// TODO give these two functions better names
|
||||||
pub(crate) fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
|
pub(crate) fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
|
||||||
|
@ -344,36 +341,6 @@ impl<'a> InferenceTable<'a> {
|
||||||
self.var_unification_table.normalize_ty_shallow(&Interner, ty).unwrap_or_else(|| ty.clone())
|
self.var_unification_table.normalize_ty_shallow(&Interner, ty).unwrap_or_else(|| ty.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the type as far as currently possible, replacing type variables
|
|
||||||
/// by their known types.
|
|
||||||
fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<InferenceVar>, ty: Ty) -> Ty {
|
|
||||||
fold_tys(
|
|
||||||
ty,
|
|
||||||
|ty, _| match ty.kind(&Interner) {
|
|
||||||
&TyKind::InferenceVar(tv, kind) => {
|
|
||||||
if tv_stack.contains(&tv) {
|
|
||||||
// recursive type
|
|
||||||
return self.type_variable_table.fallback_value(tv, kind);
|
|
||||||
}
|
|
||||||
if let Some(known_ty) = self.var_unification_table.probe_var(tv) {
|
|
||||||
// known_ty may contain other variables that are known by now
|
|
||||||
tv_stack.push(tv);
|
|
||||||
let result = self.resolve_ty_as_possible_inner(
|
|
||||||
tv_stack,
|
|
||||||
known_ty.assert_ty_ref(&Interner).clone(),
|
|
||||||
);
|
|
||||||
tv_stack.pop();
|
|
||||||
result
|
|
||||||
} else {
|
|
||||||
ty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => ty,
|
|
||||||
},
|
|
||||||
DebruijnIndex::INNERMOST,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn register_obligation(&mut self, goal: Goal) {
|
pub fn register_obligation(&mut self, goal: Goal) {
|
||||||
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
||||||
self.register_obligation_in_env(in_env)
|
self.register_obligation_in_env(in_env)
|
||||||
|
|
|
@ -117,19 +117,19 @@ fn recursive_vars_2() {
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
10..79 '{ ...x)]; }': ()
|
10..79 '{ ...x)]; }': ()
|
||||||
20..21 'x': {unknown}
|
20..21 'x': &{unknown}
|
||||||
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}); 2]
|
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}
|
||||||
67..75 '(&y, &x)': (&{unknown}, &{unknown})
|
67..75 '(&y, &x)': (&{unknown}, {unknown})
|
||||||
68..70 '&y': &{unknown}
|
68..70 '&y': &{unknown}
|
||||||
69..70 'y': {unknown}
|
69..70 'y': {unknown}
|
||||||
72..74 '&x': &{unknown}
|
72..74 '&x': &&{unknown}
|
||||||
73..74 'x': {unknown}
|
73..74 'x': &{unknown}
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3104,7 +3104,7 @@ fn foo() {
|
||||||
568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)>
|
568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)>
|
||||||
570..572 '&s': &Option<i32>
|
570..572 '&s': &Option<i32>
|
||||||
571..572 's': Option<i32>
|
571..572 's': Option<i32>
|
||||||
549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|_| -> ()>
|
549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()>
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue