2019-10-12 15:39:20 +00:00
|
|
|
//! Type inference for expressions.
|
|
|
|
|
2021-07-09 17:12:56 +00:00
|
|
|
use std::{
|
|
|
|
iter::{repeat, repeat_with},
|
|
|
|
mem,
|
|
|
|
};
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
use chalk_ir::{
|
2023-01-02 22:16:09 +00:00
|
|
|
cast::Cast, fold::Shift, DebruijnIndex, GenericArgData, Mutability, TyKind, TyVariableKind,
|
2022-03-09 18:50:24 +00:00
|
|
|
};
|
2019-11-13 06:56:33 +00:00
|
|
|
use hir_def::{
|
2022-09-06 08:48:06 +00:00
|
|
|
expr::{
|
2023-01-17 10:51:48 +00:00
|
|
|
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
|
2022-09-06 08:48:06 +00:00
|
|
|
},
|
2021-12-29 13:35:59 +00:00
|
|
|
generics::TypeOrConstParamData,
|
2023-01-27 10:25:34 +00:00
|
|
|
lang_item::LangItem,
|
2019-11-13 06:56:33 +00:00
|
|
|
path::{GenericArg, GenericArgs},
|
2019-11-21 12:39:09 +00:00
|
|
|
resolver::resolver_for_expr,
|
2022-08-05 12:16:36 +00:00
|
|
|
ConstParamId, FieldId, ItemContainerId, Lookup,
|
2019-11-13 06:56:33 +00:00
|
|
|
};
|
2023-01-27 10:15:05 +00:00
|
|
|
use hir_expand::name::{name, Name};
|
2021-03-21 16:40:14 +00:00
|
|
|
use stdx::always;
|
2020-08-12 16:26:51 +00:00
|
|
|
use syntax::ast::RangeOp;
|
2019-10-30 14:19:30 +00:00
|
|
|
|
2019-10-12 15:39:20 +00:00
|
|
|
use crate::{
|
2021-07-09 17:12:56 +00:00
|
|
|
autoderef::{self, Autoderef},
|
|
|
|
consteval,
|
2022-10-18 12:18:59 +00:00
|
|
|
infer::{coerce::CoerceMany, find_continuable, BreakableKind},
|
2022-03-09 18:50:24 +00:00
|
|
|
lower::{
|
|
|
|
const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode,
|
|
|
|
},
|
2022-03-21 15:43:19 +00:00
|
|
|
mapping::{from_chalk, ToChalk},
|
2023-01-21 16:29:07 +00:00
|
|
|
method_resolution::{self, lang_items_for_bin_op, VisibleFromModule},
|
2021-02-28 09:58:34 +00:00
|
|
|
primitive::{self, UintTy},
|
2022-10-18 12:18:59 +00:00
|
|
|
static_lifetime, to_chalk_trait_id,
|
2021-04-06 15:59:18 +00:00
|
|
|
utils::{generics, Generics},
|
2023-01-02 22:16:09 +00:00
|
|
|
Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnPointer, FnSig, FnSubst,
|
|
|
|
Interner, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt,
|
2019-10-12 15:39:20 +00:00
|
|
|
};
|
|
|
|
|
2020-05-08 15:59:58 +00:00
|
|
|
use super::{
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
coerce::auto_deref_adjust_steps, find_breakable, BindingMode, BreakableContext, Diverges,
|
|
|
|
Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch,
|
2020-05-08 15:59:58 +00:00
|
|
|
};
|
2019-11-21 12:39:09 +00:00
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
impl<'a> InferenceContext<'a> {
|
2022-03-09 18:50:24 +00:00
|
|
|
pub(crate) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
2019-10-12 15:39:20 +00:00
|
|
|
let ty = self.infer_expr_inner(tgt_expr, expected);
|
2021-05-21 15:41:20 +00:00
|
|
|
if let Some(expected_ty) = expected.only_has_type(&mut self.table) {
|
|
|
|
let could_unify = self.unify(&ty, &expected_ty);
|
|
|
|
if !could_unify {
|
|
|
|
self.result.type_mismatches.insert(
|
|
|
|
tgt_expr.into(),
|
2021-05-26 15:34:50 +00:00
|
|
|
TypeMismatch { expected: expected_ty, actual: ty.clone() },
|
2021-05-21 15:41:20 +00:00
|
|
|
);
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2021-05-16 15:56:38 +00:00
|
|
|
ty
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Infer type of expression with possibly implicit coerce to the expected type.
|
|
|
|
/// Return the type after possible coercion.
|
2019-12-20 17:27:51 +00:00
|
|
|
pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
|
2021-06-13 03:54:16 +00:00
|
|
|
let ty = self.infer_expr_inner(expr, expected);
|
2021-09-03 14:00:50 +00:00
|
|
|
if let Some(target) = expected.only_has_type(&mut self.table) {
|
2021-07-08 12:16:23 +00:00
|
|
|
match self.coerce(Some(expr), &ty, &target) {
|
2022-03-20 12:42:47 +00:00
|
|
|
Ok(res) => res,
|
2021-07-06 16:05:40 +00:00
|
|
|
Err(_) => {
|
2022-03-29 15:51:11 +00:00
|
|
|
self.result.type_mismatches.insert(
|
|
|
|
expr.into(),
|
|
|
|
TypeMismatch { expected: target.clone(), actual: ty.clone() },
|
|
|
|
);
|
|
|
|
target
|
2021-07-06 16:05:40 +00:00
|
|
|
}
|
2021-05-21 15:41:20 +00:00
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
} else {
|
2021-05-21 15:41:20 +00:00
|
|
|
ty
|
2021-09-03 14:00:50 +00:00
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
2021-05-17 17:07:10 +00:00
|
|
|
self.db.unwind_if_cancelled();
|
2021-03-29 20:15:12 +00:00
|
|
|
|
2022-04-15 19:44:47 +00:00
|
|
|
let ty = match &self.body[tgt_expr] {
|
2021-03-13 13:44:51 +00:00
|
|
|
Expr::Missing => self.err_ty(),
|
2021-07-08 12:16:23 +00:00
|
|
|
&Expr::If { condition, then_branch, else_branch } => {
|
2022-10-31 15:15:05 +00:00
|
|
|
let expected = &expected.adjust_for_branches(&mut self.table);
|
2021-03-13 13:44:51 +00:00
|
|
|
self.infer_expr(
|
2021-07-08 12:16:23 +00:00
|
|
|
condition,
|
2023-02-10 15:08:47 +00:00
|
|
|
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
2021-03-13 13:44:51 +00:00
|
|
|
);
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2020-05-08 15:36:11 +00:00
|
|
|
let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
|
|
|
let mut both_arms_diverge = Diverges::Always;
|
|
|
|
|
2021-07-08 12:16:23 +00:00
|
|
|
let then_ty = self.infer_expr_inner(then_branch, expected);
|
2020-05-08 15:36:11 +00:00
|
|
|
both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
|
2023-02-10 15:08:47 +00:00
|
|
|
let mut coerce = CoerceMany::new(expected.coercion_target_type(&mut self.table));
|
2021-07-08 12:16:23 +00:00
|
|
|
coerce.coerce(self, Some(then_branch), &then_ty);
|
2019-10-12 15:39:20 +00:00
|
|
|
let else_ty = match else_branch {
|
2021-07-08 12:16:23 +00:00
|
|
|
Some(else_branch) => self.infer_expr_inner(else_branch, expected),
|
2021-04-03 18:22:59 +00:00
|
|
|
None => TyBuilder::unit(),
|
2019-10-12 15:39:20 +00:00
|
|
|
};
|
2020-05-08 15:36:11 +00:00
|
|
|
both_arms_diverge &= self.diverges;
|
2021-05-21 15:48:15 +00:00
|
|
|
// FIXME: create a synthetic `else {}` so we have something to refer to here instead of None?
|
2021-07-08 12:16:23 +00:00
|
|
|
coerce.coerce(self, else_branch, &else_ty);
|
2020-05-08 15:36:11 +00:00
|
|
|
|
|
|
|
self.diverges = condition_diverges | both_arms_diverge;
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2021-07-08 12:16:23 +00:00
|
|
|
coerce.complete()
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-01-23 03:59:35 +00:00
|
|
|
&Expr::Let { pat, expr } => {
|
|
|
|
let input_ty = self.infer_expr(expr, &Expectation::none());
|
|
|
|
self.infer_pat(pat, &input_ty, BindingMode::default());
|
2023-02-10 15:08:47 +00:00
|
|
|
self.result.standard_types.bool_.clone()
|
2022-01-23 03:59:35 +00:00
|
|
|
}
|
2021-02-10 13:41:54 +00:00
|
|
|
Expr::Block { statements, tail, label, id: _ } => {
|
2021-02-10 14:12:45 +00:00
|
|
|
let old_resolver = mem::replace(
|
|
|
|
&mut self.resolver,
|
|
|
|
resolver_for_expr(self.db.upcast(), self.owner, tgt_expr),
|
|
|
|
);
|
|
|
|
let ty = match label {
|
2021-02-10 13:41:54 +00:00
|
|
|
Some(_) => {
|
|
|
|
let break_ty = self.table.new_type_var();
|
2022-09-01 12:54:47 +00:00
|
|
|
let (breaks, ty) = self.with_breakable_ctx(
|
|
|
|
BreakableKind::Block,
|
|
|
|
break_ty.clone(),
|
|
|
|
*label,
|
|
|
|
|this| {
|
2022-09-01 12:30:57 +00:00
|
|
|
this.infer_block(
|
|
|
|
tgt_expr,
|
|
|
|
statements,
|
|
|
|
*tail,
|
|
|
|
&Expectation::has_type(break_ty),
|
|
|
|
)
|
2022-09-01 12:54:47 +00:00
|
|
|
},
|
|
|
|
);
|
2022-09-01 12:30:57 +00:00
|
|
|
breaks.unwrap_or(ty)
|
2020-12-11 23:03:36 +00:00
|
|
|
}
|
2021-07-06 16:05:40 +00:00
|
|
|
None => self.infer_block(tgt_expr, statements, *tail, expected),
|
2021-02-10 14:12:45 +00:00
|
|
|
};
|
|
|
|
self.resolver = old_resolver;
|
|
|
|
ty
|
2021-02-10 13:41:54 +00:00
|
|
|
}
|
2022-09-01 12:54:47 +00:00
|
|
|
Expr::Unsafe { body } => self.infer_expr(*body, expected),
|
|
|
|
Expr::Const { body } => {
|
|
|
|
self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
|
|
|
|
this.infer_expr(*body, expected)
|
|
|
|
})
|
|
|
|
.1
|
|
|
|
}
|
2020-05-01 23:12:37 +00:00
|
|
|
Expr::TryBlock { body } => {
|
2022-12-28 21:25:47 +00:00
|
|
|
// The type that is returned from the try block
|
|
|
|
let try_ty = self.table.new_type_var();
|
|
|
|
if let Some(ty) = expected.only_has_type(&mut self.table) {
|
|
|
|
self.unify(&try_ty, &ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The ok-ish type that is expected from the last expression
|
2023-01-27 10:25:34 +00:00
|
|
|
let ok_ty =
|
|
|
|
self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_output());
|
2022-12-28 21:25:47 +00:00
|
|
|
|
|
|
|
self.with_breakable_ctx(BreakableKind::Block, ok_ty.clone(), None, |this| {
|
|
|
|
this.infer_expr(*body, &Expectation::has_type(ok_ty));
|
2022-09-01 12:54:47 +00:00
|
|
|
});
|
2022-12-28 21:25:47 +00:00
|
|
|
|
|
|
|
try_ty
|
2020-05-01 23:12:37 +00:00
|
|
|
}
|
2020-09-10 12:01:23 +00:00
|
|
|
Expr::Async { body } => {
|
2022-03-23 22:39:35 +00:00
|
|
|
let ret_ty = self.table.new_type_var();
|
|
|
|
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
|
|
|
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
|
|
|
|
|
2022-09-01 12:54:47 +00:00
|
|
|
let (_, inner_ty) =
|
|
|
|
self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
|
|
|
|
this.infer_expr_coerce(*body, &Expectation::has_type(ret_ty))
|
|
|
|
});
|
2022-03-23 22:39:35 +00:00
|
|
|
|
|
|
|
self.diverges = prev_diverges;
|
|
|
|
self.return_ty = prev_ret_ty;
|
|
|
|
|
2020-09-10 12:01:23 +00:00
|
|
|
// Use the first type parameter as the output type of future.
|
2021-07-08 12:16:23 +00:00
|
|
|
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
|
2021-03-13 19:05:47 +00:00
|
|
|
let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
|
|
|
|
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty))
|
|
|
|
.intern(Interner)
|
2020-09-10 12:01:23 +00:00
|
|
|
}
|
2022-09-01 12:13:08 +00:00
|
|
|
&Expr::Loop { body, label } => {
|
2023-02-10 15:08:47 +00:00
|
|
|
// FIXME: should be:
|
|
|
|
// let ty = expected.coercion_target_type(&mut self.table);
|
2022-09-01 12:13:08 +00:00
|
|
|
let ty = self.table.new_type_var();
|
2022-09-01 12:54:47 +00:00
|
|
|
let (breaks, ()) =
|
|
|
|
self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| {
|
2023-02-10 15:08:47 +00:00
|
|
|
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
2022-09-01 12:54:47 +00:00
|
|
|
});
|
2020-05-08 15:59:58 +00:00
|
|
|
|
2022-09-01 12:30:57 +00:00
|
|
|
match breaks {
|
|
|
|
Some(breaks) => {
|
|
|
|
self.diverges = Diverges::Maybe;
|
|
|
|
breaks
|
|
|
|
}
|
2023-02-10 15:08:47 +00:00
|
|
|
None => self.result.standard_types.never.clone(),
|
2020-05-08 15:59:58 +00:00
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-09-01 12:13:08 +00:00
|
|
|
&Expr::While { condition, body, label } => {
|
2022-09-01 12:54:47 +00:00
|
|
|
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
|
2022-09-01 12:13:08 +00:00
|
|
|
this.infer_expr(
|
|
|
|
condition,
|
2023-02-10 15:08:47 +00:00
|
|
|
&Expectation::HasType(this.result.standard_types.bool_.clone()),
|
2022-09-01 12:13:08 +00:00
|
|
|
);
|
2023-02-10 15:08:47 +00:00
|
|
|
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
2020-05-31 08:59:40 +00:00
|
|
|
});
|
2022-09-01 12:13:08 +00:00
|
|
|
|
2020-05-08 15:59:58 +00:00
|
|
|
// the body may not run, so it diverging doesn't mean we diverge
|
|
|
|
self.diverges = Diverges::Maybe;
|
2021-04-03 18:22:59 +00:00
|
|
|
TyBuilder::unit()
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-09-01 12:13:08 +00:00
|
|
|
&Expr::For { iterable, body, pat, label } => {
|
|
|
|
let iterable_ty = self.infer_expr(iterable, &Expectation::none());
|
2022-09-29 09:44:45 +00:00
|
|
|
let into_iter_ty =
|
2019-12-13 11:44:07 +00:00
|
|
|
self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
|
2022-09-29 09:44:45 +00:00
|
|
|
let pat_ty =
|
|
|
|
self.resolve_associated_type(into_iter_ty, self.resolve_iterator_item());
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2022-09-01 12:13:08 +00:00
|
|
|
self.infer_pat(pat, &pat_ty, BindingMode::default());
|
2022-09-01 12:54:47 +00:00
|
|
|
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
|
2023-02-10 15:08:47 +00:00
|
|
|
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
2022-09-01 12:13:08 +00:00
|
|
|
});
|
2020-05-08 15:59:58 +00:00
|
|
|
|
|
|
|
// the body may not run, so it diverging doesn't mean we diverge
|
|
|
|
self.diverges = Diverges::Maybe;
|
2021-04-03 18:22:59 +00:00
|
|
|
TyBuilder::unit()
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-09-06 08:48:06 +00:00
|
|
|
Expr::Closure { body, args, ret_type, arg_types, closure_kind } => {
|
2019-10-12 15:39:20 +00:00
|
|
|
assert_eq!(args.len(), arg_types.len());
|
|
|
|
|
2023-02-10 15:42:09 +00:00
|
|
|
let mut sig_tys = Vec::with_capacity(arg_types.len() + 1);
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2020-05-29 15:35:57 +00:00
|
|
|
// collect explicitly written argument types
|
|
|
|
for arg_type in arg_types.iter() {
|
2021-10-03 12:53:01 +00:00
|
|
|
let arg_ty = match arg_type {
|
|
|
|
Some(type_ref) => self.make_ty(type_ref),
|
|
|
|
None => self.table.new_type_var(),
|
2019-10-12 15:39:20 +00:00
|
|
|
};
|
|
|
|
sig_tys.push(arg_ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
// add return type
|
2019-12-20 15:41:32 +00:00
|
|
|
let ret_ty = match ret_type {
|
|
|
|
Some(type_ref) => self.make_ty(type_ref),
|
|
|
|
None => self.table.new_type_var(),
|
|
|
|
};
|
2019-10-12 15:39:20 +00:00
|
|
|
sig_tys.push(ret_ty.clone());
|
2021-03-13 13:44:51 +00:00
|
|
|
let sig_ty = TyKind::Function(FnPointer {
|
2021-04-05 20:23:16 +00:00
|
|
|
num_binders: 0,
|
2021-03-14 15:30:02 +00:00
|
|
|
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
|
2021-04-05 20:32:58 +00:00
|
|
|
substitution: FnSubst(
|
2023-02-10 15:42:09 +00:00
|
|
|
Substitution::from_iter(Interner, sig_tys.iter().cloned())
|
|
|
|
.shifted_in(Interner),
|
2021-04-05 20:32:58 +00:00
|
|
|
),
|
2021-03-13 13:44:51 +00:00
|
|
|
})
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner);
|
2022-09-06 08:48:06 +00:00
|
|
|
|
|
|
|
let (ty, resume_yield_tys) = if matches!(closure_kind, ClosureKind::Generator(_)) {
|
|
|
|
// FIXME: report error when there are more than 1 parameter.
|
|
|
|
let resume_ty = match sig_tys.first() {
|
|
|
|
// When `sig_tys.len() == 1` the first type is the return type, not the
|
|
|
|
// first parameter type.
|
|
|
|
Some(ty) if sig_tys.len() > 1 => ty.clone(),
|
|
|
|
_ => self.result.standard_types.unit.clone(),
|
|
|
|
};
|
|
|
|
let yield_ty = self.table.new_type_var();
|
|
|
|
|
|
|
|
let subst = TyBuilder::subst_for_generator(self.db, self.owner)
|
|
|
|
.push(resume_ty.clone())
|
|
|
|
.push(yield_ty.clone())
|
|
|
|
.push(ret_ty.clone())
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let generator_id = self.db.intern_generator((self.owner, tgt_expr)).into();
|
|
|
|
let generator_ty = TyKind::Generator(generator_id, subst).intern(Interner);
|
|
|
|
|
|
|
|
(generator_ty, Some((resume_ty, yield_ty)))
|
|
|
|
} else {
|
|
|
|
let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
|
|
|
|
let closure_ty =
|
|
|
|
TyKind::Closure(closure_id, Substitution::from1(Interner, sig_ty.clone()))
|
|
|
|
.intern(Interner);
|
|
|
|
|
|
|
|
(closure_ty, None)
|
|
|
|
};
|
2019-10-12 15:39:20 +00:00
|
|
|
|
|
|
|
// Eagerly try to relate the closure type with the expected
|
|
|
|
// type, otherwise we often won't have enough information to
|
|
|
|
// infer the body.
|
2022-09-06 08:48:06 +00:00
|
|
|
self.deduce_closure_type_from_expectations(tgt_expr, &ty, &sig_ty, expected);
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2020-05-29 15:35:57 +00:00
|
|
|
// Now go through the argument patterns
|
|
|
|
for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
|
2021-05-16 15:56:38 +00:00
|
|
|
self.infer_pat(*arg_pat, &arg_ty, BindingMode::default());
|
2020-05-29 15:35:57 +00:00
|
|
|
}
|
|
|
|
|
2020-05-08 15:36:11 +00:00
|
|
|
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
|
|
|
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
|
2022-09-06 08:48:06 +00:00
|
|
|
let prev_resume_yield_tys =
|
|
|
|
mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
|
2019-12-20 15:41:32 +00:00
|
|
|
|
2022-09-01 12:54:47 +00:00
|
|
|
self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
|
|
|
|
this.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
|
|
|
|
});
|
2019-12-20 15:41:32 +00:00
|
|
|
|
2020-05-08 15:36:11 +00:00
|
|
|
self.diverges = prev_diverges;
|
2019-12-20 15:41:32 +00:00
|
|
|
self.return_ty = prev_ret_ty;
|
2022-09-06 08:48:06 +00:00
|
|
|
self.resume_yield_tys = prev_resume_yield_tys;
|
2019-12-20 15:41:32 +00:00
|
|
|
|
2022-09-06 08:48:06 +00:00
|
|
|
ty
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-07-24 13:32:49 +00:00
|
|
|
Expr::Call { callee, args, .. } => {
|
2019-10-12 15:39:20 +00:00
|
|
|
let callee_ty = self.infer_expr(*callee, &Expectation::none());
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
|
2023-02-10 15:42:09 +00:00
|
|
|
let (res, derefed_callee) = 'b: {
|
|
|
|
// manual loop to be able to access `derefs.table`
|
|
|
|
while let Some((callee_deref_ty, _)) = derefs.next() {
|
|
|
|
let res = derefs.table.callable_sig(&callee_deref_ty, args.len());
|
|
|
|
if res.is_some() {
|
|
|
|
break 'b (res, callee_deref_ty);
|
|
|
|
}
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
}
|
2023-02-10 15:42:09 +00:00
|
|
|
(None, callee_ty.clone())
|
|
|
|
};
|
2022-03-27 17:10:31 +00:00
|
|
|
// if the function is unresolved, we use is_varargs=true to
|
|
|
|
// suppress the arg count diagnostic here
|
|
|
|
let is_varargs =
|
|
|
|
derefed_callee.callable_sig(self.db).map_or(false, |sig| sig.is_varargs)
|
|
|
|
|| res.is_none();
|
2022-03-21 15:43:19 +00:00
|
|
|
let (param_tys, ret_ty) = match res {
|
2023-01-27 10:06:41 +00:00
|
|
|
Some((func, params, ret_ty)) => {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let adjustments = auto_deref_adjust_steps(&derefs);
|
2023-01-03 10:58:31 +00:00
|
|
|
// FIXME: Handle call adjustments for Fn/FnMut
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
self.write_expr_adj(*callee, adjustments);
|
2023-01-27 10:06:41 +00:00
|
|
|
if let Some((trait_, func)) = func {
|
|
|
|
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
|
|
|
|
.push(callee_ty.clone())
|
|
|
|
.push(TyBuilder::tuple_with(params.iter().cloned()))
|
|
|
|
.build();
|
|
|
|
self.write_method_resolution(tgt_expr, func, subst.clone());
|
|
|
|
}
|
|
|
|
(params, ret_ty)
|
2021-07-09 17:12:56 +00:00
|
|
|
}
|
2022-03-27 17:10:31 +00:00
|
|
|
None => (Vec::new(), self.err_ty()), // FIXME diagnostic
|
2021-07-09 17:12:56 +00:00
|
|
|
};
|
2022-03-21 15:43:19 +00:00
|
|
|
let indices_to_skip = self.check_legacy_const_generics(derefed_callee, args);
|
2019-10-12 15:39:20 +00:00
|
|
|
self.register_obligations_for_call(&callee_ty);
|
2021-07-15 18:02:58 +00:00
|
|
|
|
|
|
|
let expected_inputs = self.expected_inputs_for_expected_output(
|
|
|
|
expected,
|
|
|
|
ret_ty.clone(),
|
|
|
|
param_tys.clone(),
|
|
|
|
);
|
|
|
|
|
2022-03-27 17:10:31 +00:00
|
|
|
self.check_call_arguments(
|
|
|
|
tgt_expr,
|
|
|
|
args,
|
|
|
|
&expected_inputs,
|
|
|
|
¶m_tys,
|
|
|
|
&indices_to_skip,
|
|
|
|
is_varargs,
|
|
|
|
);
|
2020-02-18 13:32:19 +00:00
|
|
|
self.normalize_associated_types_in(ret_ty)
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
Expr::MethodCall { receiver, args, method_name, generic_args } => self
|
2021-07-15 18:02:58 +00:00
|
|
|
.infer_method_call(
|
|
|
|
tgt_expr,
|
|
|
|
*receiver,
|
|
|
|
args,
|
|
|
|
method_name,
|
|
|
|
generic_args.as_deref(),
|
|
|
|
expected,
|
|
|
|
),
|
2019-10-12 15:39:20 +00:00
|
|
|
Expr::Match { expr, arms } => {
|
|
|
|
let input_ty = self.infer_expr(*expr, &Expectation::none());
|
|
|
|
|
2021-06-03 21:12:35 +00:00
|
|
|
let expected = expected.adjust_for_branches(&mut self.table);
|
|
|
|
|
2021-07-08 12:16:23 +00:00
|
|
|
let result_ty = if arms.is_empty() {
|
2023-02-10 15:08:47 +00:00
|
|
|
self.result.standard_types.never.clone()
|
2021-03-13 13:44:51 +00:00
|
|
|
} else {
|
2023-02-10 15:08:47 +00:00
|
|
|
expected.coercion_target_type(&mut self.table)
|
2021-03-13 13:44:51 +00:00
|
|
|
};
|
2021-07-08 12:16:23 +00:00
|
|
|
let mut coerce = CoerceMany::new(result_ty);
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2020-05-08 15:36:11 +00:00
|
|
|
let matchee_diverges = self.diverges;
|
|
|
|
let mut all_arms_diverge = Diverges::Always;
|
|
|
|
|
2021-11-20 15:00:45 +00:00
|
|
|
for arm in arms.iter() {
|
2020-05-08 15:36:11 +00:00
|
|
|
self.diverges = Diverges::Maybe;
|
2020-02-09 18:57:01 +00:00
|
|
|
let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default());
|
2022-01-23 03:59:35 +00:00
|
|
|
if let Some(guard_expr) = arm.guard {
|
|
|
|
self.infer_expr(
|
|
|
|
guard_expr,
|
2023-02-10 15:08:47 +00:00
|
|
|
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
2022-01-23 03:59:35 +00:00
|
|
|
);
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let arm_ty = self.infer_expr_inner(arm.expr, &expected);
|
2020-05-08 15:36:11 +00:00
|
|
|
all_arms_diverge &= self.diverges;
|
2021-07-08 12:16:23 +00:00
|
|
|
coerce.coerce(self, Some(arm.expr), &arm_ty);
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
|
2020-05-08 15:36:11 +00:00
|
|
|
self.diverges = matchee_diverges | all_arms_diverge;
|
|
|
|
|
2021-07-08 12:16:23 +00:00
|
|
|
coerce.complete()
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
Expr::Path(p) => {
|
|
|
|
// FIXME this could be more efficient...
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
|
2021-06-18 11:40:51 +00:00
|
|
|
self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or_else(|| self.err_ty())
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-09-01 12:30:57 +00:00
|
|
|
Expr::Continue { label } => {
|
2022-09-01 12:54:47 +00:00
|
|
|
if let None = find_continuable(&mut self.breakables, label.as_ref()) {
|
2022-09-01 12:30:57 +00:00
|
|
|
self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
|
|
|
|
expr: tgt_expr,
|
|
|
|
is_break: false,
|
|
|
|
});
|
|
|
|
};
|
2023-02-10 15:08:47 +00:00
|
|
|
self.result.standard_types.never.clone()
|
2022-09-01 12:30:57 +00:00
|
|
|
}
|
2020-05-31 08:59:40 +00:00
|
|
|
Expr::Break { expr, label } => {
|
2021-07-09 12:56:49 +00:00
|
|
|
let val_ty = if let Some(expr) = *expr {
|
2021-07-08 12:16:23 +00:00
|
|
|
self.infer_expr(expr, &Expectation::none())
|
2021-05-21 15:48:15 +00:00
|
|
|
} else {
|
|
|
|
TyBuilder::unit()
|
|
|
|
};
|
|
|
|
|
2022-09-03 15:08:18 +00:00
|
|
|
match find_breakable(&mut self.breakables, label.as_ref()) {
|
|
|
|
Some(ctxt) => {
|
|
|
|
// avoiding the borrowck
|
|
|
|
let mut coerce = mem::replace(
|
|
|
|
&mut ctxt.coerce,
|
2023-02-10 15:08:47 +00:00
|
|
|
CoerceMany::new(expected.coercion_target_type(&mut self.table)),
|
2022-09-03 15:08:18 +00:00
|
|
|
);
|
2020-05-18 21:39:10 +00:00
|
|
|
|
2022-09-03 15:08:18 +00:00
|
|
|
// FIXME: create a synthetic `()` during lowering so we have something to refer to here?
|
|
|
|
coerce.coerce(self, *expr, &val_ty);
|
2021-07-09 12:56:49 +00:00
|
|
|
|
2022-09-03 15:08:18 +00:00
|
|
|
let ctxt = find_breakable(&mut self.breakables, label.as_ref())
|
|
|
|
.expect("breakable stack changed during coercion");
|
|
|
|
ctxt.coerce = coerce;
|
|
|
|
ctxt.may_break = true;
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
|
|
|
|
expr: tgt_expr,
|
|
|
|
is_break: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2023-02-10 15:08:47 +00:00
|
|
|
self.result.standard_types.never.clone()
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
Expr::Return { expr } => {
|
|
|
|
if let Some(expr) = expr {
|
2019-12-05 22:02:31 +00:00
|
|
|
self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone()));
|
2019-12-20 15:41:32 +00:00
|
|
|
} else {
|
2021-04-03 18:22:59 +00:00
|
|
|
let unit = TyBuilder::unit();
|
2021-07-08 12:16:23 +00:00
|
|
|
let _ = self.coerce(Some(tgt_expr), &unit, &self.return_ty.clone());
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2023-02-10 15:08:47 +00:00
|
|
|
self.result.standard_types.never.clone()
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2021-01-13 15:01:50 +00:00
|
|
|
Expr::Yield { expr } => {
|
2022-09-06 08:48:06 +00:00
|
|
|
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
|
|
|
|
if let Some(expr) = expr {
|
|
|
|
self.infer_expr_coerce(*expr, &Expectation::has_type(yield_ty));
|
|
|
|
} else {
|
|
|
|
let unit = self.result.standard_types.unit.clone();
|
|
|
|
let _ = self.coerce(Some(tgt_expr), &unit, &yield_ty);
|
|
|
|
}
|
|
|
|
resume_ty
|
|
|
|
} else {
|
|
|
|
// FIXME: report error (yield expr in non-generator)
|
2023-02-10 15:08:47 +00:00
|
|
|
self.result.standard_types.unknown.clone()
|
2021-01-13 15:01:50 +00:00
|
|
|
}
|
|
|
|
}
|
2022-12-28 23:17:13 +00:00
|
|
|
Expr::Yeet { expr } => {
|
|
|
|
if let &Some(expr) = expr {
|
|
|
|
self.infer_expr_inner(expr, &Expectation::None);
|
|
|
|
}
|
2023-02-10 15:08:47 +00:00
|
|
|
self.result.standard_types.never.clone()
|
2022-12-28 23:17:13 +00:00
|
|
|
}
|
2022-07-22 09:12:21 +00:00
|
|
|
Expr::RecordLit { path, fields, spread, .. } => {
|
2021-07-22 11:40:18 +00:00
|
|
|
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
|
2019-10-12 15:39:20 +00:00
|
|
|
if let Some(variant) = def_id {
|
|
|
|
self.write_variant_resolution(tgt_expr.into(), variant);
|
|
|
|
}
|
|
|
|
|
2021-05-21 15:41:20 +00:00
|
|
|
if let Some(t) = expected.only_has_type(&mut self.table) {
|
|
|
|
self.unify(&ty, &t);
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2021-04-07 15:26:01 +00:00
|
|
|
let substs = ty
|
|
|
|
.as_adt()
|
|
|
|
.map(|(_, s)| s.clone())
|
2021-12-19 16:58:39 +00:00
|
|
|
.unwrap_or_else(|| Substitution::empty(Interner));
|
2020-02-18 12:53:02 +00:00
|
|
|
let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default();
|
2021-04-06 15:59:18 +00:00
|
|
|
let variant_data = def_id.map(|it| it.variant_data(self.db.upcast()));
|
2021-03-15 12:38:50 +00:00
|
|
|
for field in fields.iter() {
|
2019-11-27 13:25:01 +00:00
|
|
|
let field_def =
|
|
|
|
variant_data.as_ref().and_then(|it| match it.field(&field.name) {
|
2020-04-25 12:23:34 +00:00
|
|
|
Some(local_id) => Some(FieldId { parent: def_id.unwrap(), local_id }),
|
2019-11-27 13:25:01 +00:00
|
|
|
None => {
|
|
|
|
self.push_diagnostic(InferenceDiagnostic::NoSuchField {
|
2021-03-15 12:38:50 +00:00
|
|
|
expr: field.expr,
|
2019-11-27 13:25:01 +00:00
|
|
|
});
|
|
|
|
None
|
|
|
|
}
|
|
|
|
});
|
2021-03-13 13:44:51 +00:00
|
|
|
let field_ty = field_def.map_or(self.err_ty(), |it| {
|
2021-12-19 16:58:39 +00:00
|
|
|
field_types[it.local_id].clone().substitute(Interner, &substs)
|
2021-03-13 13:44:51 +00:00
|
|
|
});
|
2019-10-12 15:39:20 +00:00
|
|
|
self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
|
|
|
|
}
|
|
|
|
if let Some(expr) = spread {
|
|
|
|
self.infer_expr(*expr, &Expectation::has_type(ty.clone()));
|
|
|
|
}
|
|
|
|
ty
|
|
|
|
}
|
|
|
|
Expr::Field { expr, name } => {
|
2019-12-05 22:02:31 +00:00
|
|
|
let receiver_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
|
|
|
|
let mut autoderef = Autoderef::new(&mut self.table, receiver_ty);
|
2022-12-31 13:20:59 +00:00
|
|
|
let mut private_field = None;
|
2021-07-09 17:12:56 +00:00
|
|
|
let ty = autoderef.by_ref().find_map(|(derefed_ty, _)| {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let (field_id, parameters) = match derefed_ty.kind(Interner) {
|
|
|
|
TyKind::Tuple(_, substs) => {
|
|
|
|
return name.as_tuple_index().and_then(|idx| {
|
|
|
|
substs
|
|
|
|
.as_slice(Interner)
|
|
|
|
.get(idx)
|
|
|
|
.map(|a| a.assert_ty_ref(Interner))
|
|
|
|
.cloned()
|
|
|
|
});
|
|
|
|
}
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
|
2021-03-20 18:07:23 +00:00
|
|
|
let local_id = self.db.struct_data(*s).variant_data.field(name)?;
|
|
|
|
let field = FieldId { parent: (*s).into(), local_id };
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
(field, parameters.clone())
|
2021-03-13 13:44:51 +00:00
|
|
|
}
|
|
|
|
TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => {
|
2021-03-20 18:07:23 +00:00
|
|
|
let local_id = self.db.union_data(*u).variant_data.field(name)?;
|
|
|
|
let field = FieldId { parent: (*u).into(), local_id };
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
(field, parameters.clone())
|
2021-03-13 13:44:51 +00:00
|
|
|
}
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
_ => return None,
|
|
|
|
};
|
2022-03-31 09:12:08 +00:00
|
|
|
let is_visible = self.db.field_visibilities(field_id.parent)[field_id.local_id]
|
|
|
|
.is_visible_from(self.db.upcast(), self.resolver.module());
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
if !is_visible {
|
2022-12-31 13:20:59 +00:00
|
|
|
if private_field.is_none() {
|
|
|
|
private_field = Some(field_id);
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
}
|
|
|
|
return None;
|
2021-02-28 18:13:37 +00:00
|
|
|
}
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
// can't have `write_field_resolution` here because `self.table` is borrowed :(
|
|
|
|
self.result.field_resolutions.insert(tgt_expr, field_id);
|
|
|
|
let ty = self.db.field_types(field_id.parent)[field_id.local_id]
|
|
|
|
.clone()
|
|
|
|
.substitute(Interner, ¶meters);
|
|
|
|
Some(ty)
|
2021-07-09 17:12:56 +00:00
|
|
|
});
|
|
|
|
let ty = match ty {
|
|
|
|
Some(ty) => {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let adjustments = auto_deref_adjust_steps(&autoderef);
|
|
|
|
self.write_expr_adj(*expr, adjustments);
|
|
|
|
let ty = self.insert_type_vars(ty);
|
|
|
|
let ty = self.normalize_associated_types_in(ty);
|
2021-07-09 17:12:56 +00:00
|
|
|
ty
|
|
|
|
}
|
2022-12-31 13:20:59 +00:00
|
|
|
_ => {
|
|
|
|
// Write down the first private field resolution if we found no field
|
|
|
|
// This aids IDE features for private fields like goto def
|
|
|
|
if let Some(field) = private_field {
|
|
|
|
self.result.field_resolutions.insert(tgt_expr, field);
|
|
|
|
self.result
|
|
|
|
.diagnostics
|
|
|
|
.push(InferenceDiagnostic::PrivateField { expr: tgt_expr, field });
|
|
|
|
}
|
|
|
|
self.err_ty()
|
|
|
|
}
|
2021-07-09 17:12:56 +00:00
|
|
|
};
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
ty
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
Expr::Await { expr } => {
|
2019-12-05 22:02:31 +00:00
|
|
|
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
2020-02-18 13:32:19 +00:00
|
|
|
self.resolve_associated_type(inner_ty, self.resolve_future_future_output())
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-10-18 12:18:59 +00:00
|
|
|
Expr::Try { expr } => {
|
|
|
|
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
2023-01-27 10:25:34 +00:00
|
|
|
if let Some(trait_) = self.resolve_lang_trait(LangItem::Try) {
|
|
|
|
if let Some(func) = self.db.trait_data(trait_).method_by_name(&name!(branch)) {
|
|
|
|
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
|
|
|
|
.push(inner_ty.clone())
|
|
|
|
.build();
|
|
|
|
self.write_method_resolution(tgt_expr, func, subst.clone());
|
|
|
|
}
|
|
|
|
let try_output = self.resolve_output_on(trait_);
|
|
|
|
self.resolve_associated_type(inner_ty, try_output)
|
|
|
|
} else {
|
|
|
|
self.err_ty()
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
Expr::Cast { expr, type_ref } => {
|
|
|
|
let cast_ty = self.make_ty(type_ref);
|
2023-02-10 15:08:47 +00:00
|
|
|
// FIXME: propagate the "castable to" expectation
|
|
|
|
let _inner_ty = self.infer_expr_inner(*expr, &Expectation::None);
|
2019-10-12 15:39:20 +00:00
|
|
|
// FIXME check the cast...
|
|
|
|
cast_ty
|
|
|
|
}
|
2020-05-28 19:42:22 +00:00
|
|
|
Expr::Ref { expr, rawness, mutability } => {
|
2021-03-01 18:30:34 +00:00
|
|
|
let mutability = lower_to_chalk_mutability(*mutability);
|
2021-05-21 15:41:20 +00:00
|
|
|
let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = expected
|
|
|
|
.only_has_type(&mut self.table)
|
|
|
|
.as_ref()
|
|
|
|
.and_then(|t| t.as_reference_or_ptr())
|
2020-05-28 19:42:22 +00:00
|
|
|
{
|
2021-05-21 15:41:20 +00:00
|
|
|
if exp_mutability == Mutability::Mut && mutability == Mutability::Not {
|
2021-05-16 15:56:38 +00:00
|
|
|
// FIXME: record type error - expected mut reference but found shared ref,
|
2020-05-28 19:42:22 +00:00
|
|
|
// which cannot be coerced
|
|
|
|
}
|
2021-05-21 15:41:20 +00:00
|
|
|
if exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr {
|
2021-05-16 15:56:38 +00:00
|
|
|
// FIXME: record type error - expected reference but found ptr,
|
2020-05-28 19:42:22 +00:00
|
|
|
// which cannot be coerced
|
|
|
|
}
|
2021-07-15 18:02:58 +00:00
|
|
|
Expectation::rvalue_hint(&mut self.table, Ty::clone(exp_inner))
|
2020-05-28 19:42:22 +00:00
|
|
|
} else {
|
|
|
|
Expectation::none()
|
|
|
|
};
|
2019-12-05 22:02:31 +00:00
|
|
|
let inner_ty = self.infer_expr_inner(*expr, &expectation);
|
2021-02-28 18:13:37 +00:00
|
|
|
match rawness {
|
2021-03-14 16:40:55 +00:00
|
|
|
Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
|
2021-04-06 08:50:55 +00:00
|
|
|
Rawness::Ref => TyKind::Ref(mutability, static_lifetime(), inner_ty),
|
2021-02-28 18:13:37 +00:00
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-05-15 13:14:11 +00:00
|
|
|
&Expr::Box { expr } => self.infer_expr_box(expr, expected),
|
2019-10-12 15:39:20 +00:00
|
|
|
Expr::UnaryOp { expr, op } => {
|
2019-12-05 22:02:31 +00:00
|
|
|
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
2021-05-16 15:56:38 +00:00
|
|
|
let inner_ty = self.resolve_ty_shallow(&inner_ty);
|
2023-01-27 10:06:41 +00:00
|
|
|
// FIXME: Note down method resolution her
|
2019-10-12 15:39:20 +00:00
|
|
|
match op {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
UnaryOp::Deref => {
|
|
|
|
autoderef::deref(&mut self.table, inner_ty).unwrap_or_else(|| self.err_ty())
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
UnaryOp::Neg => {
|
2021-12-19 16:58:39 +00:00
|
|
|
match inner_ty.kind(Interner) {
|
2019-12-13 11:44:42 +00:00
|
|
|
// Fast path for builtins
|
2021-06-17 15:37:14 +00:00
|
|
|
TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_))
|
|
|
|
| TyKind::InferenceVar(
|
|
|
|
_,
|
|
|
|
TyVariableKind::Integer | TyVariableKind::Float,
|
|
|
|
) => inner_ty,
|
2019-12-13 11:44:42 +00:00
|
|
|
// Otherwise we resolve via the std::ops::Neg trait
|
|
|
|
_ => self
|
|
|
|
.resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
UnaryOp::Not => {
|
2021-12-19 16:58:39 +00:00
|
|
|
match inner_ty.kind(Interner) {
|
2019-12-13 11:44:42 +00:00
|
|
|
// Fast path for builtins
|
2021-06-17 15:37:14 +00:00
|
|
|
TyKind::Scalar(Scalar::Bool | Scalar::Int(_) | Scalar::Uint(_))
|
2021-03-13 13:44:51 +00:00
|
|
|
| TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty,
|
2019-12-13 11:44:42 +00:00
|
|
|
// Otherwise we resolve via the std::ops::Not trait
|
|
|
|
_ => self
|
|
|
|
.resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Expr::BinaryOp { lhs, rhs, op } => match op {
|
2021-08-22 15:21:47 +00:00
|
|
|
Some(BinaryOp::Assignment { op: None }) => {
|
2022-07-02 16:57:23 +00:00
|
|
|
let lhs = *lhs;
|
|
|
|
let is_ordinary = match &self.body[lhs] {
|
|
|
|
Expr::Array(_)
|
|
|
|
| Expr::RecordLit { .. }
|
|
|
|
| Expr::Tuple { .. }
|
|
|
|
| Expr::Underscore => false,
|
|
|
|
Expr::Call { callee, .. } => !matches!(&self.body[*callee], Expr::Path(_)),
|
|
|
|
_ => true,
|
|
|
|
};
|
|
|
|
|
|
|
|
// In ordinary (non-destructuring) assignments, the type of
|
|
|
|
// `lhs` must be inferred first so that the ADT fields
|
|
|
|
// instantiations in RHS can be coerced to it. Note that this
|
|
|
|
// cannot happen in destructuring assignments because of how
|
|
|
|
// they are desugared.
|
|
|
|
if is_ordinary {
|
|
|
|
let lhs_ty = self.infer_expr(lhs, &Expectation::none());
|
|
|
|
self.infer_expr_coerce(*rhs, &Expectation::has_type(lhs_ty));
|
|
|
|
} else {
|
|
|
|
let rhs_ty = self.infer_expr(*rhs, &Expectation::none());
|
|
|
|
self.infer_assignee_expr(lhs, &rhs_ty);
|
|
|
|
}
|
2021-08-22 15:21:47 +00:00
|
|
|
self.result.standard_types.unit.clone()
|
|
|
|
}
|
|
|
|
Some(BinaryOp::LogicOp(_)) => {
|
|
|
|
let bool_ty = self.result.standard_types.bool_.clone();
|
|
|
|
self.infer_expr_coerce(*lhs, &Expectation::HasType(bool_ty.clone()));
|
|
|
|
let lhs_diverges = self.diverges;
|
|
|
|
self.infer_expr_coerce(*rhs, &Expectation::HasType(bool_ty.clone()));
|
|
|
|
// Depending on the LHS' value, the RHS can never execute.
|
|
|
|
self.diverges = lhs_diverges;
|
|
|
|
bool_ty
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2021-08-22 15:21:47 +00:00
|
|
|
Some(op) => self.infer_overloadable_binop(*lhs, *op, *rhs, tgt_expr),
|
2021-03-13 13:44:51 +00:00
|
|
|
_ => self.err_ty(),
|
2019-10-12 15:39:20 +00:00
|
|
|
},
|
2019-11-29 06:49:12 +00:00
|
|
|
Expr::Range { lhs, rhs, range_type } => {
|
2019-12-05 22:02:31 +00:00
|
|
|
let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none()));
|
2019-11-29 06:49:12 +00:00
|
|
|
let rhs_expect = lhs_ty
|
|
|
|
.as_ref()
|
|
|
|
.map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone()));
|
|
|
|
let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
|
|
|
|
match (range_type, lhs_ty, rhs_ty) {
|
|
|
|
(RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
|
2021-04-03 19:29:49 +00:00
|
|
|
Some(adt) => TyBuilder::adt(self.db, adt).build(),
|
2021-03-13 13:44:51 +00:00
|
|
|
None => self.err_ty(),
|
2019-11-29 06:49:12 +00:00
|
|
|
},
|
|
|
|
(RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
|
2021-04-03 19:29:49 +00:00
|
|
|
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
|
2021-03-13 13:44:51 +00:00
|
|
|
None => self.err_ty(),
|
2019-11-29 06:49:12 +00:00
|
|
|
},
|
|
|
|
(RangeOp::Inclusive, None, Some(ty)) => {
|
|
|
|
match self.resolve_range_to_inclusive() {
|
2021-04-03 19:29:49 +00:00
|
|
|
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
|
2021-03-13 13:44:51 +00:00
|
|
|
None => self.err_ty(),
|
2019-11-29 06:49:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
(RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
|
2021-04-03 19:29:49 +00:00
|
|
|
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
|
2021-03-13 13:44:51 +00:00
|
|
|
None => self.err_ty(),
|
2019-11-29 06:49:12 +00:00
|
|
|
},
|
|
|
|
(RangeOp::Inclusive, Some(_), Some(ty)) => {
|
|
|
|
match self.resolve_range_inclusive() {
|
2021-04-03 19:29:49 +00:00
|
|
|
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
|
2021-03-13 13:44:51 +00:00
|
|
|
None => self.err_ty(),
|
2019-11-29 06:49:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
(RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
|
2021-04-03 19:29:49 +00:00
|
|
|
Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
|
2021-03-13 13:44:51 +00:00
|
|
|
None => self.err_ty(),
|
2019-11-29 06:49:12 +00:00
|
|
|
},
|
2021-03-13 13:44:51 +00:00
|
|
|
(RangeOp::Inclusive, _, None) => self.err_ty(),
|
2019-11-28 19:10:16 +00:00
|
|
|
}
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
Expr::Index { base, index } => {
|
2019-12-19 04:45:07 +00:00
|
|
|
let base_ty = self.infer_expr_inner(*base, &Expectation::none());
|
|
|
|
let index_ty = self.infer_expr(*index, &Expectation::none());
|
|
|
|
|
2023-01-27 10:25:34 +00:00
|
|
|
if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let canonicalized = self.canonicalize(base_ty.clone());
|
|
|
|
let receiver_adjustments = method_resolution::resolve_indexing_op(
|
2020-02-29 21:48:23 +00:00
|
|
|
self.db,
|
|
|
|
self.trait_env.clone(),
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
canonicalized.value,
|
2020-02-29 21:48:23 +00:00
|
|
|
index_trait,
|
|
|
|
);
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let (self_ty, adj) = receiver_adjustments
|
|
|
|
.map_or((self.err_ty(), Vec::new()), |adj| {
|
|
|
|
adj.apply(&mut self.table, base_ty)
|
|
|
|
});
|
|
|
|
self.write_expr_adj(*base, adj);
|
2023-01-27 10:15:05 +00:00
|
|
|
if let Some(func) =
|
|
|
|
self.db.trait_data(index_trait).method_by_name(&name!(index))
|
|
|
|
{
|
|
|
|
let substs = TyBuilder::subst_for_def(self.db, index_trait, None)
|
|
|
|
.push(self_ty.clone())
|
|
|
|
.push(index_ty.clone())
|
|
|
|
.build();
|
|
|
|
self.write_method_resolution(tgt_expr, func, substs.clone());
|
|
|
|
}
|
2020-02-29 21:48:23 +00:00
|
|
|
self.resolve_associated_type_with_params(
|
|
|
|
self_ty,
|
|
|
|
self.resolve_ops_index_output(),
|
2022-03-09 18:50:24 +00:00
|
|
|
&[GenericArgData::Ty(index_ty).intern(Interner)],
|
2020-02-29 21:48:23 +00:00
|
|
|
)
|
|
|
|
} else {
|
2021-03-13 13:44:51 +00:00
|
|
|
self.err_ty()
|
2020-02-29 21:48:23 +00:00
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-07-24 13:32:49 +00:00
|
|
|
Expr::Tuple { exprs, .. } => {
|
2021-05-21 15:41:20 +00:00
|
|
|
let mut tys = match expected
|
|
|
|
.only_has_type(&mut self.table)
|
|
|
|
.as_ref()
|
2021-12-19 16:58:39 +00:00
|
|
|
.map(|t| t.kind(Interner))
|
2021-05-21 15:41:20 +00:00
|
|
|
{
|
|
|
|
Some(TyKind::Tuple(_, substs)) => substs
|
2021-12-19 16:58:39 +00:00
|
|
|
.iter(Interner)
|
|
|
|
.map(|a| a.assert_ty_ref(Interner).clone())
|
2019-12-01 19:30:28 +00:00
|
|
|
.chain(repeat_with(|| self.table.new_type_var()))
|
2019-10-12 15:39:20 +00:00
|
|
|
.take(exprs.len())
|
|
|
|
.collect::<Vec<_>>(),
|
2019-12-01 19:30:28 +00:00
|
|
|
_ => (0..exprs.len()).map(|_| self.table.new_type_var()).collect(),
|
2019-10-12 15:39:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
for (expr, ty) in exprs.iter().zip(tys.iter_mut()) {
|
|
|
|
self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone()));
|
|
|
|
}
|
|
|
|
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Tuple(tys.len(), Substitution::from_iter(Interner, tys)).intern(Interner)
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
Expr::Array(array) => {
|
2021-07-08 12:16:23 +00:00
|
|
|
let elem_ty =
|
2021-12-19 16:58:39 +00:00
|
|
|
match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(Interner)) {
|
2021-06-17 15:37:14 +00:00
|
|
|
Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st.clone(),
|
2021-05-21 15:41:20 +00:00
|
|
|
_ => self.table.new_type_var(),
|
|
|
|
};
|
2021-07-08 12:16:23 +00:00
|
|
|
let mut coerce = CoerceMany::new(elem_ty.clone());
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2021-07-08 08:22:29 +00:00
|
|
|
let expected = Expectation::has_type(elem_ty.clone());
|
2021-05-11 12:06:33 +00:00
|
|
|
let len = match array {
|
2022-07-24 13:32:49 +00:00
|
|
|
Array::ElementList { elements, .. } => {
|
|
|
|
for &expr in elements.iter() {
|
2021-07-08 12:16:23 +00:00
|
|
|
let cur_elem_ty = self.infer_expr_inner(expr, &expected);
|
|
|
|
coerce.coerce(self, Some(expr), &cur_elem_ty);
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-07-24 13:32:49 +00:00
|
|
|
consteval::usize_const(Some(elements.len() as u128))
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2021-07-08 12:16:23 +00:00
|
|
|
&Array::Repeat { initializer, repeat } => {
|
|
|
|
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
|
2019-10-12 15:39:20 +00:00
|
|
|
self.infer_expr(
|
2021-07-08 12:16:23 +00:00
|
|
|
repeat,
|
2023-02-10 15:08:47 +00:00
|
|
|
&Expectation::HasType(
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
|
2021-03-13 13:44:51 +00:00
|
|
|
),
|
2019-10-12 15:39:20 +00:00
|
|
|
);
|
2021-05-12 12:59:35 +00:00
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
if let Some(g_def) = self.owner.as_generic_def_id() {
|
|
|
|
let generics = generics(self.db.upcast(), g_def);
|
|
|
|
consteval::eval_to_const(
|
|
|
|
repeat,
|
|
|
|
ParamLoweringMode::Placeholder,
|
|
|
|
self,
|
|
|
|
|| generics,
|
|
|
|
DebruijnIndex::INNERMOST,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
consteval::usize_const(None)
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2021-05-11 12:06:33 +00:00
|
|
|
};
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
TyKind::Array(coerce.complete(), len).intern(Interner)
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
Expr::Literal(lit) => match lit {
|
2023-02-10 15:08:47 +00:00
|
|
|
Literal::Bool(..) => self.result.standard_types.bool_.clone(),
|
2021-04-06 08:50:55 +00:00
|
|
|
Literal::String(..) => {
|
2021-12-19 16:58:39 +00:00
|
|
|
TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner))
|
|
|
|
.intern(Interner)
|
2021-04-06 08:50:55 +00:00
|
|
|
}
|
2021-05-12 12:44:01 +00:00
|
|
|
Literal::ByteString(bs) => {
|
2021-12-19 16:58:39 +00:00
|
|
|
let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
|
2021-05-11 12:06:33 +00:00
|
|
|
|
2022-07-17 01:18:53 +00:00
|
|
|
let len = consteval::usize_const(Some(bs.len() as u128));
|
2021-05-12 12:44:01 +00:00
|
|
|
|
2021-12-19 16:58:39 +00:00
|
|
|
let array_type = TyKind::Array(byte_type, len).intern(Interner);
|
|
|
|
TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(Interner)
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(Interner),
|
2020-06-06 15:52:00 +00:00
|
|
|
Literal::Int(_v, ty) => match ty {
|
2021-02-28 18:13:37 +00:00
|
|
|
Some(int_ty) => {
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2021-02-28 18:13:37 +00:00
|
|
|
}
|
2021-02-28 00:20:04 +00:00
|
|
|
None => self.table.new_integer_var(),
|
|
|
|
},
|
|
|
|
Literal::Uint(_v, ty) => match ty {
|
2021-02-28 18:13:37 +00:00
|
|
|
Some(int_ty) => {
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2021-02-28 18:13:37 +00:00
|
|
|
}
|
2020-06-06 15:52:00 +00:00
|
|
|
None => self.table.new_integer_var(),
|
|
|
|
},
|
|
|
|
Literal::Float(_v, ty) => match ty {
|
2021-02-28 18:13:37 +00:00
|
|
|
Some(float_ty) => {
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner)
|
2021-02-28 18:13:37 +00:00
|
|
|
}
|
2020-06-06 15:52:00 +00:00
|
|
|
None => self.table.new_float_var(),
|
|
|
|
},
|
2019-10-12 15:39:20 +00:00
|
|
|
},
|
2022-05-26 17:14:06 +00:00
|
|
|
Expr::Underscore => {
|
|
|
|
// Underscore expressions may only appear in assignee expressions,
|
|
|
|
// which are handled by `infer_assignee_expr()`, so any underscore
|
|
|
|
// expression reaching this branch is an error.
|
|
|
|
self.err_ty()
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
};
|
2021-03-13 13:44:51 +00:00
|
|
|
// use a new type variable if we got unknown here
|
2019-10-12 15:39:20 +00:00
|
|
|
let ty = self.insert_type_vars_shallow(ty);
|
|
|
|
self.write_expr_ty(tgt_expr, ty.clone());
|
2022-03-29 19:55:34 +00:00
|
|
|
if self.resolve_ty_shallow(&ty).is_never() {
|
|
|
|
// Any expression that produces a value of type `!` must have diverged
|
|
|
|
self.diverges = Diverges::Always;
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
ty
|
|
|
|
}
|
|
|
|
|
2022-05-15 13:14:11 +00:00
|
|
|
fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation) -> Ty {
|
|
|
|
if let Some(box_id) = self.resolve_boxed_box() {
|
|
|
|
let table = &mut self.table;
|
|
|
|
let inner_exp = expected
|
|
|
|
.to_option(table)
|
|
|
|
.as_ref()
|
|
|
|
.map(|e| e.as_adt())
|
|
|
|
.flatten()
|
|
|
|
.filter(|(e_adt, _)| e_adt == &box_id)
|
|
|
|
.map(|(_, subts)| {
|
|
|
|
let g = subts.at(Interner, 0);
|
|
|
|
Expectation::rvalue_hint(table, Ty::clone(g.assert_ty_ref(Interner)))
|
|
|
|
})
|
|
|
|
.unwrap_or_else(Expectation::none);
|
|
|
|
|
|
|
|
let inner_ty = self.infer_expr_inner(inner_expr, &inner_exp);
|
|
|
|
TyBuilder::adt(self.db, box_id)
|
2022-04-15 19:44:47 +00:00
|
|
|
.push(inner_ty)
|
|
|
|
.fill_with_defaults(self.db, || self.table.new_type_var())
|
|
|
|
.build()
|
|
|
|
} else {
|
|
|
|
self.err_ty()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-31 13:15:01 +00:00
|
|
|
pub(super) fn infer_assignee_expr(&mut self, lhs: ExprId, rhs_ty: &Ty) -> Ty {
|
|
|
|
let is_rest_expr = |expr| {
|
|
|
|
matches!(
|
|
|
|
&self.body[expr],
|
|
|
|
Expr::Range { lhs: None, rhs: None, range_type: RangeOp::Exclusive },
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let rhs_ty = self.resolve_ty_shallow(rhs_ty);
|
|
|
|
|
|
|
|
let ty = match &self.body[lhs] {
|
2022-07-24 13:32:49 +00:00
|
|
|
Expr::Tuple { exprs, .. } => {
|
2022-05-31 13:15:01 +00:00
|
|
|
// We don't consider multiple ellipses. This is analogous to
|
|
|
|
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
|
|
|
|
let ellipsis = exprs.iter().position(|e| is_rest_expr(*e));
|
|
|
|
let exprs: Vec<_> = exprs.iter().filter(|e| !is_rest_expr(**e)).copied().collect();
|
|
|
|
|
|
|
|
self.infer_tuple_pat_like(&rhs_ty, (), ellipsis, &exprs)
|
|
|
|
}
|
2022-07-24 13:32:49 +00:00
|
|
|
Expr::Call { callee, args, .. } => {
|
2022-05-31 13:15:01 +00:00
|
|
|
// Tuple structs
|
|
|
|
let path = match &self.body[*callee] {
|
|
|
|
Expr::Path(path) => Some(path),
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
|
|
|
|
// We don't consider multiple ellipses. This is analogous to
|
|
|
|
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
|
|
|
|
let ellipsis = args.iter().position(|e| is_rest_expr(*e));
|
|
|
|
let args: Vec<_> = args.iter().filter(|e| !is_rest_expr(**e)).copied().collect();
|
|
|
|
|
|
|
|
self.infer_tuple_struct_pat_like(path, &rhs_ty, (), lhs, ellipsis, &args)
|
|
|
|
}
|
2022-07-24 13:32:49 +00:00
|
|
|
Expr::Array(Array::ElementList { elements, .. }) => {
|
2022-05-31 13:15:01 +00:00
|
|
|
let elem_ty = match rhs_ty.kind(Interner) {
|
|
|
|
TyKind::Array(st, _) => st.clone(),
|
|
|
|
_ => self.err_ty(),
|
|
|
|
};
|
|
|
|
|
|
|
|
// There's no need to handle `..` as it cannot be bound.
|
|
|
|
let sub_exprs = elements.iter().filter(|e| !is_rest_expr(**e));
|
|
|
|
|
|
|
|
for e in sub_exprs {
|
|
|
|
self.infer_assignee_expr(*e, &elem_ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
match rhs_ty.kind(Interner) {
|
|
|
|
TyKind::Array(_, _) => rhs_ty.clone(),
|
|
|
|
// Even when `rhs_ty` is not an array type, this assignee
|
2022-07-02 15:19:06 +00:00
|
|
|
// expression is inferred to be an array (of unknown element
|
2022-05-31 13:15:01 +00:00
|
|
|
// type and length). This should not be just an error type,
|
|
|
|
// because we are to compute the unifiability of this type and
|
|
|
|
// `rhs_ty` in the end of this function to issue type mismatches.
|
|
|
|
_ => TyKind::Array(self.err_ty(), crate::consteval::usize_const(None))
|
|
|
|
.intern(Interner),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Expr::RecordLit { path, fields, .. } => {
|
|
|
|
let subs = fields.iter().map(|f| (f.name.clone(), f.expr));
|
|
|
|
|
2022-12-30 08:42:44 +00:00
|
|
|
self.infer_record_pat_like(path.as_deref(), &rhs_ty, (), lhs, subs)
|
2022-05-31 13:15:01 +00:00
|
|
|
}
|
|
|
|
Expr::Underscore => rhs_ty.clone(),
|
|
|
|
_ => {
|
|
|
|
// `lhs` is a place expression, a unit struct, or an enum variant.
|
|
|
|
let lhs_ty = self.infer_expr(lhs, &Expectation::none());
|
|
|
|
|
|
|
|
// This is the only branch where this function may coerce any type.
|
|
|
|
// We are returning early to avoid the unifiability check below.
|
|
|
|
let lhs_ty = self.insert_type_vars_shallow(lhs_ty);
|
|
|
|
let ty = match self.coerce(None, &rhs_ty, &lhs_ty) {
|
|
|
|
Ok(ty) => ty,
|
2022-07-02 17:31:07 +00:00
|
|
|
Err(_) => {
|
|
|
|
self.result.type_mismatches.insert(
|
|
|
|
lhs.into(),
|
|
|
|
TypeMismatch { expected: rhs_ty.clone(), actual: lhs_ty.clone() },
|
|
|
|
);
|
|
|
|
// `rhs_ty` is returned so no further type mismatches are
|
|
|
|
// reported because of this mismatch.
|
|
|
|
rhs_ty
|
|
|
|
}
|
2022-05-31 13:15:01 +00:00
|
|
|
};
|
|
|
|
self.write_expr_ty(lhs, ty.clone());
|
|
|
|
return ty;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let ty = self.insert_type_vars_shallow(ty);
|
|
|
|
if !self.unify(&ty, &rhs_ty) {
|
|
|
|
self.result
|
|
|
|
.type_mismatches
|
|
|
|
.insert(lhs.into(), TypeMismatch { expected: rhs_ty.clone(), actual: ty.clone() });
|
|
|
|
}
|
|
|
|
self.write_expr_ty(lhs, ty.clone());
|
|
|
|
ty
|
|
|
|
}
|
|
|
|
|
2021-08-22 15:21:47 +00:00
|
|
|
fn infer_overloadable_binop(
|
|
|
|
&mut self,
|
|
|
|
lhs: ExprId,
|
|
|
|
op: BinaryOp,
|
|
|
|
rhs: ExprId,
|
|
|
|
tgt_expr: ExprId,
|
|
|
|
) -> Ty {
|
|
|
|
let lhs_expectation = Expectation::none();
|
|
|
|
let lhs_ty = self.infer_expr(lhs, &lhs_expectation);
|
|
|
|
let rhs_ty = self.table.new_type_var();
|
|
|
|
|
2023-01-21 16:29:07 +00:00
|
|
|
let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
|
2022-10-02 13:15:57 +00:00
|
|
|
let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
|
|
|
|
let func = self.db.trait_data(trait_id).method_by_name(&name)?;
|
|
|
|
Some((trait_id, func))
|
2022-08-05 12:16:36 +00:00
|
|
|
});
|
2022-10-02 13:15:57 +00:00
|
|
|
let (trait_, func) = match trait_func {
|
|
|
|
Some(it) => it,
|
2021-08-22 15:21:47 +00:00
|
|
|
None => {
|
2023-01-17 10:51:48 +00:00
|
|
|
// HACK: `rhs_ty` is a general inference variable with no clue at all at this
|
|
|
|
// point. Passing `lhs_ty` as both operands just to check if `lhs_ty` is a builtin
|
|
|
|
// type applicable to `op`.
|
|
|
|
let ret_ty = if self.is_builtin_binop(&lhs_ty, &lhs_ty, op) {
|
|
|
|
// Assume both operands are builtin so we can continue inference. No guarantee
|
|
|
|
// on the correctness, rustc would complain as necessary lang items don't seem
|
|
|
|
// to exist anyway.
|
|
|
|
self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op)
|
|
|
|
} else {
|
|
|
|
self.err_ty()
|
|
|
|
};
|
|
|
|
|
|
|
|
self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty));
|
|
|
|
|
|
|
|
return ret_ty;
|
2021-08-22 15:21:47 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-10-02 13:15:57 +00:00
|
|
|
// HACK: We can use this substitution for the function because the function itself doesn't
|
|
|
|
// have its own generic parameters.
|
|
|
|
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
|
2021-08-22 15:21:47 +00:00
|
|
|
.push(lhs_ty.clone())
|
|
|
|
.push(rhs_ty.clone())
|
|
|
|
.build();
|
|
|
|
self.write_method_resolution(tgt_expr, func, subst.clone());
|
|
|
|
|
2021-12-19 16:58:39 +00:00
|
|
|
let method_ty = self.db.value_ty(func.into()).substitute(Interner, &subst);
|
2021-08-22 15:21:47 +00:00
|
|
|
self.register_obligations_for_call(&method_ty);
|
|
|
|
|
|
|
|
self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone()));
|
|
|
|
|
|
|
|
let ret_ty = match method_ty.callable_sig(self.db) {
|
2023-01-02 22:16:09 +00:00
|
|
|
Some(sig) => {
|
|
|
|
let p_left = &sig.params()[0];
|
|
|
|
if matches!(op, BinaryOp::CmpOp(..) | BinaryOp::Assignment { .. }) {
|
|
|
|
if let &TyKind::Ref(mtbl, _, _) = p_left.kind(Interner) {
|
|
|
|
self.write_expr_adj(
|
|
|
|
lhs,
|
|
|
|
vec![Adjustment {
|
|
|
|
kind: Adjust::Borrow(AutoBorrow::Ref(mtbl)),
|
|
|
|
target: p_left.clone(),
|
|
|
|
}],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let p_right = &sig.params()[1];
|
|
|
|
if matches!(op, BinaryOp::CmpOp(..)) {
|
|
|
|
if let &TyKind::Ref(mtbl, _, _) = p_right.kind(Interner) {
|
|
|
|
self.write_expr_adj(
|
|
|
|
rhs,
|
|
|
|
vec![Adjustment {
|
|
|
|
kind: Adjust::Borrow(AutoBorrow::Ref(mtbl)),
|
|
|
|
target: p_right.clone(),
|
|
|
|
}],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sig.ret().clone()
|
|
|
|
}
|
2021-08-22 15:21:47 +00:00
|
|
|
None => self.err_ty(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let ret_ty = self.normalize_associated_types_in(ret_ty);
|
|
|
|
|
2023-01-17 10:48:25 +00:00
|
|
|
if self.is_builtin_binop(&lhs_ty, &rhs_ty, op) {
|
|
|
|
// use knowledge of built-in binary ops, which can sometimes help inference
|
|
|
|
let builtin_ret = self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op);
|
2021-08-22 15:21:47 +00:00
|
|
|
self.unify(&builtin_ret, &ret_ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret_ty
|
|
|
|
}
|
|
|
|
|
2019-10-12 15:39:20 +00:00
|
|
|
fn infer_block(
|
|
|
|
&mut self,
|
2021-07-06 16:05:40 +00:00
|
|
|
expr: ExprId,
|
2019-10-12 15:39:20 +00:00
|
|
|
statements: &[Statement],
|
|
|
|
tail: Option<ExprId>,
|
|
|
|
expected: &Expectation,
|
|
|
|
) -> Ty {
|
|
|
|
for stmt in statements {
|
|
|
|
match stmt {
|
2021-10-07 15:05:50 +00:00
|
|
|
Statement::Let { pat, type_ref, initializer, else_branch } => {
|
2021-06-18 11:40:51 +00:00
|
|
|
let decl_ty = type_ref
|
|
|
|
.as_ref()
|
|
|
|
.map(|tr| self.make_ty(tr))
|
|
|
|
.unwrap_or_else(|| self.err_ty());
|
2019-10-12 15:39:20 +00:00
|
|
|
|
|
|
|
// Always use the declared type when specified
|
|
|
|
let mut ty = decl_ty.clone();
|
|
|
|
|
|
|
|
if let Some(expr) = initializer {
|
|
|
|
let actual_ty =
|
|
|
|
self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone()));
|
2021-03-13 13:44:51 +00:00
|
|
|
if decl_ty.is_unknown() {
|
2019-10-12 15:39:20 +00:00
|
|
|
ty = actual_ty;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-07 15:05:50 +00:00
|
|
|
if let Some(expr) = else_branch {
|
|
|
|
self.infer_expr_coerce(
|
|
|
|
*expr,
|
2023-02-10 15:08:47 +00:00
|
|
|
&Expectation::HasType(self.result.standard_types.never.clone()),
|
2021-10-07 15:05:50 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-10-12 15:39:20 +00:00
|
|
|
self.infer_pat(*pat, &ty, BindingMode::default());
|
|
|
|
}
|
2021-04-07 11:45:17 +00:00
|
|
|
Statement::Expr { expr, .. } => {
|
2020-05-08 15:36:11 +00:00
|
|
|
self.infer_expr(*expr, &Expectation::none());
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-03 14:00:50 +00:00
|
|
|
if let Some(expr) = tail {
|
2019-10-12 15:39:20 +00:00
|
|
|
self.infer_expr_coerce(expr, expected)
|
|
|
|
} else {
|
2020-05-08 15:36:11 +00:00
|
|
|
// Citing rustc: if there is no explicit tail expression,
|
|
|
|
// that is typically equivalent to a tail expression
|
|
|
|
// of `()` -- except if the block diverges. In that
|
|
|
|
// case, there is no value supplied from the tail
|
|
|
|
// expression (assuming there are no other breaks,
|
|
|
|
// this implies that the type of the block will be
|
|
|
|
// `!`).
|
|
|
|
if self.diverges.is_always() {
|
|
|
|
// we don't even make an attempt at coercion
|
2021-03-01 11:35:11 +00:00
|
|
|
self.table.new_maybe_never_var()
|
2023-01-10 20:40:08 +00:00
|
|
|
} else if let Some(t) = expected.only_has_type(&mut self.table) {
|
|
|
|
if self.coerce(Some(expr), &TyBuilder::unit(), &t).is_err() {
|
|
|
|
self.result.type_mismatches.insert(
|
|
|
|
expr.into(),
|
|
|
|
TypeMismatch { expected: t.clone(), actual: TyBuilder::unit() },
|
|
|
|
);
|
2021-05-21 15:41:20 +00:00
|
|
|
}
|
2023-01-10 20:40:08 +00:00
|
|
|
t
|
|
|
|
} else {
|
|
|
|
TyBuilder::unit()
|
2020-05-08 15:36:11 +00:00
|
|
|
}
|
2021-09-03 14:00:50 +00:00
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn infer_method_call(
|
|
|
|
&mut self,
|
|
|
|
tgt_expr: ExprId,
|
|
|
|
receiver: ExprId,
|
|
|
|
args: &[ExprId],
|
|
|
|
method_name: &Name,
|
|
|
|
generic_args: Option<&GenericArgs>,
|
2021-07-15 18:02:58 +00:00
|
|
|
expected: &Expectation,
|
2019-10-12 15:39:20 +00:00
|
|
|
) -> Ty {
|
|
|
|
let receiver_ty = self.infer_expr(receiver, &Expectation::none());
|
2021-04-11 09:20:45 +00:00
|
|
|
let canonicalized_receiver = self.canonicalize(receiver_ty.clone());
|
2020-01-14 13:20:33 +00:00
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast());
|
2020-01-14 13:20:33 +00:00
|
|
|
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let resolved = method_resolution::lookup_method(
|
|
|
|
self.db,
|
2023-01-01 12:24:48 +00:00
|
|
|
&canonicalized_receiver.value,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
self.trait_env.clone(),
|
|
|
|
&traits_in_scope,
|
2022-03-31 09:12:08 +00:00
|
|
|
VisibleFromModule::Filter(self.resolver.module()),
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
method_name,
|
|
|
|
);
|
2021-05-31 18:04:18 +00:00
|
|
|
let (receiver_ty, method_ty, substs) = match resolved {
|
2023-01-01 12:24:48 +00:00
|
|
|
Some((adjust, func, visible)) => {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty);
|
2021-05-23 14:59:23 +00:00
|
|
|
let generics = generics(self.db.upcast(), func.into());
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let substs = self.substs_for_method_call(generics, generic_args);
|
|
|
|
self.write_expr_adj(receiver, adjustments);
|
2021-05-23 14:59:23 +00:00
|
|
|
self.write_method_resolution(tgt_expr, func, substs.clone());
|
2023-01-01 12:24:48 +00:00
|
|
|
if !visible {
|
|
|
|
self.push_diagnostic(InferenceDiagnostic::PrivateAssocItem {
|
|
|
|
id: tgt_expr.into(),
|
|
|
|
item: func.into(),
|
|
|
|
})
|
|
|
|
}
|
2021-05-23 14:59:23 +00:00
|
|
|
(ty, self.db.value_ty(func.into()), substs)
|
|
|
|
}
|
|
|
|
None => (
|
|
|
|
receiver_ty,
|
2021-12-19 16:58:39 +00:00
|
|
|
Binders::empty(Interner, self.err_ty()),
|
|
|
|
Substitution::empty(Interner),
|
2021-05-23 14:59:23 +00:00
|
|
|
),
|
2019-10-12 15:39:20 +00:00
|
|
|
};
|
2021-12-19 16:58:39 +00:00
|
|
|
let method_ty = method_ty.substitute(Interner, &substs);
|
2019-10-12 15:39:20 +00:00
|
|
|
self.register_obligations_for_call(&method_ty);
|
2022-03-27 17:10:31 +00:00
|
|
|
let (formal_receiver_ty, param_tys, ret_ty, is_varargs) =
|
|
|
|
match method_ty.callable_sig(self.db) {
|
|
|
|
Some(sig) => {
|
|
|
|
if !sig.params().is_empty() {
|
|
|
|
(
|
|
|
|
sig.params()[0].clone(),
|
|
|
|
sig.params()[1..].to_vec(),
|
|
|
|
sig.ret().clone(),
|
|
|
|
sig.is_varargs,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(self.err_ty(), Vec::new(), sig.ret().clone(), sig.is_varargs)
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2022-03-27 17:10:31 +00:00
|
|
|
None => (self.err_ty(), Vec::new(), self.err_ty(), true),
|
|
|
|
};
|
2021-07-15 18:02:58 +00:00
|
|
|
self.unify(&formal_receiver_ty, &receiver_ty);
|
|
|
|
|
|
|
|
let expected_inputs =
|
|
|
|
self.expected_inputs_for_expected_output(expected, ret_ty.clone(), param_tys.clone());
|
2019-10-12 15:39:20 +00:00
|
|
|
|
2022-03-27 17:10:31 +00:00
|
|
|
self.check_call_arguments(tgt_expr, args, &expected_inputs, ¶m_tys, &[], is_varargs);
|
2020-02-18 13:32:19 +00:00
|
|
|
self.normalize_associated_types_in(ret_ty)
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
|
2021-07-15 18:02:58 +00:00
|
|
|
fn expected_inputs_for_expected_output(
|
|
|
|
&mut self,
|
|
|
|
expected_output: &Expectation,
|
|
|
|
output: Ty,
|
|
|
|
inputs: Vec<Ty>,
|
|
|
|
) -> Vec<Ty> {
|
|
|
|
if let Some(expected_ty) = expected_output.to_option(&mut self.table) {
|
2021-09-03 14:00:50 +00:00
|
|
|
self.table.fudge_inference(|table| {
|
2021-08-21 17:47:06 +00:00
|
|
|
if table.try_unify(&expected_ty, &output).is_ok() {
|
2021-10-20 17:20:17 +00:00
|
|
|
table.resolve_with_fallback(inputs, &|var, kind, _, _| match kind {
|
2021-12-19 16:58:39 +00:00
|
|
|
chalk_ir::VariableKind::Ty(tk) => var.to_ty(Interner, tk).cast(Interner),
|
2021-08-21 17:47:06 +00:00
|
|
|
chalk_ir::VariableKind::Lifetime => {
|
2021-12-19 16:58:39 +00:00
|
|
|
var.to_lifetime(Interner).cast(Interner)
|
2021-08-21 17:47:06 +00:00
|
|
|
}
|
|
|
|
chalk_ir::VariableKind::Const(ty) => {
|
2021-12-19 16:58:39 +00:00
|
|
|
var.to_const(Interner, ty).cast(Interner)
|
2021-08-21 17:47:06 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Vec::new()
|
|
|
|
}
|
2021-09-03 14:00:50 +00:00
|
|
|
})
|
2021-07-15 18:02:58 +00:00
|
|
|
} else {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-21 15:43:19 +00:00
|
|
|
fn check_call_arguments(
|
|
|
|
&mut self,
|
2022-03-27 17:10:31 +00:00
|
|
|
expr: ExprId,
|
2022-03-21 15:43:19 +00:00
|
|
|
args: &[ExprId],
|
|
|
|
expected_inputs: &[Ty],
|
|
|
|
param_tys: &[Ty],
|
|
|
|
skip_indices: &[u32],
|
2022-03-27 17:10:31 +00:00
|
|
|
is_varargs: bool,
|
2022-03-21 15:43:19 +00:00
|
|
|
) {
|
2022-03-27 17:10:31 +00:00
|
|
|
if args.len() != param_tys.len() + skip_indices.len() && !is_varargs {
|
|
|
|
self.push_diagnostic(InferenceDiagnostic::MismatchedArgCount {
|
|
|
|
call_expr: expr,
|
|
|
|
expected: param_tys.len() + skip_indices.len(),
|
|
|
|
found: args.len(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-10-12 15:39:20 +00:00
|
|
|
// Quoting https://github.com/rust-lang/rust/blob/6ef275e6c3cb1384ec78128eceeb4963ff788dca/src/librustc_typeck/check/mod.rs#L3325 --
|
|
|
|
// We do this in a pretty awful way: first we type-check any arguments
|
|
|
|
// that are not closures, then we type-check the closures. This is so
|
|
|
|
// that we have more information about the types of arguments when we
|
|
|
|
// type-check the functions. This isn't really the right way to do this.
|
2023-01-14 12:50:13 +00:00
|
|
|
for check_closures in [false, true] {
|
2022-03-21 15:43:19 +00:00
|
|
|
let mut skip_indices = skip_indices.into_iter().copied().fuse().peekable();
|
2021-03-13 13:44:51 +00:00
|
|
|
let param_iter = param_tys.iter().cloned().chain(repeat(self.err_ty()));
|
2021-07-15 18:02:58 +00:00
|
|
|
let expected_iter = expected_inputs
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
|
|
|
.chain(param_iter.clone().skip(expected_inputs.len()));
|
2022-03-21 15:43:19 +00:00
|
|
|
for (idx, ((&arg, param_ty), expected_ty)) in
|
|
|
|
args.iter().zip(param_iter).zip(expected_iter).enumerate()
|
|
|
|
{
|
2022-05-20 13:40:32 +00:00
|
|
|
let is_closure = matches!(&self.body[arg], Expr::Closure { .. });
|
2019-10-12 15:39:20 +00:00
|
|
|
if is_closure != check_closures {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-03-21 15:43:19 +00:00
|
|
|
while skip_indices.peek().map_or(false, |i| *i < idx as u32) {
|
|
|
|
skip_indices.next();
|
|
|
|
}
|
|
|
|
if skip_indices.peek().copied() == Some(idx as u32) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-07-15 18:02:58 +00:00
|
|
|
// the difference between param_ty and expected here is that
|
|
|
|
// expected is the parameter when the expected *return* type is
|
|
|
|
// taken into account. So in `let _: &[i32] = identity(&[1, 2])`
|
|
|
|
// the expected type is already `&[i32]`, whereas param_ty is
|
|
|
|
// still an unbound type variable. We don't always want to force
|
|
|
|
// the parameter to coerce to the expected type (for example in
|
|
|
|
// `coerce_unsize_expected_type_4`).
|
2019-10-12 15:39:20 +00:00
|
|
|
let param_ty = self.normalize_associated_types_in(param_ty);
|
2021-07-15 18:02:58 +00:00
|
|
|
let expected = Expectation::rvalue_hint(&mut self.table, expected_ty);
|
|
|
|
// infer with the expected type we have...
|
|
|
|
let ty = self.infer_expr_inner(arg, &expected);
|
|
|
|
|
|
|
|
// then coerce to either the expected type or just the formal parameter type
|
|
|
|
let coercion_target = if let Some(ty) = expected.only_has_type(&mut self.table) {
|
|
|
|
// if we are coercing to the expectation, unify with the
|
|
|
|
// formal parameter type to connect everything
|
|
|
|
self.unify(&ty, ¶m_ty);
|
|
|
|
ty
|
|
|
|
} else {
|
|
|
|
param_ty
|
|
|
|
};
|
2023-01-10 20:40:08 +00:00
|
|
|
if !coercion_target.is_unknown()
|
|
|
|
&& self.coerce(Some(arg), &ty, &coercion_target).is_err()
|
|
|
|
{
|
|
|
|
self.result.type_mismatches.insert(
|
|
|
|
arg.into(),
|
|
|
|
TypeMismatch { expected: coercion_target, actual: ty.clone() },
|
|
|
|
);
|
2021-07-15 18:02:58 +00:00
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn substs_for_method_call(
|
|
|
|
&mut self,
|
2021-05-23 14:59:23 +00:00
|
|
|
def_generics: Generics,
|
2019-10-12 15:39:20 +00:00
|
|
|
generic_args: Option<&GenericArgs>,
|
2021-03-15 20:02:34 +00:00
|
|
|
) -> Substitution {
|
2022-03-08 16:21:35 +00:00
|
|
|
let (parent_params, self_params, type_params, const_params, impl_trait_params) =
|
2021-05-23 14:59:23 +00:00
|
|
|
def_generics.provenance_split();
|
2020-02-07 15:24:09 +00:00
|
|
|
assert_eq!(self_params, 0); // method shouldn't have another Self param
|
2022-03-08 16:21:35 +00:00
|
|
|
let total_len = parent_params + type_params + const_params + impl_trait_params;
|
2019-12-07 12:05:05 +00:00
|
|
|
let mut substs = Vec::with_capacity(total_len);
|
2022-10-02 13:15:57 +00:00
|
|
|
|
2022-03-09 18:50:24 +00:00
|
|
|
// handle provided arguments
|
2019-10-12 15:39:20 +00:00
|
|
|
if let Some(generic_args) = generic_args {
|
|
|
|
// if args are provided, it should be all of them, but we can't rely on that
|
2022-03-09 18:50:24 +00:00
|
|
|
for (arg, kind_id) in generic_args
|
2020-12-13 10:34:44 +00:00
|
|
|
.args
|
|
|
|
.iter()
|
2022-03-09 18:50:24 +00:00
|
|
|
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
|
|
|
|
.take(type_params + const_params)
|
2022-10-02 13:15:57 +00:00
|
|
|
.zip(def_generics.iter_id())
|
2020-12-13 10:34:44 +00:00
|
|
|
{
|
2022-03-09 18:50:24 +00:00
|
|
|
if let Some(g) = generic_arg_to_chalk(
|
|
|
|
self.db,
|
|
|
|
kind_id,
|
|
|
|
arg,
|
|
|
|
self,
|
|
|
|
|this, type_ref| this.make_ty(type_ref),
|
2022-04-07 01:00:33 +00:00
|
|
|
|this, c, ty| {
|
2022-03-09 18:50:24 +00:00
|
|
|
const_or_path_to_chalk(
|
|
|
|
this.db,
|
|
|
|
&this.resolver,
|
2022-04-07 01:00:33 +00:00
|
|
|
ty,
|
2022-03-09 18:50:24 +00:00
|
|
|
c,
|
|
|
|
ParamLoweringMode::Placeholder,
|
2022-12-30 08:05:03 +00:00
|
|
|
|| generics(this.db.upcast(), this.resolver.generic_def().unwrap()),
|
2022-03-09 18:50:24 +00:00
|
|
|
DebruijnIndex::INNERMOST,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
) {
|
|
|
|
substs.push(g);
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2022-10-02 13:15:57 +00:00
|
|
|
|
|
|
|
// Handle everything else as unknown. This also handles generic arguments for the method's
|
|
|
|
// parent (impl or trait), which should come after those for the method.
|
2022-03-15 19:04:05 +00:00
|
|
|
for (id, data) in def_generics.iter().skip(substs.len()) {
|
|
|
|
match data {
|
|
|
|
TypeOrConstParamData::TypeParamData(_) => {
|
|
|
|
substs.push(GenericArgData::Ty(self.table.new_type_var()).intern(Interner))
|
|
|
|
}
|
|
|
|
TypeOrConstParamData::ConstParamData(_) => {
|
|
|
|
substs.push(
|
|
|
|
GenericArgData::Const(self.table.new_const_var(
|
|
|
|
self.db.const_param_ty(ConstParamId::from_unchecked(id)),
|
|
|
|
))
|
|
|
|
.intern(Interner),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
2019-12-07 12:05:05 +00:00
|
|
|
assert_eq!(substs.len(), total_len);
|
2021-12-19 16:58:39 +00:00
|
|
|
Substitution::from_iter(Interner, substs)
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
|
2021-06-13 03:54:16 +00:00
|
|
|
let callable_ty = self.resolve_ty_shallow(callable_ty);
|
2021-12-19 16:58:39 +00:00
|
|
|
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
|
2021-03-13 16:55:50 +00:00
|
|
|
let def: CallableDefId = from_chalk(self.db, *fn_def);
|
|
|
|
let generic_predicates = self.db.generic_predicates(def.into());
|
2021-02-28 18:13:37 +00:00
|
|
|
for predicate in generic_predicates.iter() {
|
2021-04-05 16:49:26 +00:00
|
|
|
let (predicate, binders) = predicate
|
|
|
|
.clone()
|
2021-12-19 16:58:39 +00:00
|
|
|
.substitute(Interner, parameters)
|
2021-04-05 16:49:26 +00:00
|
|
|
.into_value_and_skipped_binders();
|
2021-12-19 16:58:39 +00:00
|
|
|
always!(binders.len(Interner) == 0); // quantified where clauses not yet handled
|
|
|
|
self.push_obligation(predicate.cast(Interner));
|
2021-02-28 18:13:37 +00:00
|
|
|
}
|
|
|
|
// add obligation for trait implementation, if this is a trait method
|
|
|
|
match def {
|
|
|
|
CallableDefId::FunctionId(f) => {
|
2021-12-07 16:31:26 +00:00
|
|
|
if let ItemContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container {
|
2021-03-20 10:23:59 +00:00
|
|
|
// construct a TraitRef
|
2022-10-02 13:15:57 +00:00
|
|
|
let params_len = parameters.len(Interner);
|
|
|
|
let trait_params_len = generics(self.db.upcast(), trait_.into()).len();
|
|
|
|
let substs = Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
// The generic parameters for the trait come after those for the
|
|
|
|
// function.
|
|
|
|
¶meters.as_slice(Interner)[params_len - trait_params_len..],
|
2021-04-05 19:56:40 +00:00
|
|
|
);
|
2021-04-01 19:45:44 +00:00
|
|
|
self.push_obligation(
|
2021-03-20 10:23:59 +00:00
|
|
|
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
|
2021-12-19 16:58:39 +00:00
|
|
|
.cast(Interner),
|
2021-03-20 10:23:59 +00:00
|
|
|
);
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
2021-02-28 18:13:37 +00:00
|
|
|
CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-22 15:21:47 +00:00
|
|
|
|
2022-03-21 15:43:19 +00:00
|
|
|
/// Returns the argument indices to skip.
|
2022-06-12 14:07:08 +00:00
|
|
|
fn check_legacy_const_generics(&mut self, callee: Ty, args: &[ExprId]) -> Box<[u32]> {
|
2022-03-21 15:43:19 +00:00
|
|
|
let (func, subst) = match callee.kind(Interner) {
|
|
|
|
TyKind::FnDef(fn_id, subst) => {
|
|
|
|
let callable = CallableDefId::from_chalk(self.db, *fn_id);
|
|
|
|
let func = match callable {
|
|
|
|
CallableDefId::FunctionId(f) => f,
|
2022-06-12 14:07:08 +00:00
|
|
|
_ => return Default::default(),
|
2022-03-21 15:43:19 +00:00
|
|
|
};
|
|
|
|
(func, subst)
|
|
|
|
}
|
2022-06-12 14:07:08 +00:00
|
|
|
_ => return Default::default(),
|
2022-03-21 15:43:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let data = self.db.function_data(func);
|
|
|
|
if data.legacy_const_generics_indices.is_empty() {
|
2022-06-12 14:07:08 +00:00
|
|
|
return Default::default();
|
2022-03-21 15:43:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// only use legacy const generics if the param count matches with them
|
|
|
|
if data.params.len() + data.legacy_const_generics_indices.len() != args.len() {
|
2022-03-27 17:10:31 +00:00
|
|
|
if args.len() <= data.params.len() {
|
2022-06-12 14:07:08 +00:00
|
|
|
return Default::default();
|
2022-03-27 17:10:31 +00:00
|
|
|
} else {
|
|
|
|
// there are more parameters than there should be without legacy
|
|
|
|
// const params; use them
|
|
|
|
let mut indices = data.legacy_const_generics_indices.clone();
|
|
|
|
indices.sort();
|
|
|
|
return indices;
|
|
|
|
}
|
2022-03-21 15:43:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// check legacy const parameters
|
|
|
|
for (subst_idx, arg_idx) in data.legacy_const_generics_indices.iter().copied().enumerate() {
|
|
|
|
let arg = match subst.at(Interner, subst_idx).constant(Interner) {
|
|
|
|
Some(c) => c,
|
|
|
|
None => continue, // not a const parameter?
|
|
|
|
};
|
|
|
|
if arg_idx >= args.len() as u32 {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let _ty = arg.data(Interner).ty.clone();
|
|
|
|
let expected = Expectation::none(); // FIXME use actual const ty, when that is lowered correctly
|
|
|
|
self.infer_expr(args[arg_idx as usize], &expected);
|
|
|
|
// FIXME: evaluate and unify with the const
|
|
|
|
}
|
|
|
|
let mut indices = data.legacy_const_generics_indices.clone();
|
|
|
|
indices.sort();
|
|
|
|
indices
|
|
|
|
}
|
|
|
|
|
2023-01-17 10:48:25 +00:00
|
|
|
/// Dereferences a single level of immutable referencing.
|
|
|
|
fn deref_ty_if_possible(&mut self, ty: &Ty) -> Ty {
|
|
|
|
let ty = self.resolve_ty_shallow(ty);
|
|
|
|
match ty.kind(Interner) {
|
|
|
|
TyKind::Ref(Mutability::Not, _, inner) => self.resolve_ty_shallow(inner),
|
|
|
|
_ => ty,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Enforces expectations on lhs type and rhs type depending on the operator and returns the
|
|
|
|
/// output type of the binary op.
|
|
|
|
fn enforce_builtin_binop_types(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> Ty {
|
|
|
|
// Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work (See rust-lang/rust#57447).
|
|
|
|
let lhs = self.deref_ty_if_possible(lhs);
|
|
|
|
let rhs = self.deref_ty_if_possible(rhs);
|
|
|
|
|
|
|
|
let (op, is_assign) = match op {
|
|
|
|
BinaryOp::Assignment { op: Some(inner) } => (BinaryOp::ArithOp(inner), true),
|
|
|
|
_ => (op, false),
|
|
|
|
};
|
|
|
|
|
|
|
|
let output_ty = match op {
|
|
|
|
BinaryOp::LogicOp(_) => {
|
|
|
|
let bool_ = self.result.standard_types.bool_.clone();
|
|
|
|
self.unify(&lhs, &bool_);
|
|
|
|
self.unify(&rhs, &bool_);
|
|
|
|
bool_
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => {
|
|
|
|
// result type is same as LHS always
|
|
|
|
lhs
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::ArithOp(_) => {
|
|
|
|
// LHS, RHS, and result will have the same type
|
|
|
|
self.unify(&lhs, &rhs);
|
|
|
|
lhs
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::CmpOp(_) => {
|
|
|
|
// LHS and RHS will have the same type
|
|
|
|
self.unify(&lhs, &rhs);
|
|
|
|
self.result.standard_types.bool_.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::Assignment { op: None } => {
|
|
|
|
stdx::never!("Simple assignment operator is not binary op.");
|
|
|
|
lhs
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::Assignment { .. } => unreachable!("handled above"),
|
|
|
|
};
|
|
|
|
|
|
|
|
if is_assign {
|
|
|
|
self.result.standard_types.unit.clone()
|
|
|
|
} else {
|
|
|
|
output_ty
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_builtin_binop(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> bool {
|
|
|
|
// Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work (See rust-lang/rust#57447).
|
|
|
|
let lhs = self.deref_ty_if_possible(lhs);
|
|
|
|
let rhs = self.deref_ty_if_possible(rhs);
|
|
|
|
|
|
|
|
let op = match op {
|
|
|
|
BinaryOp::Assignment { op: Some(inner) } => BinaryOp::ArithOp(inner),
|
|
|
|
_ => op,
|
|
|
|
};
|
|
|
|
|
|
|
|
match op {
|
|
|
|
BinaryOp::LogicOp(_) => true,
|
|
|
|
|
|
|
|
BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => {
|
|
|
|
lhs.is_integral() && rhs.is_integral()
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::ArithOp(
|
|
|
|
ArithOp::Add | ArithOp::Sub | ArithOp::Mul | ArithOp::Div | ArithOp::Rem,
|
|
|
|
) => {
|
|
|
|
lhs.is_integral() && rhs.is_integral()
|
|
|
|
|| lhs.is_floating_point() && rhs.is_floating_point()
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::ArithOp(ArithOp::BitAnd | ArithOp::BitOr | ArithOp::BitXor) => {
|
|
|
|
lhs.is_integral() && rhs.is_integral()
|
|
|
|
|| lhs.is_floating_point() && rhs.is_floating_point()
|
|
|
|
|| matches!(
|
|
|
|
(lhs.kind(Interner), rhs.kind(Interner)),
|
|
|
|
(TyKind::Scalar(Scalar::Bool), TyKind::Scalar(Scalar::Bool))
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::CmpOp(_) => {
|
|
|
|
let is_scalar = |kind| {
|
|
|
|
matches!(
|
|
|
|
kind,
|
|
|
|
&TyKind::Scalar(_)
|
|
|
|
| TyKind::FnDef(..)
|
|
|
|
| TyKind::Function(_)
|
|
|
|
| TyKind::Raw(..)
|
|
|
|
| TyKind::InferenceVar(
|
|
|
|
_,
|
|
|
|
TyVariableKind::Integer | TyVariableKind::Float
|
|
|
|
)
|
|
|
|
)
|
|
|
|
};
|
|
|
|
is_scalar(lhs.kind(Interner)) && is_scalar(rhs.kind(Interner))
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::Assignment { op: None } => {
|
|
|
|
stdx::never!("Simple assignment operator is not binary op.");
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOp::Assignment { .. } => unreachable!("handled above"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-01 12:13:08 +00:00
|
|
|
fn with_breakable_ctx<T>(
|
|
|
|
&mut self,
|
2022-09-01 12:54:47 +00:00
|
|
|
kind: BreakableKind,
|
2022-09-01 12:13:08 +00:00
|
|
|
ty: Ty,
|
|
|
|
label: Option<LabelId>,
|
|
|
|
cb: impl FnOnce(&mut Self) -> T,
|
2022-09-01 12:30:57 +00:00
|
|
|
) -> (Option<Ty>, T) {
|
2022-09-01 12:13:08 +00:00
|
|
|
self.breakables.push({
|
|
|
|
let label = label.map(|label| self.body[label].name.clone());
|
2022-09-01 12:54:47 +00:00
|
|
|
BreakableContext { kind, may_break: false, coerce: CoerceMany::new(ty), label }
|
2022-09-01 12:13:08 +00:00
|
|
|
});
|
|
|
|
let res = cb(self);
|
|
|
|
let ctx = self.breakables.pop().expect("breakable stack broken");
|
2022-09-01 12:30:57 +00:00
|
|
|
(ctx.may_break.then(|| ctx.coerce.complete()), res)
|
2022-09-01 12:13:08 +00:00
|
|
|
}
|
2019-10-12 15:39:20 +00:00
|
|
|
}
|