aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs12
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs3
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs82
-rw-r--r--crates/ra_hir/src/ty/lower.rs23
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs141
-rw-r--r--crates/ra_hir/src/ty/primitive.rs22
-rw-r--r--crates/ra_hir/src/ty/tests.rs175
7 files changed, 335 insertions, 123 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 6694467a3..2370e8d4f 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -25,7 +25,7 @@ use hir_def::{
25 path::known, 25 path::known,
26 type_ref::{Mutability, TypeRef}, 26 type_ref::{Mutability, TypeRef},
27}; 27};
28use hir_expand::name; 28use hir_expand::{diagnostics::DiagnosticSink, name};
29use ra_arena::map::ArenaMap; 29use ra_arena::map::ArenaMap;
30use ra_prof::profile; 30use ra_prof::profile;
31use test_utils::tested_by; 31use test_utils::tested_by;
@@ -40,7 +40,6 @@ use crate::{
40 adt::VariantDef, 40 adt::VariantDef,
41 code_model::TypeAlias, 41 code_model::TypeAlias,
42 db::HirDatabase, 42 db::HirDatabase,
43 diagnostics::DiagnosticSink,
44 expr::{BindingAnnotation, Body, ExprId, PatId}, 43 expr::{BindingAnnotation, Body, ExprId, PatId},
45 resolve::{Resolver, TypeNs}, 44 resolve::{Resolver, TypeNs},
46 ty::infer::diagnostics::InferenceDiagnostic, 45 ty::infer::diagnostics::InferenceDiagnostic,
@@ -719,12 +718,9 @@ impl Expectation {
719} 718}
720 719
721mod diagnostics { 720mod diagnostics {
722 use crate::{ 721 use hir_expand::diagnostics::DiagnosticSink;
723 db::HirDatabase, 722
724 diagnostics::{DiagnosticSink, NoSuchField}, 723 use crate::{db::HirDatabase, diagnostics::NoSuchField, expr::ExprId, Function, HasSource};
725 expr::ExprId,
726 Function, HasSource,
727 };
728 724
729 #[derive(Debug, PartialEq, Eq, Clone)] 725 #[derive(Debug, PartialEq, Eq, Clone)]
730 pub(super) enum InferenceDiagnostic { 726 pub(super) enum InferenceDiagnostic {
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index fed52df39..a09ef5c5d 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -11,12 +11,11 @@ use crate::{
11 db::HirDatabase, 11 db::HirDatabase,
12 expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 12 expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
13 generics::{GenericParams, HasGenericParams}, 13 generics::{GenericParams, HasGenericParams},
14 nameres::Namespace,
15 ty::{ 14 ty::{
16 autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation, 15 autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation,
17 ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, 16 ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
18 }, 17 },
19 Adt, Name, 18 Adt, Name, Namespace,
20}; 19};
21 20
22impl<'a, D: HirDatabase> InferenceContext<'a, D> { 21impl<'a, D: HirDatabase> InferenceContext<'a, D> {
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 77aa35ce1..59b7f7eb6 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -6,8 +6,8 @@ use super::{ExprOrPatId, InferenceContext, TraitRef};
6use crate::{ 6use crate::{
7 db::HirDatabase, 7 db::HirDatabase,
8 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 8 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
9 ty::{Substs, Ty, TypableDef, TypeWalk}, 9 ty::{method_resolution, Substs, Ty, TypableDef, TypeWalk},
10 AssocItem, HasGenericParams, Namespace, Path, 10 AssocItem, Container, HasGenericParams, Name, Namespace, Path,
11}; 11};
12 12
13impl<'a, D: HirDatabase> InferenceContext<'a, D> { 13impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -39,7 +39,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
39 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); 39 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty);
40 self.resolve_ty_assoc_item( 40 self.resolve_ty_assoc_item(
41 ty, 41 ty,
42 path.segments.last().expect("path had at least one segment"), 42 &path.segments.last().expect("path had at least one segment").name,
43 id, 43 id,
44 )? 44 )?
45 } else { 45 } else {
@@ -122,10 +122,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
122 return None; 122 return None;
123 } 123 }
124 124
125 let ty = self.insert_type_vars(ty);
126 let ty = self.normalize_associated_types_in(ty);
127
125 let segment = 128 let segment =
126 remaining_segments.last().expect("there should be at least one segment here"); 129 remaining_segments.last().expect("there should be at least one segment here");
127 130
128 self.resolve_ty_assoc_item(ty, segment, id) 131 self.resolve_ty_assoc_item(ty, &segment.name, id)
129 } 132 }
130 } 133 }
131 } 134 }
@@ -162,7 +165,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
162 }; 165 };
163 let substs = Substs::build_for_def(self.db, item) 166 let substs = Substs::build_for_def(self.db, item)
164 .use_parent_substs(&trait_ref.substs) 167 .use_parent_substs(&trait_ref.substs)
165 .fill_with_unknown() 168 .fill_with_params()
166 .build(); 169 .build();
167 170
168 self.write_assoc_resolution(id, item); 171 self.write_assoc_resolution(id, item);
@@ -172,44 +175,51 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
172 fn resolve_ty_assoc_item( 175 fn resolve_ty_assoc_item(
173 &mut self, 176 &mut self,
174 ty: Ty, 177 ty: Ty,
175 segment: &PathSegment, 178 name: &Name,
176 id: ExprOrPatId, 179 id: ExprOrPatId,
177 ) -> Option<(ValueNs, Option<Substs>)> { 180 ) -> Option<(ValueNs, Option<Substs>)> {
178 if let Ty::Unknown = ty { 181 if let Ty::Unknown = ty {
179 return None; 182 return None;
180 } 183 }
181 184
182 let krate = self.resolver.krate()?; 185 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
183 186
184 // Find impl 187 method_resolution::iterate_method_candidates(
185 // FIXME: consider trait candidates 188 &canonical_ty.value,
186 let item = ty.clone().iterate_impl_items(self.db, krate, |item| match item { 189 self.db,
187 AssocItem::Function(func) => { 190 &self.resolver.clone(),
188 if segment.name == func.name(self.db) { 191 Some(name),
189 Some(AssocItem::Function(func)) 192 method_resolution::LookupMode::Path,
190 } else { 193 move |_ty, item| {
191 None 194 let def = match item {
192 } 195 AssocItem::Function(f) => ValueNs::Function(f),
193 } 196 AssocItem::Const(c) => ValueNs::Const(c),
194 197 AssocItem::TypeAlias(_) => unreachable!(),
195 AssocItem::Const(konst) => { 198 };
196 if konst.name(self.db).map_or(false, |n| n == segment.name) { 199 let substs = match item.container(self.db) {
197 Some(AssocItem::Const(konst)) 200 Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()),
198 } else { 201 Container::Trait(t) => {
199 None 202 // we're picking this method
200 } 203 let trait_substs = Substs::build_for_def(self.db, t)
201 } 204 .push(ty.clone())
202 AssocItem::TypeAlias(_) => None, 205 .fill(std::iter::repeat_with(|| self.new_type_var()))
203 })?; 206 .build();
204 let def = match item { 207 let substs = Substs::build_for_def(self.db, item)
205 AssocItem::Function(f) => ValueNs::Function(f), 208 .use_parent_substs(&trait_substs)
206 AssocItem::Const(c) => ValueNs::Const(c), 209 .fill_with_params()
207 AssocItem::TypeAlias(_) => unreachable!(), 210 .build();
208 }; 211 self.obligations.push(super::Obligation::Trait(TraitRef {
209 let substs = self.find_self_types(&def, ty); 212 trait_: t,
213 substs: trait_substs,
214 }));
215 Some(substs)
216 }
217 };
210 218
211 self.write_assoc_resolution(id, item); 219 self.write_assoc_resolution(id, item);
212 Some((def, substs)) 220 Some((def, substs))
221 },
222 )
213 } 223 }
214 224
215 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { 225 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 0f49a0e54..e29ab8492 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -9,6 +9,7 @@ use std::iter;
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use hir_def::{ 11use hir_def::{
12 builtin_type::BuiltinType,
12 path::{GenericArg, PathSegment}, 13 path::{GenericArg, PathSegment},
13 type_ref::{TypeBound, TypeRef}, 14 type_ref::{TypeBound, TypeRef},
14}; 15};
@@ -22,11 +23,13 @@ use crate::{
22 db::HirDatabase, 23 db::HirDatabase,
23 generics::HasGenericParams, 24 generics::HasGenericParams,
24 generics::{GenericDef, WherePredicate}, 25 generics::{GenericDef, WherePredicate},
25 nameres::Namespace,
26 resolve::{Resolver, TypeNs}, 26 resolve::{Resolver, TypeNs},
27 ty::Adt, 27 ty::{
28 primitive::{FloatTy, IntTy},
29 Adt,
30 },
28 util::make_mut_slice, 31 util::make_mut_slice,
29 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, 32 Const, Enum, EnumVariant, Function, ModuleDef, Namespace, Path, Static, Struct, StructField,
30 Trait, TypeAlias, Union, 33 Trait, TypeAlias, Union,
31}; 34};
32 35
@@ -643,14 +646,16 @@ fn type_for_builtin(def: BuiltinType) -> Ty {
643 BuiltinType::Char => TypeCtor::Char, 646 BuiltinType::Char => TypeCtor::Char,
644 BuiltinType::Bool => TypeCtor::Bool, 647 BuiltinType::Bool => TypeCtor::Bool,
645 BuiltinType::Str => TypeCtor::Str, 648 BuiltinType::Str => TypeCtor::Str,
646 BuiltinType::Int(ty) => TypeCtor::Int(ty.into()), 649 BuiltinType::Int { signedness, bitness } => {
647 BuiltinType::Float(ty) => TypeCtor::Float(ty.into()), 650 TypeCtor::Int(IntTy { signedness, bitness }.into())
651 }
652 BuiltinType::Float { bitness } => TypeCtor::Float(FloatTy { bitness }.into()),
648 }) 653 })
649} 654}
650 655
651fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { 656fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
652 let var_data = def.variant_data(db); 657 let struct_data = db.struct_data(def.id);
653 let fields = match var_data.fields() { 658 let fields = match struct_data.variant_data.fields() {
654 Some(fields) => fields, 659 Some(fields) => fields,
655 None => panic!("fn_sig_for_struct_constructor called on unit struct"), 660 None => panic!("fn_sig_for_struct_constructor called on unit struct"),
656 }; 661 };
@@ -665,8 +670,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
665 670
666/// Build the type of a tuple struct constructor. 671/// Build the type of a tuple struct constructor.
667fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 672fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
668 let var_data = def.variant_data(db); 673 let struct_data = db.struct_data(def.id);
669 if var_data.fields().is_none() { 674 if struct_data.variant_data.fields().is_none() {
670 return type_for_adt(db, def); // Unit struct 675 return type_for_adt(db, def); // Unit struct
671 } 676 }
672 let generics = def.generic_params(db); 677 let generics = def.generic_params(db);
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index eb69344f6..8c3d32d09 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -166,37 +166,78 @@ pub(crate) fn lookup_method(
166 name: &Name, 166 name: &Name,
167 resolver: &Resolver, 167 resolver: &Resolver,
168) -> Option<(Ty, Function)> { 168) -> Option<(Ty, Function)> {
169 iterate_method_candidates(ty, db, resolver, Some(name), |ty, f| Some((ty.clone(), f))) 169 iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f
170 {
171 AssocItem::Function(f) => Some((ty.clone(), f)),
172 _ => None,
173 })
174}
175
176/// Whether we're looking up a dotted method call (like `v.len()`) or a path
177/// (like `Vec::new`).
178#[derive(Copy, Clone, Debug, PartialEq, Eq)]
179pub enum LookupMode {
180 /// Looking up a method call like `v.len()`: We only consider candidates
181 /// that have a `self` parameter, and do autoderef.
182 MethodCall,
183 /// Looking up a path like `Vec::new` or `Vec::default`: We consider all
184 /// candidates including associated constants, but don't do autoderef.
185 Path,
170} 186}
171 187
172// This would be nicer if it just returned an iterator, but that runs into 188// This would be nicer if it just returned an iterator, but that runs into
173// lifetime problems, because we need to borrow temp `CrateImplBlocks`. 189// lifetime problems, because we need to borrow temp `CrateImplBlocks`.
190// FIXME add a context type here?
174pub(crate) fn iterate_method_candidates<T>( 191pub(crate) fn iterate_method_candidates<T>(
175 ty: &Canonical<Ty>, 192 ty: &Canonical<Ty>,
176 db: &impl HirDatabase, 193 db: &impl HirDatabase,
177 resolver: &Resolver, 194 resolver: &Resolver,
178 name: Option<&Name>, 195 name: Option<&Name>,
179 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 196 mode: LookupMode,
197 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
180) -> Option<T> { 198) -> Option<T> {
181 // For method calls, rust first does any number of autoderef, and then one 199 let krate = resolver.krate()?;
182 // autoref (i.e. when the method takes &self or &mut self). We just ignore 200 match mode {
183 // the autoref currently -- when we find a method matching the given name, 201 LookupMode::MethodCall => {
184 // we assume it fits. 202 // For method calls, rust first does any number of autoderef, and then one
203 // autoref (i.e. when the method takes &self or &mut self). We just ignore
204 // the autoref currently -- when we find a method matching the given name,
205 // we assume it fits.
185 206
186 // Also note that when we've got a receiver like &S, even if the method we 207 // Also note that when we've got a receiver like &S, even if the method we
187 // find in the end takes &self, we still do the autoderef step (just as 208 // find in the end takes &self, we still do the autoderef step (just as
188 // rustc does an autoderef and then autoref again). 209 // rustc does an autoderef and then autoref again).
189 210
190 let krate = resolver.krate()?; 211 for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
191 for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { 212 if let Some(result) =
192 if let Some(result) = iterate_inherent_methods(&derefed_ty, db, name, krate, &mut callback) 213 iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback)
193 { 214 {
194 return Some(result); 215 return Some(result);
216 }
217 if let Some(result) = iterate_trait_method_candidates(
218 &derefed_ty,
219 db,
220 resolver,
221 name,
222 mode,
223 &mut callback,
224 ) {
225 return Some(result);
226 }
227 }
195 } 228 }
196 if let Some(result) = 229 LookupMode::Path => {
197 iterate_trait_method_candidates(&derefed_ty, db, resolver, name, &mut callback) 230 // No autoderef for path lookups
198 { 231 if let Some(result) =
199 return Some(result); 232 iterate_inherent_methods(&ty, db, name, mode, krate, &mut callback)
233 {
234 return Some(result);
235 }
236 if let Some(result) =
237 iterate_trait_method_candidates(&ty, db, resolver, name, mode, &mut callback)
238 {
239 return Some(result);
240 }
200 } 241 }
201 } 242 }
202 None 243 None
@@ -207,7 +248,8 @@ fn iterate_trait_method_candidates<T>(
207 db: &impl HirDatabase, 248 db: &impl HirDatabase,
208 resolver: &Resolver, 249 resolver: &Resolver,
209 name: Option<&Name>, 250 name: Option<&Name>,
210 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 251 mode: LookupMode,
252 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
211) -> Option<T> { 253) -> Option<T> {
212 let krate = resolver.krate()?; 254 let krate = resolver.krate()?;
213 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) 255 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
@@ -231,22 +273,20 @@ fn iterate_trait_method_candidates<T>(
231 // trait, but if we find out it doesn't, we'll skip the rest of the 273 // trait, but if we find out it doesn't, we'll skip the rest of the
232 // iteration 274 // iteration
233 let mut known_implemented = inherently_implemented; 275 let mut known_implemented = inherently_implemented;
234 for item in data.items() { 276 for &item in data.items() {
235 if let AssocItem::Function(m) = *item { 277 if !is_valid_candidate(db, name, mode, item) {
236 let data = m.data(db); 278 continue;
237 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 279 }
238 if !known_implemented { 280 if !known_implemented {
239 let goal = generic_implements_goal(db, env.clone(), t, ty.clone()); 281 let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
240 if db.trait_solve(krate, goal).is_none() { 282 if db.trait_solve(krate, goal).is_none() {
241 continue 'traits; 283 continue 'traits;
242 }
243 }
244 known_implemented = true;
245 if let Some(result) = callback(&ty.value, m) {
246 return Some(result);
247 }
248 } 284 }
249 } 285 }
286 known_implemented = true;
287 if let Some(result) = callback(&ty.value, item) {
288 return Some(result);
289 }
250 } 290 }
251 } 291 }
252 None 292 None
@@ -256,21 +296,20 @@ fn iterate_inherent_methods<T>(
256 ty: &Canonical<Ty>, 296 ty: &Canonical<Ty>,
257 db: &impl HirDatabase, 297 db: &impl HirDatabase,
258 name: Option<&Name>, 298 name: Option<&Name>,
299 mode: LookupMode,
259 krate: Crate, 300 krate: Crate,
260 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 301 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
261) -> Option<T> { 302) -> Option<T> {
262 for krate in def_crates(db, krate, &ty.value)? { 303 for krate in def_crates(db, krate, &ty.value)? {
263 let impls = db.impls_in_crate(krate); 304 let impls = db.impls_in_crate(krate);
264 305
265 for impl_block in impls.lookup_impl_blocks(&ty.value) { 306 for impl_block in impls.lookup_impl_blocks(&ty.value) {
266 for item in impl_block.items(db) { 307 for item in impl_block.items(db) {
267 if let AssocItem::Function(f) = item { 308 if !is_valid_candidate(db, name, mode, item) {
268 let data = f.data(db); 309 continue;
269 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 310 }
270 if let Some(result) = callback(&ty.value, f) { 311 if let Some(result) = callback(&ty.value, item) {
271 return Some(result); 312 return Some(result);
272 }
273 }
274 } 313 }
275 } 314 }
276 } 315 }
@@ -278,6 +317,26 @@ fn iterate_inherent_methods<T>(
278 None 317 None
279} 318}
280 319
320fn is_valid_candidate(
321 db: &impl HirDatabase,
322 name: Option<&Name>,
323 mode: LookupMode,
324 item: AssocItem,
325) -> bool {
326 match item {
327 AssocItem::Function(m) => {
328 let data = m.data(db);
329 name.map_or(true, |name| data.name() == name)
330 && (data.has_self_param() || mode == LookupMode::Path)
331 }
332 AssocItem::Const(c) => {
333 name.map_or(true, |name| Some(name) == c.name(db).as_ref())
334 && (mode == LookupMode::Path)
335 }
336 _ => false,
337 }
338}
339
281pub(crate) fn implements_trait( 340pub(crate) fn implements_trait(
282 ty: &Canonical<Ty>, 341 ty: &Canonical<Ty>,
283 db: &impl HirDatabase, 342 db: &impl HirDatabase,
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 8966f9d1d..1749752f1 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -2,27 +2,7 @@
2 2
3use std::fmt; 3use std::fmt;
4 4
5#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 5pub use hir_def::builtin_type::{FloatBitness, IntBitness, Signedness};
6pub enum Signedness {
7 Signed,
8 Unsigned,
9}
10
11#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
12pub enum IntBitness {
13 Xsize,
14 X8,
15 X16,
16 X32,
17 X64,
18 X128,
19}
20
21#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
22pub enum FloatBitness {
23 X32,
24 X64,
25}
26 6
27#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 7#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
28pub enum UncertainIntTy { 8pub enum UncertainIntTy {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index c12326643..f27155737 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1841,8 +1841,8 @@ fn test() {
1841 [243; 254) 'Struct::FOO': u32 1841 [243; 254) 'Struct::FOO': u32
1842 [264; 265) 'y': u32 1842 [264; 265) 'y': u32
1843 [268; 277) 'Enum::BAR': u32 1843 [268; 277) 'Enum::BAR': u32
1844 [287; 288) 'z': {unknown} 1844 [287; 288) 'z': u32
1845 [291; 304) 'TraitTest::ID': {unknown} 1845 [291; 304) 'TraitTest::ID': u32
1846 "### 1846 "###
1847 ); 1847 );
1848} 1848}
@@ -2782,9 +2782,9 @@ fn test() {
2782 [97; 99) 's1': S 2782 [97; 99) 's1': S
2783 [105; 121) 'Defaul...efault': fn default<S>() -> Self 2783 [105; 121) 'Defaul...efault': fn default<S>() -> Self
2784 [105; 123) 'Defaul...ault()': S 2784 [105; 123) 'Defaul...ault()': S
2785 [133; 135) 's2': {unknown} 2785 [133; 135) 's2': S
2786 [138; 148) 'S::default': {unknown} 2786 [138; 148) 'S::default': fn default<S>() -> Self
2787 [138; 150) 'S::default()': {unknown} 2787 [138; 150) 'S::default()': S
2788 [160; 162) 's3': S 2788 [160; 162) 's3': S
2789 [165; 188) '<S as ...efault': fn default<S>() -> Self 2789 [165; 188) '<S as ...efault': fn default<S>() -> Self
2790 [165; 190) '<S as ...ault()': S 2790 [165; 190) '<S as ...ault()': S
@@ -2793,6 +2793,153 @@ fn test() {
2793} 2793}
2794 2794
2795#[test] 2795#[test]
2796fn infer_trait_assoc_method_generics_1() {
2797 assert_snapshot!(
2798 infer(r#"
2799trait Trait<T> {
2800 fn make() -> T;
2801}
2802struct S;
2803impl Trait<u32> for S {}
2804struct G<T>;
2805impl<T> Trait<T> for G<T> {}
2806fn test() {
2807 let a = S::make();
2808 let b = G::<u64>::make();
2809 let c: f64 = G::make();
2810}
2811"#),
2812 @r###"
2813 [127; 211) '{ ...e(); }': ()
2814 [137; 138) 'a': u32
2815 [141; 148) 'S::make': fn make<S, u32>() -> T
2816 [141; 150) 'S::make()': u32
2817 [160; 161) 'b': u64
2818 [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> T
2819 [164; 180) 'G::<u6...make()': u64
2820 [190; 191) 'c': f64
2821 [199; 206) 'G::make': fn make<G<f64>, f64>() -> T
2822 [199; 208) 'G::make()': f64
2823 "###
2824 );
2825}
2826
2827#[test]
2828fn infer_trait_assoc_method_generics_2() {
2829 assert_snapshot!(
2830 infer(r#"
2831trait Trait<T> {
2832 fn make<U>() -> (T, U);
2833}
2834struct S;
2835impl Trait<u32> for S {}
2836struct G<T>;
2837impl<T> Trait<T> for G<T> {}
2838fn test() {
2839 let a = S::make::<i64>();
2840 let b: (_, i64) = S::make();
2841 let c = G::<u32>::make::<i64>();
2842 let d: (u32, _) = G::make::<i64>();
2843 let e: (u32, i64) = G::make();
2844}
2845"#),
2846 @r###"
2847 [135; 313) '{ ...e(); }': ()
2848 [145; 146) 'a': (u32, i64)
2849 [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (T, U)
2850 [149; 165) 'S::mak...i64>()': (u32, i64)
2851 [175; 176) 'b': (u32, i64)
2852 [189; 196) 'S::make': fn make<S, u32, i64>() -> (T, U)
2853 [189; 198) 'S::make()': (u32, i64)
2854 [208; 209) 'c': (u32, i64)
2855 [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
2856 [212; 235) 'G::<u3...i64>()': (u32, i64)
2857 [245; 246) 'd': (u32, i64)
2858 [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
2859 [259; 275) 'G::mak...i64>()': (u32, i64)
2860 [285; 286) 'e': (u32, i64)
2861 [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (T, U)
2862 [301; 310) 'G::make()': (u32, i64)
2863 "###
2864 );
2865}
2866
2867#[test]
2868fn infer_trait_assoc_method_generics_3() {
2869 assert_snapshot!(
2870 infer(r#"
2871trait Trait<T> {
2872 fn make() -> (Self, T);
2873}
2874struct S<T>;
2875impl Trait<i64> for S<i32> {}
2876fn test() {
2877 let a = S::make();
2878}
2879"#),
2880 @r###"
2881 [101; 127) '{ ...e(); }': ()
2882 [111; 112) 'a': (S<i32>, i64)
2883 [115; 122) 'S::make': fn make<S<i32>, i64>() -> (Self, T)
2884 [115; 124) 'S::make()': (S<i32>, i64)
2885 "###
2886 );
2887}
2888
2889#[test]
2890fn infer_trait_assoc_method_generics_4() {
2891 assert_snapshot!(
2892 infer(r#"
2893trait Trait<T> {
2894 fn make() -> (Self, T);
2895}
2896struct S<T>;
2897impl Trait<i64> for S<u64> {}
2898impl Trait<i32> for S<u32> {}
2899fn test() {
2900 let a: (S<u64>, _) = S::make();
2901 let b: (_, i32) = S::make();
2902}
2903"#),
2904 @r###"
2905 [131; 203) '{ ...e(); }': ()
2906 [141; 142) 'a': (S<u64>, i64)
2907 [158; 165) 'S::make': fn make<S<u64>, i64>() -> (Self, T)
2908 [158; 167) 'S::make()': (S<u64>, i64)
2909 [177; 178) 'b': (S<u32>, i32)
2910 [191; 198) 'S::make': fn make<S<u32>, i32>() -> (Self, T)
2911 [191; 200) 'S::make()': (S<u32>, i32)
2912 "###
2913 );
2914}
2915
2916#[test]
2917fn infer_trait_assoc_method_generics_5() {
2918 assert_snapshot!(
2919 infer(r#"
2920trait Trait<T> {
2921 fn make<U>() -> (Self, T, U);
2922}
2923struct S<T>;
2924impl Trait<i64> for S<u64> {}
2925fn test() {
2926 let a = <S as Trait<i64>>::make::<u8>();
2927 let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>();
2928}
2929"#),
2930 @r###"
2931 [107; 211) '{ ...>(); }': ()
2932 [117; 118) 'a': (S<u64>, i64, u8)
2933 [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
2934 [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8)
2935 [162; 163) 'b': (S<u64>, i64, u8)
2936 [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
2937 [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8)
2938 "###
2939 );
2940}
2941
2942#[test]
2796fn infer_from_bound_1() { 2943fn infer_from_bound_1() {
2797 assert_snapshot!( 2944 assert_snapshot!(
2798 infer(r#" 2945 infer(r#"
@@ -3256,7 +3403,7 @@ fn test() { S.foo()<|>; }
3256 3403
3257#[test] 3404#[test]
3258fn infer_macro_with_dollar_crate_is_correct_in_expr() { 3405fn infer_macro_with_dollar_crate_is_correct_in_expr() {
3259 covers!(macro_dollar_crate_other); 3406 // covers!(macro_dollar_crate_other);
3260 let (mut db, pos) = MockDatabase::with_position( 3407 let (mut db, pos) = MockDatabase::with_position(
3261 r#" 3408 r#"
3262//- /main.rs 3409//- /main.rs
@@ -3303,6 +3450,22 @@ fn test() { S.foo()<|>; }
3303 assert_eq!(t, "u128"); 3450 assert_eq!(t, "u128");
3304} 3451}
3305 3452
3453#[ignore]
3454#[test]
3455fn method_resolution_by_value_before_autoref() {
3456 let t = type_at(
3457 r#"
3458//- /main.rs
3459trait Clone { fn clone(&self) -> Self; }
3460struct S;
3461impl Clone for S {}
3462impl Clone for &S {}
3463fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; }
3464"#,
3465 );
3466 assert_eq!(t, "(S, S, &S)");
3467}
3468
3306#[test] 3469#[test]
3307fn method_resolution_trait_before_autoderef() { 3470fn method_resolution_trait_before_autoderef() {
3308 let t = type_at( 3471 let t = type_at(