aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-06-29 15:13:41 +0100
committerGitHub <[email protected]>2020-06-29 15:13:41 +0100
commit82ce5792ab70ab8d20a1afde72c5400c27b9c190 (patch)
tree79cc454a617f30080a611b8ac66de849b0af53b7 /crates
parentca31b1d63ae91a69f1ce9c0b075403834ba19f38 (diff)
parent8e8d2ffecbc9e260ee5f0d37ba057b660e16076f (diff)
Merge #5124
5124: (Partially) fix handling of type params depending on type params r=matklad a=flodiebold If the first type parameter gets inferred, that's still not handled correctly; it'll require some more refactoring: E.g. if we have `Thing<T, F=fn() -> T>` and then instantiate `Thing<_>`, that gets turned into `Thing<_, fn() -> _>` before the `_` is instantiated into a type variable -- so afterwards, we have two type variables without any connection to each other. Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs9
-rw-r--r--crates/ra_hir_ty/src/db.rs4
-rw-r--r--crates/ra_hir_ty/src/display.rs18
-rw-r--r--crates/ra_hir_ty/src/lower.rs43
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs45
5 files changed, 98 insertions, 21 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 27e94b7fe..e86077dd6 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -543,7 +543,7 @@ impl_froms!(Adt: Struct, Union, Enum);
543impl Adt { 543impl Adt {
544 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 544 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
545 let subst = db.generic_defaults(self.into()); 545 let subst = db.generic_defaults(self.into());
546 subst.iter().any(|ty| ty == &Ty::Unknown) 546 subst.iter().any(|ty| &ty.value == &Ty::Unknown)
547 } 547 }
548 548
549 /// Turns this ADT into a type. Any type parameters of the ADT will be 549 /// Turns this ADT into a type. Any type parameters of the ADT will be
@@ -775,7 +775,7 @@ pub struct TypeAlias {
775impl TypeAlias { 775impl TypeAlias {
776 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 776 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
777 let subst = db.generic_defaults(self.id.into()); 777 let subst = db.generic_defaults(self.id.into());
778 subst.iter().any(|ty| ty == &Ty::Unknown) 778 subst.iter().any(|ty| &ty.value == &Ty::Unknown)
779 } 779 }
780 780
781 pub fn module(self, db: &dyn HirDatabase) -> Module { 781 pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1035,7 +1035,10 @@ impl TypeParam {
1035 let local_idx = hir_ty::param_idx(db, self.id)?; 1035 let local_idx = hir_ty::param_idx(db, self.id)?;
1036 let resolver = self.id.parent.resolver(db.upcast()); 1036 let resolver = self.id.parent.resolver(db.upcast());
1037 let environment = TraitEnvironment::lower(db, &resolver); 1037 let environment = TraitEnvironment::lower(db, &resolver);
1038 params.get(local_idx).cloned().map(|ty| Type { 1038 let ty = params.get(local_idx)?.clone();
1039 let subst = Substs::type_params(db, self.id.parent);
1040 let ty = ty.subst(&subst.prefix(local_idx));
1041 Some(Type {
1039 krate: self.id.parent.module(db.upcast()).krate, 1042 krate: self.id.parent.module(db.upcast()).krate,
1040 ty: InEnvironment { value: ty, environment }, 1043 ty: InEnvironment { value: ty, environment },
1041 }) 1044 })
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index 7889b8d2c..cad553273 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -14,7 +14,7 @@ use crate::{
14 method_resolution::CrateImplDefs, 14 method_resolution::CrateImplDefs,
15 traits::{chalk, AssocTyValue, Impl}, 15 traits::{chalk, AssocTyValue, Impl},
16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, 16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
17 ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, 17 ReturnTypeImplTraits, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId,
18}; 18};
19use hir_expand::name::Name; 19use hir_expand::name::Name;
20 20
@@ -65,7 +65,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
65 fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>; 65 fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>;
66 66
67 #[salsa::invoke(crate::lower::generic_defaults_query)] 67 #[salsa::invoke(crate::lower::generic_defaults_query)]
68 fn generic_defaults(&self, def: GenericDefId) -> Substs; 68 fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>;
69 69
70 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)] 70 #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)]
71 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>; 71 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>;
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 3c97e1354..23cea1a2a 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -308,7 +308,6 @@ impl HirDisplay for ApplicationTy {
308 } 308 }
309 309
310 if self.parameters.len() > 0 { 310 if self.parameters.len() > 0 {
311 let mut non_default_parameters = Vec::with_capacity(self.parameters.len());
312 let parameters_to_write = 311 let parameters_to_write =
313 if f.display_target.is_source_code() || f.omit_verbose_types() { 312 if f.display_target.is_source_code() || f.omit_verbose_types() {
314 match self 313 match self
@@ -319,20 +318,23 @@ impl HirDisplay for ApplicationTy {
319 { 318 {
320 None => self.parameters.0.as_ref(), 319 None => self.parameters.0.as_ref(),
321 Some(default_parameters) => { 320 Some(default_parameters) => {
321 let mut default_from = 0;
322 for (i, parameter) in self.parameters.iter().enumerate() { 322 for (i, parameter) in self.parameters.iter().enumerate() {
323 match (parameter, default_parameters.get(i)) { 323 match (parameter, default_parameters.get(i)) {
324 (&Ty::Unknown, _) | (_, None) => { 324 (&Ty::Unknown, _) | (_, None) => {
325 non_default_parameters.push(parameter.clone()) 325 default_from = i + 1;
326 } 326 }
327 (_, Some(default_parameter)) 327 (_, Some(default_parameter)) => {
328 if parameter != default_parameter => 328 let actual_default = default_parameter
329 { 329 .clone()
330 non_default_parameters.push(parameter.clone()) 330 .subst(&self.parameters.prefix(i));
331 if parameter != &actual_default {
332 default_from = i + 1;
333 }
331 } 334 }
332 _ => (),
333 } 335 }
334 } 336 }
335 &non_default_parameters 337 &self.parameters.0[0..default_from]
336 } 338 }
337 } 339 }
338 } else { 340 } else {
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index d5154f436..3dc154e92 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -578,11 +578,13 @@ fn substs_from_path_segment(
578 // (i.e. defaults aren't used). 578 // (i.e. defaults aren't used).
579 if !infer_args || had_explicit_args { 579 if !infer_args || had_explicit_args {
580 if let Some(def_generic) = def_generic { 580 if let Some(def_generic) = def_generic {
581 let default_substs = ctx.db.generic_defaults(def_generic); 581 let defaults = ctx.db.generic_defaults(def_generic);
582 assert_eq!(total_len, default_substs.len()); 582 assert_eq!(total_len, defaults.len());
583 583
584 for default_ty in default_substs.iter().skip(substs.len()) { 584 for default_ty in defaults.iter().skip(substs.len()) {
585 substs.push(default_ty.clone()); 585 // each default can depend on the previous parameters
586 let substs_so_far = Substs(substs.clone().into());
587 substs.push(default_ty.clone().subst(&substs_so_far));
586 } 588 }
587 } 589 }
588 } 590 }
@@ -945,17 +947,42 @@ pub(crate) fn generic_predicates_query(
945} 947}
946 948
947/// Resolve the default type params from generics 949/// Resolve the default type params from generics
948pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> Substs { 950pub(crate) fn generic_defaults_query(
951 db: &dyn HirDatabase,
952 def: GenericDefId,
953) -> Arc<[Binders<Ty>]> {
949 let resolver = def.resolver(db.upcast()); 954 let resolver = def.resolver(db.upcast());
950 let ctx = TyLoweringContext::new(db, &resolver); 955 let ctx =
956 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
951 let generic_params = generics(db.upcast(), def); 957 let generic_params = generics(db.upcast(), def);
952 958
953 let defaults = generic_params 959 let defaults = generic_params
954 .iter() 960 .iter()
955 .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t))) 961 .enumerate()
962 .map(|(idx, (_, p))| {
963 let mut ty = p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t));
964
965 // Each default can only refer to previous parameters.
966 ty.walk_mut_binders(
967 &mut |ty, binders| match ty {
968 Ty::Bound(BoundVar { debruijn, index }) if *debruijn == binders => {
969 if *index >= idx {
970 // type variable default referring to parameter coming
971 // after it. This is forbidden (FIXME: report
972 // diagnostic)
973 *ty = Ty::Unknown;
974 }
975 }
976 _ => {}
977 },
978 DebruijnIndex::INNERMOST,
979 );
980
981 Binders::new(idx, ty)
982 })
956 .collect(); 983 .collect();
957 984
958 Substs(defaults) 985 defaults
959} 986}
960 987
961fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { 988fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index cd919466f..5e3f2bd3c 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -2152,3 +2152,48 @@ fn test() {
2152 "### 2152 "###
2153 ); 2153 );
2154} 2154}
2155
2156#[test]
2157fn generic_default_depending_on_other_type_arg() {
2158 assert_snapshot!(
2159 infer(r#"
2160struct Thing<T = u128, F = fn() -> T> { t: T }
2161
2162fn test(t1: Thing<u32>, t2: Thing) {
2163 t1;
2164 t2;
2165 Thing::<_> { t: 1u32 };
2166}
2167"#),
2168 // FIXME: the {unknown} is a bug
2169 @r###"
2170 56..58 't1': Thing<u32, fn() -> u32>
2171 72..74 't2': Thing<u128, fn() -> u128>
2172 83..130 '{ ...2 }; }': ()
2173 89..91 't1': Thing<u32, fn() -> u32>
2174 97..99 't2': Thing<u128, fn() -> u128>
2175 105..127 'Thing:...1u32 }': Thing<u32, fn() -> {unknown}>
2176 121..125 '1u32': u32
2177 "###
2178 );
2179}
2180
2181#[test]
2182fn generic_default_depending_on_other_type_arg_forward() {
2183 assert_snapshot!(
2184 infer(r#"
2185struct Thing<F = fn() -> T, T = u128> { t: T }
2186
2187fn test(t1: Thing) {
2188 t1;
2189}
2190"#),
2191 // the {unknown} here is intentional, as defaults are not allowed to
2192 // refer to type parameters coming later
2193 @r###"
2194 56..58 't1': Thing<fn() -> {unknown}, u128>
2195 67..78 '{ t1; }': ()
2196 73..75 't1': Thing<fn() -> {unknown}, u128>
2197 "###
2198 );
2199}