rustc: Better resolve errors for &T, &mut T, remove failure condition.
This commit is contained in:
parent
1ba7bd10c9
commit
f9695a6256
@ -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<Rc<Module>> {
|
||||
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::<Vec<_>>();
|
||||
@ -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,
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
113
src/test/compile-fail/issue-14254.rs
Normal file
113
src/test/compile-fail/issue-14254.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Self>) { }
|
||||
}
|
||||
|
||||
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<BarTy> {
|
||||
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<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`?
|
||||
}
|
||||
}
|
100
src/test/run-pass/issue-14254.rs
Normal file
100
src/test/run-pass/issue-14254.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Self>) { }
|
||||
}
|
||||
|
||||
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<BarTy> {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
Foo::bah(None::<Box<BarTy>>);
|
||||
}
|
||||
}
|
||||
|
||||
// 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<int> {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
Foo::bah(None::<Box<int>>);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user