]> git.lizzy.rs Git - rust.git/commitdiff
Display secondary span for E0053 for Mutability TypeErrors
authorKeith Yeung <kungfukeith11@gmail.com>
Wed, 17 Aug 2016 11:04:14 +0000 (04:04 -0700)
committerKeith Yeung <kungfukeith11@gmail.com>
Wed, 17 Aug 2016 22:12:56 +0000 (15:12 -0700)
src/librustc_typeck/check/compare_method.rs
src/test/compile-fail/E0053.rs

index 93badd981300622d5bbc3e39a98411440fe6fa80..043883df035d0378ed7b34a52b4bd558aaa81cc8 100644 (file)
@@ -338,6 +338,34 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             };
 
             let (impl_err_span, trait_err_span) = match terr {
+                TypeError::Mutability => {
+                    if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
+                        let trait_m_iter = match tcx.map.expect_trait_item(trait_m_node_id).node {
+                            TraitItem_::MethodTraitItem(ref trait_m_sig, _) =>
+                                trait_m_sig.decl.inputs.iter(),
+                            _ => bug!("{:?} is not a MethodTraitItem", trait_m)
+                        };
+
+                        impl_m_iter.zip(trait_m_iter).find(|&(ref impl_arg, ref trait_arg)| {
+                            match (&impl_arg.ty.node, &trait_arg.ty.node) {
+                                (&Ty_::TyRptr(_, ref impl_mt), &Ty_::TyRptr(_, ref trait_mt)) |
+                                (&Ty_::TyPtr(ref impl_mt), &Ty_::TyPtr(ref trait_mt)) =>
+                                    impl_mt.mutbl != trait_mt.mutbl,
+                                _ => false
+                            }
+                        }).map(|(ref impl_arg, ref trait_arg)| {
+                            match (impl_arg.to_self(), trait_arg.to_self()) {
+                                (Some(impl_self), Some(trait_self)) =>
+                                    (impl_self.span, Some(trait_self.span)),
+                                (None, None) => (impl_arg.ty.span, Some(trait_arg.ty.span)),
+                                _ => bug!("impl and trait fns have different first args, \
+                                           impl: {:?}, trait: {:?}", impl_arg, trait_arg)
+                            }
+                        }).unwrap_or((origin.span(), tcx.map.span_if_local(trait_m.def_id)))
+                    } else {
+                        (origin.span(), tcx.map.span_if_local(trait_m.def_id))
+                    }
+                }
                 TypeError::Sorts(ExpectedFound { expected, found }) => {
                     if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) {
                         let trait_m_iter = match tcx.map.expect_trait_item(trait_m_node_id).node {
index 4effda3c49e8e6c4e0c7f65d677f851377130fe4..7022010714aa77ed380d5ad5110ae56740150a94 100644 (file)
@@ -9,15 +9,21 @@
 // except according to those terms.
 
 trait Foo {
-    fn foo(x: u16);
-    fn bar(&self);
+    fn foo(x: u16); //~ NOTE original trait requirement
+    fn bar(&self); //~ NOTE original trait requirement
 }
 
 struct Bar;
 
 impl Foo for Bar {
-    fn foo(x: i16) { } //~ ERROR E0053
-    fn bar(&mut self) { } //~ ERROR E0053
+    fn foo(x: i16) { }
+    //~^ ERROR method `foo` has an incompatible type for trait
+    //~| NOTE expected u16
+    fn bar(&mut self) { }
+    //~^ ERROR method `bar` has an incompatible type for trait
+    //~| NOTE values differ in mutability
+    //~| NOTE expected type `fn(&Bar)`
+    //~| NOTE found type `fn(&mut Bar)`
 }
 
 fn main() {