2019-02-23 14:24:07 +00:00
|
|
|
//! Type inference, i.e. the process of walking through the code and determining
|
|
|
|
//! the type of each expression and pattern.
|
|
|
|
//!
|
|
|
|
//! For type inference, compare the implementations in rustc (the various
|
2022-09-26 11:00:29 +00:00
|
|
|
//! check_* methods in rustc_hir_analysis/check/mod.rs are a good entry point) and
|
2019-02-23 14:24:07 +00:00
|
|
|
//! IntelliJ-Rust (org.rust.lang.core.types.infer). Our entry point for
|
|
|
|
//! inference here is the `infer` function, which infers the types of all
|
|
|
|
//! expressions in a given function.
|
|
|
|
//!
|
|
|
|
//! During inference, types (i.e. the `Ty` struct) can contain type 'variables'
|
|
|
|
//! which represent currently unknown types; as we walk through the expressions,
|
|
|
|
//! we might determine that certain variables need to be equal to each other, or
|
|
|
|
//! to certain types. To record this, we use the union-find implementation from
|
|
|
|
//! the `ena` crate, which is extracted from rustc.
|
|
|
|
|
|
|
|
use std::sync::Arc;
|
2023-03-29 12:31:32 +00:00
|
|
|
use std::{convert::identity, ops::Index};
|
2019-02-23 14:24:07 +00:00
|
|
|
|
2023-03-29 12:44:23 +00:00
|
|
|
use chalk_ir::{cast::Cast, DebruijnIndex, Mutability, Safety, Scalar, TypeFlags};
|
2023-02-25 12:50:27 +00:00
|
|
|
use either::Either;
|
2023-04-06 10:50:16 +00:00
|
|
|
use hir_def::expr::LabelId;
|
2019-10-30 14:28:30 +00:00
|
|
|
use hir_def::{
|
2019-11-27 12:56:20 +00:00
|
|
|
body::Body,
|
2022-12-06 22:29:38 +00:00
|
|
|
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
|
2022-04-26 14:25:10 +00:00
|
|
|
data::{ConstData, StaticData},
|
2023-02-18 20:32:55 +00:00
|
|
|
expr::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, PatId},
|
2023-01-21 16:29:07 +00:00
|
|
|
lang_item::{LangItem, LangItemTarget},
|
2022-12-06 22:29:38 +00:00
|
|
|
layout::Integer,
|
2023-03-08 17:28:52 +00:00
|
|
|
path::{ModPath, Path},
|
2021-07-22 11:40:18 +00:00
|
|
|
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
2021-03-01 18:30:34 +00:00
|
|
|
type_ref::TypeRef,
|
2023-03-08 17:28:52 +00:00
|
|
|
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, ItemContainerId, Lookup,
|
|
|
|
TraitId, TypeAliasId, VariantId,
|
2019-10-30 14:28:30 +00:00
|
|
|
};
|
2023-03-03 18:32:18 +00:00
|
|
|
use hir_expand::name::{name, Name};
|
2021-01-15 00:11:07 +00:00
|
|
|
use la_arena::ArenaMap;
|
2023-03-05 14:04:46 +00:00
|
|
|
use rustc_hash::{FxHashMap, FxHashSet};
|
2023-03-08 17:28:52 +00:00
|
|
|
use stdx::{always, never};
|
2019-02-23 14:24:07 +00:00
|
|
|
|
2020-01-24 14:22:00 +00:00
|
|
|
use crate::{
|
2023-03-29 12:44:23 +00:00
|
|
|
db::HirDatabase, fold_tys, infer::coerce::CoerceMany, lower::ImplTraitLoweringMode,
|
|
|
|
static_lifetime, to_assoc_type_id, AliasEq, AliasTy, DomainGoal, GenericArg, Goal, ImplTraitId,
|
|
|
|
InEnvironment, Interner, ProjectionTy, RpitId, Substitution, TraitRef, Ty, TyBuilder, TyExt,
|
|
|
|
TyKind,
|
2020-01-24 14:22:00 +00:00
|
|
|
};
|
2019-02-23 14:24:07 +00:00
|
|
|
|
2021-03-16 15:45:46 +00:00
|
|
|
// This lint has a false positive here. See the link below for details.
|
|
|
|
//
|
|
|
|
// https://github.com/rust-lang/rust/issues/57411
|
2022-03-21 17:54:20 +00:00
|
|
|
#[allow(unreachable_pub)]
|
2022-03-20 23:08:12 +00:00
|
|
|
pub use coerce::could_coerce;
|
2021-03-16 15:45:46 +00:00
|
|
|
#[allow(unreachable_pub)]
|
|
|
|
pub use unify::could_unify;
|
2019-12-01 21:14:28 +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
|
|
|
pub(crate) mod unify;
|
2019-09-23 16:53:52 +00:00
|
|
|
mod path;
|
2019-10-12 15:39:20 +00:00
|
|
|
mod expr;
|
|
|
|
mod pat;
|
|
|
|
mod coerce;
|
2021-06-29 15:35:37 +00:00
|
|
|
mod closure;
|
2023-03-17 10:32:55 +00:00
|
|
|
mod mutability;
|
2019-04-20 10:34:36 +00:00
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
/// The entry point of type inference.
|
2020-03-13 15:05:46 +00:00
|
|
|
pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
|
2020-08-12 14:32:36 +00:00
|
|
|
let _p = profile::span("infer_query");
|
2020-03-13 15:05:46 +00:00
|
|
|
let resolver = def.resolver(db.upcast());
|
2022-04-15 19:44:47 +00:00
|
|
|
let body = db.body(def);
|
|
|
|
let mut ctx = InferenceContext::new(db, def, &body, resolver);
|
2019-02-23 14:24:07 +00:00
|
|
|
|
2019-11-27 13:02:33 +00:00
|
|
|
match def {
|
2023-03-03 15:44:25 +00:00
|
|
|
DefWithBodyId::FunctionId(f) => {
|
|
|
|
ctx.collect_fn(f);
|
|
|
|
}
|
2019-11-27 13:02:33 +00:00
|
|
|
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
|
2020-05-10 15:08:28 +00:00
|
|
|
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
|
2022-10-11 07:37:35 +00:00
|
|
|
DefWithBodyId::VariantId(v) => {
|
|
|
|
ctx.return_ty = TyBuilder::builtin(match db.enum_data(v.parent).variant_body_type() {
|
2022-12-06 22:29:38 +00:00
|
|
|
hir_def::layout::IntegerType::Pointer(signed) => match signed {
|
|
|
|
true => BuiltinType::Int(BuiltinInt::Isize),
|
|
|
|
false => BuiltinType::Uint(BuiltinUint::Usize),
|
|
|
|
},
|
|
|
|
hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
|
|
|
|
true => BuiltinType::Int(match size {
|
|
|
|
Integer::I8 => BuiltinInt::I8,
|
|
|
|
Integer::I16 => BuiltinInt::I16,
|
|
|
|
Integer::I32 => BuiltinInt::I32,
|
|
|
|
Integer::I64 => BuiltinInt::I64,
|
|
|
|
Integer::I128 => BuiltinInt::I128,
|
|
|
|
}),
|
|
|
|
false => BuiltinType::Uint(match size {
|
|
|
|
Integer::I8 => BuiltinUint::U8,
|
|
|
|
Integer::I16 => BuiltinUint::U16,
|
|
|
|
Integer::I32 => BuiltinUint::U32,
|
|
|
|
Integer::I64 => BuiltinUint::U64,
|
|
|
|
Integer::I128 => BuiltinUint::U128,
|
|
|
|
}),
|
|
|
|
},
|
2022-10-11 07:37:35 +00:00
|
|
|
});
|
|
|
|
}
|
2019-03-30 11:17:31 +00:00
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
|
|
|
|
ctx.infer_body();
|
|
|
|
|
2023-03-17 10:32:55 +00:00
|
|
|
ctx.infer_mut_body();
|
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
Arc::new(ctx.resolve_all())
|
|
|
|
}
|
|
|
|
|
2021-11-27 13:13:47 +00:00
|
|
|
/// Fully normalize all the types found within `ty` in context of `owner` body definition.
|
|
|
|
///
|
|
|
|
/// This is appropriate to use only after type-check: it assumes
|
|
|
|
/// that normalization will succeed, for example.
|
|
|
|
pub(crate) fn normalize(db: &dyn HirDatabase, owner: DefWithBodyId, ty: Ty) -> Ty {
|
|
|
|
if !ty.data(Interner).flags.intersects(TypeFlags::HAS_PROJECTION) {
|
|
|
|
return ty;
|
|
|
|
}
|
2023-03-08 17:28:52 +00:00
|
|
|
let trait_env = db.trait_environment_for_body(owner);
|
2022-03-12 13:35:25 +00:00
|
|
|
let mut table = unify::InferenceTable::new(db, trait_env);
|
2021-11-27 13:13:47 +00:00
|
|
|
|
|
|
|
let ty_with_vars = table.normalize_associated_types_in(ty);
|
|
|
|
table.resolve_obligations_as_possible();
|
|
|
|
table.propagate_diverging_flag();
|
|
|
|
table.resolve_completely(ty_with_vars)
|
|
|
|
}
|
|
|
|
|
2019-03-16 18:13:13 +00:00
|
|
|
/// Binding modes inferred for patterns.
|
2021-06-14 04:57:10 +00:00
|
|
|
/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>
|
2019-03-16 18:13:13 +00:00
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
2021-12-12 09:24:10 +00:00
|
|
|
pub enum BindingMode {
|
2019-03-16 18:13:13 +00:00
|
|
|
Move,
|
|
|
|
Ref(Mutability),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BindingMode {
|
2020-11-02 15:31:38 +00:00
|
|
|
fn convert(annotation: BindingAnnotation) -> BindingMode {
|
2019-03-16 18:13:13 +00:00
|
|
|
match annotation {
|
|
|
|
BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move,
|
2021-03-01 18:30:34 +00:00
|
|
|
BindingAnnotation::Ref => BindingMode::Ref(Mutability::Not),
|
2019-03-16 18:13:13 +00:00
|
|
|
BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-17 18:46:01 +00:00
|
|
|
impl Default for BindingMode {
|
|
|
|
fn default() -> Self {
|
|
|
|
BindingMode::Move
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-01 19:53:10 +00:00
|
|
|
#[derive(Debug)]
|
2021-07-06 16:05:40 +00:00
|
|
|
pub(crate) struct InferOk<T> {
|
|
|
|
value: T,
|
2021-05-16 16:27:17 +00:00
|
|
|
goals: Vec<InEnvironment<Goal>>,
|
2021-05-01 19:53:10 +00:00
|
|
|
}
|
2021-07-06 16:05:40 +00:00
|
|
|
|
|
|
|
impl<T> InferOk<T> {
|
|
|
|
fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<U> {
|
|
|
|
InferOk { value: f(self.value), goals: self.goals }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-01 19:53:10 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct TypeError;
|
2021-07-06 16:05:40 +00:00
|
|
|
pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>;
|
2021-05-01 19:53:10 +00:00
|
|
|
|
2021-06-12 14:17:23 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
|
|
pub enum InferenceDiagnostic {
|
2023-03-03 19:41:17 +00:00
|
|
|
NoSuchField {
|
|
|
|
expr: ExprId,
|
|
|
|
},
|
|
|
|
PrivateField {
|
|
|
|
expr: ExprId,
|
|
|
|
field: FieldId,
|
|
|
|
},
|
|
|
|
PrivateAssocItem {
|
|
|
|
id: ExprOrPatId,
|
|
|
|
item: AssocItemId,
|
|
|
|
},
|
|
|
|
UnresolvedField {
|
|
|
|
expr: ExprId,
|
|
|
|
receiver: Ty,
|
|
|
|
name: Name,
|
|
|
|
method_with_same_name_exists: bool,
|
|
|
|
},
|
|
|
|
UnresolvedMethodCall {
|
|
|
|
expr: ExprId,
|
|
|
|
receiver: Ty,
|
|
|
|
name: Name,
|
|
|
|
/// Contains the type the field resolves to
|
|
|
|
field_with_same_name: Option<Ty>,
|
|
|
|
},
|
2023-04-06 13:37:53 +00:00
|
|
|
// FIXME: This should be emitted in body lowering
|
|
|
|
BreakOutsideOfLoop {
|
|
|
|
expr: ExprId,
|
|
|
|
is_break: bool,
|
|
|
|
bad_value_break: bool,
|
|
|
|
},
|
2023-03-03 19:41:17 +00:00
|
|
|
MismatchedArgCount {
|
|
|
|
call_expr: ExprId,
|
|
|
|
expected: usize,
|
|
|
|
found: usize,
|
|
|
|
},
|
|
|
|
ExpectedFunction {
|
|
|
|
call_expr: ExprId,
|
|
|
|
found: Ty,
|
|
|
|
},
|
2021-06-12 14:17:23 +00:00
|
|
|
}
|
|
|
|
|
2019-08-11 10:40:08 +00:00
|
|
|
/// A mismatch between an expected and an inferred type.
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
|
|
|
pub struct TypeMismatch {
|
|
|
|
pub expected: Ty,
|
|
|
|
pub actual: Ty,
|
|
|
|
}
|
|
|
|
|
2021-03-14 16:25:29 +00:00
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
|
|
struct InternedStandardTypes {
|
|
|
|
unknown: Ty,
|
2021-08-22 15:21:47 +00:00
|
|
|
bool_: Ty,
|
|
|
|
unit: Ty,
|
2023-02-10 15:08:47 +00:00
|
|
|
never: Ty,
|
2021-03-14 16:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for InternedStandardTypes {
|
|
|
|
fn default() -> Self {
|
2021-08-22 15:21:47 +00:00
|
|
|
InternedStandardTypes {
|
2021-12-19 16:58:39 +00:00
|
|
|
unknown: TyKind::Error.intern(Interner),
|
|
|
|
bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
|
|
|
|
unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
|
2023-02-10 15:08:47 +00:00
|
|
|
never: TyKind::Never.intern(Interner),
|
2021-08-22 15:21:47 +00:00
|
|
|
}
|
2021-03-14 16:25:29 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-08 12:31:16 +00:00
|
|
|
/// Represents coercing a value to a different type of value.
|
|
|
|
///
|
|
|
|
/// We transform values by following a number of `Adjust` steps in order.
|
|
|
|
/// See the documentation on variants of `Adjust` for more details.
|
|
|
|
///
|
|
|
|
/// Here are some common scenarios:
|
|
|
|
///
|
|
|
|
/// 1. The simplest cases are where a pointer is not adjusted fat vs thin.
|
|
|
|
/// Here the pointer will be dereferenced N times (where a dereference can
|
|
|
|
/// happen to raw or borrowed pointers or any smart pointer which implements
|
|
|
|
/// Deref, including Box<_>). The types of dereferences is given by
|
|
|
|
/// `autoderefs`. It can then be auto-referenced zero or one times, indicated
|
|
|
|
/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
|
|
|
|
/// `false`.
|
|
|
|
///
|
|
|
|
/// 2. A thin-to-fat coercion involves unsizing the underlying data. We start
|
|
|
|
/// with a thin pointer, deref a number of times, unsize the underlying data,
|
|
|
|
/// then autoref. The 'unsize' phase may change a fixed length array to a
|
|
|
|
/// dynamically sized one, a concrete object to a trait object, or statically
|
|
|
|
/// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
|
|
|
|
/// represented by:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// Deref(None) -> [i32; 4],
|
|
|
|
/// Borrow(AutoBorrow::Ref) -> &[i32; 4],
|
|
|
|
/// Unsize -> &[i32],
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
|
|
|
|
/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
|
|
|
|
/// The autoderef and -ref are the same as in the above example, but the type
|
|
|
|
/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
|
|
|
|
/// the underlying conversions from `[i32; 4]` to `[i32]`.
|
|
|
|
///
|
|
|
|
/// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In
|
|
|
|
/// that case, we have the pointer we need coming in, so there are no
|
|
|
|
/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
|
|
|
|
/// At some point, of course, `Box` should move out of the compiler, in which
|
|
|
|
/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
|
|
|
|
/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
|
2021-07-06 16:05:40 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Adjustment {
|
|
|
|
pub kind: Adjust,
|
|
|
|
pub target: Ty,
|
|
|
|
}
|
|
|
|
|
2023-03-11 18:13:53 +00:00
|
|
|
impl Adjustment {
|
|
|
|
pub fn borrow(m: Mutability, ty: Ty) -> Self {
|
|
|
|
let ty = TyKind::Ref(m, static_lifetime(), ty).intern(Interner);
|
|
|
|
Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(m)), target: ty }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-06 16:05:40 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum Adjust {
|
|
|
|
/// Go from ! to any type.
|
|
|
|
NeverToAny,
|
|
|
|
/// Dereference once, producing a place.
|
|
|
|
Deref(Option<OverloadedDeref>),
|
|
|
|
/// Take the address and produce either a `&` or `*` pointer.
|
|
|
|
Borrow(AutoBorrow),
|
|
|
|
Pointer(PointerCast),
|
|
|
|
}
|
|
|
|
|
2021-07-08 12:31:16 +00:00
|
|
|
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
|
|
|
|
/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
|
|
|
|
/// The target type is `U` in both cases, with the region and mutability
|
|
|
|
/// being those shared by both the receiver and the returned reference.
|
2023-03-04 20:08:04 +00:00
|
|
|
///
|
|
|
|
/// Mutability is `None` when we are not sure.
|
2021-07-06 16:05:40 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
2023-03-04 20:08:04 +00:00
|
|
|
pub struct OverloadedDeref(pub Option<Mutability>);
|
2021-07-06 16:05:40 +00:00
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum AutoBorrow {
|
2021-07-08 12:31:16 +00:00
|
|
|
/// Converts from T to &T.
|
2021-07-06 16:05:40 +00:00
|
|
|
Ref(Mutability),
|
2021-07-08 12:31:16 +00:00
|
|
|
/// Converts from T to *T.
|
2021-07-06 16:05:40 +00:00
|
|
|
RawPtr(Mutability),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum PointerCast {
|
|
|
|
/// Go from a fn-item type to a fn-pointer type.
|
|
|
|
ReifyFnPointer,
|
|
|
|
|
|
|
|
/// Go from a safe fn pointer to an unsafe fn pointer.
|
|
|
|
UnsafeFnPointer,
|
|
|
|
|
|
|
|
/// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
|
|
|
|
/// It cannot convert a closure that requires unsafe.
|
|
|
|
ClosureFnPointer(Safety),
|
|
|
|
|
|
|
|
/// Go from a mut raw pointer to a const raw pointer.
|
|
|
|
MutToConstPointer,
|
|
|
|
|
2022-02-02 12:35:46 +00:00
|
|
|
#[allow(dead_code)]
|
2021-07-06 16:05:40 +00:00
|
|
|
/// Go from `*const [T; N]` to `*const T`
|
|
|
|
ArrayToPointer,
|
|
|
|
|
|
|
|
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
|
|
|
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
|
|
|
/// This will do things like convert thin pointers to fat
|
|
|
|
/// pointers, or convert structs containing thin pointers to
|
|
|
|
/// structs containing fat pointers, or convert between fat
|
|
|
|
/// pointers. We don't store the details of how the transform is
|
|
|
|
/// done (in fact, we don't know that, because it might depend on
|
|
|
|
/// the precise type parameters). We just store the target
|
|
|
|
/// type. Codegen backends and miri figure out what has to be done
|
|
|
|
/// based on the precise source/target type at hand.
|
|
|
|
Unsize,
|
|
|
|
}
|
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
/// The result of type inference: A mapping from expressions and patterns to types.
|
2019-07-14 12:23:44 +00:00
|
|
|
#[derive(Clone, PartialEq, Eq, Debug, Default)]
|
2019-02-23 14:24:07 +00:00
|
|
|
pub struct InferenceResult {
|
|
|
|
/// For each method call expr, records the function it resolves to.
|
2021-05-23 14:59:23 +00:00
|
|
|
method_resolutions: FxHashMap<ExprId, (FunctionId, Substitution)>,
|
2019-02-23 14:24:07 +00:00
|
|
|
/// For each field access expr, records the field it resolves to.
|
2020-04-25 12:23:34 +00:00
|
|
|
field_resolutions: FxHashMap<ExprId, FieldId>,
|
2021-04-06 17:44:28 +00:00
|
|
|
/// For each struct literal or pattern, records the variant it resolves to.
|
2019-11-27 13:25:01 +00:00
|
|
|
variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
|
2019-03-02 19:05:37 +00:00
|
|
|
/// For each associated item record what it resolves to
|
2022-12-10 16:05:33 +00:00
|
|
|
assoc_resolutions: FxHashMap<ExprOrPatId, (AssocItemId, Substitution)>,
|
2021-06-12 14:17:23 +00:00
|
|
|
pub diagnostics: Vec<InferenceDiagnostic>,
|
2019-11-27 14:46:02 +00:00
|
|
|
pub type_of_expr: ArenaMap<ExprId, Ty>,
|
2021-05-19 04:23:16 +00:00
|
|
|
/// For each pattern record the type it resolves to.
|
|
|
|
///
|
|
|
|
/// **Note**: When a pattern type is resolved it may still contain
|
|
|
|
/// unresolved or missing subpatterns or subpatterns of mismatched types.
|
2019-11-27 14:46:02 +00:00
|
|
|
pub type_of_pat: ArenaMap<PatId, Ty>,
|
2023-02-18 20:32:55 +00:00
|
|
|
pub type_of_binding: ArenaMap<BindingId, Ty>,
|
2023-02-06 17:20:25 +00:00
|
|
|
pub type_of_rpit: ArenaMap<RpitId, Ty>,
|
2023-03-02 07:48:50 +00:00
|
|
|
/// Type of the result of `.into_iter()` on the for. `ExprId` is the one of the whole for loop.
|
2023-03-04 20:08:04 +00:00
|
|
|
pub type_of_for_iterator: FxHashMap<ExprId, Ty>,
|
2021-05-19 04:23:16 +00:00
|
|
|
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
|
2022-10-11 07:37:35 +00:00
|
|
|
/// Interned common types to return references to.
|
2021-03-14 16:25:29 +00:00
|
|
|
standard_types: InternedStandardTypes,
|
2021-06-01 20:29:07 +00:00
|
|
|
/// Stores the types which were implicitly dereferenced in pattern binding modes.
|
2022-05-14 12:26:08 +00:00
|
|
|
pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
|
2021-12-12 09:24:10 +00:00
|
|
|
pub pat_binding_modes: FxHashMap<PatId, BindingMode>,
|
2021-07-06 16:05:40 +00:00
|
|
|
pub expr_adjustments: FxHashMap<ExprId, Vec<Adjustment>>,
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl InferenceResult {
|
2021-05-23 14:59:23 +00:00
|
|
|
pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, Substitution)> {
|
|
|
|
self.method_resolutions.get(&expr).cloned()
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2020-04-25 12:23:34 +00:00
|
|
|
pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> {
|
2019-07-04 17:26:44 +00:00
|
|
|
self.field_resolutions.get(&expr).copied()
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2019-11-27 13:25:01 +00:00
|
|
|
pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
|
2019-07-21 11:11:45 +00:00
|
|
|
self.variant_resolutions.get(&id.into()).copied()
|
|
|
|
}
|
2019-11-27 13:25:01 +00:00
|
|
|
pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {
|
2019-07-21 11:11:45 +00:00
|
|
|
self.variant_resolutions.get(&id.into()).copied()
|
2019-07-12 16:56:18 +00:00
|
|
|
}
|
2022-12-10 16:05:33 +00:00
|
|
|
pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<(AssocItemId, Substitution)> {
|
2022-12-05 01:53:11 +00:00
|
|
|
self.assoc_resolutions.get(&id.into()).cloned()
|
2019-03-04 14:49:18 +00:00
|
|
|
}
|
2022-12-10 16:05:33 +00:00
|
|
|
pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<(AssocItemId, Substitution)> {
|
2022-12-05 01:53:11 +00:00
|
|
|
self.assoc_resolutions.get(&id.into()).cloned()
|
2019-03-01 23:26:49 +00:00
|
|
|
}
|
2019-08-11 10:40:08 +00:00
|
|
|
pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
|
2021-05-19 04:23:16 +00:00
|
|
|
self.type_mismatches.get(&expr.into())
|
|
|
|
}
|
|
|
|
pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> {
|
|
|
|
self.type_mismatches.get(&pat.into())
|
|
|
|
}
|
2023-02-28 14:13:45 +00:00
|
|
|
pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch)> {
|
|
|
|
self.type_mismatches.iter().map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch))
|
|
|
|
}
|
2021-05-19 04:23:16 +00:00
|
|
|
pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> {
|
|
|
|
self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat {
|
|
|
|
ExprOrPatId::ExprId(expr) => Some((expr, mismatch)),
|
|
|
|
_ => None,
|
|
|
|
})
|
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Index<ExprId> for InferenceResult {
|
|
|
|
type Output = Ty;
|
|
|
|
|
|
|
|
fn index(&self, expr: ExprId) -> &Ty {
|
2021-03-14 16:25:29 +00:00
|
|
|
self.type_of_expr.get(expr).unwrap_or(&self.standard_types.unknown)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Index<PatId> for InferenceResult {
|
|
|
|
type Output = Ty;
|
|
|
|
|
|
|
|
fn index(&self, pat: PatId) -> &Ty {
|
2021-03-14 16:25:29 +00:00
|
|
|
self.type_of_pat.get(pat).unwrap_or(&self.standard_types.unknown)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-18 20:32:55 +00:00
|
|
|
impl Index<BindingId> for InferenceResult {
|
|
|
|
type Output = Ty;
|
|
|
|
|
|
|
|
fn index(&self, b: BindingId) -> &Ty {
|
|
|
|
self.type_of_binding.get(b).unwrap_or(&self.standard_types.unknown)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
/// The inference context contains all information needed during type inference.
|
|
|
|
#[derive(Clone, Debug)]
|
2022-03-09 18:50:24 +00:00
|
|
|
pub(crate) struct InferenceContext<'a> {
|
|
|
|
pub(crate) db: &'a dyn HirDatabase,
|
2022-03-20 13:45:28 +00:00
|
|
|
pub(crate) owner: DefWithBodyId,
|
2022-04-15 19:44:47 +00:00
|
|
|
pub(crate) body: &'a Body,
|
2022-03-09 18:50:24 +00:00
|
|
|
pub(crate) resolver: Resolver,
|
2021-04-11 09:20:45 +00:00
|
|
|
table: unify::InferenceTable<'a>,
|
2023-03-05 14:04:46 +00:00
|
|
|
/// The traits in scope, disregarding block modules. This is used for caching purposes.
|
|
|
|
traits_in_scope: FxHashSet<TraitId>,
|
2022-03-20 13:45:28 +00:00
|
|
|
pub(crate) result: InferenceResult,
|
2022-03-23 22:39:35 +00:00
|
|
|
/// The return type of the function being inferred, the closure or async block if we're
|
2019-12-20 15:41:32 +00:00
|
|
|
/// currently within one.
|
|
|
|
///
|
|
|
|
/// We might consider using a nested inference context for checking
|
2023-03-03 15:44:25 +00:00
|
|
|
/// closures so we can swap all shared things out at once.
|
2019-02-23 14:24:07 +00:00
|
|
|
return_ty: Ty,
|
2023-03-03 15:44:25 +00:00
|
|
|
/// If `Some`, this stores coercion information for returned
|
|
|
|
/// expressions. If `None`, this is in a context where return is
|
|
|
|
/// inappropriate, such as a const expression.
|
|
|
|
return_coercion: Option<CoerceMany>,
|
2022-10-11 07:37:35 +00:00
|
|
|
/// The resume type and the yield type, respectively, of the generator being inferred.
|
|
|
|
resume_yield_tys: Option<(Ty, Ty)>,
|
2020-05-08 15:36:11 +00:00
|
|
|
diverges: Diverges,
|
2020-05-08 15:59:58 +00:00
|
|
|
breakables: Vec<BreakableContext>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
struct BreakableContext {
|
2022-09-06 18:20:49 +00:00
|
|
|
/// Whether this context contains at least one break expression.
|
2020-11-02 12:13:32 +00:00
|
|
|
may_break: bool,
|
2022-09-06 18:20:49 +00:00
|
|
|
/// The coercion target of the context.
|
2023-03-03 16:28:57 +00:00
|
|
|
coerce: Option<CoerceMany>,
|
2022-09-06 18:20:49 +00:00
|
|
|
/// The optional label of the context.
|
2023-04-06 10:50:16 +00:00
|
|
|
label: Option<LabelId>,
|
2022-09-06 18:20:49 +00:00
|
|
|
kind: BreakableKind,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
enum BreakableKind {
|
|
|
|
Block,
|
|
|
|
Loop,
|
|
|
|
/// A border is something like an async block, closure etc. Anything that prevents
|
|
|
|
/// breaking/continuing through
|
|
|
|
Border,
|
2020-05-31 08:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn find_breakable<'c>(
|
|
|
|
ctxs: &'c mut [BreakableContext],
|
2023-04-06 10:50:16 +00:00
|
|
|
label: Option<LabelId>,
|
2022-09-06 18:20:49 +00:00
|
|
|
) -> Option<&'c mut BreakableContext> {
|
|
|
|
let mut ctxs = ctxs
|
|
|
|
.iter_mut()
|
|
|
|
.rev()
|
|
|
|
.take_while(|it| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));
|
|
|
|
match label {
|
2023-04-06 10:50:16 +00:00
|
|
|
Some(_) => ctxs.find(|ctx| ctx.label == label),
|
2022-09-06 18:20:49 +00:00
|
|
|
None => ctxs.find(|ctx| matches!(ctx.kind, BreakableKind::Loop)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-06 13:37:53 +00:00
|
|
|
fn find_continuable<'c>(
|
|
|
|
ctxs: &'c mut [BreakableContext],
|
|
|
|
label: Option<LabelId>,
|
|
|
|
) -> Option<&'c mut BreakableContext> {
|
|
|
|
match label {
|
|
|
|
Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),
|
|
|
|
None => find_breakable(ctxs, label),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-13 15:05:46 +00:00
|
|
|
impl<'a> InferenceContext<'a> {
|
2022-04-15 19:44:47 +00:00
|
|
|
fn new(
|
|
|
|
db: &'a dyn HirDatabase,
|
|
|
|
owner: DefWithBodyId,
|
|
|
|
body: &'a Body,
|
|
|
|
resolver: Resolver,
|
|
|
|
) -> Self {
|
2023-03-08 17:28:52 +00:00
|
|
|
let trait_env = db.trait_environment_for_body(owner);
|
2019-02-23 14:24:07 +00:00
|
|
|
InferenceContext {
|
2019-07-14 12:23:44 +00:00
|
|
|
result: InferenceResult::default(),
|
2023-03-28 06:29:07 +00:00
|
|
|
table: unify::InferenceTable::new(db, trait_env),
|
2022-12-09 19:07:00 +00:00
|
|
|
return_ty: TyKind::Error.intern(Interner), // set in collect_* calls
|
2022-10-11 07:37:35 +00:00
|
|
|
resume_yield_tys: None,
|
2023-03-03 15:44:25 +00:00
|
|
|
return_coercion: None,
|
2019-02-23 14:24:07 +00:00
|
|
|
db,
|
2019-11-12 13:46:27 +00:00
|
|
|
owner,
|
2022-04-15 19:44:47 +00:00
|
|
|
body,
|
2023-03-05 14:04:46 +00:00
|
|
|
traits_in_scope: resolver.traits_in_scope(db.upcast()),
|
2019-02-23 14:24:07 +00:00
|
|
|
resolver,
|
2020-05-08 15:36:11 +00:00
|
|
|
diverges: Diverges::Maybe,
|
2020-05-08 15:59:58 +00:00
|
|
|
breakables: Vec::new(),
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-03 11:16:25 +00:00
|
|
|
// FIXME: This function should be private in module. It is currently only used in the consteval, since we need
|
|
|
|
// `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you
|
|
|
|
// used this function for another workaround, mention it here. If you really need this function and believe that
|
|
|
|
// there is no problem in it being `pub(crate)`, remove this comment.
|
|
|
|
pub(crate) fn resolve_all(self) -> InferenceResult {
|
2022-04-15 19:25:44 +00:00
|
|
|
let InferenceContext { mut table, mut result, .. } = self;
|
2021-03-13 13:44:51 +00:00
|
|
|
|
2023-01-05 12:31:10 +00:00
|
|
|
table.fallback_if_possible();
|
|
|
|
|
2019-03-31 18:02:16 +00:00
|
|
|
// FIXME resolve obligations as well (use Guidance if necessary)
|
2022-04-15 19:25:44 +00:00
|
|
|
table.resolve_obligations_as_possible();
|
2021-05-15 17:28:58 +00:00
|
|
|
|
|
|
|
// make sure diverging type variables are marked as such
|
2022-04-15 19:25:44 +00:00
|
|
|
table.propagate_diverging_flag();
|
2019-07-14 12:23:44 +00:00
|
|
|
for ty in result.type_of_expr.values_mut() {
|
2022-04-15 19:25:44 +00:00
|
|
|
*ty = table.resolve_completely(ty.clone());
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2019-07-14 12:23:44 +00:00
|
|
|
for ty in result.type_of_pat.values_mut() {
|
2022-04-15 19:25:44 +00:00
|
|
|
*ty = table.resolve_completely(ty.clone());
|
2021-05-16 15:56:38 +00:00
|
|
|
}
|
2023-02-18 20:32:55 +00:00
|
|
|
for ty in result.type_of_binding.values_mut() {
|
|
|
|
*ty = table.resolve_completely(ty.clone());
|
|
|
|
}
|
|
|
|
for ty in result.type_of_rpit.values_mut() {
|
2023-02-06 17:20:25 +00:00
|
|
|
*ty = table.resolve_completely(ty.clone());
|
|
|
|
}
|
2023-03-02 07:48:50 +00:00
|
|
|
for ty in result.type_of_for_iterator.values_mut() {
|
|
|
|
*ty = table.resolve_completely(ty.clone());
|
|
|
|
}
|
2021-05-16 15:56:38 +00:00
|
|
|
for mismatch in result.type_mismatches.values_mut() {
|
2022-04-15 19:25:44 +00:00
|
|
|
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
|
|
|
|
mismatch.actual = table.resolve_completely(mismatch.actual.clone());
|
2021-05-23 14:59:23 +00:00
|
|
|
}
|
2023-03-03 18:32:18 +00:00
|
|
|
result.diagnostics.retain_mut(|diagnostic| {
|
|
|
|
if let InferenceDiagnostic::ExpectedFunction { found: ty, .. }
|
2023-03-03 19:41:17 +00:00
|
|
|
| InferenceDiagnostic::UnresolvedField { receiver: ty, .. }
|
|
|
|
| InferenceDiagnostic::UnresolvedMethodCall { receiver: ty, .. } = diagnostic
|
2023-03-03 18:32:18 +00:00
|
|
|
{
|
|
|
|
*ty = table.resolve_completely(ty.clone());
|
2023-03-03 19:41:17 +00:00
|
|
|
// FIXME: Remove this when we are on par with rustc in terms of inference
|
2023-03-07 14:24:43 +00:00
|
|
|
if ty.contains_unknown() {
|
2023-03-03 18:32:18 +00:00
|
|
|
return false;
|
2023-03-03 17:04:24 +00:00
|
|
|
}
|
2023-03-03 19:41:17 +00:00
|
|
|
|
|
|
|
if let InferenceDiagnostic::UnresolvedMethodCall { field_with_same_name, .. } =
|
|
|
|
diagnostic
|
|
|
|
{
|
|
|
|
let clear = if let Some(ty) = field_with_same_name {
|
|
|
|
*ty = table.resolve_completely(ty.clone());
|
2023-03-07 14:24:43 +00:00
|
|
|
ty.contains_unknown()
|
2023-03-03 19:41:17 +00:00
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
if clear {
|
|
|
|
*field_with_same_name = None;
|
|
|
|
}
|
|
|
|
}
|
2023-03-03 17:04:24 +00:00
|
|
|
}
|
2023-03-03 18:32:18 +00:00
|
|
|
true
|
|
|
|
});
|
2021-05-23 14:59:23 +00:00
|
|
|
for (_, subst) in result.method_resolutions.values_mut() {
|
2022-04-15 19:25:44 +00:00
|
|
|
*subst = table.resolve_completely(subst.clone());
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2022-12-14 12:56:55 +00:00
|
|
|
for (_, subst) in result.assoc_resolutions.values_mut() {
|
|
|
|
*subst = table.resolve_completely(subst.clone());
|
|
|
|
}
|
2021-07-10 16:19:23 +00:00
|
|
|
for adjustment in result.expr_adjustments.values_mut().flatten() {
|
2022-04-15 19:25:44 +00:00
|
|
|
adjustment.target = table.resolve_completely(adjustment.target.clone());
|
2021-07-10 16:19:23 +00:00
|
|
|
}
|
|
|
|
for adjustment in result.pat_adjustments.values_mut().flatten() {
|
2022-05-14 12:26:08 +00:00
|
|
|
*adjustment = table.resolve_completely(adjustment.clone());
|
2021-07-10 16:19:23 +00:00
|
|
|
}
|
2019-07-14 12:23:44 +00:00
|
|
|
result
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2022-04-15 19:25:44 +00:00
|
|
|
fn collect_const(&mut self, data: &ConstData) {
|
|
|
|
self.return_ty = self.make_ty(&data.type_ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn collect_static(&mut self, data: &StaticData) {
|
|
|
|
self.return_ty = self.make_ty(&data.type_ref);
|
|
|
|
}
|
|
|
|
|
2022-04-26 14:25:10 +00:00
|
|
|
fn collect_fn(&mut self, func: FunctionId) {
|
|
|
|
let data = self.db.function_data(func);
|
2022-04-15 19:25:44 +00:00
|
|
|
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
|
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Param);
|
2022-11-28 23:32:13 +00:00
|
|
|
let mut param_tys =
|
2022-04-15 19:25:44 +00:00
|
|
|
data.params.iter().map(|(_, type_ref)| ctx.lower_ty(type_ref)).collect::<Vec<_>>();
|
2022-11-28 23:32:13 +00:00
|
|
|
// Check if function contains a va_list, if it does then we append it to the parameter types
|
|
|
|
// that are collected from the function data
|
|
|
|
if data.is_varargs() {
|
|
|
|
let va_list_ty = match self.resolve_va_list() {
|
|
|
|
Some(va_list) => TyBuilder::adt(self.db, va_list)
|
|
|
|
.fill_with_defaults(self.db, || self.table.new_type_var())
|
|
|
|
.build(),
|
|
|
|
None => self.err_ty(),
|
|
|
|
};
|
|
|
|
|
|
|
|
param_tys.push(va_list_ty)
|
|
|
|
}
|
2022-04-15 19:44:47 +00:00
|
|
|
for (ty, pat) in param_tys.into_iter().zip(self.body.params.iter()) {
|
2022-04-15 19:25:44 +00:00
|
|
|
let ty = self.insert_type_vars(ty);
|
|
|
|
let ty = self.normalize_associated_types_in(ty);
|
|
|
|
|
2023-03-03 09:23:20 +00:00
|
|
|
self.infer_top_pat(*pat, &ty);
|
2022-04-15 19:25:44 +00:00
|
|
|
}
|
2023-04-01 01:05:28 +00:00
|
|
|
let return_ty = &*data.ret_type;
|
2022-04-26 14:25:10 +00:00
|
|
|
|
2022-12-09 19:07:00 +00:00
|
|
|
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
|
|
|
|
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
|
|
|
|
let return_ty = ctx.lower_ty(return_ty);
|
|
|
|
let return_ty = self.insert_type_vars(return_ty);
|
|
|
|
|
|
|
|
let return_ty = if let Some(rpits) = self.db.return_type_impl_traits(func) {
|
2022-04-26 14:25:10 +00:00
|
|
|
// RPIT opaque types use substitution of their parent function.
|
|
|
|
let fn_placeholders = TyBuilder::placeholder_subst(self.db, func);
|
2022-12-09 19:07:00 +00:00
|
|
|
fold_tys(
|
|
|
|
return_ty,
|
2022-04-26 14:25:10 +00:00
|
|
|
|ty, _| {
|
|
|
|
let opaque_ty_id = match ty.kind(Interner) {
|
|
|
|
TyKind::OpaqueType(opaque_ty_id, _) => *opaque_ty_id,
|
|
|
|
_ => return ty,
|
|
|
|
};
|
|
|
|
let idx = match self.db.lookup_intern_impl_trait_id(opaque_ty_id.into()) {
|
|
|
|
ImplTraitId::ReturnTypeImplTrait(_, idx) => idx,
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
let bounds = (*rpits).map_ref(|rpits| {
|
2023-02-06 17:20:25 +00:00
|
|
|
rpits.impl_traits[idx].bounds.map_ref(|it| it.into_iter())
|
2022-04-26 14:25:10 +00:00
|
|
|
});
|
|
|
|
let var = self.table.new_type_var();
|
|
|
|
let var_subst = Substitution::from1(Interner, var.clone());
|
|
|
|
for bound in bounds {
|
|
|
|
let predicate =
|
|
|
|
bound.map(|it| it.cloned()).substitute(Interner, &fn_placeholders);
|
|
|
|
let (var_predicate, binders) = predicate
|
|
|
|
.substitute(Interner, &var_subst)
|
|
|
|
.into_value_and_skipped_binders();
|
2022-12-09 19:07:00 +00:00
|
|
|
always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
|
2022-04-26 14:25:10 +00:00
|
|
|
self.push_obligation(var_predicate.cast(Interner));
|
|
|
|
}
|
2023-02-06 17:20:25 +00:00
|
|
|
self.result.type_of_rpit.insert(idx, var.clone());
|
2022-04-26 14:25:10 +00:00
|
|
|
var
|
|
|
|
},
|
|
|
|
DebruijnIndex::INNERMOST,
|
2022-12-09 19:07:00 +00:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
return_ty
|
|
|
|
};
|
|
|
|
|
|
|
|
self.return_ty = self.normalize_associated_types_in(return_ty);
|
2023-03-03 15:44:25 +00:00
|
|
|
self.return_coercion = Some(CoerceMany::new(self.return_ty.clone()));
|
2022-04-15 19:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn infer_body(&mut self) {
|
2023-03-03 15:44:25 +00:00
|
|
|
match self.return_coercion {
|
|
|
|
Some(_) => self.infer_return(self.body.body_expr),
|
|
|
|
None => {
|
|
|
|
_ = self.infer_expr_coerce(
|
|
|
|
self.body.body_expr,
|
|
|
|
&Expectation::has_type(self.return_ty.clone()),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2022-04-15 19:25:44 +00:00
|
|
|
}
|
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
fn write_expr_ty(&mut self, expr: ExprId, ty: Ty) {
|
2019-07-14 12:23:44 +00:00
|
|
|
self.result.type_of_expr.insert(expr, ty);
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2021-07-06 16:05:40 +00:00
|
|
|
fn write_expr_adj(&mut self, expr: ExprId, adjustments: Vec<Adjustment>) {
|
|
|
|
self.result.expr_adjustments.insert(expr, adjustments);
|
|
|
|
}
|
|
|
|
|
2021-05-23 14:59:23 +00:00
|
|
|
fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) {
|
|
|
|
self.result.method_resolutions.insert(expr, (func, subst));
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 13:25:01 +00:00
|
|
|
fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) {
|
2019-07-21 11:11:45 +00:00
|
|
|
self.result.variant_resolutions.insert(id, variant);
|
2019-07-12 16:56:18 +00:00
|
|
|
}
|
|
|
|
|
2022-12-10 16:05:33 +00:00
|
|
|
fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItemId, subs: Substitution) {
|
2022-12-05 01:53:11 +00:00
|
|
|
self.result.assoc_resolutions.insert(id, (item, subs));
|
2019-03-01 23:26:49 +00:00
|
|
|
}
|
|
|
|
|
2019-02-23 14:24:07 +00:00
|
|
|
fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
|
2019-07-14 12:23:44 +00:00
|
|
|
self.result.type_of_pat.insert(pat, ty);
|
|
|
|
}
|
|
|
|
|
2023-02-18 20:32:55 +00:00
|
|
|
fn write_binding_ty(&mut self, id: BindingId, ty: Ty) {
|
|
|
|
self.result.type_of_binding.insert(id, ty);
|
|
|
|
}
|
|
|
|
|
2019-07-14 12:23:44 +00:00
|
|
|
fn push_diagnostic(&mut self, diagnostic: InferenceDiagnostic) {
|
|
|
|
self.result.diagnostics.push(diagnostic);
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2022-12-09 19:07:00 +00:00
|
|
|
fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
|
|
|
|
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
|
2021-03-13 21:44:36 +00:00
|
|
|
let ty = ctx.lower_ty(type_ref);
|
2019-08-07 20:06:09 +00:00
|
|
|
let ty = self.insert_type_vars(ty);
|
|
|
|
self.normalize_associated_types_in(ty)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2022-04-15 19:25:44 +00:00
|
|
|
fn err_ty(&self) -> Ty {
|
|
|
|
self.result.standard_types.unknown.clone()
|
|
|
|
}
|
|
|
|
|
2022-12-28 20:43:12 +00:00
|
|
|
/// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
|
2019-02-23 14:24:07 +00:00
|
|
|
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
|
2023-03-29 12:44:23 +00:00
|
|
|
self.table.insert_type_vars_shallow(ty)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn insert_type_vars(&mut self, ty: Ty) -> Ty {
|
2023-03-29 12:44:23 +00:00
|
|
|
self.table.insert_type_vars(ty)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2021-04-01 19:45:44 +00:00
|
|
|
fn push_obligation(&mut self, o: DomainGoal) {
|
2021-12-19 16:58:39 +00:00
|
|
|
self.table.register_obligation(o.cast(Interner));
|
2021-04-01 19:45:44 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:30:28 +00:00
|
|
|
fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
|
|
|
|
self.table.unify(ty1, ty2)
|
|
|
|
}
|
|
|
|
|
2023-03-29 12:31:32 +00:00
|
|
|
/// Attempts to returns the deeply last field of nested structures, but
|
|
|
|
/// does not apply any normalization in its search. Returns the same type
|
|
|
|
/// if input `ty` is not a structure at all.
|
|
|
|
fn struct_tail_without_normalization(&mut self, ty: Ty) -> Ty {
|
|
|
|
self.struct_tail_with_normalize(ty, identity)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the deeply last field of nested structures, or the same type if
|
|
|
|
/// not a structure at all. Corresponds to the only possible unsized field,
|
|
|
|
/// and its type can be used to determine unsizing strategy.
|
|
|
|
///
|
|
|
|
/// This is parameterized over the normalization strategy (i.e. how to
|
|
|
|
/// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
|
|
|
|
/// function to indicate no normalization should take place.
|
|
|
|
fn struct_tail_with_normalize(
|
|
|
|
&mut self,
|
|
|
|
mut ty: Ty,
|
|
|
|
mut normalize: impl FnMut(Ty) -> Ty,
|
|
|
|
) -> Ty {
|
|
|
|
// FIXME: fetch the limit properly
|
|
|
|
let recursion_limit = 10;
|
|
|
|
for iteration in 0.. {
|
|
|
|
if iteration > recursion_limit {
|
|
|
|
return self.err_ty();
|
|
|
|
}
|
|
|
|
match ty.kind(Interner) {
|
|
|
|
TyKind::Adt(chalk_ir::AdtId(hir_def::AdtId::StructId(struct_id)), substs) => {
|
|
|
|
match self.db.field_types((*struct_id).into()).values().next_back().cloned() {
|
|
|
|
Some(field) => {
|
|
|
|
ty = field.substitute(Interner, substs);
|
|
|
|
}
|
|
|
|
None => break,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TyKind::Adt(..) => break,
|
|
|
|
TyKind::Tuple(_, substs) => {
|
|
|
|
match substs
|
|
|
|
.as_slice(Interner)
|
|
|
|
.split_last()
|
|
|
|
.and_then(|(last_ty, _)| last_ty.ty(Interner))
|
|
|
|
{
|
|
|
|
Some(last_ty) => ty = last_ty.clone(),
|
|
|
|
None => break,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TyKind::Alias(..) => {
|
|
|
|
let normalized = normalize(ty.clone());
|
|
|
|
if ty == normalized {
|
|
|
|
return ty;
|
|
|
|
} else {
|
|
|
|
ty = normalized;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => break,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ty
|
|
|
|
}
|
|
|
|
|
2022-04-15 19:25:44 +00:00
|
|
|
/// Recurses through the given type, normalizing associated types mentioned
|
|
|
|
/// in it by replacing them by type variables and registering obligations to
|
|
|
|
/// resolve later. This should be done once for every type we get from some
|
|
|
|
/// type annotation (e.g. from a let type annotation, field type or function
|
|
|
|
/// call). `make_ty` handles this already, but e.g. for field types we need
|
|
|
|
/// to do it as well.
|
|
|
|
fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
|
|
|
|
self.table.normalize_associated_types_in(ty)
|
|
|
|
}
|
|
|
|
|
2021-05-16 13:56:27 +00:00
|
|
|
fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
|
2019-12-01 19:30:28 +00:00
|
|
|
self.table.resolve_ty_shallow(ty)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
2019-12-13 11:44:07 +00:00
|
|
|
fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
|
2019-12-19 04:45:07 +00:00
|
|
|
self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_associated_type_with_params(
|
|
|
|
&mut self,
|
|
|
|
inner_ty: Ty,
|
|
|
|
assoc_ty: Option<TypeAliasId>,
|
2022-10-11 07:37:35 +00:00
|
|
|
// FIXME(GATs): these are args for the trait ref, args for assoc type itself should be
|
|
|
|
// handled when we support them.
|
2022-03-09 18:50:24 +00:00
|
|
|
params: &[GenericArg],
|
2019-12-19 04:45:07 +00:00
|
|
|
) -> Ty {
|
2019-12-13 11:44:07 +00:00
|
|
|
match assoc_ty {
|
|
|
|
Some(res_assoc_ty) => {
|
2020-07-03 15:39:06 +00:00
|
|
|
let trait_ = match res_assoc_ty.lookup(self.db.upcast()).container {
|
2021-12-07 16:31:26 +00:00
|
|
|
hir_def::ItemContainerId::TraitId(trait_) => trait_,
|
2020-07-03 15:39:06 +00:00
|
|
|
_ => panic!("resolve_associated_type called with non-associated type"),
|
|
|
|
};
|
2019-12-13 11:44:07 +00:00
|
|
|
let ty = self.table.new_type_var();
|
2022-03-09 18:50:24 +00:00
|
|
|
let mut param_iter = params.iter().cloned();
|
2021-04-03 19:50:52 +00:00
|
|
|
let trait_ref = TyBuilder::trait_ref(self.db, trait_)
|
2019-12-19 19:04:55 +00:00
|
|
|
.push(inner_ty)
|
2022-03-09 18:50:24 +00:00
|
|
|
.fill(|_| param_iter.next().unwrap())
|
2020-07-03 15:39:06 +00:00
|
|
|
.build();
|
2021-03-19 01:07:15 +00:00
|
|
|
let alias_eq = AliasEq {
|
|
|
|
alias: AliasTy::Projection(ProjectionTy {
|
2021-03-14 15:26:12 +00:00
|
|
|
associated_ty_id: to_assoc_type_id(res_assoc_ty),
|
2021-04-03 19:50:52 +00:00
|
|
|
substitution: trait_ref.substitution.clone(),
|
2021-03-19 01:07:15 +00:00
|
|
|
}),
|
|
|
|
ty: ty.clone(),
|
2019-12-13 11:44:07 +00:00
|
|
|
};
|
2021-12-19 16:58:39 +00:00
|
|
|
self.push_obligation(trait_ref.cast(Interner));
|
|
|
|
self.push_obligation(alias_eq.cast(Interner));
|
2021-05-16 15:56:38 +00:00
|
|
|
ty
|
2019-12-13 11:44:07 +00:00
|
|
|
}
|
2021-03-13 13:44:51 +00:00
|
|
|
None => self.err_ty(),
|
2019-12-13 11:44:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-22 11:40:18 +00:00
|
|
|
fn resolve_variant(&mut self, path: Option<&Path>, value_ns: bool) -> (Ty, Option<VariantId>) {
|
2019-02-23 14:24:07 +00:00
|
|
|
let path = match path {
|
|
|
|
Some(path) => path,
|
2021-03-13 13:44:51 +00:00
|
|
|
None => return (self.err_ty(), None),
|
2019-02-23 14:24:07 +00:00
|
|
|
};
|
2020-01-25 22:38:33 +00:00
|
|
|
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
|
2021-07-22 11:40:18 +00:00
|
|
|
let (resolution, unresolved) = if value_ns {
|
2023-03-08 17:28:52 +00:00
|
|
|
match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path) {
|
2021-07-22 11:40:18 +00:00
|
|
|
Some(ResolveValueResult::ValueNs(value)) => match value {
|
|
|
|
ValueNs::EnumVariantId(var) => {
|
|
|
|
let substs = ctx.substs_from_path(path, var.into(), true);
|
|
|
|
let ty = self.db.ty(var.parent.into());
|
2021-12-19 16:58:39 +00:00
|
|
|
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
2021-07-22 11:40:18 +00:00
|
|
|
return (ty, Some(var.into()));
|
|
|
|
}
|
|
|
|
ValueNs::StructId(strukt) => {
|
|
|
|
let substs = ctx.substs_from_path(path, strukt.into(), true);
|
|
|
|
let ty = self.db.ty(strukt.into());
|
2021-12-19 16:58:39 +00:00
|
|
|
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
2021-07-22 11:40:18 +00:00
|
|
|
return (ty, Some(strukt.into()));
|
|
|
|
}
|
2022-08-23 07:05:52 +00:00
|
|
|
ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None),
|
2021-07-22 11:40:18 +00:00
|
|
|
_ => return (self.err_ty(), None),
|
|
|
|
},
|
|
|
|
Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)),
|
|
|
|
None => return (self.err_ty(), None),
|
|
|
|
}
|
|
|
|
} else {
|
2023-03-08 17:28:52 +00:00
|
|
|
match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
|
2020-05-15 15:15:40 +00:00
|
|
|
Some(it) => it,
|
2021-03-13 13:44:51 +00:00
|
|
|
None => return (self.err_ty(), None),
|
2021-07-22 11:40:18 +00:00
|
|
|
}
|
|
|
|
};
|
2023-03-08 17:28:52 +00:00
|
|
|
let Some(mod_path) = path.mod_path() else {
|
|
|
|
never!("resolver should always resolve lang item paths");
|
|
|
|
return (self.err_ty(), None);
|
|
|
|
};
|
2020-05-15 15:15:40 +00:00
|
|
|
return match resolution {
|
|
|
|
TypeNs::AdtId(AdtId::StructId(strukt)) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let substs = ctx.substs_from_path(path, strukt.into(), true);
|
2019-11-26 18:04:24 +00:00
|
|
|
let ty = self.db.ty(strukt.into());
|
2021-12-19 16:58:39 +00:00
|
|
|
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
2020-05-15 15:15:40 +00:00
|
|
|
forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2020-08-07 13:24:20 +00:00
|
|
|
TypeNs::AdtId(AdtId::UnionId(u)) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let substs = ctx.substs_from_path(path, u.into(), true);
|
2020-08-07 13:24:20 +00:00
|
|
|
let ty = self.db.ty(u.into());
|
2021-12-19 16:58:39 +00:00
|
|
|
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
2020-08-07 13:24:20 +00:00
|
|
|
forbid_unresolved_segments((ty, Some(u.into())), unresolved)
|
|
|
|
}
|
2020-05-15 15:15:40 +00:00
|
|
|
TypeNs::EnumVariantId(var) => {
|
2021-03-13 21:44:36 +00:00
|
|
|
let substs = ctx.substs_from_path(path, var.into(), true);
|
2019-11-26 18:04:24 +00:00
|
|
|
let ty = self.db.ty(var.parent.into());
|
2021-12-19 16:58:39 +00:00
|
|
|
let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
|
2020-05-15 15:15:40 +00:00
|
|
|
forbid_unresolved_segments((ty, Some(var.into())), unresolved)
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2020-05-15 15:15:40 +00:00
|
|
|
TypeNs::SelfType(impl_id) => {
|
2020-03-13 15:05:46 +00:00
|
|
|
let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
|
2022-03-09 18:50:24 +00:00
|
|
|
let substs = generics.placeholder_subst(self.db);
|
2023-03-29 12:44:23 +00:00
|
|
|
let mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
|
|
|
|
|
|
|
|
let Some(mut remaining_idx) = unresolved else {
|
|
|
|
return self.resolve_variant_on_alias(ty, None, mod_path);
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut remaining_segments = path.segments().skip(remaining_idx);
|
|
|
|
|
|
|
|
// We need to try resolving unresolved segments one by one because each may resolve
|
|
|
|
// to a projection, which `TyLoweringContext` cannot handle on its own.
|
|
|
|
while !remaining_segments.is_empty() {
|
|
|
|
let resolved_segment = path.segments().get(remaining_idx - 1).unwrap();
|
|
|
|
let current_segment = remaining_segments.take(1);
|
|
|
|
|
|
|
|
// If we can resolve to an enum variant, it takes priority over associated type
|
|
|
|
// of the same name.
|
|
|
|
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
|
|
|
|
let enum_data = self.db.enum_data(id);
|
|
|
|
let name = current_segment.first().unwrap().name;
|
|
|
|
if let Some(local_id) = enum_data.variant(name) {
|
|
|
|
let variant = EnumVariantId { parent: id, local_id };
|
|
|
|
return if remaining_segments.len() == 1 {
|
|
|
|
(ty, Some(variant.into()))
|
|
|
|
} else {
|
|
|
|
// We still have unresolved paths, but enum variants never have
|
|
|
|
// associated types!
|
|
|
|
(self.err_ty(), None)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// `lower_partly_resolved_path()` returns `None` as type namespace unless
|
|
|
|
// `remaining_segments` is empty, which is never the case here. We don't know
|
|
|
|
// which namespace the new `ty` is in until normalized anyway.
|
|
|
|
(ty, _) = ctx.lower_partly_resolved_path(
|
|
|
|
resolution,
|
|
|
|
resolved_segment,
|
|
|
|
current_segment,
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
|
|
|
|
ty = self.table.insert_type_vars(ty);
|
|
|
|
ty = self.table.normalize_associated_types_in(ty);
|
|
|
|
ty = self.table.resolve_ty_shallow(&ty);
|
|
|
|
if ty.is_unknown() {
|
|
|
|
return (self.err_ty(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME(inherent_associated_types): update `resolution` based on `ty` here.
|
|
|
|
remaining_idx += 1;
|
|
|
|
remaining_segments = remaining_segments.skip(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
let variant = ty.as_adt().and_then(|(id, _)| match id {
|
|
|
|
AdtId::StructId(s) => Some(VariantId::StructId(s)),
|
|
|
|
AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
|
|
|
|
AdtId::EnumId(_) => {
|
|
|
|
// FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
|
|
|
|
None
|
|
|
|
}
|
|
|
|
});
|
|
|
|
(ty, variant)
|
2020-03-06 14:26:49 +00:00
|
|
|
}
|
2020-05-15 15:15:40 +00:00
|
|
|
TypeNs::TypeAliasId(it) => {
|
2022-10-11 07:37:35 +00:00
|
|
|
let container = it.lookup(self.db.upcast()).container;
|
|
|
|
let parent_subst = match container {
|
|
|
|
ItemContainerId::TraitId(id) => {
|
|
|
|
let subst = TyBuilder::subst_for_def(self.db, id, None)
|
|
|
|
.fill_with_inference_vars(&mut self.table)
|
|
|
|
.build();
|
|
|
|
Some(subst)
|
|
|
|
}
|
|
|
|
// Type aliases do not exist in impls.
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
let ty = TyBuilder::def_ty(self.db, it.into(), parent_subst)
|
2022-03-17 11:39:42 +00:00
|
|
|
.fill_with_inference_vars(&mut self.table)
|
2020-03-06 14:26:49 +00:00
|
|
|
.build();
|
2023-03-08 17:28:52 +00:00
|
|
|
self.resolve_variant_on_alias(ty, unresolved, mod_path)
|
2020-05-15 15:15:40 +00:00
|
|
|
}
|
|
|
|
TypeNs::AdtSelfType(_) => {
|
|
|
|
// FIXME this could happen in array size expressions, once we're checking them
|
2021-03-13 13:44:51 +00:00
|
|
|
(self.err_ty(), None)
|
2020-05-15 15:15:40 +00:00
|
|
|
}
|
|
|
|
TypeNs::GenericParam(_) => {
|
|
|
|
// FIXME potentially resolve assoc type
|
2021-03-13 13:44:51 +00:00
|
|
|
(self.err_ty(), None)
|
2020-05-15 15:15:40 +00:00
|
|
|
}
|
2023-03-03 15:24:07 +00:00
|
|
|
TypeNs::AdtId(AdtId::EnumId(_))
|
|
|
|
| TypeNs::BuiltinType(_)
|
|
|
|
| TypeNs::TraitId(_)
|
|
|
|
| TypeNs::TraitAliasId(_) => {
|
2020-05-15 15:15:40 +00:00
|
|
|
// FIXME diagnostic
|
2021-03-13 13:44:51 +00:00
|
|
|
(self.err_ty(), None)
|
2020-03-06 14:26:49 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-15 15:15:40 +00:00
|
|
|
fn forbid_unresolved_segments(
|
|
|
|
result: (Ty, Option<VariantId>),
|
|
|
|
unresolved: Option<usize>,
|
|
|
|
) -> (Ty, Option<VariantId>) {
|
|
|
|
if unresolved.is_none() {
|
|
|
|
result
|
|
|
|
} else {
|
|
|
|
// FIXME diagnostic
|
2021-12-19 16:58:39 +00:00
|
|
|
(TyKind::Error.intern(Interner), None)
|
2020-05-15 15:15:40 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-07 09:31:50 +00:00
|
|
|
}
|
2020-05-15 15:15:40 +00:00
|
|
|
|
2021-04-07 09:31:50 +00:00
|
|
|
fn resolve_variant_on_alias(
|
|
|
|
&mut self,
|
|
|
|
ty: Ty,
|
|
|
|
unresolved: Option<usize>,
|
2023-03-08 17:28:52 +00:00
|
|
|
path: &ModPath,
|
2021-04-07 09:31:50 +00:00
|
|
|
) -> (Ty, Option<VariantId>) {
|
2023-03-08 17:28:52 +00:00
|
|
|
let remaining = unresolved.map(|x| path.segments()[x..].len()).filter(|x| x > &0);
|
2022-04-27 15:34:08 +00:00
|
|
|
match remaining {
|
2021-04-07 09:31:50 +00:00
|
|
|
None => {
|
|
|
|
let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
|
|
|
|
AdtId::StructId(s) => Some(VariantId::StructId(s)),
|
|
|
|
AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
|
|
|
|
AdtId::EnumId(_) => {
|
|
|
|
// FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
|
|
|
|
None
|
|
|
|
}
|
|
|
|
});
|
|
|
|
(ty, variant)
|
|
|
|
}
|
|
|
|
Some(1) => {
|
2023-03-08 17:28:52 +00:00
|
|
|
let segment = path.segments().last().unwrap();
|
2021-04-07 09:31:50 +00:00
|
|
|
// this could be an enum variant or associated type
|
|
|
|
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
|
|
|
|
let enum_data = self.db.enum_data(enum_id);
|
|
|
|
if let Some(local_id) = enum_data.variant(segment) {
|
|
|
|
let variant = EnumVariantId { parent: enum_id, local_id };
|
|
|
|
return (ty, Some(variant.into()));
|
|
|
|
}
|
2020-03-06 14:26:49 +00:00
|
|
|
}
|
2021-04-07 09:31:50 +00:00
|
|
|
// FIXME potentially resolve assoc type
|
|
|
|
(self.err_ty(), None)
|
|
|
|
}
|
|
|
|
Some(_) => {
|
|
|
|
// FIXME diagnostic
|
|
|
|
(self.err_ty(), None)
|
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-21 16:29:07 +00:00
|
|
|
fn resolve_lang_item(&self, item: LangItem) -> Option<LangItemTarget> {
|
2022-03-31 09:12:08 +00:00
|
|
|
let krate = self.resolver.krate();
|
2023-01-21 16:29:07 +00:00
|
|
|
self.db.lang_item(krate, item)
|
2019-12-29 16:39:31 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 12:56:20 +00:00
|
|
|
fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let ItemContainerId::TraitId(trait_) = self.resolve_lang_item(LangItem::IntoIterIntoIter)?
|
|
|
|
.as_function()?
|
|
|
|
.lookup(self.db.upcast()).container
|
|
|
|
else { return None };
|
2022-10-11 07:37:35 +00:00
|
|
|
self.db.trait_data(trait_).associated_type_by_name(&name![IntoIter])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_iterator_item(&self) -> Option<TypeAliasId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let ItemContainerId::TraitId(trait_) = self.resolve_lang_item(LangItem::IteratorNext)?
|
|
|
|
.as_function()?
|
|
|
|
.lookup(self.db.upcast()).container
|
|
|
|
else { return None };
|
2019-12-13 21:01:06 +00:00
|
|
|
self.db.trait_data(trait_).associated_type_by_name(&name![Item])
|
2019-07-07 07:31:09 +00:00
|
|
|
}
|
2019-07-08 15:02:15 +00:00
|
|
|
|
2023-01-27 10:25:34 +00:00
|
|
|
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
2022-10-26 14:40:41 +00:00
|
|
|
}
|
|
|
|
|
2023-01-27 10:25:34 +00:00
|
|
|
fn resolve_lang_trait(&self, lang: LangItem) -> Option<TraitId> {
|
|
|
|
self.resolve_lang_item(lang)?.as_trait()
|
|
|
|
}
|
|
|
|
|
2019-12-13 11:44:42 +00:00
|
|
|
fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
|
2023-01-27 10:25:34 +00:00
|
|
|
self.resolve_output_on(self.resolve_lang_trait(LangItem::Neg)?)
|
2019-12-13 11:44:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
|
2023-01-27 10:25:34 +00:00
|
|
|
self.resolve_output_on(self.resolve_lang_trait(LangItem::Not)?)
|
2019-12-13 11:44:42 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 12:56:20 +00:00
|
|
|
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let ItemContainerId::TraitId(trait_) = self
|
|
|
|
.resolve_lang_item(LangItem::IntoFutureIntoFuture)?
|
|
|
|
.as_function()?
|
|
|
|
.lookup(self.db.upcast())
|
|
|
|
.container
|
|
|
|
else { return None };
|
2023-01-27 10:25:34 +00:00
|
|
|
self.resolve_output_on(trait_)
|
2019-07-20 11:11:18 +00:00
|
|
|
}
|
2019-09-11 15:53:41 +00:00
|
|
|
|
2019-11-26 11:29:12 +00:00
|
|
|
fn resolve_boxed_box(&self) -> Option<AdtId> {
|
2023-01-21 16:29:07 +00:00
|
|
|
let struct_ = self.resolve_lang_item(LangItem::OwnedBox)?.as_struct()?;
|
2019-11-26 11:29:12 +00:00
|
|
|
Some(struct_.into())
|
2019-09-11 15:53:41 +00:00
|
|
|
}
|
2019-11-28 19:10:16 +00:00
|
|
|
|
|
|
|
fn resolve_range_full(&self) -> Option<AdtId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let struct_ = self.resolve_lang_item(LangItem::RangeFull)?.as_struct()?;
|
2019-11-28 19:10:16 +00:00
|
|
|
Some(struct_.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_range(&self) -> Option<AdtId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let struct_ = self.resolve_lang_item(LangItem::Range)?.as_struct()?;
|
2019-11-28 19:10:16 +00:00
|
|
|
Some(struct_.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_range_inclusive(&self) -> Option<AdtId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let struct_ = self.resolve_lang_item(LangItem::RangeInclusiveStruct)?.as_struct()?;
|
2019-11-28 19:10:16 +00:00
|
|
|
Some(struct_.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_range_from(&self) -> Option<AdtId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let struct_ = self.resolve_lang_item(LangItem::RangeFrom)?.as_struct()?;
|
2019-11-28 19:10:16 +00:00
|
|
|
Some(struct_.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_range_to(&self) -> Option<AdtId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let struct_ = self.resolve_lang_item(LangItem::RangeTo)?.as_struct()?;
|
2019-11-28 19:10:16 +00:00
|
|
|
Some(struct_.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
|
2023-01-21 17:47:37 +00:00
|
|
|
let struct_ = self.resolve_lang_item(LangItem::RangeToInclusive)?.as_struct()?;
|
2019-11-28 19:10:16 +00:00
|
|
|
Some(struct_.into())
|
|
|
|
}
|
2019-12-19 04:45:07 +00:00
|
|
|
|
|
|
|
fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
|
2023-01-27 10:25:34 +00:00
|
|
|
self.resolve_output_on(self.resolve_lang_trait(LangItem::Index)?)
|
2019-12-19 04:45:07 +00:00
|
|
|
}
|
2022-11-28 23:32:13 +00:00
|
|
|
|
|
|
|
fn resolve_va_list(&self) -> Option<AdtId> {
|
2023-01-21 16:29:07 +00:00
|
|
|
let struct_ = self.resolve_lang_item(LangItem::VaList)?.as_struct()?;
|
2022-11-28 23:32:13 +00:00
|
|
|
Some(struct_.into())
|
|
|
|
}
|
2023-03-05 14:04:46 +00:00
|
|
|
|
|
|
|
fn get_traits_in_scope(&self) -> Either<FxHashSet<TraitId>, &FxHashSet<TraitId>> {
|
|
|
|
let mut b_traits = self.resolver.traits_in_scope_from_block_scopes().peekable();
|
|
|
|
if b_traits.peek().is_some() {
|
|
|
|
Either::Left(self.traits_in_scope.iter().copied().chain(b_traits).collect())
|
|
|
|
} else {
|
|
|
|
Either::Right(&self.traits_in_scope)
|
|
|
|
}
|
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// When inferring an expression, we propagate downward whatever type hint we
|
|
|
|
/// are able in the form of an `Expectation`.
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
2022-03-09 18:50:24 +00:00
|
|
|
pub(crate) enum Expectation {
|
2021-05-21 15:41:20 +00:00
|
|
|
None,
|
|
|
|
HasType(Ty),
|
2023-02-10 15:08:47 +00:00
|
|
|
#[allow(dead_code)]
|
2023-02-08 11:57:08 +00:00
|
|
|
Castable(Ty),
|
2021-05-21 15:41:20 +00:00
|
|
|
RValueLikeUnsized(Ty),
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Expectation {
|
|
|
|
/// The expectation that the type of the expression needs to equal the given
|
|
|
|
/// type.
|
|
|
|
fn has_type(ty: Ty) -> Self {
|
2021-05-21 15:41:20 +00:00
|
|
|
if ty.is_unknown() {
|
|
|
|
// FIXME: get rid of this?
|
|
|
|
Expectation::None
|
|
|
|
} else {
|
|
|
|
Expectation::HasType(ty)
|
|
|
|
}
|
2020-02-29 14:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// The following explanation is copied straight from rustc:
|
|
|
|
/// Provides an expectation for an rvalue expression given an *optional*
|
|
|
|
/// hint, which is not required for type safety (the resulting type might
|
|
|
|
/// be checked higher up, as is the case with `&expr` and `box expr`), but
|
|
|
|
/// is useful in determining the concrete type.
|
|
|
|
///
|
|
|
|
/// The primary use case is where the expected type is a fat pointer,
|
|
|
|
/// like `&[isize]`. For example, consider the following statement:
|
|
|
|
///
|
2022-11-09 19:49:10 +00:00
|
|
|
/// let x: &[isize] = &[1, 2, 3];
|
2020-02-29 14:31:07 +00:00
|
|
|
///
|
|
|
|
/// In this case, the expected type for the `&[1, 2, 3]` expression is
|
|
|
|
/// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
|
|
|
|
/// expectation `ExpectHasType([isize])`, that would be too strong --
|
|
|
|
/// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
|
|
|
|
/// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
|
|
|
|
/// to the type `&[isize]`. Therefore, we propagate this more limited hint,
|
|
|
|
/// which still is useful, because it informs integer literals and the like.
|
|
|
|
/// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
|
|
|
|
/// for examples of where this comes up,.
|
2023-03-29 12:31:32 +00:00
|
|
|
fn rvalue_hint(ctx: &mut InferenceContext<'_>, ty: Ty) -> Self {
|
|
|
|
match ctx.struct_tail_without_normalization(ty.clone()).kind(Interner) {
|
2021-05-21 15:41:20 +00:00
|
|
|
TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => Expectation::RValueLikeUnsized(ty),
|
|
|
|
_ => Expectation::has_type(ty),
|
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// This expresses no expectation on the type.
|
|
|
|
fn none() -> Self {
|
2021-05-21 15:41:20 +00:00
|
|
|
Expectation::None
|
|
|
|
}
|
|
|
|
|
2022-07-20 13:02:08 +00:00
|
|
|
fn resolve(&self, table: &mut unify::InferenceTable<'_>) -> Expectation {
|
2021-05-21 15:41:20 +00:00
|
|
|
match self {
|
|
|
|
Expectation::None => Expectation::None,
|
|
|
|
Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)),
|
2023-02-08 11:57:08 +00:00
|
|
|
Expectation::Castable(t) => Expectation::Castable(table.resolve_ty_shallow(t)),
|
2021-05-21 15:41:20 +00:00
|
|
|
Expectation::RValueLikeUnsized(t) => {
|
|
|
|
Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t))
|
|
|
|
}
|
2021-03-14 16:25:29 +00:00
|
|
|
}
|
2020-02-29 14:31:07 +00:00
|
|
|
}
|
|
|
|
|
2022-07-20 13:02:08 +00:00
|
|
|
fn to_option(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
|
2021-05-21 15:41:20 +00:00
|
|
|
match self.resolve(table) {
|
|
|
|
Expectation::None => None,
|
2023-02-08 11:57:08 +00:00
|
|
|
Expectation::HasType(t)
|
|
|
|
| Expectation::Castable(t)
|
|
|
|
| Expectation::RValueLikeUnsized(t) => Some(t),
|
2021-05-21 15:41:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-20 13:02:08 +00:00
|
|
|
fn only_has_type(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
|
2021-05-21 15:41:20 +00:00
|
|
|
match self {
|
|
|
|
Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)),
|
2023-02-08 11:57:08 +00:00
|
|
|
Expectation::Castable(_) | Expectation::RValueLikeUnsized(_) | Expectation::None => {
|
|
|
|
None
|
|
|
|
}
|
2020-02-29 14:31:07 +00:00
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2021-06-03 21:12:35 +00:00
|
|
|
|
2023-02-10 15:08:47 +00:00
|
|
|
fn coercion_target_type(&self, table: &mut unify::InferenceTable<'_>) -> Ty {
|
|
|
|
self.only_has_type(table).unwrap_or_else(|| table.new_type_var())
|
|
|
|
}
|
|
|
|
|
2021-06-03 21:12:35 +00:00
|
|
|
/// Comment copied from rustc:
|
|
|
|
/// Disregard "castable to" expectations because they
|
|
|
|
/// can lead us astray. Consider for example `if cond
|
|
|
|
/// {22} else {c} as u8` -- if we propagate the
|
|
|
|
/// "castable to u8" constraint to 22, it will pick the
|
|
|
|
/// type 22u8, which is overly constrained (c might not
|
|
|
|
/// be a u8). In effect, the problem is that the
|
|
|
|
/// "castable to" expectation is not the tightest thing
|
|
|
|
/// we can say, so we want to drop it in this case.
|
|
|
|
/// The tightest thing we can say is "must unify with
|
|
|
|
/// else branch". Note that in the case of a "has type"
|
|
|
|
/// constraint, this limitation does not hold.
|
|
|
|
///
|
|
|
|
/// If the expected type is just a type variable, then don't use
|
|
|
|
/// an expected type. Otherwise, we might write parts of the type
|
|
|
|
/// when checking the 'then' block which are incompatible with the
|
|
|
|
/// 'else' branch.
|
2022-07-20 13:02:08 +00:00
|
|
|
fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation {
|
2021-06-03 21:12:35 +00:00
|
|
|
match self {
|
|
|
|
Expectation::HasType(ety) => {
|
2021-06-13 03:54:16 +00:00
|
|
|
let ety = table.resolve_ty_shallow(ety);
|
2021-06-03 21:12:35 +00:00
|
|
|
if !ety.is_ty_var() {
|
|
|
|
Expectation::HasType(ety)
|
|
|
|
} else {
|
|
|
|
Expectation::None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()),
|
|
|
|
_ => Expectation::None,
|
|
|
|
}
|
|
|
|
}
|
2019-02-23 14:24:07 +00:00
|
|
|
}
|
2019-03-23 13:28:47 +00:00
|
|
|
|
2020-05-08 15:36:11 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
enum Diverges {
|
|
|
|
Maybe,
|
|
|
|
Always,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Diverges {
|
|
|
|
fn is_always(self) -> bool {
|
|
|
|
self == Diverges::Always
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::ops::BitAnd for Diverges {
|
|
|
|
type Output = Self;
|
|
|
|
fn bitand(self, other: Self) -> Self {
|
|
|
|
std::cmp::min(self, other)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::ops::BitOr for Diverges {
|
|
|
|
type Output = Self;
|
|
|
|
fn bitor(self, other: Self) -> Self {
|
|
|
|
std::cmp::max(self, other)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::ops::BitAndAssign for Diverges {
|
|
|
|
fn bitand_assign(&mut self, other: Self) {
|
|
|
|
*self = *self & other;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::ops::BitOrAssign for Diverges {
|
|
|
|
fn bitor_assign(&mut self, other: Self) {
|
|
|
|
*self = *self | other;
|
|
|
|
}
|
|
|
|
}
|