From f9695a6256a2473636d3e16b5347cddf592fd00d Mon Sep 17 00:00:00 2001 From: Kevin Butler Date: Mon, 19 May 2014 22:27:03 +0100 Subject: [PATCH] rustc: Better resolve errors for &T, &mut T, remove failure condition. --- src/librustc/middle/resolve.rs | 57 +++++++++----- src/test/compile-fail/issue-14254.rs | 113 +++++++++++++++++++++++++++ src/test/run-pass/issue-14254.rs | 100 ++++++++++++++++++++++++ 3 files changed, 252 insertions(+), 18 deletions(-) create mode 100644 src/test/compile-fail/issue-14254.rs create mode 100644 src/test/run-pass/issue-14254.rs diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 87919c8a4f470..cd3375799a3ca 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -4891,6 +4891,25 @@ impl<'a> Resolver<'a> { } fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion { + #[deriving(Eq)] + enum FallbackChecks { + Everything, + OnlyTraitAndStatics + } + + fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks) + -> Option<(Path, NodeId, FallbackChecks)> { + match t.node { + TyPath(ref path, _, node_id) => Some((path.clone(), node_id, allow)), + TyPtr(mut_ty) => extract_path_and_node_id(mut_ty.ty, OnlyTraitAndStatics), + TyRptr(_, mut_ty) => extract_path_and_node_id(mut_ty.ty, allow), + // This doesn't handle the remaining `Ty` variants as they are not + // that commonly the self_type, it might be interesting to provide + // support for those in future. + _ => None, + } + } + fn get_module(this: &mut Resolver, span: Span, ident_path: &[ast::Ident]) -> Option> { let root = this.current_module.clone(); @@ -4918,27 +4937,29 @@ impl<'a> Resolver<'a> { } } - let (path, node_id) = match self.current_self_type { - Some(ref ty) => match ty.node { - TyPath(ref path, _, node_id) => (path.clone(), node_id), - _ => unreachable!(), + let (path, node_id, allowed) = match self.current_self_type { + Some(ref ty) => match extract_path_and_node_id(ty, Everything) { + Some(x) => x, + None => return NoSuggestion, }, None => return NoSuggestion, }; - // Look for a field with the same name in the current self_type. - match self.def_map.borrow().find(&node_id) { - Some(&DefTy(did)) - | Some(&DefStruct(did)) - | Some(&DefVariant(_, did, _)) => match self.structs.find(&did) { - None => {} - Some(fields) => { - if fields.iter().any(|&field_name| name == field_name) { - return Field; + if allowed == Everything { + // Look for a field with the same name in the current self_type. + match self.def_map.borrow().find(&node_id) { + Some(&DefTy(did)) + | Some(&DefStruct(did)) + | Some(&DefVariant(_, did, _)) => match self.structs.find(&did) { + None => {} + Some(fields) => { + if fields.iter().any(|&field_name| name == field_name) { + return Field; + } } - } - }, - _ => {} // Self type didn't resolve properly + }, + _ => {} // Self type didn't resolve properly + } } let ident_path = path.segments.iter().map(|seg| seg.identifier).collect::>(); @@ -4955,8 +4976,8 @@ impl<'a> Resolver<'a> { FromTrait(_) => unreachable!() } } - Some(DefMethod(_, None)) => return Method, - Some(DefMethod(_, _)) => return TraitMethod, + Some(DefMethod(_, None)) if allowed == Everything => return Method, + Some(DefMethod(_, Some(_))) => return TraitMethod, _ => () } } diff --git a/src/test/compile-fail/issue-14254.rs b/src/test/compile-fail/issue-14254.rs new file mode 100644 index 0000000000000..8b7267ab77664 --- /dev/null +++ b/src/test/compile-fail/issue-14254.rs @@ -0,0 +1,113 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + fn bar(&self); + fn baz(&self) { } + fn bah(_: Option) { } +} + +struct BarTy { + x : int, + y : f64, +} + +impl BarTy { + fn a() {} + fn b(&self) {} +} + +impl Foo for *BarTy { + fn bar(&self) { + baz(); + //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? + a; + //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + } +} + +impl<'a> Foo for &'a BarTy { + fn bar(&self) { + baz(); + //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? + x; + //~^ ERROR: unresolved name `x`. Did you mean `self.x`? + y; + //~^ ERROR: unresolved name `y`. Did you mean `self.y`? + a; + //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + bah; + //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? + b; + //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`? + } +} + +impl<'a> Foo for &'a mut BarTy { + fn bar(&self) { + baz(); + //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? + x; + //~^ ERROR: unresolved name `x`. Did you mean `self.x`? + y; + //~^ ERROR: unresolved name `y`. Did you mean `self.y`? + a; + //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + bah; + //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? + b; + //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`? + } +} + +impl Foo for Box { + fn bar(&self) { + baz(); + //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? + bah; + //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? + } +} + +impl Foo for *int { + fn bar(&self) { + baz(); + //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? + bah; + //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? + } +} + +impl<'a> Foo for &'a int { + fn bar(&self) { + baz(); + //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? + bah; + //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? + } +} + +impl<'a> Foo for &'a mut int { + fn bar(&self) { + baz(); + //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? + bah; + //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? + } +} + +impl Foo for Box { + fn bar(&self) { + baz(); + //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? + bah; + //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? + } +} diff --git a/src/test/run-pass/issue-14254.rs b/src/test/run-pass/issue-14254.rs new file mode 100644 index 0000000000000..a3ead0a668581 --- /dev/null +++ b/src/test/run-pass/issue-14254.rs @@ -0,0 +1,100 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + fn bar(&self); + fn baz(&self) { } + fn bah(_: Option) { } +} + +struct BarTy { + x : int, + y : f64, +} + +impl BarTy { + fn a() {} + fn b(&self) {} +} + +// If these fail, it's necessary to update middle::resolve and the cfail tests. +impl Foo for *BarTy { + fn bar(&self) { + self.baz(); + BarTy::a(); + Foo::bah(None::<*BarTy>); + } +} + +// If these fail, it's necessary to update middle::resolve and the cfail tests. +impl<'a> Foo for &'a BarTy { + fn bar(&self) { + self.baz(); + self.x; + self.y; + BarTy::a(); + Foo::bah(None::<&BarTy>); + self.b(); + } +} + +// If these fail, it's necessary to update middle::resolve and the cfail tests. +impl<'a> Foo for &'a mut BarTy { + fn bar(&self) { + self.baz(); + self.x; + self.y; + BarTy::a(); + Foo::bah(None::<&mut BarTy>); + self.b(); + } +} + +// If these fail, it's necessary to update middle::resolve and the cfail tests. +impl Foo for Box { + fn bar(&self) { + self.baz(); + Foo::bah(None::>); + } +} + +// If these fail, it's necessary to update middle::resolve and the cfail tests. +impl Foo for *int { + fn bar(&self) { + self.baz(); + Foo::bah(None::<*int>); + } +} + +// If these fail, it's necessary to update middle::resolve and the cfail tests. +impl<'a> Foo for &'a int { + fn bar(&self) { + self.baz(); + Foo::bah(None::<&int>); + } +} + +// If these fail, it's necessary to update middle::resolve and the cfail tests. +impl<'a> Foo for &'a mut int { + fn bar(&self) { + self.baz(); + Foo::bah(None::<&mut int>); + } +} + +// If these fail, it's necessary to update middle::resolve and the cfail tests. +impl Foo for Box { + fn bar(&self) { + self.baz(); + Foo::bah(None::>); + } +} + +fn main() {}