diff options
Diffstat (limited to 'crates/hir_ty/src')
30 files changed, 1239 insertions, 1441 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index ece68183e..be1fd1f13 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -81,7 +81,7 @@ fn deref_by_trait( | |||
81 | 81 | ||
82 | // Now do the assoc type projection | 82 | // Now do the assoc type projection |
83 | let projection = super::traits::ProjectionPredicate { | 83 | let projection = super::traits::ProjectionPredicate { |
84 | ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())), | 84 | ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())), |
85 | projection_ty: super::ProjectionTy { associated_ty: target, parameters }, | 85 | projection_ty: super::ProjectionTy { associated_ty: target, parameters }, |
86 | }; | 86 | }; |
87 | 87 | ||
@@ -89,8 +89,10 @@ fn deref_by_trait( | |||
89 | 89 | ||
90 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; | 90 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; |
91 | 91 | ||
92 | let canonical = | 92 | let canonical = Canonical::new( |
93 | Canonical::new(in_env, ty.value.kinds.iter().copied().chain(Some(super::TyKind::General))); | 93 | in_env, |
94 | ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)), | ||
95 | ); | ||
94 | 96 | ||
95 | let solution = db.trait_solve(krate, canonical)?; | 97 | let solution = db.trait_solve(krate, canonical)?; |
96 | 98 | ||
@@ -112,7 +114,8 @@ fn deref_by_trait( | |||
112 | // new variables in that case | 114 | // new variables in that case |
113 | 115 | ||
114 | for i in 1..vars.0.kinds.len() { | 116 | for i in 1..vars.0.kinds.len() { |
115 | if vars.0.value[i - 1] != Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | 117 | if vars.0.value[i - 1] |
118 | != Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | ||
116 | { | 119 | { |
117 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); | 120 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); |
118 | return None; | 121 | return None; |
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index b3af82444..06714409f 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -130,7 +130,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
130 | ) -> chalk_ir::ProgramClauses<chalk::Interner>; | 130 | ) -> chalk_ir::ProgramClauses<chalk::Interner>; |
131 | } | 131 | } |
132 | 132 | ||
133 | fn infer_wait(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { | 133 | fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { |
134 | let _p = profile::span("infer:wait").detail(|| match def { | 134 | let _p = profile::span("infer:wait").detail(|| match def { |
135 | DefWithBodyId::FunctionId(it) => db.function_data(it).name.to_string(), | 135 | DefWithBodyId::FunctionId(it) => db.function_data(it).name.to_string(), |
136 | DefWithBodyId::StaticId(it) => { | 136 | DefWithBodyId::StaticId(it) => { |
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index 6bca7aa0d..86f937e1d 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -706,6 +706,35 @@ fn x(a: S) { | |||
706 | } | 706 | } |
707 | 707 | ||
708 | #[test] | 708 | #[test] |
709 | fn import_extern_crate_clash_with_inner_item() { | ||
710 | // This is more of a resolver test, but doesn't really work with the hir_def testsuite. | ||
711 | |||
712 | check_diagnostics( | ||
713 | r#" | ||
714 | //- /lib.rs crate:lib deps:jwt | ||
715 | mod permissions; | ||
716 | |||
717 | use permissions::jwt; | ||
718 | |||
719 | fn f() { | ||
720 | fn inner() {} | ||
721 | jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic | ||
722 | } | ||
723 | |||
724 | //- /permissions.rs | ||
725 | pub mod jwt { | ||
726 | pub struct Claims {} | ||
727 | } | ||
728 | |||
729 | //- /jwt/lib.rs crate:jwt | ||
730 | pub struct Claims { | ||
731 | field: u8, | ||
732 | } | ||
733 | "#, | ||
734 | ); | ||
735 | } | ||
736 | |||
737 | #[test] | ||
709 | fn break_outside_of_loop() { | 738 | fn break_outside_of_loop() { |
710 | check_diagnostics( | 739 | check_diagnostics( |
711 | r#" | 740 | r#" |
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index 6773ddea3..3605ca581 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs | |||
@@ -28,7 +28,6 @@ use syntax::{ | |||
28 | ast::{self, NameOwner}, | 28 | ast::{self, NameOwner}, |
29 | AstNode, AstPtr, | 29 | AstNode, AstPtr, |
30 | }; | 30 | }; |
31 | use test_utils::mark; | ||
32 | 31 | ||
33 | use crate::{ | 32 | use crate::{ |
34 | db::HirDatabase, | 33 | db::HirDatabase, |
@@ -93,16 +92,21 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
93 | fn validate_func(&mut self, func: FunctionId) { | 92 | fn validate_func(&mut self, func: FunctionId) { |
94 | let data = self.db.function_data(func); | 93 | let data = self.db.function_data(func); |
95 | if data.is_extern { | 94 | if data.is_extern { |
96 | mark::hit!(extern_func_incorrect_case_ignored); | 95 | cov_mark::hit!(extern_func_incorrect_case_ignored); |
97 | return; | 96 | return; |
98 | } | 97 | } |
99 | 98 | ||
100 | let body = self.db.body(func.into()); | 99 | let body = self.db.body(func.into()); |
101 | 100 | ||
102 | // Recursively validate inner scope items, such as static variables and constants. | 101 | // Recursively validate inner scope items, such as static variables and constants. |
103 | for (item_id, _) in body.item_scope.values() { | 102 | let db = self.db; |
104 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); | 103 | for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { |
105 | validator.validate_item(item_id); | 104 | for (_, module) in block_def_map.modules() { |
105 | for (def_id, _) in module.scope.values() { | ||
106 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); | ||
107 | validator.validate_item(def_id); | ||
108 | } | ||
109 | } | ||
106 | } | 110 | } |
107 | 111 | ||
108 | // Check whether non-snake case identifiers are allowed for this function. | 112 | // Check whether non-snake case identifiers are allowed for this function. |
@@ -625,7 +629,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
625 | fn validate_static(&mut self, static_id: StaticId) { | 629 | fn validate_static(&mut self, static_id: StaticId) { |
626 | let data = self.db.static_data(static_id); | 630 | let data = self.db.static_data(static_id); |
627 | if data.is_extern { | 631 | if data.is_extern { |
628 | mark::hit!(extern_static_incorrect_case_ignored); | 632 | cov_mark::hit!(extern_static_incorrect_case_ignored); |
629 | return; | 633 | return; |
630 | } | 634 | } |
631 | 635 | ||
@@ -673,8 +677,6 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
673 | 677 | ||
674 | #[cfg(test)] | 678 | #[cfg(test)] |
675 | mod tests { | 679 | mod tests { |
676 | use test_utils::mark; | ||
677 | |||
678 | use crate::diagnostics::tests::check_diagnostics; | 680 | use crate::diagnostics::tests::check_diagnostics; |
679 | 681 | ||
680 | #[test] | 682 | #[test] |
@@ -889,8 +891,8 @@ fn main() { | |||
889 | 891 | ||
890 | #[test] | 892 | #[test] |
891 | fn ignores_extern_items() { | 893 | fn ignores_extern_items() { |
892 | mark::check!(extern_func_incorrect_case_ignored); | 894 | cov_mark::check!(extern_func_incorrect_case_ignored); |
893 | mark::check!(extern_static_incorrect_case_ignored); | 895 | cov_mark::check!(extern_static_incorrect_case_ignored); |
894 | check_diagnostics( | 896 | check_diagnostics( |
895 | r#" | 897 | r#" |
896 | extern { | 898 | extern { |
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index d740b7265..2751cd304 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -2,9 +2,7 @@ | |||
2 | 2 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::{ | 5 | use hir_def::{expr::Statement, path::path, resolver::HasResolver, AssocItemId, DefWithBodyId}; |
6 | expr::Statement, path::path, resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, | ||
7 | }; | ||
8 | use hir_expand::{diagnostics::DiagnosticSink, name}; | 6 | use hir_expand::{diagnostics::DiagnosticSink, name}; |
9 | use rustc_hash::FxHashSet; | 7 | use rustc_hash::FxHashSet; |
10 | use syntax::{ast, AstPtr}; | 8 | use syntax::{ast, AstPtr}; |
@@ -17,7 +15,7 @@ use crate::{ | |||
17 | MissingPatFields, RemoveThisSemicolon, | 15 | MissingPatFields, RemoveThisSemicolon, |
18 | }, | 16 | }, |
19 | utils::variant_data, | 17 | utils::variant_data, |
20 | ApplicationTy, InferenceResult, Ty, TypeCtor, | 18 | AdtId, InferenceResult, Ty, |
21 | }; | 19 | }; |
22 | 20 | ||
23 | pub(crate) use hir_def::{ | 21 | pub(crate) use hir_def::{ |
@@ -381,14 +379,15 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
381 | _ => return, | 379 | _ => return, |
382 | }; | 380 | }; |
383 | 381 | ||
384 | let core_result_ctor = TypeCtor::Adt(AdtId::EnumId(core_result_enum)); | 382 | let (params, required) = match mismatch.expected { |
385 | let core_option_ctor = TypeCtor::Adt(AdtId::EnumId(core_option_enum)); | 383 | Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) |
386 | 384 | if enum_id == core_result_enum => | |
387 | let (params, required) = match &mismatch.expected { | 385 | { |
388 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_result_ctor => { | ||
389 | (parameters, "Ok".to_string()) | 386 | (parameters, "Ok".to_string()) |
390 | } | 387 | } |
391 | Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &core_option_ctor => { | 388 | Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) |
389 | if enum_id == core_option_enum => | ||
390 | { | ||
392 | (parameters, "Some".to_string()) | 391 | (parameters, "Some".to_string()) |
393 | } | 392 | } |
394 | _ => return, | 393 | _ => return, |
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 1c1423fbf..04d39c571 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
@@ -222,12 +222,12 @@ use hir_def::{ | |||
222 | adt::VariantData, | 222 | adt::VariantData, |
223 | body::Body, | 223 | body::Body, |
224 | expr::{Expr, Literal, Pat, PatId}, | 224 | expr::{Expr, Literal, Pat, PatId}, |
225 | AdtId, EnumVariantId, StructId, VariantId, | 225 | EnumVariantId, StructId, VariantId, |
226 | }; | 226 | }; |
227 | use la_arena::Idx; | 227 | use la_arena::Idx; |
228 | use smallvec::{smallvec, SmallVec}; | 228 | use smallvec::{smallvec, SmallVec}; |
229 | 229 | ||
230 | use crate::{db::HirDatabase, ApplicationTy, InferenceResult, Ty, TypeCtor}; | 230 | use crate::{db::HirDatabase, AdtId, InferenceResult, Ty}; |
231 | 231 | ||
232 | #[derive(Debug, Clone, Copy)] | 232 | #[derive(Debug, Clone, Copy)] |
233 | /// Either a pattern from the source code being analyzed, represented as | 233 | /// Either a pattern from the source code being analyzed, represented as |
@@ -627,14 +627,12 @@ pub(super) fn is_useful( | |||
627 | // - `!` type | 627 | // - `!` type |
628 | // In those cases, no match arm is useful. | 628 | // In those cases, no match arm is useful. |
629 | match cx.infer[cx.match_expr].strip_references() { | 629 | match cx.infer[cx.match_expr].strip_references() { |
630 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) => { | 630 | Ty::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { |
631 | if cx.db.enum_data(*enum_id).variants.is_empty() { | 631 | if cx.db.enum_data(*enum_id).variants.is_empty() { |
632 | return Ok(Usefulness::NotUseful); | 632 | return Ok(Usefulness::NotUseful); |
633 | } | 633 | } |
634 | } | 634 | } |
635 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) => { | 635 | Ty::Never => return Ok(Usefulness::NotUseful), |
636 | return Ok(Usefulness::NotUseful); | ||
637 | } | ||
638 | _ => (), | 636 | _ => (), |
639 | } | 637 | } |
640 | 638 | ||
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index 9c506112d..e77a20fea 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs | |||
@@ -11,9 +11,7 @@ use hir_def::{ | |||
11 | }; | 11 | }; |
12 | use hir_expand::diagnostics::DiagnosticSink; | 12 | use hir_expand::diagnostics::DiagnosticSink; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Ty}; |
15 | db::HirDatabase, diagnostics::MissingUnsafe, ApplicationTy, InferenceResult, Ty, TypeCtor, | ||
16 | }; | ||
17 | 15 | ||
18 | pub(super) struct UnsafeValidator<'a, 'b: 'a> { | 16 | pub(super) struct UnsafeValidator<'a, 'b: 'a> { |
19 | owner: DefWithBodyId, | 17 | owner: DefWithBodyId, |
@@ -112,7 +110,7 @@ fn walk_unsafe( | |||
112 | } | 110 | } |
113 | } | 111 | } |
114 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { | 112 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { |
115 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }) = &infer[*expr] { | 113 | if let Ty::Raw(..) = &infer[*expr] { |
116 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 114 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
117 | } | 115 | } |
118 | } | 116 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 271fcbfaf..ab51cb0a6 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -2,17 +2,20 @@ | |||
2 | 2 | ||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::{borrow::Cow, fmt}; |
4 | 4 | ||
5 | use crate::{ | ||
6 | db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, | ||
7 | Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | ||
8 | }; | ||
9 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | ||
10 | use hir_def::{ | 7 | use hir_def::{ |
11 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, | 8 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, |
12 | AssocContainerId, HasModule, Lookup, ModuleId, TraitId, | 9 | AssocContainerId, Lookup, ModuleId, TraitId, |
13 | }; | 10 | }; |
14 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
15 | 12 | ||
13 | use crate::{ | ||
14 | db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig, | ||
15 | GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, | ||
16 | TraitRef, Ty, | ||
17 | }; | ||
18 | |||
16 | pub struct HirFormatter<'a> { | 19 | pub struct HirFormatter<'a> { |
17 | pub db: &'a dyn HirDatabase, | 20 | pub db: &'a dyn HirDatabase, |
18 | fmt: &'a mut dyn fmt::Write, | 21 | fmt: &'a mut dyn fmt::Write, |
@@ -234,39 +237,79 @@ impl HirDisplay for &Ty { | |||
234 | } | 237 | } |
235 | } | 238 | } |
236 | 239 | ||
237 | impl HirDisplay for ApplicationTy { | 240 | impl HirDisplay for ProjectionTy { |
238 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 241 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
239 | if f.should_truncate() { | 242 | if f.should_truncate() { |
240 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 243 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
241 | } | 244 | } |
242 | 245 | ||
243 | match self.ctor { | 246 | let trait_ = f.db.trait_data(self.trait_(f.db)); |
244 | TypeCtor::Bool => write!(f, "bool")?, | 247 | let first_parameter = self.parameters[0].into_displayable( |
245 | TypeCtor::Char => write!(f, "char")?, | 248 | f.db, |
246 | TypeCtor::Int(t) => write!(f, "{}", t)?, | 249 | f.max_size, |
247 | TypeCtor::Float(t) => write!(f, "{}", t)?, | 250 | f.omit_verbose_types, |
248 | TypeCtor::Str => write!(f, "str")?, | 251 | f.display_target, |
249 | TypeCtor::Slice => { | 252 | ); |
250 | let t = self.parameters.as_single(); | 253 | write!(f, "<{} as {}", first_parameter, trait_.name)?; |
254 | if self.parameters.len() > 1 { | ||
255 | write!(f, "<")?; | ||
256 | f.write_joined(&self.parameters[1..], ", ")?; | ||
257 | write!(f, ">")?; | ||
258 | } | ||
259 | write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; | ||
260 | Ok(()) | ||
261 | } | ||
262 | } | ||
263 | |||
264 | impl HirDisplay for Ty { | ||
265 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
266 | if f.should_truncate() { | ||
267 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | ||
268 | } | ||
269 | |||
270 | match self { | ||
271 | Ty::Never => write!(f, "!")?, | ||
272 | Ty::Str => write!(f, "str")?, | ||
273 | Ty::Scalar(Scalar::Bool) => write!(f, "bool")?, | ||
274 | Ty::Scalar(Scalar::Char) => write!(f, "char")?, | ||
275 | &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, | ||
276 | &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, | ||
277 | &Ty::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, | ||
278 | Ty::Slice(parameters) => { | ||
279 | let t = parameters.as_single(); | ||
251 | write!(f, "[")?; | 280 | write!(f, "[")?; |
252 | t.hir_fmt(f)?; | 281 | t.hir_fmt(f)?; |
253 | write!(f, "]")?; | 282 | write!(f, "]")?; |
254 | } | 283 | } |
255 | TypeCtor::Array => { | 284 | Ty::Array(parameters) => { |
256 | let t = self.parameters.as_single(); | 285 | let t = parameters.as_single(); |
257 | write!(f, "[")?; | 286 | write!(f, "[")?; |
258 | t.hir_fmt(f)?; | 287 | t.hir_fmt(f)?; |
259 | write!(f, "; _]")?; | 288 | write!(f, "; _]")?; |
260 | } | 289 | } |
261 | TypeCtor::RawPtr(m) | TypeCtor::Ref(m) => { | 290 | Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => { |
262 | let t = self.parameters.as_single(); | 291 | let t = parameters.as_single(); |
263 | let ty_display = | 292 | let ty_display = |
264 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | 293 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
265 | 294 | ||
266 | if matches!(self.ctor, TypeCtor::RawPtr(_)) { | 295 | if matches!(self, Ty::Raw(..)) { |
267 | write!(f, "*{}", m.as_keyword_for_ptr())?; | 296 | write!( |
297 | f, | ||
298 | "*{}", | ||
299 | match m { | ||
300 | Mutability::Not => "const ", | ||
301 | Mutability::Mut => "mut ", | ||
302 | } | ||
303 | )?; | ||
268 | } else { | 304 | } else { |
269 | write!(f, "&{}", m.as_keyword_for_ref())?; | 305 | write!( |
306 | f, | ||
307 | "&{}", | ||
308 | match m { | ||
309 | Mutability::Not => "", | ||
310 | Mutability::Mut => "mut ", | ||
311 | } | ||
312 | )?; | ||
270 | } | 313 | } |
271 | 314 | ||
272 | let datas; | 315 | let datas; |
@@ -274,10 +317,10 @@ impl HirDisplay for ApplicationTy { | |||
274 | Ty::Dyn(predicates) if predicates.len() > 1 => { | 317 | Ty::Dyn(predicates) if predicates.len() > 1 => { |
275 | Cow::Borrowed(predicates.as_ref()) | 318 | Cow::Borrowed(predicates.as_ref()) |
276 | } | 319 | } |
277 | &Ty::Opaque(OpaqueTy { | 320 | &Ty::Alias(AliasTy::Opaque(OpaqueTy { |
278 | opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), | 321 | opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), |
279 | ref parameters, | 322 | ref parameters, |
280 | }) => { | 323 | })) => { |
281 | datas = | 324 | datas = |
282 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 325 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
283 | let data = (*datas) | 326 | let data = (*datas) |
@@ -304,25 +347,24 @@ impl HirDisplay for ApplicationTy { | |||
304 | write!(f, "{}", ty_display)?; | 347 | write!(f, "{}", ty_display)?; |
305 | } | 348 | } |
306 | } | 349 | } |
307 | TypeCtor::Never => write!(f, "!")?, | 350 | Ty::Tuple(_, substs) => { |
308 | TypeCtor::Tuple { .. } => { | 351 | if substs.len() == 1 { |
309 | let ts = &self.parameters; | ||
310 | if ts.len() == 1 { | ||
311 | write!(f, "(")?; | 352 | write!(f, "(")?; |
312 | ts[0].hir_fmt(f)?; | 353 | substs[0].hir_fmt(f)?; |
313 | write!(f, ",)")?; | 354 | write!(f, ",)")?; |
314 | } else { | 355 | } else { |
315 | write!(f, "(")?; | 356 | write!(f, "(")?; |
316 | f.write_joined(&*ts.0, ", ")?; | 357 | f.write_joined(&*substs.0, ", ")?; |
317 | write!(f, ")")?; | 358 | write!(f, ")")?; |
318 | } | 359 | } |
319 | } | 360 | } |
320 | TypeCtor::FnPtr { is_varargs, .. } => { | 361 | Ty::Function(fn_ptr) => { |
321 | let sig = FnSig::from_fn_ptr_substs(&self.parameters, is_varargs); | 362 | let sig = CallableSig::from_fn_ptr(fn_ptr); |
322 | sig.hir_fmt(f)?; | 363 | sig.hir_fmt(f)?; |
323 | } | 364 | } |
324 | TypeCtor::FnDef(def) => { | 365 | Ty::FnDef(def, parameters) => { |
325 | let sig = f.db.callable_item_signature(def).subst(&self.parameters); | 366 | let def = *def; |
367 | let sig = f.db.callable_item_signature(def).subst(parameters); | ||
326 | match def { | 368 | match def { |
327 | CallableDefId::FunctionId(ff) => { | 369 | CallableDefId::FunctionId(ff) => { |
328 | write!(f, "fn {}", f.db.function_data(ff).name)? | 370 | write!(f, "fn {}", f.db.function_data(ff).name)? |
@@ -332,7 +374,7 @@ impl HirDisplay for ApplicationTy { | |||
332 | write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? | 374 | write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? |
333 | } | 375 | } |
334 | }; | 376 | }; |
335 | if self.parameters.len() > 0 { | 377 | if parameters.len() > 0 { |
336 | let generics = generics(f.db.upcast(), def.into()); | 378 | let generics = generics(f.db.upcast(), def.into()); |
337 | let (parent_params, self_param, type_params, _impl_trait_params) = | 379 | let (parent_params, self_param, type_params, _impl_trait_params) = |
338 | generics.provenance_split(); | 380 | generics.provenance_split(); |
@@ -340,7 +382,7 @@ impl HirDisplay for ApplicationTy { | |||
340 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? | 382 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? |
341 | if total_len > 0 { | 383 | if total_len > 0 { |
342 | write!(f, "<")?; | 384 | write!(f, "<")?; |
343 | f.write_joined(&self.parameters.0[..total_len], ", ")?; | 385 | f.write_joined(¶meters.0[..total_len], ", ")?; |
344 | write!(f, ">")?; | 386 | write!(f, ">")?; |
345 | } | 387 | } |
346 | } | 388 | } |
@@ -359,20 +401,20 @@ impl HirDisplay for ApplicationTy { | |||
359 | write!(f, " -> {}", ret_display)?; | 401 | write!(f, " -> {}", ret_display)?; |
360 | } | 402 | } |
361 | } | 403 | } |
362 | TypeCtor::Adt(def_id) => { | 404 | Ty::Adt(AdtId(def_id), parameters) => { |
363 | match f.display_target { | 405 | match f.display_target { |
364 | DisplayTarget::Diagnostics | DisplayTarget::Test => { | 406 | DisplayTarget::Diagnostics | DisplayTarget::Test => { |
365 | let name = match def_id { | 407 | let name = match *def_id { |
366 | AdtId::StructId(it) => f.db.struct_data(it).name.clone(), | 408 | hir_def::AdtId::StructId(it) => f.db.struct_data(it).name.clone(), |
367 | AdtId::UnionId(it) => f.db.union_data(it).name.clone(), | 409 | hir_def::AdtId::UnionId(it) => f.db.union_data(it).name.clone(), |
368 | AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), | 410 | hir_def::AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), |
369 | }; | 411 | }; |
370 | write!(f, "{}", name)?; | 412 | write!(f, "{}", name)?; |
371 | } | 413 | } |
372 | DisplayTarget::SourceCode { module_id } => { | 414 | DisplayTarget::SourceCode { module_id } => { |
373 | if let Some(path) = find_path::find_path( | 415 | if let Some(path) = find_path::find_path( |
374 | f.db.upcast(), | 416 | f.db.upcast(), |
375 | ItemInNs::Types(def_id.into()), | 417 | ItemInNs::Types((*def_id).into()), |
376 | module_id, | 418 | module_id, |
377 | ) { | 419 | ) { |
378 | write!(f, "{}", path)?; | 420 | write!(f, "{}", path)?; |
@@ -384,19 +426,18 @@ impl HirDisplay for ApplicationTy { | |||
384 | } | 426 | } |
385 | } | 427 | } |
386 | 428 | ||
387 | if self.parameters.len() > 0 { | 429 | if parameters.len() > 0 { |
388 | let parameters_to_write = | 430 | let parameters_to_write = |
389 | if f.display_target.is_source_code() || f.omit_verbose_types() { | 431 | if f.display_target.is_source_code() || f.omit_verbose_types() { |
390 | match self | 432 | match self |
391 | .ctor | ||
392 | .as_generic_def() | 433 | .as_generic_def() |
393 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) | 434 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) |
394 | .filter(|defaults| !defaults.is_empty()) | 435 | .filter(|defaults| !defaults.is_empty()) |
395 | { | 436 | { |
396 | None => self.parameters.0.as_ref(), | 437 | None => parameters.0.as_ref(), |
397 | Some(default_parameters) => { | 438 | Some(default_parameters) => { |
398 | let mut default_from = 0; | 439 | let mut default_from = 0; |
399 | for (i, parameter) in self.parameters.iter().enumerate() { | 440 | for (i, parameter) in parameters.iter().enumerate() { |
400 | match (parameter, default_parameters.get(i)) { | 441 | match (parameter, default_parameters.get(i)) { |
401 | (&Ty::Unknown, _) | (_, None) => { | 442 | (&Ty::Unknown, _) | (_, None) => { |
402 | default_from = i + 1; | 443 | default_from = i + 1; |
@@ -404,18 +445,18 @@ impl HirDisplay for ApplicationTy { | |||
404 | (_, Some(default_parameter)) => { | 445 | (_, Some(default_parameter)) => { |
405 | let actual_default = default_parameter | 446 | let actual_default = default_parameter |
406 | .clone() | 447 | .clone() |
407 | .subst(&self.parameters.prefix(i)); | 448 | .subst(¶meters.prefix(i)); |
408 | if parameter != &actual_default { | 449 | if parameter != &actual_default { |
409 | default_from = i + 1; | 450 | default_from = i + 1; |
410 | } | 451 | } |
411 | } | 452 | } |
412 | } | 453 | } |
413 | } | 454 | } |
414 | &self.parameters.0[0..default_from] | 455 | ¶meters.0[0..default_from] |
415 | } | 456 | } |
416 | } | 457 | } |
417 | } else { | 458 | } else { |
418 | self.parameters.0.as_ref() | 459 | parameters.0.as_ref() |
419 | }; | 460 | }; |
420 | if !parameters_to_write.is_empty() { | 461 | if !parameters_to_write.is_empty() { |
421 | write!(f, "<")?; | 462 | write!(f, "<")?; |
@@ -424,61 +465,54 @@ impl HirDisplay for ApplicationTy { | |||
424 | } | 465 | } |
425 | } | 466 | } |
426 | } | 467 | } |
427 | TypeCtor::AssociatedType(type_alias) => { | 468 | Ty::AssociatedType(type_alias, parameters) => { |
428 | let trait_ = match type_alias.lookup(f.db.upcast()).container { | 469 | let trait_ = match type_alias.lookup(f.db.upcast()).container { |
429 | AssocContainerId::TraitId(it) => it, | 470 | AssocContainerId::TraitId(it) => it, |
430 | _ => panic!("not an associated type"), | 471 | _ => panic!("not an associated type"), |
431 | }; | 472 | }; |
432 | let trait_ = f.db.trait_data(trait_); | 473 | let trait_ = f.db.trait_data(trait_); |
433 | let type_alias_data = f.db.type_alias_data(type_alias); | 474 | let type_alias_data = f.db.type_alias_data(*type_alias); |
434 | 475 | ||
435 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) | 476 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) |
436 | if f.display_target.is_test() { | 477 | if f.display_target.is_test() { |
437 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; | 478 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; |
438 | if self.parameters.len() > 0 { | 479 | if parameters.len() > 0 { |
439 | write!(f, "<")?; | 480 | write!(f, "<")?; |
440 | f.write_joined(&*self.parameters.0, ", ")?; | 481 | f.write_joined(&*parameters.0, ", ")?; |
441 | write!(f, ">")?; | 482 | write!(f, ">")?; |
442 | } | 483 | } |
443 | } else { | 484 | } else { |
444 | let projection_ty = ProjectionTy { | 485 | let projection_ty = |
445 | associated_ty: type_alias, | 486 | ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() }; |
446 | parameters: self.parameters.clone(), | ||
447 | }; | ||
448 | 487 | ||
449 | projection_ty.hir_fmt(f)?; | 488 | projection_ty.hir_fmt(f)?; |
450 | } | 489 | } |
451 | } | 490 | } |
452 | TypeCtor::ForeignType(type_alias) => { | 491 | Ty::ForeignType(type_alias) => { |
453 | let type_alias = f.db.type_alias_data(type_alias); | 492 | let type_alias = f.db.type_alias_data(*type_alias); |
454 | write!(f, "{}", type_alias.name)?; | 493 | write!(f, "{}", type_alias.name)?; |
455 | if self.parameters.len() > 0 { | ||
456 | write!(f, "<")?; | ||
457 | f.write_joined(&*self.parameters.0, ", ")?; | ||
458 | write!(f, ">")?; | ||
459 | } | ||
460 | } | 494 | } |
461 | TypeCtor::OpaqueType(opaque_ty_id) => { | 495 | Ty::OpaqueType(opaque_ty_id, parameters) => { |
462 | match opaque_ty_id { | 496 | match opaque_ty_id { |
463 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 497 | &OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
464 | let datas = | 498 | let datas = |
465 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 499 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
466 | let data = (*datas) | 500 | let data = (*datas) |
467 | .as_ref() | 501 | .as_ref() |
468 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 502 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
469 | let bounds = data.subst(&self.parameters); | 503 | let bounds = data.subst(¶meters); |
470 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; | 504 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; |
471 | // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution | 505 | // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution |
472 | } | 506 | } |
473 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | 507 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { |
474 | write!(f, "impl Future<Output = ")?; | 508 | write!(f, "impl Future<Output = ")?; |
475 | self.parameters[0].hir_fmt(f)?; | 509 | parameters[0].hir_fmt(f)?; |
476 | write!(f, ">")?; | 510 | write!(f, ">")?; |
477 | } | 511 | } |
478 | } | 512 | } |
479 | } | 513 | } |
480 | TypeCtor::Closure { .. } => { | 514 | Ty::Closure(.., substs) => { |
481 | let sig = self.parameters[0].callable_sig(f.db); | 515 | let sig = substs[0].callable_sig(f.db); |
482 | if let Some(sig) = sig { | 516 | if let Some(sig) = sig { |
483 | if sig.params().is_empty() { | 517 | if sig.params().is_empty() { |
484 | write!(f, "||")?; | 518 | write!(f, "||")?; |
@@ -501,44 +535,6 @@ impl HirDisplay for ApplicationTy { | |||
501 | write!(f, "{{closure}}")?; | 535 | write!(f, "{{closure}}")?; |
502 | } | 536 | } |
503 | } | 537 | } |
504 | } | ||
505 | Ok(()) | ||
506 | } | ||
507 | } | ||
508 | |||
509 | impl HirDisplay for ProjectionTy { | ||
510 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
511 | if f.should_truncate() { | ||
512 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | ||
513 | } | ||
514 | |||
515 | let trait_ = f.db.trait_data(self.trait_(f.db)); | ||
516 | let first_parameter = self.parameters[0].into_displayable( | ||
517 | f.db, | ||
518 | f.max_size, | ||
519 | f.omit_verbose_types, | ||
520 | f.display_target, | ||
521 | ); | ||
522 | write!(f, "<{} as {}", first_parameter, trait_.name)?; | ||
523 | if self.parameters.len() > 1 { | ||
524 | write!(f, "<")?; | ||
525 | f.write_joined(&self.parameters[1..], ", ")?; | ||
526 | write!(f, ">")?; | ||
527 | } | ||
528 | write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; | ||
529 | Ok(()) | ||
530 | } | ||
531 | } | ||
532 | |||
533 | impl HirDisplay for Ty { | ||
534 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
535 | if f.should_truncate() { | ||
536 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | ||
537 | } | ||
538 | |||
539 | match self { | ||
540 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, | ||
541 | Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, | ||
542 | Ty::Placeholder(id) => { | 538 | Ty::Placeholder(id) => { |
543 | let generics = generics(f.db.upcast(), id.parent); | 539 | let generics = generics(f.db.upcast(), id.parent); |
544 | let param_data = &generics.params.types[id.local_id]; | 540 | let param_data = &generics.params.types[id.local_id]; |
@@ -557,11 +553,12 @@ impl HirDisplay for Ty { | |||
557 | } | 553 | } |
558 | } | 554 | } |
559 | } | 555 | } |
560 | Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 556 | Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
561 | Ty::Dyn(predicates) => { | 557 | Ty::Dyn(predicates) => { |
562 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 558 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; |
563 | } | 559 | } |
564 | Ty::Opaque(opaque_ty) => { | 560 | Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
561 | Ty::Alias(AliasTy::Opaque(opaque_ty)) => { | ||
565 | match opaque_ty.opaque_ty_id { | 562 | match opaque_ty.opaque_ty_id { |
566 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 563 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
567 | let datas = | 564 | let datas = |
@@ -585,13 +582,13 @@ impl HirDisplay for Ty { | |||
585 | } | 582 | } |
586 | write!(f, "{{unknown}}")?; | 583 | write!(f, "{{unknown}}")?; |
587 | } | 584 | } |
588 | Ty::Infer(..) => write!(f, "_")?, | 585 | Ty::InferenceVar(..) => write!(f, "_")?, |
589 | } | 586 | } |
590 | Ok(()) | 587 | Ok(()) |
591 | } | 588 | } |
592 | } | 589 | } |
593 | 590 | ||
594 | impl HirDisplay for FnSig { | 591 | impl HirDisplay for CallableSig { |
595 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 592 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
596 | write!(f, "fn(")?; | 593 | write!(f, "fn(")?; |
597 | f.write_joined(self.params(), ", ")?; | 594 | f.write_joined(self.params(), ", ")?; |
@@ -614,7 +611,7 @@ impl HirDisplay for FnSig { | |||
614 | } | 611 | } |
615 | 612 | ||
616 | fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> { | 613 | fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> { |
617 | let krate = trait_.lookup(db).container.module(db).krate(); | 614 | let krate = trait_.lookup(db).container.krate(); |
618 | let fn_traits = [ | 615 | let fn_traits = [ |
619 | db.lang_item(krate, "fn".into()), | 616 | db.lang_item(krate, "fn".into()), |
620 | db.lang_item(krate, "fn_mut".into()), | 617 | db.lang_item(krate, "fn_mut".into()), |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 4b683c5a7..4d771a91e 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -18,6 +18,7 @@ use std::mem; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::Mutability; | ||
21 | use hir_def::{ | 22 | use hir_def::{ |
22 | body::Body, | 23 | body::Body, |
23 | data::{ConstData, FunctionData, StaticData}, | 24 | data::{ConstData, FunctionData, StaticData}, |
@@ -25,7 +26,7 @@ use hir_def::{ | |||
25 | lang_item::LangItemTarget, | 26 | lang_item::LangItemTarget, |
26 | path::{path, Path}, | 27 | path::{path, Path}, |
27 | resolver::{HasResolver, Resolver, TypeNs}, | 28 | resolver::{HasResolver, Resolver, TypeNs}, |
28 | type_ref::{Mutability, TypeRef}, | 29 | type_ref::TypeRef, |
29 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, | 30 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, |
30 | TypeAliasId, VariantId, | 31 | TypeAliasId, VariantId, |
31 | }; | 32 | }; |
@@ -36,25 +37,15 @@ use stdx::impl_from; | |||
36 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
37 | 38 | ||
38 | use super::{ | 39 | use super::{ |
39 | primitive::{FloatTy, IntTy}, | ||
40 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 40 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, |
41 | InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, | 41 | InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk, |
42 | }; | 42 | }; |
43 | use crate::{ | 43 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, AliasTy, |
45 | }; | 45 | }; |
46 | 46 | ||
47 | pub(crate) use unify::unify; | 47 | pub(crate) use unify::unify; |
48 | 48 | ||
49 | macro_rules! ty_app { | ||
50 | ($ctor:pat, $param:pat) => { | ||
51 | crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param }) | ||
52 | }; | ||
53 | ($ctor:pat) => { | ||
54 | ty_app!($ctor, _) | ||
55 | }; | ||
56 | } | ||
57 | |||
58 | mod unify; | 49 | mod unify; |
59 | mod path; | 50 | mod path; |
60 | mod expr; | 51 | mod expr; |
@@ -97,7 +88,7 @@ impl BindingMode { | |||
97 | fn convert(annotation: BindingAnnotation) -> BindingMode { | 88 | fn convert(annotation: BindingAnnotation) -> BindingMode { |
98 | match annotation { | 89 | match annotation { |
99 | BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move, | 90 | BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move, |
100 | BindingAnnotation::Ref => BindingMode::Ref(Mutability::Shared), | 91 | BindingAnnotation::Ref => BindingMode::Ref(Mutability::Not), |
101 | BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut), | 92 | BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut), |
102 | } | 93 | } |
103 | } | 94 | } |
@@ -405,7 +396,7 @@ impl<'a> InferenceContext<'a> { | |||
405 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | 396 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { |
406 | let ty = self.resolve_ty_as_possible(ty); | 397 | let ty = self.resolve_ty_as_possible(ty); |
407 | ty.fold(&mut |ty| match ty { | 398 | ty.fold(&mut |ty| match ty { |
408 | Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty), | 399 | Ty::Alias(AliasTy::Projection(proj_ty)) => self.normalize_projection_ty(proj_ty), |
409 | _ => ty, | 400 | _ => ty, |
410 | }) | 401 | }) |
411 | } | 402 | } |
@@ -664,30 +655,17 @@ impl<'a> InferenceContext<'a> { | |||
664 | /// two are used for inference of literal values (e.g. `100` could be one of | 655 | /// two are used for inference of literal values (e.g. `100` could be one of |
665 | /// several integer types). | 656 | /// several integer types). |
666 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 657 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
667 | pub enum InferTy { | 658 | pub struct InferenceVar { |
668 | TypeVar(unify::TypeVarId), | 659 | index: u32, |
669 | IntVar(unify::TypeVarId), | ||
670 | FloatVar(unify::TypeVarId), | ||
671 | MaybeNeverTypeVar(unify::TypeVarId), | ||
672 | } | 660 | } |
673 | 661 | ||
674 | impl InferTy { | 662 | impl InferenceVar { |
675 | fn to_inner(self) -> unify::TypeVarId { | 663 | fn to_inner(self) -> unify::TypeVarId { |
676 | match self { | 664 | unify::TypeVarId(self.index) |
677 | InferTy::TypeVar(ty) | ||
678 | | InferTy::IntVar(ty) | ||
679 | | InferTy::FloatVar(ty) | ||
680 | | InferTy::MaybeNeverTypeVar(ty) => ty, | ||
681 | } | ||
682 | } | 665 | } |
683 | 666 | ||
684 | fn fallback_value(self) -> Ty { | 667 | fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self { |
685 | match self { | 668 | InferenceVar { index } |
686 | InferTy::TypeVar(..) => Ty::Unknown, | ||
687 | InferTy::IntVar(..) => Ty::simple(TypeCtor::Int(IntTy::i32())), | ||
688 | InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(FloatTy::f64())), | ||
689 | InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never), | ||
690 | } | ||
691 | } | 669 | } |
692 | } | 670 | } |
693 | 671 | ||
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 32c7c57cd..7e8846f27 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -4,12 +4,12 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; | 7 | use chalk_ir::{Mutability, TyVariableKind}; |
8 | use test_utils::mark; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | 9 | ||
10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; | 10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; |
11 | 11 | ||
12 | use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext}; | 12 | use super::{InEnvironment, InferenceContext}; |
13 | 13 | ||
14 | impl<'a> InferenceContext<'a> { | 14 | impl<'a> InferenceContext<'a> { |
15 | /// Unify two types, but may coerce the first one to the second one | 15 | /// Unify two types, but may coerce the first one to the second one |
@@ -33,8 +33,8 @@ impl<'a> InferenceContext<'a> { | |||
33 | } else if self.coerce(ty2, ty1) { | 33 | } else if self.coerce(ty2, ty1) { |
34 | ty1.clone() | 34 | ty1.clone() |
35 | } else { | 35 | } else { |
36 | if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { | 36 | if let (Ty::FnDef(..), Ty::FnDef(..)) = (ty1, ty2) { |
37 | mark::hit!(coerce_fn_reification); | 37 | cov_mark::hit!(coerce_fn_reification); |
38 | // Special case: two function types. Try to coerce both to | 38 | // Special case: two function types. Try to coerce both to |
39 | // pointers to have a chance at getting a match. See | 39 | // pointers to have a chance at getting a match. See |
40 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 | 40 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 |
@@ -44,7 +44,7 @@ impl<'a> InferenceContext<'a> { | |||
44 | let ptr_ty2 = Ty::fn_ptr(sig2); | 44 | let ptr_ty2 = Ty::fn_ptr(sig2); |
45 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) | 45 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) |
46 | } else { | 46 | } else { |
47 | mark::hit!(coerce_merge_fail_fallback); | 47 | cov_mark::hit!(coerce_merge_fail_fallback); |
48 | ty1.clone() | 48 | ty1.clone() |
49 | } | 49 | } |
50 | } | 50 | } |
@@ -53,12 +53,11 @@ impl<'a> InferenceContext<'a> { | |||
53 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { | 53 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { |
54 | match (&from_ty, to_ty) { | 54 | match (&from_ty, to_ty) { |
55 | // Never type will make type variable to fallback to Never Type instead of Unknown. | 55 | // Never type will make type variable to fallback to Never Type instead of Unknown. |
56 | (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { | 56 | (Ty::Never, Ty::InferenceVar(tv, TyVariableKind::General)) => { |
57 | let var = self.table.new_maybe_never_type_var(); | 57 | self.table.type_variable_table.set_diverging(*tv, true); |
58 | self.table.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); | ||
59 | return true; | 58 | return true; |
60 | } | 59 | } |
61 | (ty_app!(TypeCtor::Never), _) => return true, | 60 | (Ty::Never, _) => return true, |
62 | 61 | ||
63 | // Trivial cases, this should go after `never` check to | 62 | // Trivial cases, this should go after `never` check to |
64 | // avoid infer result type to be never | 63 | // avoid infer result type to be never |
@@ -71,38 +70,33 @@ impl<'a> InferenceContext<'a> { | |||
71 | 70 | ||
72 | // Pointer weakening and function to pointer | 71 | // Pointer weakening and function to pointer |
73 | match (&mut from_ty, to_ty) { | 72 | match (&mut from_ty, to_ty) { |
74 | // `*mut T`, `&mut T, `&T`` -> `*const T` | 73 | // `*mut T` -> `*const T` |
75 | // `&mut T` -> `&T` | 74 | // `&mut T` -> `&T` |
76 | // `&mut T` -> `*mut T` | 75 | (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Not, ..)) |
77 | (ty_app!(c1@TypeCtor::RawPtr(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) | 76 | | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Not, ..)) => { |
78 | | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) | 77 | *m1 = *m2; |
79 | | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::Ref(Mutability::Shared))) | 78 | } |
80 | | (ty_app!(c1@TypeCtor::Ref(Mutability::Mut)), ty_app!(c2@TypeCtor::RawPtr(_))) => { | 79 | // `&T` -> `*const T` |
81 | *c1 = *c2; | 80 | // `&mut T` -> `*mut T`/`*const T` |
81 | (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Not, ..)) | ||
82 | | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { | ||
83 | from_ty = Ty::Raw(m2, substs.clone()); | ||
82 | } | 84 | } |
83 | 85 | ||
84 | // Illegal mutablity conversion | 86 | // Illegal mutability conversion |
85 | ( | 87 | (Ty::Raw(Mutability::Not, ..), Ty::Raw(Mutability::Mut, ..)) |
86 | ty_app!(TypeCtor::RawPtr(Mutability::Shared)), | 88 | | (Ty::Ref(Mutability::Not, ..), Ty::Ref(Mutability::Mut, ..)) => return false, |
87 | ty_app!(TypeCtor::RawPtr(Mutability::Mut)), | ||
88 | ) | ||
89 | | ( | ||
90 | ty_app!(TypeCtor::Ref(Mutability::Shared)), | ||
91 | ty_app!(TypeCtor::Ref(Mutability::Mut)), | ||
92 | ) => return false, | ||
93 | 89 | ||
94 | // `{function_type}` -> `fn()` | 90 | // `{function_type}` -> `fn()` |
95 | (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnPtr { .. })) => { | 91 | (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { |
96 | match from_ty.callable_sig(self.db) { | 92 | None => return false, |
97 | None => return false, | 93 | Some(sig) => { |
98 | Some(sig) => { | 94 | from_ty = Ty::fn_ptr(sig); |
99 | from_ty = Ty::fn_ptr(sig); | ||
100 | } | ||
101 | } | 95 | } |
102 | } | 96 | }, |
103 | 97 | ||
104 | (ty_app!(TypeCtor::Closure { .. }, params), ty_app!(TypeCtor::FnPtr { .. })) => { | 98 | (Ty::Closure(.., substs), Ty::Function { .. }) => { |
105 | from_ty = params[0].clone(); | 99 | from_ty = substs[0].clone(); |
106 | } | 100 | } |
107 | 101 | ||
108 | _ => {} | 102 | _ => {} |
@@ -115,9 +109,7 @@ impl<'a> InferenceContext<'a> { | |||
115 | // Auto Deref if cannot coerce | 109 | // Auto Deref if cannot coerce |
116 | match (&from_ty, to_ty) { | 110 | match (&from_ty, to_ty) { |
117 | // FIXME: DerefMut | 111 | // FIXME: DerefMut |
118 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) => { | 112 | (Ty::Ref(_, st1), Ty::Ref(_, st2)) => self.unify_autoderef_behind_ref(&st1[0], &st2[0]), |
119 | self.unify_autoderef_behind_ref(&st1[0], &st2[0]) | ||
120 | } | ||
121 | 113 | ||
122 | // Otherwise, normal unify | 114 | // Otherwise, normal unify |
123 | _ => self.unify(&from_ty, to_ty), | 115 | _ => self.unify(&from_ty, to_ty), |
@@ -178,17 +170,17 @@ impl<'a> InferenceContext<'a> { | |||
178 | }, | 170 | }, |
179 | ) { | 171 | ) { |
180 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 172 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
181 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { | 173 | let from_ty = self.resolve_ty_shallow(&derefed_ty); |
182 | // Stop when constructor matches. | 174 | // Stop when constructor matches. |
183 | (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { | 175 | if from_ty.equals_ctor(&to_ty) { |
184 | // It will not recurse to `coerce`. | 176 | // It will not recurse to `coerce`. |
185 | return self.table.unify_substs(st1, st2, 0); | 177 | return match (from_ty.substs(), to_ty.substs()) { |
186 | } | 178 | (Some(st1), Some(st2)) => self.table.unify_substs(st1, st2, 0), |
187 | _ => { | 179 | (None, None) => true, |
188 | if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { | 180 | _ => false, |
189 | return true; | 181 | }; |
190 | } | 182 | } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { |
191 | } | 183 | return true; |
192 | } | 184 | } |
193 | } | 185 | } |
194 | 186 | ||
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index cb59a6937..262177ffb 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -3,23 +3,25 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::{Mutability, TyVariableKind}; | ||
6 | use hir_def::{ | 7 | use hir_def::{ |
7 | builtin_type::Signedness, | ||
8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
10 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
11 | AdtId, AssocContainerId, FieldId, Lookup, | 11 | AssocContainerId, FieldId, Lookup, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use syntax::ast::RangeOp; | 14 | use syntax::ast::RangeOp; |
15 | use test_utils::mark; | ||
16 | 15 | ||
17 | use crate::{ | 16 | use crate::{ |
18 | autoderef, method_resolution, op, | 17 | autoderef, |
18 | lower::lower_to_chalk_mutability, | ||
19 | method_resolution, op, | ||
20 | primitive::{self, UintTy}, | ||
19 | traits::{FnTrait, InEnvironment}, | 21 | traits::{FnTrait, InEnvironment}, |
20 | utils::{generics, variant_data, Generics}, | 22 | utils::{generics, variant_data, Generics}, |
21 | ApplicationTy, Binders, CallableDefId, InferTy, IntTy, Mutability, Obligation, OpaqueTyId, | 23 | AdtId, Binders, CallableDefId, FnPointer, FnSig, Obligation, OpaqueTyId, Rawness, Scalar, |
22 | Rawness, Substs, TraitRef, Ty, TypeCtor, | 24 | Substs, TraitRef, Ty, |
23 | }; | 25 | }; |
24 | 26 | ||
25 | use super::{ | 27 | use super::{ |
@@ -82,10 +84,7 @@ impl<'a> InferenceContext<'a> { | |||
82 | arg_tys.push(arg); | 84 | arg_tys.push(arg); |
83 | } | 85 | } |
84 | let parameters = param_builder.build(); | 86 | let parameters = param_builder.build(); |
85 | let arg_ty = Ty::Apply(ApplicationTy { | 87 | let arg_ty = Ty::Tuple(num_args, parameters); |
86 | ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, | ||
87 | parameters, | ||
88 | }); | ||
89 | let substs = | 88 | let substs = |
90 | Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 89 | Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
91 | 90 | ||
@@ -120,7 +119,7 @@ impl<'a> InferenceContext<'a> { | |||
120 | Expr::Missing => Ty::Unknown, | 119 | Expr::Missing => Ty::Unknown, |
121 | Expr::If { condition, then_branch, else_branch } => { | 120 | Expr::If { condition, then_branch, else_branch } => { |
122 | // if let is desugared to match, so this is always simple if | 121 | // if let is desugared to match, so this is always simple if |
123 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 122 | self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); |
124 | 123 | ||
125 | let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); | 124 | let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |
126 | let mut both_arms_diverge = Diverges::Always; | 125 | let mut both_arms_diverge = Diverges::Always; |
@@ -175,7 +174,7 @@ impl<'a> InferenceContext<'a> { | |||
175 | // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> | 174 | // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> |
176 | let inner_ty = self.infer_expr(*body, &Expectation::none()); | 175 | let inner_ty = self.infer_expr(*body, &Expectation::none()); |
177 | let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); | 176 | let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); |
178 | Ty::apply_one(TypeCtor::OpaqueType(opaque_ty_id), inner_ty) | 177 | Ty::OpaqueType(opaque_ty_id, Substs::single(inner_ty)) |
179 | } | 178 | } |
180 | Expr::Loop { body, label } => { | 179 | Expr::Loop { body, label } => { |
181 | self.breakables.push(BreakableContext { | 180 | self.breakables.push(BreakableContext { |
@@ -193,7 +192,7 @@ impl<'a> InferenceContext<'a> { | |||
193 | if ctxt.may_break { | 192 | if ctxt.may_break { |
194 | ctxt.break_ty | 193 | ctxt.break_ty |
195 | } else { | 194 | } else { |
196 | Ty::simple(TypeCtor::Never) | 195 | Ty::Never |
197 | } | 196 | } |
198 | } | 197 | } |
199 | Expr::While { condition, body, label } => { | 198 | Expr::While { condition, body, label } => { |
@@ -203,7 +202,7 @@ impl<'a> InferenceContext<'a> { | |||
203 | label: label.map(|label| self.body[label].name.clone()), | 202 | label: label.map(|label| self.body[label].name.clone()), |
204 | }); | 203 | }); |
205 | // while let is desugared to a match loop, so this is always simple while | 204 | // while let is desugared to a match loop, so this is always simple while |
206 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 205 | self.infer_expr(*condition, &Expectation::has_type(Ty::Scalar(Scalar::Bool))); |
207 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 206 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
208 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); | 207 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); |
209 | // the body may not run, so it diverging doesn't mean we diverge | 208 | // the body may not run, so it diverging doesn't mean we diverge |
@@ -250,12 +249,12 @@ impl<'a> InferenceContext<'a> { | |||
250 | None => self.table.new_type_var(), | 249 | None => self.table.new_type_var(), |
251 | }; | 250 | }; |
252 | sig_tys.push(ret_ty.clone()); | 251 | sig_tys.push(ret_ty.clone()); |
253 | let sig_ty = Ty::apply( | 252 | let sig_ty = Ty::Function(FnPointer { |
254 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false }, | 253 | num_args: sig_tys.len() - 1, |
255 | Substs(sig_tys.clone().into()), | 254 | sig: FnSig { variadic: false }, |
256 | ); | 255 | substs: Substs(sig_tys.clone().into()), |
257 | let closure_ty = | 256 | }); |
258 | Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); | 257 | let closure_ty = Ty::Closure(self.owner, tgt_expr, Substs::single(sig_ty)); |
259 | 258 | ||
260 | // Eagerly try to relate the closure type with the expected | 259 | // Eagerly try to relate the closure type with the expected |
261 | // type, otherwise we often won't have enough information to | 260 | // type, otherwise we often won't have enough information to |
@@ -306,11 +305,8 @@ impl<'a> InferenceContext<'a> { | |||
306 | Expr::Match { expr, arms } => { | 305 | Expr::Match { expr, arms } => { |
307 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | 306 | let input_ty = self.infer_expr(*expr, &Expectation::none()); |
308 | 307 | ||
309 | let mut result_ty = if arms.is_empty() { | 308 | let mut result_ty = |
310 | Ty::simple(TypeCtor::Never) | 309 | if arms.is_empty() { Ty::Never } else { self.table.new_type_var() }; |
311 | } else { | ||
312 | self.table.new_type_var() | ||
313 | }; | ||
314 | 310 | ||
315 | let matchee_diverges = self.diverges; | 311 | let matchee_diverges = self.diverges; |
316 | let mut all_arms_diverge = Diverges::Always; | 312 | let mut all_arms_diverge = Diverges::Always; |
@@ -321,7 +317,7 @@ impl<'a> InferenceContext<'a> { | |||
321 | if let Some(guard_expr) = arm.guard { | 317 | if let Some(guard_expr) = arm.guard { |
322 | self.infer_expr( | 318 | self.infer_expr( |
323 | guard_expr, | 319 | guard_expr, |
324 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), | 320 | &Expectation::has_type(Ty::Scalar(Scalar::Bool)), |
325 | ); | 321 | ); |
326 | } | 322 | } |
327 | 323 | ||
@@ -339,7 +335,7 @@ impl<'a> InferenceContext<'a> { | |||
339 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); | 335 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); |
340 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) | 336 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) |
341 | } | 337 | } |
342 | Expr::Continue { .. } => Ty::simple(TypeCtor::Never), | 338 | Expr::Continue { .. } => Ty::Never, |
343 | Expr::Break { expr, label } => { | 339 | Expr::Break { expr, label } => { |
344 | let val_ty = if let Some(expr) = expr { | 340 | let val_ty = if let Some(expr) = expr { |
345 | self.infer_expr(*expr, &Expectation::none()) | 341 | self.infer_expr(*expr, &Expectation::none()) |
@@ -364,8 +360,7 @@ impl<'a> InferenceContext<'a> { | |||
364 | expr: tgt_expr, | 360 | expr: tgt_expr, |
365 | }); | 361 | }); |
366 | } | 362 | } |
367 | 363 | Ty::Never | |
368 | Ty::simple(TypeCtor::Never) | ||
369 | } | 364 | } |
370 | Expr::Return { expr } => { | 365 | Expr::Return { expr } => { |
371 | if let Some(expr) = expr { | 366 | if let Some(expr) = expr { |
@@ -374,14 +369,14 @@ impl<'a> InferenceContext<'a> { | |||
374 | let unit = Ty::unit(); | 369 | let unit = Ty::unit(); |
375 | self.coerce(&unit, &self.return_ty.clone()); | 370 | self.coerce(&unit, &self.return_ty.clone()); |
376 | } | 371 | } |
377 | Ty::simple(TypeCtor::Never) | 372 | Ty::Never |
378 | } | 373 | } |
379 | Expr::Yield { expr } => { | 374 | Expr::Yield { expr } => { |
380 | // FIXME: track yield type for coercion | 375 | // FIXME: track yield type for coercion |
381 | if let Some(expr) = expr { | 376 | if let Some(expr) = expr { |
382 | self.infer_expr(*expr, &Expectation::none()); | 377 | self.infer_expr(*expr, &Expectation::none()); |
383 | } | 378 | } |
384 | Ty::simple(TypeCtor::Never) | 379 | Ty::Never |
385 | } | 380 | } |
386 | Expr::RecordLit { path, fields, spread } => { | 381 | Expr::RecordLit { path, fields, spread } => { |
387 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 382 | let (ty, def_id) = self.resolve_variant(path.as_ref()); |
@@ -391,7 +386,7 @@ impl<'a> InferenceContext<'a> { | |||
391 | 386 | ||
392 | self.unify(&ty, &expected.ty); | 387 | self.unify(&ty, &expected.ty); |
393 | 388 | ||
394 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 389 | let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); |
395 | let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); | 390 | let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); |
396 | let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); | 391 | let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); |
397 | for (field_idx, field) in fields.iter().enumerate() { | 392 | for (field_idx, field) in fields.iter().enumerate() { |
@@ -430,30 +425,23 @@ impl<'a> InferenceContext<'a> { | |||
430 | }, | 425 | }, |
431 | ) | 426 | ) |
432 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { | 427 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { |
433 | Ty::Apply(a_ty) => match a_ty.ctor { | 428 | Ty::Tuple(_, substs) => { |
434 | TypeCtor::Tuple { .. } => name | 429 | name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) |
435 | .as_tuple_index() | 430 | } |
436 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), | 431 | Ty::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { |
437 | TypeCtor::Adt(AdtId::StructId(s)) => { | 432 | self.db.struct_data(s).variant_data.field(name).map(|local_id| { |
438 | self.db.struct_data(s).variant_data.field(name).map(|local_id| { | 433 | let field = FieldId { parent: s.into(), local_id }; |
439 | let field = FieldId { parent: s.into(), local_id }; | 434 | self.write_field_resolution(tgt_expr, field); |
440 | self.write_field_resolution(tgt_expr, field); | 435 | self.db.field_types(s.into())[field.local_id].clone().subst(¶meters) |
441 | self.db.field_types(s.into())[field.local_id] | 436 | }) |
442 | .clone() | 437 | } |
443 | .subst(&a_ty.parameters) | 438 | Ty::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { |
444 | }) | 439 | self.db.union_data(u).variant_data.field(name).map(|local_id| { |
445 | } | 440 | let field = FieldId { parent: u.into(), local_id }; |
446 | TypeCtor::Adt(AdtId::UnionId(u)) => { | 441 | self.write_field_resolution(tgt_expr, field); |
447 | self.db.union_data(u).variant_data.field(name).map(|local_id| { | 442 | self.db.field_types(u.into())[field.local_id].clone().subst(¶meters) |
448 | let field = FieldId { parent: u.into(), local_id }; | 443 | }) |
449 | self.write_field_resolution(tgt_expr, field); | 444 | } |
450 | self.db.field_types(u.into())[field.local_id] | ||
451 | .clone() | ||
452 | .subst(&a_ty.parameters) | ||
453 | }) | ||
454 | } | ||
455 | _ => None, | ||
456 | }, | ||
457 | _ => None, | 445 | _ => None, |
458 | }) | 446 | }) |
459 | .unwrap_or(Ty::Unknown); | 447 | .unwrap_or(Ty::Unknown); |
@@ -475,10 +463,11 @@ impl<'a> InferenceContext<'a> { | |||
475 | cast_ty | 463 | cast_ty |
476 | } | 464 | } |
477 | Expr::Ref { expr, rawness, mutability } => { | 465 | Expr::Ref { expr, rawness, mutability } => { |
466 | let mutability = lower_to_chalk_mutability(*mutability); | ||
478 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = | 467 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = |
479 | &expected.ty.as_reference_or_ptr() | 468 | &expected.ty.as_reference_or_ptr() |
480 | { | 469 | { |
481 | if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { | 470 | if *exp_mutability == Mutability::Mut && mutability == Mutability::Not { |
482 | // FIXME: throw type error - expected mut reference but found shared ref, | 471 | // FIXME: throw type error - expected mut reference but found shared ref, |
483 | // which cannot be coerced | 472 | // which cannot be coerced |
484 | } | 473 | } |
@@ -491,19 +480,24 @@ impl<'a> InferenceContext<'a> { | |||
491 | Expectation::none() | 480 | Expectation::none() |
492 | }; | 481 | }; |
493 | let inner_ty = self.infer_expr_inner(*expr, &expectation); | 482 | let inner_ty = self.infer_expr_inner(*expr, &expectation); |
494 | let ty = match rawness { | 483 | match rawness { |
495 | Rawness::RawPtr => TypeCtor::RawPtr(*mutability), | 484 | Rawness::RawPtr => Ty::Raw(mutability, Substs::single(inner_ty)), |
496 | Rawness::Ref => TypeCtor::Ref(*mutability), | 485 | Rawness::Ref => Ty::Ref(mutability, Substs::single(inner_ty)), |
497 | }; | 486 | } |
498 | Ty::apply_one(ty, inner_ty) | ||
499 | } | 487 | } |
500 | Expr::Box { expr } => { | 488 | Expr::Box { expr } => { |
501 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 489 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
502 | if let Some(box_) = self.resolve_boxed_box() { | 490 | if let Some(box_) = self.resolve_boxed_box() { |
503 | let mut sb = Substs::build_for_type_ctor(self.db, TypeCtor::Adt(box_)); | 491 | let mut sb = Substs::builder(generics(self.db.upcast(), box_.into()).len()); |
504 | sb = sb.push(inner_ty); | 492 | sb = sb.push(inner_ty); |
493 | match self.db.generic_defaults(box_.into()).as_ref() { | ||
494 | [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => { | ||
495 | sb = sb.push(alloc_ty.value.clone()); | ||
496 | } | ||
497 | _ => (), | ||
498 | } | ||
505 | sb = sb.fill(repeat_with(|| self.table.new_type_var())); | 499 | sb = sb.fill(repeat_with(|| self.table.new_type_var())); |
506 | Ty::apply(TypeCtor::Adt(box_), sb.build()) | 500 | Ty::adt_ty(box_, sb.build()) |
507 | } else { | 501 | } else { |
508 | Ty::Unknown | 502 | Ty::Unknown |
509 | } | 503 | } |
@@ -533,13 +527,11 @@ impl<'a> InferenceContext<'a> { | |||
533 | UnaryOp::Neg => { | 527 | UnaryOp::Neg => { |
534 | match &inner_ty { | 528 | match &inner_ty { |
535 | // Fast path for builtins | 529 | // Fast path for builtins |
536 | Ty::Apply(ApplicationTy { | 530 | Ty::Scalar(Scalar::Int(_)) |
537 | ctor: TypeCtor::Int(IntTy { signedness: Signedness::Signed, .. }), | 531 | | Ty::Scalar(Scalar::Uint(_)) |
538 | .. | 532 | | Ty::Scalar(Scalar::Float(_)) |
539 | }) | 533 | | Ty::InferenceVar(_, TyVariableKind::Integer) |
540 | | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. }) | 534 | | Ty::InferenceVar(_, TyVariableKind::Float) => inner_ty, |
541 | | Ty::Infer(InferTy::IntVar(..)) | ||
542 | | Ty::Infer(InferTy::FloatVar(..)) => inner_ty, | ||
543 | // Otherwise we resolve via the std::ops::Neg trait | 535 | // Otherwise we resolve via the std::ops::Neg trait |
544 | _ => self | 536 | _ => self |
545 | .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), | 537 | .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), |
@@ -548,9 +540,10 @@ impl<'a> InferenceContext<'a> { | |||
548 | UnaryOp::Not => { | 540 | UnaryOp::Not => { |
549 | match &inner_ty { | 541 | match &inner_ty { |
550 | // Fast path for builtins | 542 | // Fast path for builtins |
551 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }) | 543 | Ty::Scalar(Scalar::Bool) |
552 | | Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. }) | 544 | | Ty::Scalar(Scalar::Int(_)) |
553 | | Ty::Infer(InferTy::IntVar(..)) => inner_ty, | 545 | | Ty::Scalar(Scalar::Uint(_)) |
546 | | Ty::InferenceVar(_, TyVariableKind::Integer) => inner_ty, | ||
554 | // Otherwise we resolve via the std::ops::Not trait | 547 | // Otherwise we resolve via the std::ops::Not trait |
555 | _ => self | 548 | _ => self |
556 | .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), | 549 | .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), |
@@ -561,7 +554,7 @@ impl<'a> InferenceContext<'a> { | |||
561 | Expr::BinaryOp { lhs, rhs, op } => match op { | 554 | Expr::BinaryOp { lhs, rhs, op } => match op { |
562 | Some(op) => { | 555 | Some(op) => { |
563 | let lhs_expectation = match op { | 556 | let lhs_expectation = match op { |
564 | BinaryOp::LogicOp(..) => Expectation::has_type(Ty::simple(TypeCtor::Bool)), | 557 | BinaryOp::LogicOp(..) => Expectation::has_type(Ty::Scalar(Scalar::Bool)), |
565 | _ => Expectation::none(), | 558 | _ => Expectation::none(), |
566 | }; | 559 | }; |
567 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); | 560 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); |
@@ -571,7 +564,7 @@ impl<'a> InferenceContext<'a> { | |||
571 | let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone()); | 564 | let ret = op::binary_op_return_ty(*op, lhs_ty.clone(), rhs_ty.clone()); |
572 | 565 | ||
573 | if ret == Ty::Unknown { | 566 | if ret == Ty::Unknown { |
574 | mark::hit!(infer_expr_inner_binary_operator_overload); | 567 | cov_mark::hit!(infer_expr_inner_binary_operator_overload); |
575 | 568 | ||
576 | self.resolve_associated_type_with_params( | 569 | self.resolve_associated_type_with_params( |
577 | lhs_ty, | 570 | lhs_ty, |
@@ -592,31 +585,31 @@ impl<'a> InferenceContext<'a> { | |||
592 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); | 585 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); |
593 | match (range_type, lhs_ty, rhs_ty) { | 586 | match (range_type, lhs_ty, rhs_ty) { |
594 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { | 587 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { |
595 | Some(adt) => Ty::simple(TypeCtor::Adt(adt)), | 588 | Some(adt) => Ty::adt_ty(adt, Substs::empty()), |
596 | None => Ty::Unknown, | 589 | None => Ty::Unknown, |
597 | }, | 590 | }, |
598 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { | 591 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { |
599 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 592 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
600 | None => Ty::Unknown, | 593 | None => Ty::Unknown, |
601 | }, | 594 | }, |
602 | (RangeOp::Inclusive, None, Some(ty)) => { | 595 | (RangeOp::Inclusive, None, Some(ty)) => { |
603 | match self.resolve_range_to_inclusive() { | 596 | match self.resolve_range_to_inclusive() { |
604 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 597 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
605 | None => Ty::Unknown, | 598 | None => Ty::Unknown, |
606 | } | 599 | } |
607 | } | 600 | } |
608 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { | 601 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { |
609 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 602 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
610 | None => Ty::Unknown, | 603 | None => Ty::Unknown, |
611 | }, | 604 | }, |
612 | (RangeOp::Inclusive, Some(_), Some(ty)) => { | 605 | (RangeOp::Inclusive, Some(_), Some(ty)) => { |
613 | match self.resolve_range_inclusive() { | 606 | match self.resolve_range_inclusive() { |
614 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 607 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
615 | None => Ty::Unknown, | 608 | None => Ty::Unknown, |
616 | } | 609 | } |
617 | } | 610 | } |
618 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { | 611 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { |
619 | Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), | 612 | Some(adt) => Ty::adt_ty(adt, Substs::single(ty)), |
620 | None => Ty::Unknown, | 613 | None => Ty::Unknown, |
621 | }, | 614 | }, |
622 | (RangeOp::Inclusive, _, None) => Ty::Unknown, | 615 | (RangeOp::Inclusive, _, None) => Ty::Unknown, |
@@ -650,7 +643,7 @@ impl<'a> InferenceContext<'a> { | |||
650 | } | 643 | } |
651 | Expr::Tuple { exprs } => { | 644 | Expr::Tuple { exprs } => { |
652 | let mut tys = match &expected.ty { | 645 | let mut tys = match &expected.ty { |
653 | ty_app!(TypeCtor::Tuple { .. }, st) => st | 646 | Ty::Tuple(_, substs) => substs |
654 | .iter() | 647 | .iter() |
655 | .cloned() | 648 | .cloned() |
656 | .chain(repeat_with(|| self.table.new_type_var())) | 649 | .chain(repeat_with(|| self.table.new_type_var())) |
@@ -663,15 +656,11 @@ impl<'a> InferenceContext<'a> { | |||
663 | self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); | 656 | self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); |
664 | } | 657 | } |
665 | 658 | ||
666 | Ty::apply(TypeCtor::Tuple { cardinality: tys.len() as u16 }, Substs(tys.into())) | 659 | Ty::Tuple(tys.len(), Substs(tys.into())) |
667 | } | 660 | } |
668 | Expr::Array(array) => { | 661 | Expr::Array(array) => { |
669 | let elem_ty = match &expected.ty { | 662 | let elem_ty = match &expected.ty { |
670 | // FIXME: remove when https://github.com/rust-lang/rust/issues/80501 is fixed | 663 | Ty::Array(st) | Ty::Slice(st) => st.as_single().clone(), |
671 | #[allow(unreachable_patterns)] | ||
672 | ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => { | ||
673 | st.as_single().clone() | ||
674 | } | ||
675 | _ => self.table.new_type_var(), | 664 | _ => self.table.new_type_var(), |
676 | }; | 665 | }; |
677 | 666 | ||
@@ -688,30 +677,38 @@ impl<'a> InferenceContext<'a> { | |||
688 | ); | 677 | ); |
689 | self.infer_expr( | 678 | self.infer_expr( |
690 | *repeat, | 679 | *repeat, |
691 | &Expectation::has_type(Ty::simple(TypeCtor::Int(IntTy::usize()))), | 680 | &Expectation::has_type(Ty::Scalar(Scalar::Uint(UintTy::Usize))), |
692 | ); | 681 | ); |
693 | } | 682 | } |
694 | } | 683 | } |
695 | 684 | ||
696 | Ty::apply_one(TypeCtor::Array, elem_ty) | 685 | Ty::Array(Substs::single(elem_ty)) |
697 | } | 686 | } |
698 | Expr::Literal(lit) => match lit { | 687 | Expr::Literal(lit) => match lit { |
699 | Literal::Bool(..) => Ty::simple(TypeCtor::Bool), | 688 | Literal::Bool(..) => Ty::Scalar(Scalar::Bool), |
700 | Literal::String(..) => { | 689 | Literal::String(..) => Ty::Ref(Mutability::Not, Substs::single(Ty::Str)), |
701 | Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str)) | ||
702 | } | ||
703 | Literal::ByteString(..) => { | 690 | Literal::ByteString(..) => { |
704 | let byte_type = Ty::simple(TypeCtor::Int(IntTy::u8())); | 691 | let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); |
705 | let array_type = Ty::apply_one(TypeCtor::Array, byte_type); | 692 | let array_type = Ty::Array(Substs::single(byte_type)); |
706 | Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type) | 693 | Ty::Ref(Mutability::Not, Substs::single(array_type)) |
707 | } | 694 | } |
708 | Literal::Char(..) => Ty::simple(TypeCtor::Char), | 695 | Literal::Char(..) => Ty::Scalar(Scalar::Char), |
709 | Literal::Int(_v, ty) => match ty { | 696 | Literal::Int(_v, ty) => match ty { |
710 | Some(int_ty) => Ty::simple(TypeCtor::Int((*int_ty).into())), | 697 | Some(int_ty) => { |
698 | Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty))) | ||
699 | } | ||
700 | None => self.table.new_integer_var(), | ||
701 | }, | ||
702 | Literal::Uint(_v, ty) => match ty { | ||
703 | Some(int_ty) => { | ||
704 | Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty))) | ||
705 | } | ||
711 | None => self.table.new_integer_var(), | 706 | None => self.table.new_integer_var(), |
712 | }, | 707 | }, |
713 | Literal::Float(_v, ty) => match ty { | 708 | Literal::Float(_v, ty) => match ty { |
714 | Some(float_ty) => Ty::simple(TypeCtor::Float((*float_ty).into())), | 709 | Some(float_ty) => { |
710 | Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty))) | ||
711 | } | ||
715 | None => self.table.new_float_var(), | 712 | None => self.table.new_float_var(), |
716 | }, | 713 | }, |
717 | }, | 714 | }, |
@@ -767,7 +764,7 @@ impl<'a> InferenceContext<'a> { | |||
767 | // `!`). | 764 | // `!`). |
768 | if self.diverges.is_always() { | 765 | if self.diverges.is_always() { |
769 | // we don't even make an attempt at coercion | 766 | // we don't even make an attempt at coercion |
770 | self.table.new_maybe_never_type_var() | 767 | self.table.new_maybe_never_var() |
771 | } else { | 768 | } else { |
772 | self.coerce(&Ty::unit(), expected.coercion_target()); | 769 | self.coerce(&Ty::unit(), expected.coercion_target()); |
773 | Ty::unit() | 770 | Ty::unit() |
@@ -824,7 +821,7 @@ impl<'a> InferenceContext<'a> { | |||
824 | // Apply autoref so the below unification works correctly | 821 | // Apply autoref so the below unification works correctly |
825 | // FIXME: return correct autorefs from lookup_method | 822 | // FIXME: return correct autorefs from lookup_method |
826 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { | 823 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { |
827 | Some((_, mutability)) => Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty), | 824 | Some((_, mutability)) => Ty::Ref(mutability, Substs::single(derefed_receiver_ty)), |
828 | _ => derefed_receiver_ty, | 825 | _ => derefed_receiver_ty, |
829 | }; | 826 | }; |
830 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | 827 | self.unify(&expected_receiver_ty, &actual_receiver_ty); |
@@ -901,30 +898,26 @@ impl<'a> InferenceContext<'a> { | |||
901 | } | 898 | } |
902 | 899 | ||
903 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { | 900 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { |
904 | if let Ty::Apply(a_ty) = callable_ty { | 901 | if let &Ty::FnDef(def, ref parameters) = callable_ty { |
905 | if let TypeCtor::FnDef(def) = a_ty.ctor { | 902 | let generic_predicates = self.db.generic_predicates(def.into()); |
906 | let generic_predicates = self.db.generic_predicates(def.into()); | 903 | for predicate in generic_predicates.iter() { |
907 | for predicate in generic_predicates.iter() { | 904 | let predicate = predicate.clone().subst(parameters); |
908 | let predicate = predicate.clone().subst(&a_ty.parameters); | 905 | if let Some(obligation) = Obligation::from_predicate(predicate) { |
909 | if let Some(obligation) = Obligation::from_predicate(predicate) { | 906 | self.obligations.push(obligation); |
910 | self.obligations.push(obligation); | ||
911 | } | ||
912 | } | 907 | } |
913 | // add obligation for trait implementation, if this is a trait method | 908 | } |
914 | match def { | 909 | // add obligation for trait implementation, if this is a trait method |
915 | CallableDefId::FunctionId(f) => { | 910 | match def { |
916 | if let AssocContainerId::TraitId(trait_) = | 911 | CallableDefId::FunctionId(f) => { |
917 | f.lookup(self.db.upcast()).container | 912 | if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container |
918 | { | 913 | { |
919 | // construct a TraitDef | 914 | // construct a TraitDef |
920 | let substs = a_ty | 915 | let substs = |
921 | .parameters | 916 | parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); |
922 | .prefix(generics(self.db.upcast(), trait_.into()).len()); | 917 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); |
923 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); | ||
924 | } | ||
925 | } | 918 | } |
926 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} | ||
927 | } | 919 | } |
920 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} | ||
928 | } | 921 | } |
929 | } | 922 | } |
930 | } | 923 | } |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index d974f805b..a0ac8d80f 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -3,17 +3,16 @@ | |||
3 | use std::iter::repeat; | 3 | use std::iter::repeat; |
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use chalk_ir::Mutability; | ||
6 | use hir_def::{ | 7 | use hir_def::{ |
7 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, | 8 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, |
8 | path::Path, | 9 | path::Path, |
9 | type_ref::Mutability, | ||
10 | FieldId, | 10 | FieldId, |
11 | }; | 11 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use test_utils::mark; | ||
14 | 13 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; | 15 | use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty}; |
17 | 16 | ||
18 | impl<'a> InferenceContext<'a> { | 17 | impl<'a> InferenceContext<'a> { |
19 | fn infer_tuple_struct_pat( | 18 | fn infer_tuple_struct_pat( |
@@ -32,7 +31,7 @@ impl<'a> InferenceContext<'a> { | |||
32 | } | 31 | } |
33 | self.unify(&ty, expected); | 32 | self.unify(&ty, expected); |
34 | 33 | ||
35 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 34 | let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); |
36 | 35 | ||
37 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 36 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
38 | let (pre, post) = match ellipsis { | 37 | let (pre, post) = match ellipsis { |
@@ -71,7 +70,7 @@ impl<'a> InferenceContext<'a> { | |||
71 | 70 | ||
72 | self.unify(&ty, expected); | 71 | self.unify(&ty, expected); |
73 | 72 | ||
74 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 73 | let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); |
75 | 74 | ||
76 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 75 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
77 | for subpat in subpats { | 76 | for subpat in subpats { |
@@ -103,12 +102,12 @@ impl<'a> InferenceContext<'a> { | |||
103 | expected = inner; | 102 | expected = inner; |
104 | default_bm = match default_bm { | 103 | default_bm = match default_bm { |
105 | BindingMode::Move => BindingMode::Ref(mutability), | 104 | BindingMode::Move => BindingMode::Ref(mutability), |
106 | BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared), | 105 | BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), |
107 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), | 106 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), |
108 | } | 107 | } |
109 | } | 108 | } |
110 | } else if let Pat::Ref { .. } = &body[pat] { | 109 | } else if let Pat::Ref { .. } = &body[pat] { |
111 | mark::hit!(match_ergonomics_ref); | 110 | cov_mark::hit!(match_ergonomics_ref); |
112 | // When you encounter a `&pat` pattern, reset to Move. | 111 | // When you encounter a `&pat` pattern, reset to Move. |
113 | // This is so that `w` is by value: `let (_, &w) = &(1, &2);` | 112 | // This is so that `w` is by value: `let (_, &w) = &(1, &2);` |
114 | default_bm = BindingMode::Move; | 113 | default_bm = BindingMode::Move; |
@@ -138,10 +137,7 @@ impl<'a> InferenceContext<'a> { | |||
138 | inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); | 137 | inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); |
139 | inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); | 138 | inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); |
140 | 139 | ||
141 | Ty::apply( | 140 | Ty::Tuple(inner_tys.len(), Substs(inner_tys.into())) |
142 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, | ||
143 | Substs(inner_tys.into()), | ||
144 | ) | ||
145 | } | 141 | } |
146 | Pat::Or(ref pats) => { | 142 | Pat::Or(ref pats) => { |
147 | if let Some((first_pat, rest)) = pats.split_first() { | 143 | if let Some((first_pat, rest)) = pats.split_first() { |
@@ -155,9 +151,10 @@ impl<'a> InferenceContext<'a> { | |||
155 | } | 151 | } |
156 | } | 152 | } |
157 | Pat::Ref { pat, mutability } => { | 153 | Pat::Ref { pat, mutability } => { |
154 | let mutability = lower_to_chalk_mutability(*mutability); | ||
158 | let expectation = match expected.as_reference() { | 155 | let expectation = match expected.as_reference() { |
159 | Some((inner_ty, exp_mut)) => { | 156 | Some((inner_ty, exp_mut)) => { |
160 | if *mutability != exp_mut { | 157 | if mutability != exp_mut { |
161 | // FIXME: emit type error? | 158 | // FIXME: emit type error? |
162 | } | 159 | } |
163 | inner_ty | 160 | inner_ty |
@@ -165,7 +162,7 @@ impl<'a> InferenceContext<'a> { | |||
165 | _ => &Ty::Unknown, | 162 | _ => &Ty::Unknown, |
166 | }; | 163 | }; |
167 | let subty = self.infer_pat(*pat, expectation, default_bm); | 164 | let subty = self.infer_pat(*pat, expectation, default_bm); |
168 | Ty::apply_one(TypeCtor::Ref(*mutability), subty) | 165 | Ty::Ref(mutability, Substs::single(subty)) |
169 | } | 166 | } |
170 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( | 167 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( |
171 | p.as_ref(), | 168 | p.as_ref(), |
@@ -198,7 +195,7 @@ impl<'a> InferenceContext<'a> { | |||
198 | 195 | ||
199 | let bound_ty = match mode { | 196 | let bound_ty = match mode { |
200 | BindingMode::Ref(mutability) => { | 197 | BindingMode::Ref(mutability) => { |
201 | Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone()) | 198 | Ty::Ref(mutability, Substs::single(inner_ty.clone())) |
202 | } | 199 | } |
203 | BindingMode::Move => inner_ty.clone(), | 200 | BindingMode::Move => inner_ty.clone(), |
204 | }; | 201 | }; |
@@ -207,17 +204,17 @@ impl<'a> InferenceContext<'a> { | |||
207 | return inner_ty; | 204 | return inner_ty; |
208 | } | 205 | } |
209 | Pat::Slice { prefix, slice, suffix } => { | 206 | Pat::Slice { prefix, slice, suffix } => { |
210 | let (container_ty, elem_ty) = match &expected { | 207 | let (container_ty, elem_ty): (fn(_) -> _, _) = match &expected { |
211 | ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()), | 208 | Ty::Array(st) => (Ty::Array, st.as_single().clone()), |
212 | ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()), | 209 | Ty::Slice(st) => (Ty::Slice, st.as_single().clone()), |
213 | _ => (TypeCtor::Slice, Ty::Unknown), | 210 | _ => (Ty::Slice, Ty::Unknown), |
214 | }; | 211 | }; |
215 | 212 | ||
216 | for pat_id in prefix.iter().chain(suffix) { | 213 | for pat_id in prefix.iter().chain(suffix) { |
217 | self.infer_pat(*pat_id, &elem_ty, default_bm); | 214 | self.infer_pat(*pat_id, &elem_ty, default_bm); |
218 | } | 215 | } |
219 | 216 | ||
220 | let pat_ty = Ty::apply_one(container_ty, elem_ty); | 217 | let pat_ty = container_ty(Substs::single(elem_ty)); |
221 | if let Some(slice_pat_id) = slice { | 218 | if let Some(slice_pat_id) = slice { |
222 | self.infer_pat(*slice_pat_id, &pat_ty, default_bm); | 219 | self.infer_pat(*slice_pat_id, &pat_ty, default_bm); |
223 | } | 220 | } |
@@ -239,7 +236,7 @@ impl<'a> InferenceContext<'a> { | |||
239 | }; | 236 | }; |
240 | 237 | ||
241 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); | 238 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); |
242 | Ty::apply_one(TypeCtor::Adt(box_adt), inner_ty) | 239 | Ty::adt_ty(box_adt, Substs::single(inner_ty)) |
243 | } | 240 | } |
244 | None => Ty::Unknown, | 241 | None => Ty::Unknown, |
245 | }, | 242 | }, |
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 5d541104e..ae3554bac 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -260,7 +260,7 @@ impl<'a> InferenceContext<'a> { | |||
260 | })); | 260 | })); |
261 | Some(trait_substs) | 261 | Some(trait_substs) |
262 | } | 262 | } |
263 | AssocContainerId::ContainerId(_) => None, | 263 | AssocContainerId::ModuleId(_) => None, |
264 | }; | 264 | }; |
265 | 265 | ||
266 | self.write_assoc_resolution(id, item); | 266 | self.write_assoc_resolution(id, item); |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 76984242e..54fcfed10 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,14 +2,13 @@ | |||
2 | 2 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | ||
5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
6 | 7 | ||
7 | use test_utils::mark; | ||
8 | |||
9 | use super::{InferenceContext, Obligation}; | 8 | use super::{InferenceContext, Obligation}; |
10 | use crate::{ | 9 | use crate::{ |
11 | BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty, | 10 | BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Scalar, |
12 | TyKind, TypeCtor, TypeWalk, | 11 | Substs, Ty, TypeWalk, |
13 | }; | 12 | }; |
14 | 13 | ||
15 | impl<'a> InferenceContext<'a> { | 14 | impl<'a> InferenceContext<'a> { |
@@ -26,7 +25,7 @@ where | |||
26 | 'a: 'b, | 25 | 'a: 'b, |
27 | { | 26 | { |
28 | ctx: &'b mut InferenceContext<'a>, | 27 | ctx: &'b mut InferenceContext<'a>, |
29 | free_vars: Vec<InferTy>, | 28 | free_vars: Vec<(InferenceVar, TyVariableKind)>, |
30 | /// A stack of type variables that is used to detect recursive types (which | 29 | /// A stack of type variables that is used to detect recursive types (which |
31 | /// are an error, but we need to protect against them to avoid stack | 30 | /// are an error, but we need to protect against them to avoid stack |
32 | /// overflows). | 31 | /// overflows). |
@@ -36,17 +35,14 @@ where | |||
36 | #[derive(Debug)] | 35 | #[derive(Debug)] |
37 | pub(super) struct Canonicalized<T> { | 36 | pub(super) struct Canonicalized<T> { |
38 | pub(super) value: Canonical<T>, | 37 | pub(super) value: Canonical<T>, |
39 | free_vars: Vec<InferTy>, | 38 | free_vars: Vec<(InferenceVar, TyVariableKind)>, |
40 | } | 39 | } |
41 | 40 | ||
42 | impl<'a, 'b> Canonicalizer<'a, 'b> | 41 | impl<'a, 'b> Canonicalizer<'a, 'b> { |
43 | where | 42 | fn add(&mut self, free_var: InferenceVar, kind: TyVariableKind) -> usize { |
44 | 'a: 'b, | 43 | self.free_vars.iter().position(|&(v, _)| v == free_var).unwrap_or_else(|| { |
45 | { | ||
46 | fn add(&mut self, free_var: InferTy) -> usize { | ||
47 | self.free_vars.iter().position(|&v| v == free_var).unwrap_or_else(|| { | ||
48 | let next_index = self.free_vars.len(); | 44 | let next_index = self.free_vars.len(); |
49 | self.free_vars.push(free_var); | 45 | self.free_vars.push((free_var, kind)); |
50 | next_index | 46 | next_index |
51 | }) | 47 | }) |
52 | } | 48 | } |
@@ -54,11 +50,11 @@ where | |||
54 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { | 50 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { |
55 | t.fold_binders( | 51 | t.fold_binders( |
56 | &mut |ty, binders| match ty { | 52 | &mut |ty, binders| match ty { |
57 | Ty::Infer(tv) => { | 53 | Ty::InferenceVar(var, kind) => { |
58 | let inner = tv.to_inner(); | 54 | let inner = var.to_inner(); |
59 | if self.var_stack.contains(&inner) { | 55 | if self.var_stack.contains(&inner) { |
60 | // recursive type | 56 | // recursive type |
61 | return tv.fallback_value(); | 57 | return self.ctx.table.type_variable_table.fallback_value(var, kind); |
62 | } | 58 | } |
63 | if let Some(known_ty) = | 59 | if let Some(known_ty) = |
64 | self.ctx.table.var_unification_table.inlined_probe_value(inner).known() | 60 | self.ctx.table.var_unification_table.inlined_probe_value(inner).known() |
@@ -69,14 +65,8 @@ where | |||
69 | result | 65 | result |
70 | } else { | 66 | } else { |
71 | let root = self.ctx.table.var_unification_table.find(inner); | 67 | let root = self.ctx.table.var_unification_table.find(inner); |
72 | let free_var = match tv { | 68 | let position = self.add(InferenceVar::from_inner(root), kind); |
73 | InferTy::TypeVar(_) => InferTy::TypeVar(root), | 69 | Ty::BoundVar(BoundVar::new(binders, position)) |
74 | InferTy::IntVar(_) => InferTy::IntVar(root), | ||
75 | InferTy::FloatVar(_) => InferTy::FloatVar(root), | ||
76 | InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root), | ||
77 | }; | ||
78 | let position = self.add(free_var); | ||
79 | Ty::Bound(BoundVar::new(binders, position)) | ||
80 | } | 70 | } |
81 | } | 71 | } |
82 | _ => ty, | 72 | _ => ty, |
@@ -86,19 +76,7 @@ where | |||
86 | } | 76 | } |
87 | 77 | ||
88 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
89 | let kinds = self | 79 | let kinds = self.free_vars.iter().map(|&(_, k)| k).collect(); |
90 | .free_vars | ||
91 | .iter() | ||
92 | .map(|v| match v { | ||
93 | // mapping MaybeNeverTypeVar to the same kind as general ones | ||
94 | // should be fine, because as opposed to int or float type vars, | ||
95 | // they don't restrict what kind of type can go into them, they | ||
96 | // just affect fallback. | ||
97 | InferTy::TypeVar(_) | InferTy::MaybeNeverTypeVar(_) => TyKind::General, | ||
98 | InferTy::IntVar(_) => TyKind::Integer, | ||
99 | InferTy::FloatVar(_) => TyKind::Float, | ||
100 | }) | ||
101 | .collect(); | ||
102 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } | 80 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } |
103 | } | 81 | } |
104 | 82 | ||
@@ -130,9 +108,10 @@ impl<T> Canonicalized<T> { | |||
130 | pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { | 108 | pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { |
131 | ty.walk_mut_binders( | 109 | ty.walk_mut_binders( |
132 | &mut |ty, binders| { | 110 | &mut |ty, binders| { |
133 | if let &mut Ty::Bound(bound) = ty { | 111 | if let &mut Ty::BoundVar(bound) = ty { |
134 | if bound.debruijn >= binders { | 112 | if bound.debruijn >= binders { |
135 | *ty = Ty::Infer(self.free_vars[bound.index]); | 113 | let (v, k) = self.free_vars[bound.index]; |
114 | *ty = Ty::InferenceVar(v, k); | ||
136 | } | 115 | } |
137 | } | 116 | } |
138 | }, | 117 | }, |
@@ -152,18 +131,18 @@ impl<T> Canonicalized<T> { | |||
152 | .kinds | 131 | .kinds |
153 | .iter() | 132 | .iter() |
154 | .map(|k| match k { | 133 | .map(|k| match k { |
155 | TyKind::General => ctx.table.new_type_var(), | 134 | TyVariableKind::General => ctx.table.new_type_var(), |
156 | TyKind::Integer => ctx.table.new_integer_var(), | 135 | TyVariableKind::Integer => ctx.table.new_integer_var(), |
157 | TyKind::Float => ctx.table.new_float_var(), | 136 | TyVariableKind::Float => ctx.table.new_float_var(), |
158 | }) | 137 | }) |
159 | .collect(), | 138 | .collect(), |
160 | ); | 139 | ); |
161 | for (i, ty) in solution.value.into_iter().enumerate() { | 140 | for (i, ty) in solution.value.into_iter().enumerate() { |
162 | let var = self.free_vars[i]; | 141 | let (v, k) = self.free_vars[i]; |
163 | // eagerly replace projections in the type; we may be getting types | 142 | // eagerly replace projections in the type; we may be getting types |
164 | // e.g. from where clauses where this hasn't happened yet | 143 | // e.g. from where clauses where this hasn't happened yet |
165 | let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); | 144 | let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); |
166 | ctx.table.unify(&Ty::Infer(var), &ty); | 145 | ctx.table.unify(&Ty::InferenceVar(v, k), &ty); |
167 | } | 146 | } |
168 | } | 147 | } |
169 | } | 148 | } |
@@ -187,7 +166,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> { | |||
187 | // (kind of hacky) | 166 | // (kind of hacky) |
188 | for (i, var) in vars.iter().enumerate() { | 167 | for (i, var) in vars.iter().enumerate() { |
189 | if &*table.resolve_ty_shallow(var) == var { | 168 | if &*table.resolve_ty_shallow(var) == var { |
190 | table.unify(var, &Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i))); | 169 | table.unify(var, &Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i))); |
191 | } | 170 | } |
192 | } | 171 | } |
193 | Some( | 172 | Some( |
@@ -198,31 +177,73 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> { | |||
198 | } | 177 | } |
199 | 178 | ||
200 | #[derive(Clone, Debug)] | 179 | #[derive(Clone, Debug)] |
180 | pub(super) struct TypeVariableTable { | ||
181 | inner: Vec<TypeVariableData>, | ||
182 | } | ||
183 | |||
184 | impl TypeVariableTable { | ||
185 | fn push(&mut self, data: TypeVariableData) { | ||
186 | self.inner.push(data); | ||
187 | } | ||
188 | |||
189 | pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { | ||
190 | self.inner[iv.to_inner().0 as usize].diverging = diverging; | ||
191 | } | ||
192 | |||
193 | fn is_diverging(&mut self, iv: InferenceVar) -> bool { | ||
194 | self.inner[iv.to_inner().0 as usize].diverging | ||
195 | } | ||
196 | |||
197 | fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { | ||
198 | match kind { | ||
199 | _ if self.inner[iv.to_inner().0 as usize].diverging => Ty::Never, | ||
200 | TyVariableKind::General => Ty::Unknown, | ||
201 | TyVariableKind::Integer => Ty::Scalar(Scalar::Int(IntTy::I32)), | ||
202 | TyVariableKind::Float => Ty::Scalar(Scalar::Float(FloatTy::F64)), | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | #[derive(Copy, Clone, Debug)] | ||
208 | pub(crate) struct TypeVariableData { | ||
209 | diverging: bool, | ||
210 | } | ||
211 | |||
212 | #[derive(Clone, Debug)] | ||
201 | pub(crate) struct InferenceTable { | 213 | pub(crate) struct InferenceTable { |
202 | pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>, | 214 | pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>, |
215 | pub(super) type_variable_table: TypeVariableTable, | ||
203 | } | 216 | } |
204 | 217 | ||
205 | impl InferenceTable { | 218 | impl InferenceTable { |
206 | pub(crate) fn new() -> Self { | 219 | pub(crate) fn new() -> Self { |
207 | InferenceTable { var_unification_table: InPlaceUnificationTable::new() } | 220 | InferenceTable { |
221 | var_unification_table: InPlaceUnificationTable::new(), | ||
222 | type_variable_table: TypeVariableTable { inner: Vec::new() }, | ||
223 | } | ||
224 | } | ||
225 | |||
226 | fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty { | ||
227 | self.type_variable_table.push(TypeVariableData { diverging }); | ||
228 | let key = self.var_unification_table.new_key(TypeVarValue::Unknown); | ||
229 | assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); | ||
230 | Ty::InferenceVar(InferenceVar::from_inner(key), kind) | ||
208 | } | 231 | } |
209 | 232 | ||
210 | pub(crate) fn new_type_var(&mut self) -> Ty { | 233 | pub(crate) fn new_type_var(&mut self) -> Ty { |
211 | Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) | 234 | self.new_var(TyVariableKind::General, false) |
212 | } | 235 | } |
213 | 236 | ||
214 | pub(crate) fn new_integer_var(&mut self) -> Ty { | 237 | pub(crate) fn new_integer_var(&mut self) -> Ty { |
215 | Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) | 238 | self.new_var(TyVariableKind::Integer, false) |
216 | } | 239 | } |
217 | 240 | ||
218 | pub(crate) fn new_float_var(&mut self) -> Ty { | 241 | pub(crate) fn new_float_var(&mut self) -> Ty { |
219 | Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) | 242 | self.new_var(TyVariableKind::Float, false) |
220 | } | 243 | } |
221 | 244 | ||
222 | pub(crate) fn new_maybe_never_type_var(&mut self) -> Ty { | 245 | pub(crate) fn new_maybe_never_var(&mut self) -> Ty { |
223 | Ty::Infer(InferTy::MaybeNeverTypeVar( | 246 | self.new_var(TyVariableKind::General, true) |
224 | self.var_unification_table.new_key(TypeVarValue::Unknown), | ||
225 | )) | ||
226 | } | 247 | } |
227 | 248 | ||
228 | pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { | 249 | pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { |
@@ -257,12 +278,14 @@ impl InferenceTable { | |||
257 | // try to resolve type vars first | 278 | // try to resolve type vars first |
258 | let ty1 = self.resolve_ty_shallow(ty1); | 279 | let ty1 = self.resolve_ty_shallow(ty1); |
259 | let ty2 = self.resolve_ty_shallow(ty2); | 280 | let ty2 = self.resolve_ty_shallow(ty2); |
260 | match (&*ty1, &*ty2) { | 281 | if ty1.equals_ctor(&ty2) { |
261 | (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { | 282 | match (ty1.substs(), ty2.substs()) { |
262 | self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) | 283 | (Some(st1), Some(st2)) => self.unify_substs(st1, st2, depth + 1), |
284 | (None, None) => true, | ||
285 | _ => false, | ||
263 | } | 286 | } |
264 | 287 | } else { | |
265 | _ => self.unify_inner_trivial(&ty1, &ty2, depth), | 288 | self.unify_inner_trivial(&ty1, &ty2, depth) |
266 | } | 289 | } |
267 | } | 290 | } |
268 | 291 | ||
@@ -281,31 +304,46 @@ impl InferenceTable { | |||
281 | true | 304 | true |
282 | } | 305 | } |
283 | 306 | ||
284 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | 307 | ( |
285 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | 308 | Ty::InferenceVar(tv1, TyVariableKind::General), |
286 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) | 309 | Ty::InferenceVar(tv2, TyVariableKind::General), |
310 | ) | ||
287 | | ( | 311 | | ( |
288 | Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)), | 312 | Ty::InferenceVar(tv1, TyVariableKind::Integer), |
289 | Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)), | 313 | Ty::InferenceVar(tv2, TyVariableKind::Integer), |
290 | ) => { | 314 | ) |
315 | | ( | ||
316 | Ty::InferenceVar(tv1, TyVariableKind::Float), | ||
317 | Ty::InferenceVar(tv2, TyVariableKind::Float), | ||
318 | ) if self.type_variable_table.is_diverging(*tv1) | ||
319 | == self.type_variable_table.is_diverging(*tv2) => | ||
320 | { | ||
291 | // both type vars are unknown since we tried to resolve them | 321 | // both type vars are unknown since we tried to resolve them |
292 | self.var_unification_table.union(*tv1, *tv2); | 322 | self.var_unification_table.union(tv1.to_inner(), tv2.to_inner()); |
293 | true | 323 | true |
294 | } | 324 | } |
295 | 325 | ||
296 | // The order of MaybeNeverTypeVar matters here. | 326 | // The order of MaybeNeverTypeVar matters here. |
297 | // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. | 327 | // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. |
298 | // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. | 328 | // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. |
299 | (Ty::Infer(InferTy::TypeVar(tv)), other) | 329 | (Ty::InferenceVar(tv, TyVariableKind::General), other) |
300 | | (other, Ty::Infer(InferTy::TypeVar(tv))) | 330 | | (other, Ty::InferenceVar(tv, TyVariableKind::General)) |
301 | | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other) | 331 | | (Ty::InferenceVar(tv, TyVariableKind::Integer), other @ Ty::Scalar(Scalar::Int(_))) |
302 | | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv))) | 332 | | (other @ Ty::Scalar(Scalar::Int(_)), Ty::InferenceVar(tv, TyVariableKind::Integer)) |
303 | | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_))) | 333 | | ( |
304 | | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv))) | 334 | Ty::InferenceVar(tv, TyVariableKind::Integer), |
305 | | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_))) | 335 | other @ Ty::Scalar(Scalar::Uint(_)), |
306 | | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => { | 336 | ) |
337 | | ( | ||
338 | other @ Ty::Scalar(Scalar::Uint(_)), | ||
339 | Ty::InferenceVar(tv, TyVariableKind::Integer), | ||
340 | ) | ||
341 | | (Ty::InferenceVar(tv, TyVariableKind::Float), other @ Ty::Scalar(Scalar::Float(_))) | ||
342 | | (other @ Ty::Scalar(Scalar::Float(_)), Ty::InferenceVar(tv, TyVariableKind::Float)) => | ||
343 | { | ||
307 | // the type var is unknown since we tried to resolve it | 344 | // the type var is unknown since we tried to resolve it |
308 | self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); | 345 | self.var_unification_table |
346 | .union_value(tv.to_inner(), TypeVarValue::Known(other.clone())); | ||
309 | true | 347 | true |
310 | } | 348 | } |
311 | 349 | ||
@@ -347,10 +385,10 @@ impl InferenceTable { | |||
347 | // more than once | 385 | // more than once |
348 | for i in 0..3 { | 386 | for i in 0..3 { |
349 | if i > 0 { | 387 | if i > 0 { |
350 | mark::hit!(type_var_resolves_to_int_var); | 388 | cov_mark::hit!(type_var_resolves_to_int_var); |
351 | } | 389 | } |
352 | match &*ty { | 390 | match &*ty { |
353 | Ty::Infer(tv) => { | 391 | Ty::InferenceVar(tv, _) => { |
354 | let inner = tv.to_inner(); | 392 | let inner = tv.to_inner(); |
355 | match self.var_unification_table.inlined_probe_value(inner).known() { | 393 | match self.var_unification_table.inlined_probe_value(inner).known() { |
356 | Some(known_ty) => { | 394 | Some(known_ty) => { |
@@ -373,12 +411,12 @@ impl InferenceTable { | |||
373 | /// known type. | 411 | /// known type. |
374 | fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 412 | fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
375 | ty.fold(&mut |ty| match ty { | 413 | ty.fold(&mut |ty| match ty { |
376 | Ty::Infer(tv) => { | 414 | Ty::InferenceVar(tv, kind) => { |
377 | let inner = tv.to_inner(); | 415 | let inner = tv.to_inner(); |
378 | if tv_stack.contains(&inner) { | 416 | if tv_stack.contains(&inner) { |
379 | mark::hit!(type_var_cycles_resolve_as_possible); | 417 | cov_mark::hit!(type_var_cycles_resolve_as_possible); |
380 | // recursive type | 418 | // recursive type |
381 | return tv.fallback_value(); | 419 | return self.type_variable_table.fallback_value(tv, kind); |
382 | } | 420 | } |
383 | if let Some(known_ty) = | 421 | if let Some(known_ty) = |
384 | self.var_unification_table.inlined_probe_value(inner).known() | 422 | self.var_unification_table.inlined_probe_value(inner).known() |
@@ -400,12 +438,12 @@ impl InferenceTable { | |||
400 | /// replaced by Ty::Unknown. | 438 | /// replaced by Ty::Unknown. |
401 | fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 439 | fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
402 | ty.fold(&mut |ty| match ty { | 440 | ty.fold(&mut |ty| match ty { |
403 | Ty::Infer(tv) => { | 441 | Ty::InferenceVar(tv, kind) => { |
404 | let inner = tv.to_inner(); | 442 | let inner = tv.to_inner(); |
405 | if tv_stack.contains(&inner) { | 443 | if tv_stack.contains(&inner) { |
406 | mark::hit!(type_var_cycles_resolve_completely); | 444 | cov_mark::hit!(type_var_cycles_resolve_completely); |
407 | // recursive type | 445 | // recursive type |
408 | return tv.fallback_value(); | 446 | return self.type_variable_table.fallback_value(tv, kind); |
409 | } | 447 | } |
410 | if let Some(known_ty) = | 448 | if let Some(known_ty) = |
411 | self.var_unification_table.inlined_probe_value(inner).known() | 449 | self.var_unification_table.inlined_probe_value(inner).known() |
@@ -416,7 +454,7 @@ impl InferenceTable { | |||
416 | tv_stack.pop(); | 454 | tv_stack.pop(); |
417 | result | 455 | result |
418 | } else { | 456 | } else { |
419 | tv.fallback_value() | 457 | self.type_variable_table.fallback_value(tv, kind) |
420 | } | 458 | } |
421 | } | 459 | } |
422 | _ => ty, | 460 | _ => ty, |
@@ -426,7 +464,7 @@ impl InferenceTable { | |||
426 | 464 | ||
427 | /// The ID of a type variable. | 465 | /// The ID of a type variable. |
428 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | 466 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
429 | pub struct TypeVarId(pub(super) u32); | 467 | pub(super) struct TypeVarId(pub(super) u32); |
430 | 468 | ||
431 | impl UnifyKey for TypeVarId { | 469 | impl UnifyKey for TypeVarId { |
432 | type Value = TypeVarValue; | 470 | type Value = TypeVarValue; |
@@ -447,7 +485,7 @@ impl UnifyKey for TypeVarId { | |||
447 | /// The value of a type variable: either we already know the type, or we don't | 485 | /// The value of a type variable: either we already know the type, or we don't |
448 | /// know it yet. | 486 | /// know it yet. |
449 | #[derive(Clone, PartialEq, Eq, Debug)] | 487 | #[derive(Clone, PartialEq, Eq, Debug)] |
450 | pub enum TypeVarValue { | 488 | pub(super) enum TypeVarValue { |
451 | Known(Ty), | 489 | Known(Ty), |
452 | Unknown, | 490 | Unknown, |
453 | } | 491 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 50d248674..e77f24e4e 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -25,32 +25,31 @@ mod test_db; | |||
25 | 25 | ||
26 | use std::{iter, mem, ops::Deref, sync::Arc}; | 26 | use std::{iter, mem, ops::Deref, sync::Arc}; |
27 | 27 | ||
28 | use base_db::{salsa, CrateId}; | 28 | use base_db::salsa; |
29 | use hir_def::{ | 29 | use hir_def::{ |
30 | builtin_type::BuiltinType, | 30 | builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, DefWithBodyId, |
31 | expr::ExprId, | 31 | FunctionId, GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, |
32 | type_ref::{Mutability, Rawness}, | 32 | TypeParamId, |
33 | AdtId, AssocContainerId, DefWithBodyId, FunctionId, GenericDefId, HasModule, LifetimeParamId, | ||
34 | Lookup, TraitId, TypeAliasId, TypeParamId, | ||
35 | }; | 33 | }; |
36 | use itertools::Itertools; | 34 | use itertools::Itertools; |
37 | 35 | ||
38 | use crate::{ | 36 | use crate::{ |
39 | db::HirDatabase, | 37 | db::HirDatabase, |
40 | display::HirDisplay, | 38 | display::HirDisplay, |
41 | primitive::{FloatTy, IntTy}, | ||
42 | utils::{generics, make_mut_slice, Generics}, | 39 | utils::{generics, make_mut_slice, Generics}, |
43 | }; | 40 | }; |
44 | 41 | ||
45 | pub use autoderef::autoderef; | 42 | pub use autoderef::autoderef; |
46 | pub use infer::{InferTy, InferenceResult}; | 43 | pub use infer::{InferenceResult, InferenceVar}; |
47 | pub use lower::{ | 44 | pub use lower::{ |
48 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, | 45 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, |
49 | TyDefId, TyLoweringContext, ValueTyDefId, | 46 | TyDefId, TyLoweringContext, ValueTyDefId, |
50 | }; | 47 | }; |
51 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 48 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; |
52 | 49 | ||
53 | pub use chalk_ir::{BoundVar, DebruijnIndex}; | 50 | pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind}; |
51 | |||
52 | pub(crate) use crate::traits::chalk::Interner; | ||
54 | 53 | ||
55 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 54 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
56 | pub enum Lifetime { | 55 | pub enum Lifetime { |
@@ -58,211 +57,6 @@ pub enum Lifetime { | |||
58 | Static, | 57 | Static, |
59 | } | 58 | } |
60 | 59 | ||
61 | /// A type constructor or type name: this might be something like the primitive | ||
62 | /// type `bool`, a struct like `Vec`, or things like function pointers or | ||
63 | /// tuples. | ||
64 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | ||
65 | pub enum TypeCtor { | ||
66 | /// The primitive boolean type. Written as `bool`. | ||
67 | Bool, | ||
68 | |||
69 | /// The primitive character type; holds a Unicode scalar value | ||
70 | /// (a non-surrogate code point). Written as `char`. | ||
71 | Char, | ||
72 | |||
73 | /// A primitive integer type. For example, `i32`. | ||
74 | Int(IntTy), | ||
75 | |||
76 | /// A primitive floating-point type. For example, `f64`. | ||
77 | Float(FloatTy), | ||
78 | |||
79 | /// Structures, enumerations and unions. | ||
80 | Adt(AdtId), | ||
81 | |||
82 | /// The pointee of a string slice. Written as `str`. | ||
83 | Str, | ||
84 | |||
85 | /// The pointee of an array slice. Written as `[T]`. | ||
86 | Slice, | ||
87 | |||
88 | /// An array with the given length. Written as `[T; n]`. | ||
89 | Array, | ||
90 | |||
91 | /// A raw pointer. Written as `*mut T` or `*const T` | ||
92 | RawPtr(Mutability), | ||
93 | |||
94 | /// A reference; a pointer with an associated lifetime. Written as | ||
95 | /// `&'a mut T` or `&'a T`. | ||
96 | Ref(Mutability), | ||
97 | |||
98 | /// The anonymous type of a function declaration/definition. Each | ||
99 | /// function has a unique type, which is output (for a function | ||
100 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
101 | /// | ||
102 | /// This includes tuple struct / enum variant constructors as well. | ||
103 | /// | ||
104 | /// For example the type of `bar` here: | ||
105 | /// | ||
106 | /// ``` | ||
107 | /// fn foo() -> i32 { 1 } | ||
108 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
109 | /// ``` | ||
110 | FnDef(CallableDefId), | ||
111 | |||
112 | /// A pointer to a function. Written as `fn() -> i32`. | ||
113 | /// | ||
114 | /// For example the type of `bar` here: | ||
115 | /// | ||
116 | /// ``` | ||
117 | /// fn foo() -> i32 { 1 } | ||
118 | /// let bar: fn() -> i32 = foo; | ||
119 | /// ``` | ||
120 | // FIXME make this a Ty variant like in Chalk | ||
121 | FnPtr { num_args: u16, is_varargs: bool }, | ||
122 | |||
123 | /// The never type `!`. | ||
124 | Never, | ||
125 | |||
126 | /// A tuple type. For example, `(i32, bool)`. | ||
127 | Tuple { cardinality: u16 }, | ||
128 | |||
129 | /// Represents an associated item like `Iterator::Item`. This is used | ||
130 | /// when we have tried to normalize a projection like `T::Item` but | ||
131 | /// couldn't find a better representation. In that case, we generate | ||
132 | /// an **application type** like `(Iterator::Item)<T>`. | ||
133 | AssociatedType(TypeAliasId), | ||
134 | |||
135 | /// This represents a placeholder for an opaque type in situations where we | ||
136 | /// don't know the hidden type (i.e. currently almost always). This is | ||
137 | /// analogous to the `AssociatedType` type constructor. | ||
138 | /// It is also used as the type of async block, with one type parameter | ||
139 | /// representing the Future::Output type. | ||
140 | OpaqueType(OpaqueTyId), | ||
141 | |||
142 | /// Represents a foreign type declared in external blocks. | ||
143 | ForeignType(TypeAliasId), | ||
144 | |||
145 | /// The type of a specific closure. | ||
146 | /// | ||
147 | /// The closure signature is stored in a `FnPtr` type in the first type | ||
148 | /// parameter. | ||
149 | Closure { def: DefWithBodyId, expr: ExprId }, | ||
150 | } | ||
151 | |||
152 | impl TypeCtor { | ||
153 | pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize { | ||
154 | match self { | ||
155 | TypeCtor::Bool | ||
156 | | TypeCtor::Char | ||
157 | | TypeCtor::Int(_) | ||
158 | | TypeCtor::Float(_) | ||
159 | | TypeCtor::Str | ||
160 | | TypeCtor::Never => 0, | ||
161 | TypeCtor::Slice | ||
162 | | TypeCtor::Array | ||
163 | | TypeCtor::RawPtr(_) | ||
164 | | TypeCtor::Ref(_) | ||
165 | | TypeCtor::Closure { .. } // 1 param representing the signature of the closure | ||
166 | => 1, | ||
167 | TypeCtor::Adt(adt) => { | ||
168 | let generic_params = generics(db.upcast(), adt.into()); | ||
169 | generic_params.len() | ||
170 | } | ||
171 | TypeCtor::FnDef(callable) => { | ||
172 | let generic_params = generics(db.upcast(), callable.into()); | ||
173 | generic_params.len() | ||
174 | } | ||
175 | TypeCtor::AssociatedType(type_alias) => { | ||
176 | let generic_params = generics(db.upcast(), type_alias.into()); | ||
177 | generic_params.len() | ||
178 | } | ||
179 | TypeCtor::ForeignType(type_alias) => { | ||
180 | let generic_params = generics(db.upcast(), type_alias.into()); | ||
181 | generic_params.len() | ||
182 | } | ||
183 | TypeCtor::OpaqueType(opaque_ty_id) => { | ||
184 | match opaque_ty_id { | ||
185 | OpaqueTyId::ReturnTypeImplTrait(func, _) => { | ||
186 | let generic_params = generics(db.upcast(), func.into()); | ||
187 | generic_params.len() | ||
188 | } | ||
189 | // 1 param representing Future::Output type. | ||
190 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => 1, | ||
191 | } | ||
192 | } | ||
193 | TypeCtor::FnPtr { num_args, is_varargs: _ } => num_args as usize + 1, | ||
194 | TypeCtor::Tuple { cardinality } => cardinality as usize, | ||
195 | } | ||
196 | } | ||
197 | |||
198 | pub fn krate(self, db: &dyn HirDatabase) -> Option<CrateId> { | ||
199 | match self { | ||
200 | TypeCtor::Bool | ||
201 | | TypeCtor::Char | ||
202 | | TypeCtor::Int(_) | ||
203 | | TypeCtor::Float(_) | ||
204 | | TypeCtor::Str | ||
205 | | TypeCtor::Never | ||
206 | | TypeCtor::Slice | ||
207 | | TypeCtor::Array | ||
208 | | TypeCtor::RawPtr(_) | ||
209 | | TypeCtor::Ref(_) | ||
210 | | TypeCtor::FnPtr { .. } | ||
211 | | TypeCtor::Tuple { .. } => None, | ||
212 | // Closure's krate is irrelevant for coherence I would think? | ||
213 | TypeCtor::Closure { .. } => None, | ||
214 | TypeCtor::Adt(adt) => Some(adt.module(db.upcast()).krate()), | ||
215 | TypeCtor::FnDef(callable) => Some(callable.krate(db)), | ||
216 | TypeCtor::AssociatedType(type_alias) => { | ||
217 | Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate()) | ||
218 | } | ||
219 | TypeCtor::ForeignType(type_alias) => { | ||
220 | Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate()) | ||
221 | } | ||
222 | TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id { | ||
223 | OpaqueTyId::ReturnTypeImplTrait(func, _) => { | ||
224 | Some(func.lookup(db.upcast()).module(db.upcast()).krate()) | ||
225 | } | ||
226 | OpaqueTyId::AsyncBlockTypeImplTrait(def, _) => { | ||
227 | Some(def.module(db.upcast()).krate()) | ||
228 | } | ||
229 | }, | ||
230 | } | ||
231 | } | ||
232 | |||
233 | pub fn as_generic_def(self) -> Option<GenericDefId> { | ||
234 | match self { | ||
235 | TypeCtor::Bool | ||
236 | | TypeCtor::Char | ||
237 | | TypeCtor::Int(_) | ||
238 | | TypeCtor::Float(_) | ||
239 | | TypeCtor::Str | ||
240 | | TypeCtor::Never | ||
241 | | TypeCtor::Slice | ||
242 | | TypeCtor::Array | ||
243 | | TypeCtor::RawPtr(_) | ||
244 | | TypeCtor::Ref(_) | ||
245 | | TypeCtor::FnPtr { .. } | ||
246 | | TypeCtor::Tuple { .. } | ||
247 | | TypeCtor::Closure { .. } => None, | ||
248 | TypeCtor::Adt(adt) => Some(adt.into()), | ||
249 | TypeCtor::FnDef(callable) => Some(callable.into()), | ||
250 | TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()), | ||
251 | TypeCtor::ForeignType(type_alias) => Some(type_alias.into()), | ||
252 | TypeCtor::OpaqueType(_impl_trait_id) => None, | ||
253 | } | ||
254 | } | ||
255 | } | ||
256 | |||
257 | /// A nominal type with (maybe 0) type parameters. This might be a primitive | ||
258 | /// type like `bool`, a struct, tuple, function pointer, reference or | ||
259 | /// several other things. | ||
260 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
261 | pub struct ApplicationTy { | ||
262 | pub ctor: TypeCtor, | ||
263 | pub parameters: Substs, | ||
264 | } | ||
265 | |||
266 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 60 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
267 | pub struct OpaqueTy { | 61 | pub struct OpaqueTy { |
268 | pub opaque_ty_id: OpaqueTyId, | 62 | pub opaque_ty_id: OpaqueTyId, |
@@ -305,29 +99,118 @@ impl TypeWalk for ProjectionTy { | |||
305 | } | 99 | } |
306 | } | 100 | } |
307 | 101 | ||
308 | /// A type. | 102 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] |
309 | /// | 103 | pub struct FnSig { |
310 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | 104 | pub variadic: bool, |
311 | /// the same thing (but in a different way). | 105 | } |
312 | /// | 106 | |
313 | /// This should be cheap to clone. | ||
314 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 107 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
315 | pub enum Ty { | 108 | pub struct FnPointer { |
316 | /// A nominal type with (maybe 0) type parameters. This might be a primitive | 109 | pub num_args: usize, |
317 | /// type like `bool`, a struct, tuple, function pointer, reference or | 110 | pub sig: FnSig, |
318 | /// several other things. | 111 | pub substs: Substs, |
319 | Apply(ApplicationTy), | 112 | } |
320 | 113 | ||
114 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
115 | pub enum AliasTy { | ||
321 | /// A "projection" type corresponds to an (unnormalized) | 116 | /// A "projection" type corresponds to an (unnormalized) |
322 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | 117 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the |
323 | /// trait and all its parameters are fully known. | 118 | /// trait and all its parameters are fully known. |
324 | Projection(ProjectionTy), | 119 | Projection(ProjectionTy), |
325 | |||
326 | /// An opaque type (`impl Trait`). | 120 | /// An opaque type (`impl Trait`). |
327 | /// | 121 | /// |
328 | /// This is currently only used for return type impl trait; each instance of | 122 | /// This is currently only used for return type impl trait; each instance of |
329 | /// `impl Trait` in a return type gets its own ID. | 123 | /// `impl Trait` in a return type gets its own ID. |
330 | Opaque(OpaqueTy), | 124 | Opaque(OpaqueTy), |
125 | } | ||
126 | |||
127 | /// A type. | ||
128 | /// | ||
129 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | ||
130 | /// the same thing (but in a different way). | ||
131 | /// | ||
132 | /// This should be cheap to clone. | ||
133 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
134 | pub enum Ty { | ||
135 | /// Structures, enumerations and unions. | ||
136 | Adt(AdtId<Interner>, Substs), | ||
137 | |||
138 | /// Represents an associated item like `Iterator::Item`. This is used | ||
139 | /// when we have tried to normalize a projection like `T::Item` but | ||
140 | /// couldn't find a better representation. In that case, we generate | ||
141 | /// an **application type** like `(Iterator::Item)<T>`. | ||
142 | AssociatedType(TypeAliasId, Substs), | ||
143 | |||
144 | /// a scalar type like `bool` or `u32` | ||
145 | Scalar(Scalar), | ||
146 | |||
147 | /// A tuple type. For example, `(i32, bool)`. | ||
148 | Tuple(usize, Substs), | ||
149 | |||
150 | /// An array with the given length. Written as `[T; n]`. | ||
151 | Array(Substs), | ||
152 | |||
153 | /// The pointee of an array slice. Written as `[T]`. | ||
154 | Slice(Substs), | ||
155 | |||
156 | /// A raw pointer. Written as `*mut T` or `*const T` | ||
157 | Raw(Mutability, Substs), | ||
158 | |||
159 | /// A reference; a pointer with an associated lifetime. Written as | ||
160 | /// `&'a mut T` or `&'a T`. | ||
161 | Ref(Mutability, Substs), | ||
162 | |||
163 | /// This represents a placeholder for an opaque type in situations where we | ||
164 | /// don't know the hidden type (i.e. currently almost always). This is | ||
165 | /// analogous to the `AssociatedType` type constructor. | ||
166 | /// It is also used as the type of async block, with one type parameter | ||
167 | /// representing the Future::Output type. | ||
168 | OpaqueType(OpaqueTyId, Substs), | ||
169 | |||
170 | /// The anonymous type of a function declaration/definition. Each | ||
171 | /// function has a unique type, which is output (for a function | ||
172 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
173 | /// | ||
174 | /// This includes tuple struct / enum variant constructors as well. | ||
175 | /// | ||
176 | /// For example the type of `bar` here: | ||
177 | /// | ||
178 | /// ``` | ||
179 | /// fn foo() -> i32 { 1 } | ||
180 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
181 | /// ``` | ||
182 | FnDef(CallableDefId, Substs), | ||
183 | |||
184 | /// The pointee of a string slice. Written as `str`. | ||
185 | Str, | ||
186 | |||
187 | /// The never type `!`. | ||
188 | Never, | ||
189 | |||
190 | /// The type of a specific closure. | ||
191 | /// | ||
192 | /// The closure signature is stored in a `FnPtr` type in the first type | ||
193 | /// parameter. | ||
194 | Closure(DefWithBodyId, ExprId, Substs), | ||
195 | |||
196 | /// Represents a foreign type declared in external blocks. | ||
197 | ForeignType(TypeAliasId), | ||
198 | |||
199 | /// A pointer to a function. Written as `fn() -> i32`. | ||
200 | /// | ||
201 | /// For example the type of `bar` here: | ||
202 | /// | ||
203 | /// ``` | ||
204 | /// fn foo() -> i32 { 1 } | ||
205 | /// let bar: fn() -> i32 = foo; | ||
206 | /// ``` | ||
207 | Function(FnPointer), | ||
208 | |||
209 | /// An "alias" type represents some form of type alias, such as: | ||
210 | /// - An associated type projection like `<T as Iterator>::Item` | ||
211 | /// - `impl Trait` types | ||
212 | /// - Named type aliases like `type Foo<X> = Vec<X>` | ||
213 | Alias(AliasTy), | ||
331 | 214 | ||
332 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) | 215 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) |
333 | /// {}` when we're type-checking the body of that function. In this | 216 | /// {}` when we're type-checking the body of that function. In this |
@@ -340,10 +223,10 @@ pub enum Ty { | |||
340 | /// parameters get turned into variables; during trait resolution, inference | 223 | /// parameters get turned into variables; during trait resolution, inference |
341 | /// variables get turned into bound variables and back; and in `Dyn` the | 224 | /// variables get turned into bound variables and back; and in `Dyn` the |
342 | /// `Self` type is represented with a bound variable as well. | 225 | /// `Self` type is represented with a bound variable as well. |
343 | Bound(BoundVar), | 226 | BoundVar(BoundVar), |
344 | 227 | ||
345 | /// A type variable used during type checking. | 228 | /// A type variable used during type checking. |
346 | Infer(InferTy), | 229 | InferenceVar(InferenceVar, TyVariableKind), |
347 | 230 | ||
348 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | 231 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). |
349 | /// | 232 | /// |
@@ -424,7 +307,7 @@ impl Substs { | |||
424 | generic_params | 307 | generic_params |
425 | .iter() | 308 | .iter() |
426 | .enumerate() | 309 | .enumerate() |
427 | .map(|(idx, _)| Ty::Bound(BoundVar::new(debruijn, idx))) | 310 | .map(|(idx, _)| Ty::BoundVar(BoundVar::new(debruijn, idx))) |
428 | .collect(), | 311 | .collect(), |
429 | ) | 312 | ) |
430 | } | 313 | } |
@@ -440,10 +323,6 @@ impl Substs { | |||
440 | Substs::builder(generic_params.len()) | 323 | Substs::builder(generic_params.len()) |
441 | } | 324 | } |
442 | 325 | ||
443 | pub fn build_for_type_ctor(db: &dyn HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder { | ||
444 | Substs::builder(type_ctor.num_ty_params(db)) | ||
445 | } | ||
446 | |||
447 | fn builder(param_count: usize) -> SubstsBuilder { | 326 | fn builder(param_count: usize) -> SubstsBuilder { |
448 | SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } | 327 | SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } |
449 | } | 328 | } |
@@ -476,7 +355,7 @@ impl SubstsBuilder { | |||
476 | } | 355 | } |
477 | 356 | ||
478 | pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { | 357 | pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { |
479 | self.fill((starting_from..).map(|idx| Ty::Bound(BoundVar::new(debruijn, idx)))) | 358 | self.fill((starting_from..).map(|idx| Ty::BoundVar(BoundVar::new(debruijn, idx)))) |
480 | } | 359 | } |
481 | 360 | ||
482 | pub fn fill_with_unknown(self) -> Self { | 361 | pub fn fill_with_unknown(self) -> Self { |
@@ -656,41 +535,41 @@ impl TypeWalk for GenericPredicate { | |||
656 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 535 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
657 | pub struct Canonical<T> { | 536 | pub struct Canonical<T> { |
658 | pub value: T, | 537 | pub value: T, |
659 | pub kinds: Arc<[TyKind]>, | 538 | pub kinds: Arc<[TyVariableKind]>, |
660 | } | 539 | } |
661 | 540 | ||
662 | impl<T> Canonical<T> { | 541 | impl<T> Canonical<T> { |
663 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyKind>) -> Self { | 542 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { |
664 | Self { value, kinds: kinds.into_iter().collect() } | 543 | Self { value, kinds: kinds.into_iter().collect() } |
665 | } | 544 | } |
666 | } | 545 | } |
667 | 546 | ||
668 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | ||
669 | pub enum TyKind { | ||
670 | General, | ||
671 | Integer, | ||
672 | Float, | ||
673 | } | ||
674 | |||
675 | /// A function signature as seen by type inference: Several parameter types and | 547 | /// A function signature as seen by type inference: Several parameter types and |
676 | /// one return type. | 548 | /// one return type. |
677 | #[derive(Clone, PartialEq, Eq, Debug)] | 549 | #[derive(Clone, PartialEq, Eq, Debug)] |
678 | pub struct FnSig { | 550 | pub struct CallableSig { |
679 | params_and_return: Arc<[Ty]>, | 551 | params_and_return: Arc<[Ty]>, |
680 | is_varargs: bool, | 552 | is_varargs: bool, |
681 | } | 553 | } |
682 | 554 | ||
683 | /// A polymorphic function signature. | 555 | /// A polymorphic function signature. |
684 | pub type PolyFnSig = Binders<FnSig>; | 556 | pub type PolyFnSig = Binders<CallableSig>; |
685 | 557 | ||
686 | impl FnSig { | 558 | impl CallableSig { |
687 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> FnSig { | 559 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig { |
688 | params.push(ret); | 560 | params.push(ret); |
689 | FnSig { params_and_return: params.into(), is_varargs } | 561 | CallableSig { params_and_return: params.into(), is_varargs } |
562 | } | ||
563 | |||
564 | pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { | ||
565 | CallableSig { | ||
566 | params_and_return: Arc::clone(&fn_ptr.substs.0), | ||
567 | is_varargs: fn_ptr.sig.variadic, | ||
568 | } | ||
690 | } | 569 | } |
691 | 570 | ||
692 | pub fn from_fn_ptr_substs(substs: &Substs, is_varargs: bool) -> FnSig { | 571 | pub fn from_substs(substs: &Substs) -> CallableSig { |
693 | FnSig { params_and_return: Arc::clone(&substs.0), is_varargs } | 572 | CallableSig { params_and_return: Arc::clone(&substs.0), is_varargs: false } |
694 | } | 573 | } |
695 | 574 | ||
696 | pub fn params(&self) -> &[Ty] { | 575 | pub fn params(&self) -> &[Ty] { |
@@ -702,7 +581,7 @@ impl FnSig { | |||
702 | } | 581 | } |
703 | } | 582 | } |
704 | 583 | ||
705 | impl TypeWalk for FnSig { | 584 | impl TypeWalk for CallableSig { |
706 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | 585 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
707 | for t in self.params_and_return.iter() { | 586 | for t in self.params_and_return.iter() { |
708 | t.walk(f); | 587 | t.walk(f); |
@@ -721,49 +600,46 @@ impl TypeWalk for FnSig { | |||
721 | } | 600 | } |
722 | 601 | ||
723 | impl Ty { | 602 | impl Ty { |
724 | pub fn simple(ctor: TypeCtor) -> Ty { | ||
725 | Ty::Apply(ApplicationTy { ctor, parameters: Substs::empty() }) | ||
726 | } | ||
727 | pub fn apply_one(ctor: TypeCtor, param: Ty) -> Ty { | ||
728 | Ty::Apply(ApplicationTy { ctor, parameters: Substs::single(param) }) | ||
729 | } | ||
730 | pub fn apply(ctor: TypeCtor, parameters: Substs) -> Ty { | ||
731 | Ty::Apply(ApplicationTy { ctor, parameters }) | ||
732 | } | ||
733 | pub fn unit() -> Self { | 603 | pub fn unit() -> Self { |
734 | Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty()) | 604 | Ty::Tuple(0, Substs::empty()) |
735 | } | 605 | } |
736 | pub fn fn_ptr(sig: FnSig) -> Self { | 606 | |
737 | Ty::apply( | 607 | pub fn adt_ty(adt: hir_def::AdtId, substs: Substs) -> Ty { |
738 | TypeCtor::FnPtr { num_args: sig.params().len() as u16, is_varargs: sig.is_varargs }, | 608 | Ty::Adt(AdtId(adt), substs) |
739 | Substs(sig.params_and_return), | ||
740 | ) | ||
741 | } | 609 | } |
742 | pub fn builtin(builtin: BuiltinType) -> Self { | 610 | |
743 | Ty::simple(match builtin { | 611 | pub fn fn_ptr(sig: CallableSig) -> Self { |
744 | BuiltinType::Char => TypeCtor::Char, | 612 | Ty::Function(FnPointer { |
745 | BuiltinType::Bool => TypeCtor::Bool, | 613 | num_args: sig.params().len(), |
746 | BuiltinType::Str => TypeCtor::Str, | 614 | sig: FnSig { variadic: sig.is_varargs }, |
747 | BuiltinType::Int(t) => TypeCtor::Int(IntTy::from(t).into()), | 615 | substs: Substs(sig.params_and_return), |
748 | BuiltinType::Float(t) => TypeCtor::Float(FloatTy::from(t).into()), | ||
749 | }) | 616 | }) |
750 | } | 617 | } |
751 | 618 | ||
619 | pub fn builtin(builtin: BuiltinType) -> Self { | ||
620 | match builtin { | ||
621 | BuiltinType::Char => Ty::Scalar(Scalar::Char), | ||
622 | BuiltinType::Bool => Ty::Scalar(Scalar::Bool), | ||
623 | BuiltinType::Str => Ty::Str, | ||
624 | BuiltinType::Int(t) => Ty::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))), | ||
625 | BuiltinType::Uint(t) => Ty::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))), | ||
626 | BuiltinType::Float(t) => Ty::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))), | ||
627 | } | ||
628 | } | ||
629 | |||
752 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { | 630 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { |
753 | match self { | 631 | match self { |
754 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { | 632 | Ty::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)), |
755 | Some((parameters.as_single(), *mutability)) | ||
756 | } | ||
757 | _ => None, | 633 | _ => None, |
758 | } | 634 | } |
759 | } | 635 | } |
760 | 636 | ||
761 | pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { | 637 | pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { |
762 | match self { | 638 | match self { |
763 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { | 639 | Ty::Ref(mutability, parameters) => { |
764 | Some((parameters.as_single(), Rawness::Ref, *mutability)) | 640 | Some((parameters.as_single(), Rawness::Ref, *mutability)) |
765 | } | 641 | } |
766 | Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(mutability), parameters }) => { | 642 | Ty::Raw(mutability, parameters) => { |
767 | Some((parameters.as_single(), Rawness::RawPtr, *mutability)) | 643 | Some((parameters.as_single(), Rawness::RawPtr, *mutability)) |
768 | } | 644 | } |
769 | _ => None, | 645 | _ => None, |
@@ -773,39 +649,69 @@ impl Ty { | |||
773 | pub fn strip_references(&self) -> &Ty { | 649 | pub fn strip_references(&self) -> &Ty { |
774 | let mut t: &Ty = self; | 650 | let mut t: &Ty = self; |
775 | 651 | ||
776 | while let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_mutability), parameters }) = t { | 652 | while let Ty::Ref(_mutability, parameters) = t { |
777 | t = parameters.as_single(); | 653 | t = parameters.as_single(); |
778 | } | 654 | } |
779 | 655 | ||
780 | t | 656 | t |
781 | } | 657 | } |
782 | 658 | ||
783 | pub fn as_adt(&self) -> Option<(AdtId, &Substs)> { | 659 | pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substs)> { |
784 | match self { | 660 | match self { |
785 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => { | 661 | Ty::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), |
786 | Some((*adt_def, parameters)) | ||
787 | } | ||
788 | _ => None, | 662 | _ => None, |
789 | } | 663 | } |
790 | } | 664 | } |
791 | 665 | ||
792 | pub fn as_tuple(&self) -> Option<&Substs> { | 666 | pub fn as_tuple(&self) -> Option<&Substs> { |
793 | match self { | 667 | match self { |
794 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { .. }, parameters }) => { | 668 | Ty::Tuple(_, substs) => Some(substs), |
795 | Some(parameters) | 669 | _ => None, |
796 | } | 670 | } |
671 | } | ||
672 | |||
673 | pub fn as_generic_def(&self) -> Option<GenericDefId> { | ||
674 | match *self { | ||
675 | Ty::Adt(AdtId(adt), ..) => Some(adt.into()), | ||
676 | Ty::FnDef(callable, ..) => Some(callable.into()), | ||
677 | Ty::AssociatedType(type_alias, ..) => Some(type_alias.into()), | ||
678 | Ty::ForeignType(type_alias, ..) => Some(type_alias.into()), | ||
797 | _ => None, | 679 | _ => None, |
798 | } | 680 | } |
799 | } | 681 | } |
800 | 682 | ||
801 | pub fn is_never(&self) -> bool { | 683 | pub fn is_never(&self) -> bool { |
802 | matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. })) | 684 | matches!(self, Ty::Never) |
803 | } | 685 | } |
804 | 686 | ||
805 | pub fn is_unknown(&self) -> bool { | 687 | pub fn is_unknown(&self) -> bool { |
806 | matches!(self, Ty::Unknown) | 688 | matches!(self, Ty::Unknown) |
807 | } | 689 | } |
808 | 690 | ||
691 | pub fn equals_ctor(&self, other: &Ty) -> bool { | ||
692 | match (self, other) { | ||
693 | (Ty::Adt(adt, ..), Ty::Adt(adt2, ..)) => adt == adt2, | ||
694 | (Ty::Slice(_), Ty::Slice(_)) | (Ty::Array(_), Ty::Array(_)) => true, | ||
695 | (Ty::FnDef(def_id, ..), Ty::FnDef(def_id2, ..)) => def_id == def_id2, | ||
696 | (Ty::OpaqueType(ty_id, ..), Ty::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, | ||
697 | (Ty::AssociatedType(ty_id, ..), Ty::AssociatedType(ty_id2, ..)) | ||
698 | | (Ty::ForeignType(ty_id, ..), Ty::ForeignType(ty_id2, ..)) => ty_id == ty_id2, | ||
699 | (Ty::Closure(def, expr, _), Ty::Closure(def2, expr2, _)) => { | ||
700 | expr == expr2 && def == def2 | ||
701 | } | ||
702 | (Ty::Ref(mutability, ..), Ty::Ref(mutability2, ..)) | ||
703 | | (Ty::Raw(mutability, ..), Ty::Raw(mutability2, ..)) => mutability == mutability2, | ||
704 | ( | ||
705 | Ty::Function(FnPointer { num_args, sig, .. }), | ||
706 | Ty::Function(FnPointer { num_args: num_args2, sig: sig2, .. }), | ||
707 | ) => num_args == num_args2 && sig == sig2, | ||
708 | (Ty::Tuple(cardinality, _), Ty::Tuple(cardinality2, _)) => cardinality == cardinality2, | ||
709 | (Ty::Str, Ty::Str) | (Ty::Never, Ty::Never) => true, | ||
710 | (Ty::Scalar(scalar), Ty::Scalar(scalar2)) => scalar == scalar2, | ||
711 | _ => false, | ||
712 | } | ||
713 | } | ||
714 | |||
809 | /// If this is a `dyn Trait` type, this returns the `Trait` part. | 715 | /// If this is a `dyn Trait` type, this returns the `Trait` part. |
810 | pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { | 716 | pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { |
811 | match self { | 717 | match self { |
@@ -824,41 +730,30 @@ impl Ty { | |||
824 | 730 | ||
825 | fn builtin_deref(&self) -> Option<Ty> { | 731 | fn builtin_deref(&self) -> Option<Ty> { |
826 | match self { | 732 | match self { |
827 | Ty::Apply(a_ty) => match a_ty.ctor { | 733 | Ty::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())), |
828 | TypeCtor::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())), | 734 | Ty::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())), |
829 | TypeCtor::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())), | ||
830 | _ => None, | ||
831 | }, | ||
832 | _ => None, | 735 | _ => None, |
833 | } | 736 | } |
834 | } | 737 | } |
835 | 738 | ||
836 | pub fn as_fn_def(&self) -> Option<FunctionId> { | 739 | pub fn as_fn_def(&self) -> Option<FunctionId> { |
837 | match self { | 740 | match self { |
838 | &Ty::Apply(ApplicationTy { | 741 | &Ty::FnDef(CallableDefId::FunctionId(func), ..) => Some(func), |
839 | ctor: TypeCtor::FnDef(CallableDefId::FunctionId(func)), | ||
840 | .. | ||
841 | }) => Some(func), | ||
842 | _ => None, | 742 | _ => None, |
843 | } | 743 | } |
844 | } | 744 | } |
845 | 745 | ||
846 | pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> { | 746 | pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> { |
847 | match self { | 747 | match self { |
848 | Ty::Apply(a_ty) => match a_ty.ctor { | 748 | Ty::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)), |
849 | TypeCtor::FnPtr { is_varargs, .. } => { | 749 | Ty::FnDef(def, parameters) => { |
850 | Some(FnSig::from_fn_ptr_substs(&a_ty.parameters, is_varargs)) | 750 | let sig = db.callable_item_signature(*def); |
851 | } | 751 | Some(sig.subst(¶meters)) |
852 | TypeCtor::FnDef(def) => { | 752 | } |
853 | let sig = db.callable_item_signature(def); | 753 | Ty::Closure(.., substs) => { |
854 | Some(sig.subst(&a_ty.parameters)) | 754 | let sig_param = &substs[0]; |
855 | } | 755 | sig_param.callable_sig(db) |
856 | TypeCtor::Closure { .. } => { | 756 | } |
857 | let sig_param = &a_ty.parameters[0]; | ||
858 | sig_param.callable_sig(db) | ||
859 | } | ||
860 | _ => None, | ||
861 | }, | ||
862 | _ => None, | 757 | _ => None, |
863 | } | 758 | } |
864 | } | 759 | } |
@@ -867,28 +762,66 @@ impl Ty { | |||