From 795d718ba17545aedb0475051332aed6db2104ed Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 17 Feb 2019 14:43:59 +0100 Subject: Unify with the autorefed/autoderefed receiver type during method resolution --- crates/ra_hir/src/ty/method_resolution.rs | 12 +++++++----- .../tests__infer_impl_generics_with_autoderef.snap | 16 ++++++++++++++++ crates/ra_hir/src/ty/tests.rs | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap (limited to 'crates/ra_hir/src/ty') diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 8d1076774..94b757af2 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -118,11 +118,13 @@ impl Ty { // TODO: cache this as a query? // - if so, what signature? (TyFingerprint, Name)? // - or maybe cache all names and def_ids of methods per fingerprint? - pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option { - self.iterate_methods(db, |f| { + /// Look up the method with the given name, returning the actual autoderefed + /// receiver type (but without autoref applied yet). + pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<(Ty, Function)> { + self.iterate_methods(db, |ty, f| { let sig = f.signature(db); if sig.name() == name && sig.has_self_param() { - Some(f) + Some((ty.clone(), f)) } else { None } @@ -134,7 +136,7 @@ impl Ty { pub fn iterate_methods( self, db: &impl HirDatabase, - mut callback: impl FnMut(Function) -> Option, + mut callback: impl FnMut(&Ty, Function) -> Option, ) -> Option { // For method calls, rust first does any number of autoderef, and then one // autoref (i.e. when the method takes &self or &mut self). We just ignore @@ -156,7 +158,7 @@ impl Ty { for item in impl_block.items(db) { match item { ImplItem::Method(f) => { - if let Some(result) = callback(f) { + if let Some(result) = callback(&derefed_ty, f) { return Some(result); } } diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap new file mode 100644 index 000000000..f609eaf7c --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics_with_autoderef.snap @@ -0,0 +1,16 @@ +--- +created: "2019-02-17T13:35:06.385679926Z" +creator: insta@0.6.2 +source: crates/ra_hir/src/ty/tests.rs +expression: "&result" +--- +[78; 82) 'self': &Option +[98; 100) '{}': () +[111; 112) 'o': Option +[127; 165) '{ ...f(); }': () +[133; 146) '(&o).as_ref()': Option<&u32> +[134; 136) '&o': &Option +[135; 136) 'o': Option +[152; 153) 'o': Option +[152; 162) 'o.as_ref()': Option<&u32> + diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 1eca68dc5..5eb9c4f5b 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -538,6 +538,26 @@ fn test() -> i128 { ); } +#[test] +fn infer_impl_generics_with_autoderef() { + check_inference( + "infer_impl_generics_with_autoderef", + r#" +enum Option { + Some(T), + None, +} +impl Option { + fn as_ref(&self) -> Option<&T> {} +} +fn test(o: Option) { + (&o).as_ref(); + o.as_ref(); +} +"#, + ); +} + #[test] fn infer_generic_chain() { check_inference( -- cgit v1.2.3