aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-01 19:03:05 +0000
committerGitHub <[email protected]>2019-11-01 19:03:05 +0000
commit9db97820f4c1c38110175f4efda2702356a4199a (patch)
treef560ab731b9da35902d3da720e19731b51ab62df /crates/ra_hir/src/ty
parented5212e1ac71e959d802a9a7ad28d06c8b18e022 (diff)
parent895238088417b292e35705e72182ff8cc3ab6f63 (diff)
Merge #2151
2151: Resolve (and complete) trait calls like `Vec::default()` r=flodiebold a=flodiebold Similar to rustc, we do this using the same code as the method call resolution, just without doing autoderef (and considering more potential candidates). (Btw, we currently don't complete methods with `self` in path notation, even though they'd be legal to use, so maybe we should -- on the other hand, that will usually not be the most interesting completions...) Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs82
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs141
-rw-r--r--crates/ra_hir/src/ty/tests.rs173
3 files changed, 314 insertions, 82 deletions
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/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/tests.rs b/crates/ra_hir/src/ty/tests.rs
index c12326643..bfef48b16 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#"
@@ -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(