diff options
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/diagnostics.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 15 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 23 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 66 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 56 | ||||
-rw-r--r-- | crates/hir_ty/src/utils.rs | 24 |
7 files changed, 161 insertions, 43 deletions
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index e59487e54..1c72f766e 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -624,4 +624,14 @@ fn foo() { break; } | |||
624 | "#, | 624 | "#, |
625 | ); | 625 | ); |
626 | } | 626 | } |
627 | |||
628 | #[test] | ||
629 | fn missing_semicolon() { | ||
630 | check_diagnostics( | ||
631 | r#" | ||
632 | fn test() -> i32 { 123; } | ||
633 | //^^^ Remove this semicolon | ||
634 | "#, | ||
635 | ); | ||
636 | } | ||
627 | } | 637 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index aa286c8c2..0e827a29e 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -4,7 +4,7 @@ use std::fmt; | |||
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, | 6 | db::HirDatabase, utils::generics, ApplicationTy, CallableDefId, FnSig, GenericPredicate, |
7 | Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 7 | Lifetime, Obligation, OpaqueTyId, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
8 | }; | 8 | }; |
9 | use hir_def::{ | 9 | use hir_def::{ |
10 | find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId, | 10 | find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId, |
@@ -718,6 +718,19 @@ impl HirDisplay for GenericPredicate { | |||
718 | } | 718 | } |
719 | } | 719 | } |
720 | 720 | ||
721 | impl HirDisplay for Lifetime { | ||
722 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
723 | match self { | ||
724 | Lifetime::Parameter(id) => { | ||
725 | let generics = generics(f.db.upcast(), id.parent); | ||
726 | let param_data = &generics.params.lifetimes[id.local_id]; | ||
727 | write!(f, "{}", ¶m_data.name) | ||
728 | } | ||
729 | Lifetime::Static => write!(f, "'static"), | ||
730 | } | ||
731 | } | ||
732 | } | ||
733 | |||
721 | impl HirDisplay for Obligation { | 734 | impl HirDisplay for Obligation { |
722 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 735 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
723 | match self { | 736 | match self { |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 605951b10..ca005bc99 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -137,10 +137,24 @@ impl<'a> InferenceContext<'a> { | |||
137 | 137 | ||
138 | self.coerce_merge_branch(&then_ty, &else_ty) | 138 | self.coerce_merge_branch(&then_ty, &else_ty) |
139 | } | 139 | } |
140 | Expr::Block { statements, tail, .. } => { | 140 | Expr::Block { statements, tail, label } => match label { |
141 | // FIXME: Breakable block inference | 141 | Some(_) => { |
142 | self.infer_block(statements, *tail, expected) | 142 | let break_ty = self.table.new_type_var(); |
143 | } | 143 | self.breakables.push(BreakableContext { |
144 | may_break: false, | ||
145 | break_ty: break_ty.clone(), | ||
146 | label: label.clone(), | ||
147 | }); | ||
148 | let ty = self.infer_block(statements, *tail, &Expectation::has_type(break_ty)); | ||
149 | let ctxt = self.breakables.pop().expect("breakable stack broken"); | ||
150 | if ctxt.may_break { | ||
151 | ctxt.break_ty | ||
152 | } else { | ||
153 | ty | ||
154 | } | ||
155 | } | ||
156 | None => self.infer_block(statements, *tail, expected), | ||
157 | }, | ||
144 | Expr::Unsafe { body } => self.infer_expr(*body, expected), | 158 | Expr::Unsafe { body } => self.infer_expr(*body, expected), |
145 | Expr::TryBlock { body } => { | 159 | Expr::TryBlock { body } => { |
146 | let _inner = self.infer_expr(*body, expected); | 160 | let _inner = self.infer_expr(*body, expected); |
@@ -848,6 +862,7 @@ impl<'a> InferenceContext<'a> { | |||
848 | let ty = self.make_ty(type_ref); | 862 | let ty = self.make_ty(type_ref); |
849 | substs.push(ty); | 863 | substs.push(ty); |
850 | } | 864 | } |
865 | GenericArg::Lifetime(_) => {} | ||
851 | } | 866 | } |
852 | } | 867 | } |
853 | }; | 868 | }; |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 5a8c97198..357bd92f9 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -29,8 +29,8 @@ use base_db::{salsa, CrateId}; | |||
29 | use hir_def::{ | 29 | use hir_def::{ |
30 | expr::ExprId, | 30 | expr::ExprId, |
31 | type_ref::{Mutability, Rawness}, | 31 | type_ref::{Mutability, Rawness}, |
32 | AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, | 32 | AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, LifetimeParamId, Lookup, |
33 | TypeParamId, | 33 | TraitId, TypeAliasId, TypeParamId, |
34 | }; | 34 | }; |
35 | use itertools::Itertools; | 35 | use itertools::Itertools; |
36 | 36 | ||
@@ -52,6 +52,12 @@ pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironmen | |||
52 | 52 | ||
53 | pub use chalk_ir::{BoundVar, DebruijnIndex}; | 53 | pub use chalk_ir::{BoundVar, DebruijnIndex}; |
54 | 54 | ||
55 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
56 | pub enum Lifetime { | ||
57 | Parameter(LifetimeParamId), | ||
58 | Static, | ||
59 | } | ||
60 | |||
55 | /// A type constructor or type name: this might be something like the primitive | 61 | /// A type constructor or type name: this might be something like the primitive |
56 | /// type `bool`, a struct like `Vec`, or things like function pointers or | 62 | /// type `bool`, a struct like `Vec`, or things like function pointers or |
57 | /// tuples. | 63 | /// tuples. |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 708e2af0f..92f779360 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -12,7 +12,7 @@ use base_db::CrateId; | |||
12 | use hir_def::{ | 12 | use hir_def::{ |
13 | adt::StructKind, | 13 | adt::StructKind, |
14 | builtin_type::BuiltinType, | 14 | builtin_type::BuiltinType, |
15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget}, | 15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, |
16 | path::{GenericArg, Path, PathSegment, PathSegments}, | 16 | path::{GenericArg, Path, PathSegment, PathSegments}, |
17 | resolver::{HasResolver, Resolver, TypeNs}, | 17 | resolver::{HasResolver, Resolver, TypeNs}, |
18 | type_ref::{TypeBound, TypeRef}, | 18 | type_ref::{TypeBound, TypeRef}, |
@@ -171,7 +171,7 @@ impl Ty { | |||
171 | let inner_ty = Ty::from_hir(ctx, inner); | 171 | let inner_ty = Ty::from_hir(ctx, inner); |
172 | Ty::apply_one(TypeCtor::Slice, inner_ty) | 172 | Ty::apply_one(TypeCtor::Slice, inner_ty) |
173 | } | 173 | } |
174 | TypeRef::Reference(inner, mutability) => { | 174 | TypeRef::Reference(inner, _, mutability) => { |
175 | let inner_ty = Ty::from_hir(ctx, inner); | 175 | let inner_ty = Ty::from_hir(ctx, inner); |
176 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | 176 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) |
177 | } | 177 | } |
@@ -555,7 +555,7 @@ fn substs_from_path_segment( | |||
555 | 555 | ||
556 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); | 556 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); |
557 | 557 | ||
558 | let mut had_explicit_args = false; | 558 | let mut had_explicit_type_args = false; |
559 | 559 | ||
560 | if let Some(generic_args) = &segment.args_and_bindings { | 560 | if let Some(generic_args) = &segment.args_and_bindings { |
561 | if !generic_args.has_self_type { | 561 | if !generic_args.has_self_type { |
@@ -568,10 +568,11 @@ fn substs_from_path_segment( | |||
568 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { | 568 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { |
569 | match arg { | 569 | match arg { |
570 | GenericArg::Type(type_ref) => { | 570 | GenericArg::Type(type_ref) => { |
571 | had_explicit_args = true; | 571 | had_explicit_type_args = true; |
572 | let ty = Ty::from_hir(ctx, type_ref); | 572 | let ty = Ty::from_hir(ctx, type_ref); |
573 | substs.push(ty); | 573 | substs.push(ty); |
574 | } | 574 | } |
575 | GenericArg::Lifetime(_) => {} | ||
575 | } | 576 | } |
576 | } | 577 | } |
577 | } | 578 | } |
@@ -579,7 +580,7 @@ fn substs_from_path_segment( | |||
579 | // handle defaults. In expression or pattern path segments without | 580 | // handle defaults. In expression or pattern path segments without |
580 | // explicitly specified type arguments, missing type arguments are inferred | 581 | // explicitly specified type arguments, missing type arguments are inferred |
581 | // (i.e. defaults aren't used). | 582 | // (i.e. defaults aren't used). |
582 | if !infer_args || had_explicit_args { | 583 | if !infer_args || had_explicit_type_args { |
583 | if let Some(def_generic) = def_generic { | 584 | if let Some(def_generic) = def_generic { |
584 | let defaults = ctx.db.generic_defaults(def_generic); | 585 | let defaults = ctx.db.generic_defaults(def_generic); |
585 | assert_eq!(total_len, defaults.len()); | 586 | assert_eq!(total_len, defaults.len()); |
@@ -657,7 +658,7 @@ impl TraitRef { | |||
657 | ) -> Option<TraitRef> { | 658 | ) -> Option<TraitRef> { |
658 | match bound { | 659 | match bound { |
659 | TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)), | 660 | TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)), |
660 | TypeBound::Error => None, | 661 | TypeBound::Lifetime(_) | TypeBound::Error => None, |
661 | } | 662 | } |
662 | } | 663 | } |
663 | } | 664 | } |
@@ -667,22 +668,30 @@ impl GenericPredicate { | |||
667 | ctx: &'a TyLoweringContext<'a>, | 668 | ctx: &'a TyLoweringContext<'a>, |
668 | where_predicate: &'a WherePredicate, | 669 | where_predicate: &'a WherePredicate, |
669 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 670 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
670 | let self_ty = match &where_predicate.target { | 671 | match where_predicate { |
671 | WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), | 672 | WherePredicate::TypeBound { target, bound } => { |
672 | WherePredicateTarget::TypeParam(param_id) => { | 673 | let self_ty = match target { |
673 | let generic_def = ctx.resolver.generic_def().expect("generics in scope"); | 674 | WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), |
674 | let generics = generics(ctx.db.upcast(), generic_def); | 675 | WherePredicateTypeTarget::TypeParam(param_id) => { |
675 | let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; | 676 | let generic_def = ctx.resolver.generic_def().expect("generics in scope"); |
676 | match ctx.type_param_mode { | 677 | let generics = generics(ctx.db.upcast(), generic_def); |
677 | TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), | 678 | let param_id = |
678 | TypeParamLoweringMode::Variable => { | 679 | hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; |
679 | let idx = generics.param_idx(param_id).expect("matching generics"); | 680 | match ctx.type_param_mode { |
680 | Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)) | 681 | TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), |
682 | TypeParamLoweringMode::Variable => { | ||
683 | let idx = generics.param_idx(param_id).expect("matching generics"); | ||
684 | Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)) | ||
685 | } | ||
686 | } | ||
681 | } | 687 | } |
682 | } | 688 | }; |
689 | GenericPredicate::from_type_bound(ctx, bound, self_ty) | ||
690 | .collect::<Vec<_>>() | ||
691 | .into_iter() | ||
683 | } | 692 | } |
684 | }; | 693 | WherePredicate::Lifetime { .. } => vec![].into_iter(), |
685 | GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) | 694 | } |
686 | } | 695 | } |
687 | 696 | ||
688 | pub(crate) fn from_type_bound<'a>( | 697 | pub(crate) fn from_type_bound<'a>( |
@@ -707,7 +716,7 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
707 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 716 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
708 | let last_segment = match bound { | 717 | let last_segment = match bound { |
709 | TypeBound::Path(path) => path.segments().last(), | 718 | TypeBound::Path(path) => path.segments().last(), |
710 | TypeBound::Error => None, | 719 | TypeBound::Error | TypeBound::Lifetime(_) => None, |
711 | }; | 720 | }; |
712 | last_segment | 721 | last_segment |
713 | .into_iter() | 722 | .into_iter() |
@@ -872,11 +881,16 @@ pub(crate) fn generic_predicates_for_param_query( | |||
872 | resolver | 881 | resolver |
873 | .where_predicates_in_scope() | 882 | .where_predicates_in_scope() |
874 | // we have to filter out all other predicates *first*, before attempting to lower them | 883 | // we have to filter out all other predicates *first*, before attempting to lower them |
875 | .filter(|pred| match &pred.target { | 884 | .filter(|pred| match pred { |
876 | WherePredicateTarget::TypeRef(type_ref) => { | 885 | WherePredicate::TypeBound { |
877 | Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) | 886 | target: WherePredicateTypeTarget::TypeRef(type_ref), |
878 | } | 887 | .. |
879 | WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.local_id, | 888 | } => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id), |
889 | WherePredicate::TypeBound { | ||
890 | target: WherePredicateTypeTarget::TypeParam(local_id), | ||
891 | .. | ||
892 | } => *local_id == param_id.local_id, | ||
893 | WherePredicate::Lifetime { .. } => false, | ||
880 | }) | 894 | }) |
881 | .flat_map(|pred| { | 895 | .flat_map(|pred| { |
882 | GenericPredicate::from_where_predicate(&ctx, pred) | 896 | GenericPredicate::from_where_predicate(&ctx, pred) |
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 4f72582b6..a569223b4 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -2075,6 +2075,62 @@ fn infer_labelled_break_with_val() { | |||
2075 | } | 2075 | } |
2076 | 2076 | ||
2077 | #[test] | 2077 | #[test] |
2078 | fn infer_labelled_block_break_with_val() { | ||
2079 | check_infer( | ||
2080 | r#" | ||
2081 | fn default<T>() -> T { loop {} } | ||
2082 | fn foo() { | ||
2083 | let _x = 'outer: { | ||
2084 | let inner = 'inner: { | ||
2085 | let i = default(); | ||
2086 | if (break 'outer i) { | ||
2087 | break 'inner 5i8; | ||
2088 | } else if true { | ||
2089 | break 'inner 6; | ||
2090 | } | ||
2091 | break 'inner 'innermost: { 0 }; | ||
2092 | 42 | ||
2093 | }; | ||
2094 | break 'outer inner < 8; | ||
2095 | }; | ||
2096 | } | ||
2097 | "#, | ||
2098 | expect![[r#" | ||
2099 | 21..32 '{ loop {} }': T | ||
2100 | 23..30 'loop {}': ! | ||
2101 | 28..30 '{}': () | ||
2102 | 42..381 '{ ... }; }': () | ||
2103 | 52..54 '_x': bool | ||
2104 | 65..378 '{ ... }': bool | ||
2105 | 79..84 'inner': i8 | ||
2106 | 95..339 '{ ... }': i8 | ||
2107 | 113..114 'i': bool | ||
2108 | 117..124 'default': fn default<bool>() -> bool | ||
2109 | 117..126 'default()': bool | ||
2110 | 140..270 'if (br... }': () | ||
2111 | 144..158 'break 'outer i': ! | ||
2112 | 157..158 'i': bool | ||
2113 | 160..209 '{ ... }': () | ||
2114 | 178..194 'break ...er 5i8': ! | ||
2115 | 191..194 '5i8': i8 | ||
2116 | 215..270 'if tru... }': () | ||
2117 | 218..222 'true': bool | ||
2118 | 223..270 '{ ... }': () | ||
2119 | 241..255 'break 'inner 6': ! | ||
2120 | 254..255 '6': i8 | ||
2121 | 283..313 'break ... { 0 }': ! | ||
2122 | 308..313 '{ 0 }': i8 | ||
2123 | 310..311 '0': i8 | ||
2124 | 327..329 '42': i8 | ||
2125 | 349..371 'break ...er < 8': ! | ||
2126 | 362..367 'inner': i8 | ||
2127 | 362..371 'inner < 8': bool | ||
2128 | 370..371 '8': i8 | ||
2129 | "#]], | ||
2130 | ); | ||
2131 | } | ||
2132 | |||
2133 | #[test] | ||
2078 | fn generic_default() { | 2134 | fn generic_default() { |
2079 | check_infer( | 2135 | check_infer( |
2080 | r#" | 2136 | r#" |
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index e3e244268..af880c065 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -2,11 +2,10 @@ | |||
2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). | 2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). |
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::generics::WherePredicateTarget; | ||
6 | use hir_def::{ | 5 | use hir_def::{ |
7 | adt::VariantData, | 6 | adt::VariantData, |
8 | db::DefDatabase, | 7 | db::DefDatabase, |
9 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | 8 | generics::{GenericParams, TypeParamData, TypeParamProvenance, WherePredicateTypeTarget}, |
10 | path::Path, | 9 | path::Path, |
11 | resolver::{HasResolver, TypeNs}, | 10 | resolver::{HasResolver, TypeNs}, |
12 | type_ref::TypeRef, | 11 | type_ref::TypeRef, |
@@ -27,14 +26,19 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | |||
27 | generic_params | 26 | generic_params |
28 | .where_predicates | 27 | .where_predicates |
29 | .iter() | 28 | .iter() |
30 | .filter_map(|pred| match &pred.target { | 29 | .filter_map(|pred| match pred { |
31 | WherePredicateTarget::TypeRef(TypeRef::Path(p)) if p == &Path::from(name![Self]) => { | 30 | hir_def::generics::WherePredicate::TypeBound { target, bound } => match target { |
32 | pred.bound.as_path() | 31 | WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) |
33 | } | 32 | if p == &Path::from(name![Self]) => |
34 | WherePredicateTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { | 33 | { |
35 | pred.bound.as_path() | 34 | bound.as_path() |
36 | } | 35 | } |
37 | _ => None, | 36 | WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { |
37 | bound.as_path() | ||
38 | } | ||
39 | _ => None, | ||
40 | }, | ||
41 | hir_def::generics::WherePredicate::Lifetime { .. } => None, | ||
38 | }) | 42 | }) |
39 | .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { | 43 | .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { |
40 | Some(TypeNs::TraitId(t)) => Some(t), | 44 | Some(TypeNs::TraitId(t)) => Some(t), |