aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/diagnostics.rs10
-rw-r--r--crates/hir_ty/src/display.rs25
-rw-r--r--crates/hir_ty/src/infer/expr.rs30
-rw-r--r--crates/hir_ty/src/lib.rs10
-rw-r--r--crates/hir_ty/src/lower.rs74
-rw-r--r--crates/hir_ty/src/tests/regression.rs37
-rw-r--r--crates/hir_ty/src/tests/simple.rs56
-rw-r--r--crates/hir_ty/src/utils.rs24
8 files changed, 220 insertions, 46 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 e77481906..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
5use crate::{ 5use 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};
9use hir_def::{ 9use hir_def::{
10 find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId, 10 find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId,
@@ -178,6 +178,7 @@ impl DisplayTarget {
178#[derive(Debug)] 178#[derive(Debug)]
179pub enum DisplaySourceCodeError { 179pub enum DisplaySourceCodeError {
180 PathNotFound, 180 PathNotFound,
181 UnknownType,
181} 182}
182 183
183pub enum HirDisplayError { 184pub enum HirDisplayError {
@@ -558,7 +559,14 @@ impl HirDisplay for Ty {
558 } 559 }
559 }; 560 };
560 } 561 }
561 Ty::Unknown => write!(f, "{{unknown}}")?, 562 Ty::Unknown => {
563 if f.display_target.is_source_code() {
564 return Err(HirDisplayError::DisplaySourceCodeError(
565 DisplaySourceCodeError::UnknownType,
566 ));
567 }
568 write!(f, "{{unknown}}")?;
569 }
562 Ty::Infer(..) => write!(f, "_")?, 570 Ty::Infer(..) => write!(f, "_")?,
563 } 571 }
564 Ok(()) 572 Ok(())
@@ -710,6 +718,19 @@ impl HirDisplay for GenericPredicate {
710 } 718 }
711} 719}
712 720
721impl 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, "{}", &param_data.name)
728 }
729 Lifetime::Static => write!(f, "'static"),
730 }
731 }
732}
733
713impl HirDisplay for Obligation { 734impl HirDisplay for Obligation {
714 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 735 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
715 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..2cdce2cef 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);
@@ -842,12 +856,18 @@ impl<'a> InferenceContext<'a> {
842 // handle provided type arguments 856 // handle provided type arguments
843 if let Some(generic_args) = generic_args { 857 if let Some(generic_args) = generic_args {
844 // if args are provided, it should be all of them, but we can't rely on that 858 // if args are provided, it should be all of them, but we can't rely on that
845 for arg in generic_args.args.iter().take(type_params) { 859 for arg in generic_args
860 .args
861 .iter()
862 .filter(|arg| matches!(arg, GenericArg::Type(_)))
863 .take(type_params)
864 {
846 match arg { 865 match arg {
847 GenericArg::Type(type_ref) => { 866 GenericArg::Type(type_ref) => {
848 let ty = self.make_ty(type_ref); 867 let ty = self.make_ty(type_ref);
849 substs.push(ty); 868 substs.push(ty);
850 } 869 }
870 GenericArg::Lifetime(_) => {}
851 } 871 }
852 } 872 }
853 }; 873 };
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};
29use hir_def::{ 29use 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};
35use itertools::Itertools; 35use itertools::Itertools;
36 36
@@ -52,6 +52,12 @@ pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironmen
52 52
53pub use chalk_ir::{BoundVar, DebruijnIndex}; 53pub use chalk_ir::{BoundVar, DebruijnIndex};
54 54
55#[derive(Clone, PartialEq, Eq, Debug, Hash)]
56pub 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..8392cb770 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -12,7 +12,7 @@ use base_db::CrateId;
12use hir_def::{ 12use 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 {
@@ -565,13 +565,20 @@ fn substs_from_path_segment(
565 if generic_args.has_self_type { self_params + type_params } else { type_params }; 565 if generic_args.has_self_type { self_params + type_params } else { type_params };
566 let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 }; 566 let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
567 // if args are provided, it should be all of them, but we can't rely on that 567 // if args are provided, it should be all of them, but we can't rely on that
568 for arg in generic_args.args.iter().skip(skip).take(expected_num) { 568 for arg in generic_args
569 .args
570 .iter()
571 .filter(|arg| matches!(arg, GenericArg::Type(_)))
572 .skip(skip)
573 .take(expected_num)
574 {
569 match arg { 575 match arg {
570 GenericArg::Type(type_ref) => { 576 GenericArg::Type(type_ref) => {
571 had_explicit_args = true; 577 had_explicit_type_args = true;
572 let ty = Ty::from_hir(ctx, type_ref); 578 let ty = Ty::from_hir(ctx, type_ref);
573 substs.push(ty); 579 substs.push(ty);
574 } 580 }
581 GenericArg::Lifetime(_) => {}
575 } 582 }
576 } 583 }
577 } 584 }
@@ -579,7 +586,7 @@ fn substs_from_path_segment(
579 // handle defaults. In expression or pattern path segments without 586 // handle defaults. In expression or pattern path segments without
580 // explicitly specified type arguments, missing type arguments are inferred 587 // explicitly specified type arguments, missing type arguments are inferred
581 // (i.e. defaults aren't used). 588 // (i.e. defaults aren't used).
582 if !infer_args || had_explicit_args { 589 if !infer_args || had_explicit_type_args {
583 if let Some(def_generic) = def_generic { 590 if let Some(def_generic) = def_generic {
584 let defaults = ctx.db.generic_defaults(def_generic); 591 let defaults = ctx.db.generic_defaults(def_generic);
585 assert_eq!(total_len, defaults.len()); 592 assert_eq!(total_len, defaults.len());
@@ -657,7 +664,7 @@ impl TraitRef {
657 ) -> Option<TraitRef> { 664 ) -> Option<TraitRef> {
658 match bound { 665 match bound {
659 TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)), 666 TypeBound::Path(path) => TraitRef::from_path(ctx, path, Some(self_ty)),
660 TypeBound::Error => None, 667 TypeBound::Lifetime(_) | TypeBound::Error => None,
661 } 668 }
662 } 669 }
663} 670}
@@ -667,22 +674,30 @@ impl GenericPredicate {
667 ctx: &'a TyLoweringContext<'a>, 674 ctx: &'a TyLoweringContext<'a>,
668 where_predicate: &'a WherePredicate, 675 where_predicate: &'a WherePredicate,
669 ) -> impl Iterator<Item = GenericPredicate> + 'a { 676 ) -> impl Iterator<Item = GenericPredicate> + 'a {
670 let self_ty = match &where_predicate.target { 677 match where_predicate {
671 WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), 678 WherePredicate::TypeBound { target, bound } => {
672 WherePredicateTarget::TypeParam(param_id) => { 679 let self_ty = match target {
673 let generic_def = ctx.resolver.generic_def().expect("generics in scope"); 680 WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref),
674 let generics = generics(ctx.db.upcast(), generic_def); 681 WherePredicateTypeTarget::TypeParam(param_id) => {
675 let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; 682 let generic_def = ctx.resolver.generic_def().expect("generics in scope");
676 match ctx.type_param_mode { 683 let generics = generics(ctx.db.upcast(), generic_def);
677 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 684 let param_id =
678 TypeParamLoweringMode::Variable => { 685 hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
679 let idx = generics.param_idx(param_id).expect("matching generics"); 686 match ctx.type_param_mode {
680 Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)) 687 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
688 TypeParamLoweringMode::Variable => {
689 let idx = generics.param_idx(param_id).expect("matching generics");
690 Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
691 }
692 }
681 } 693 }
682 } 694 };
695 GenericPredicate::from_type_bound(ctx, bound, self_ty)
696 .collect::<Vec<_>>()
697 .into_iter()
683 } 698 }
684 }; 699 WherePredicate::Lifetime { .. } => vec![].into_iter(),
685 GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) 700 }
686 } 701 }
687 702
688 pub(crate) fn from_type_bound<'a>( 703 pub(crate) fn from_type_bound<'a>(
@@ -707,7 +722,7 @@ fn assoc_type_bindings_from_type_bound<'a>(
707) -> impl Iterator<Item = GenericPredicate> + 'a { 722) -> impl Iterator<Item = GenericPredicate> + 'a {
708 let last_segment = match bound { 723 let last_segment = match bound {
709 TypeBound::Path(path) => path.segments().last(), 724 TypeBound::Path(path) => path.segments().last(),
710 TypeBound::Error => None, 725 TypeBound::Error | TypeBound::Lifetime(_) => None,
711 }; 726 };
712 last_segment 727 last_segment
713 .into_iter() 728 .into_iter()
@@ -872,11 +887,16 @@ pub(crate) fn generic_predicates_for_param_query(
872 resolver 887 resolver
873 .where_predicates_in_scope() 888 .where_predicates_in_scope()
874 // we have to filter out all other predicates *first*, before attempting to lower them 889 // we have to filter out all other predicates *first*, before attempting to lower them
875 .filter(|pred| match &pred.target { 890 .filter(|pred| match pred {
876 WherePredicateTarget::TypeRef(type_ref) => { 891 WherePredicate::TypeBound {
877 Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) 892 target: WherePredicateTypeTarget::TypeRef(type_ref),
878 } 893 ..
879 WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.local_id, 894 } => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id),
895 WherePredicate::TypeBound {
896 target: WherePredicateTypeTarget::TypeParam(local_id),
897 ..
898 } => *local_id == param_id.local_id,
899 WherePredicate::Lifetime { .. } => false,
880 }) 900 })
881 .flat_map(|pred| { 901 .flat_map(|pred| {
882 GenericPredicate::from_where_predicate(&ctx, pred) 902 GenericPredicate::from_where_predicate(&ctx, pred)
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index 8cf4e7012..da8170417 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -883,3 +883,40 @@ fn issue_6628() {
883 "#]], 883 "#]],
884 ); 884 );
885} 885}
886
887#[test]
888fn issue_6852() {
889 check_infer(
890 r#"
891 #[lang = "deref"]
892 pub trait Deref {
893 type Target;
894 }
895
896 struct BufWriter {}
897
898 struct Mutex<T> {}
899 struct MutexGuard<'a, T> {}
900 impl<T> Mutex<T> {
901 fn lock(&self) -> MutexGuard<'_, T> {}
902 }
903 impl<'a, T: 'a> Deref for MutexGuard<'a, T> {
904 type Target = T;
905 }
906 fn flush(&self) {
907 let w: &Mutex<BufWriter>;
908 *(w.lock());
909 }
910 "#,
911 expect![[r#"
912 156..160 'self': &Mutex<T>
913 183..185 '{}': ()
914 267..271 'self': &{unknown}
915 273..323 '{ ...()); }': ()
916 283..284 'w': &Mutex<BufWriter>
917 309..320 '*(w.lock())': BufWriter
918 311..312 'w': &Mutex<BufWriter>
919 311..319 'w.lock()': MutexGuard<BufWriter>
920 "#]],
921 );
922}
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]
2078fn 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]
2078fn generic_default() { 2134fn 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`).
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::generics::WherePredicateTarget;
6use hir_def::{ 5use 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),