From d92355c1db65035e508020e746c141c79dfdbd99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 23 Nov 2019 16:01:20 -0800 Subject: [PATCH 1/2] Highlight parts of fn in type errors When a type error arises between two fn items, fn pointers or tuples, highlight only the differing parts of each. --- src/librustc/infer/error_reporting/mod.rs | 177 +++++++++++++++++- src/librustc/ty/print/pretty.rs | 31 ++- src/librustc_errors/diagnostic.rs | 7 + ...regions-bound-missing-bound-in-impl.stderr | 4 +- src/test/ui/c-variadic/variadic-ffi-1.stderr | 8 +- .../fn-const-param-infer.stderr | 4 +- src/test/ui/fn/fn-item-type.rs | 8 +- src/test/ui/fn/fn-item-type.stderr | 12 +- src/test/ui/issues/issue-15094.stderr | 4 +- src/test/ui/issues/issue-35869.stderr | 4 +- src/test/ui/issues/issue-37884.stderr | 4 +- src/test/ui/issues/issue-9575.stderr | 4 +- src/test/ui/unsafe/unsafe-subtyping.stderr | 4 +- src/test/ui/unsafe/unsafe-trait-impl.rs | 4 +- src/test/ui/unsafe/unsafe-trait-impl.stderr | 4 +- src/test/ui/wrong-mul-method-signature.stderr | 4 +- 16 files changed, 238 insertions(+), 45 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 0f93ef6b1a9e4..7d7e7da1def63 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -63,8 +63,8 @@ use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldabl use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_error_codes::*; +use rustc_target::spec::abi; use syntax_pos::{Pos, Span}; - use std::{cmp, fmt}; mod note; @@ -766,7 +766,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if len > 0 && i != len - 1 { value.push_normal(", "); } - //self.push_comma(&mut value, &mut other_value, len, i); } if len > 0 { value.push_highlighted(">"); @@ -868,6 +867,120 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { substs.truncate_to(self.tcx, &generics) } + /// Given two `fn` signatures highlight only sub-parts that are different. + fn cmp_fn_sig( + &self, + sig1: &ty::PolyFnSig<'tcx>, + sig2: &ty::PolyFnSig<'tcx>, + ) -> (DiagnosticStyledString, DiagnosticStyledString) { + let get_lifetimes = |sig| { + use crate::hir::def::Namespace; + let mut s = String::new(); + let (_, (sig, reg)) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS) + .name_all_regions(sig) + .unwrap(); + let lts: Vec = reg.into_iter().map(|(_, kind)| kind.to_string()).collect(); + (if lts.is_empty() { + String::new() + } else { + format!("for<{}> ", lts.join(", ")) + }, sig) + }; + + let (lt1, sig1) = get_lifetimes(sig1); + let (lt2, sig2) = get_lifetimes(sig2); + + // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + let mut values = ( + DiagnosticStyledString::normal("".to_string()), + DiagnosticStyledString::normal("".to_string()), + ); + + // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + // ^^^^^^ + values.0.push(sig1.unsafety.prefix_str().to_string(), sig1.unsafety != sig2.unsafety); + values.1.push(sig2.unsafety.prefix_str().to_string(), sig1.unsafety != sig2.unsafety); + + // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + // ^^^^^^^^^^ + if sig1.abi != abi::Abi::Rust { + values.0.push(format!("extern {} ", sig1.abi), sig1.abi != sig2.abi); + } + if sig2.abi != abi::Abi::Rust { + values.1.push(format!("extern {} ", sig2.abi), sig1.abi != sig2.abi); + } + + // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + // ^^^^^^^^ + let lifetime_diff = lt1 != lt2; + values.0.push(lt1, lifetime_diff); + values.1.push(lt2, lifetime_diff); + + // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + // ^^^ + values.0.push_normal("fn(".to_string()); + values.1.push_normal("fn(".to_string()); + + // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + // ^^^^^ + let len1 = sig1.inputs().len(); + let len2 = sig2.inputs().len(); + if len1 == len2 { + for (i, (l, r)) in sig1.inputs().iter().zip(sig2.inputs().iter()).enumerate() { + let (x1, x2) = self.cmp(l, r); + (values.0).0.extend(x1.0); + (values.1).0.extend(x2.0); + self.push_comma(&mut values.0, &mut values.1, len1, i); + } + } else { + for (i, l) in sig1.inputs().iter().enumerate() { + values.0.push_highlighted(l.to_string()); + if i != len1 - 1 { + values.0.push_highlighted(", ".to_string()); + } + } + for (i, r) in sig2.inputs().iter().enumerate() { + values.1.push_highlighted(r.to_string()); + if i != len2 - 1 { + values.1.push_highlighted(", ".to_string()); + } + } + } + + if sig1.c_variadic { + if len1 > 0 { + values.0.push_normal(", ".to_string()); + } + values.0.push("...".to_string(), !sig2.c_variadic); + } + if sig2.c_variadic { + if len2 > 0 { + values.1.push_normal(", ".to_string()); + } + values.1.push("...".to_string(), !sig1.c_variadic); + } + + // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + // ^ + values.0.push_normal(")".to_string()); + values.1.push_normal(")".to_string()); + + // unsafe extern "C" for<'a> fn(&'a T) -> &'a T + // ^^^^^^^^ + let output1 = sig1.output(); + let output2 = sig2.output(); + let (x1, x2) = self.cmp(output1, output2); + if !output1.is_unit() { + values.0.push_normal(" -> ".to_string()); + (values.0).0.extend(x1.0); + } + if !output2.is_unit() { + values.1.push_normal(" -> ".to_string()); + (values.1).0.extend(x2.0); + } + values + } + /// Compares two given types, eliding parts that are the same between them and highlighting /// relevant differences, and return two representation of those types for highlighted printing. fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) { @@ -968,7 +1081,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { for (i, lifetimes) in lifetimes.enumerate() { let l1 = lifetime_display(lifetimes.0); let l2 = lifetime_display(lifetimes.1); - if l1 == l2 { + if lifetimes.0 == lifetimes.1 { values.0.push_normal("'_"); values.1.push_normal("'_"); } else { @@ -1124,6 +1237,64 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { values } + // When encountering tuples of the same size, highlight only the differing types + (&ty::Tuple(substs1), &ty::Tuple(substs2)) if substs1.len() == substs2.len() => { + let mut values = ( + DiagnosticStyledString::normal("(".to_string()), + DiagnosticStyledString::normal("(".to_string()), + ); + let len = substs1.len(); + for (i, (left, right)) in substs1.types().zip(substs2.types()).enumerate() { + let (x1, x2) = self.cmp(left, right); + (values.0).0.extend(x1.0); + (values.1).0.extend(x2.0); + self.push_comma(&mut values.0, &mut values.1, len, i); + } + if len == 1 { // Keep the output for single element tuples as `(ty,)`. + values.0.push_normal(",".to_string()); + values.1.push_normal(",".to_string()); + } + values.0.push_normal(")".to_string()); + values.1.push_normal(")".to_string()); + values + } + + (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => { + let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1); + let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2); + let mut values = self.cmp_fn_sig(&sig1, &sig2); + let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1)); + let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2)); + let same_path = path1 == path2; + values.0.push(path1, !same_path); + values.1.push(path2, !same_path); + values + } + + (ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => { + let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1); + let mut values = self.cmp_fn_sig(&sig1, sig2); + values.0.push_normal(format!( + " {{{}}}", + self.tcx.def_path_str_with_substs(*did1, substs1)), + ); + values + } + + (ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => { + let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2); + let mut values = self.cmp_fn_sig(sig1, &sig2); + values.1.push_normal(format!( + " {{{}}}", + self.tcx.def_path_str_with_substs(*did2, substs2)), + ); + values + } + + (ty::FnPtr(sig1), ty::FnPtr(sig2)) => { + self.cmp_fn_sig(sig1, sig2) + } + _ => { if t1 == t2 { // The two types are the same, elide and don't highlight. diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 594550dd967ac..93813f71cd264 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -17,6 +17,7 @@ use syntax::attr::{SignedInt, UnsignedInt}; use syntax::symbol::{kw, Symbol}; use std::cell::Cell; +use std::collections::BTreeMap; use std::fmt::{self, Write as _}; use std::ops::{Deref, DerefMut}; @@ -1054,7 +1055,7 @@ impl FmtPrinter<'a, 'tcx, F> { } } -impl TyCtxt<'_> { +impl TyCtxt<'t> { // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always // (but also some things just print a `DefId` generally so maybe we need this?) fn guess_def_namespace(self, def_id: DefId) -> Namespace { @@ -1077,11 +1078,14 @@ impl TyCtxt<'_> { /// Returns a string identifying this `DefId`. This string is /// suitable for user output. pub fn def_path_str(self, def_id: DefId) -> String { + self.def_path_str_with_substs(def_id, &[]) + } + + pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String { let ns = self.guess_def_namespace(def_id); debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); let mut s = String::new(); - let _ = FmtPrinter::new(self, &mut s, ns) - .print_def_path(def_id, &[]); + let _ = FmtPrinter::new(self, &mut s, ns).print_def_path(def_id, substs); s } } @@ -1494,7 +1498,10 @@ impl FmtPrinter<'_, '_, F> { // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, // `region_index` and `used_region_names`. impl FmtPrinter<'_, 'tcx, F> { - pub fn pretty_in_binder(mut self, value: &ty::Binder) -> Result + pub fn name_all_regions( + mut self, + value: &ty::Binder, + ) -> Result<(Self, (T, BTreeMap>)), fmt::Error> where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { @@ -1527,8 +1534,7 @@ impl FmtPrinter<'_, 'tcx, F> { define_scoped_cx!(self); - let old_region_index = self.region_index; - let mut region_index = old_region_index; + let mut region_index = self.region_index; let new_value = self.tcx.replace_late_bound_regions(value, |br| { let _ = start_or_continue(&mut self, "for<", ", "); let br = match br { @@ -1550,12 +1556,21 @@ impl FmtPrinter<'_, 'tcx, F> { } }; self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) - }).0; + }); start_or_continue(&mut self, "", "> ")?; self.binder_depth += 1; self.region_index = region_index; - let mut inner = new_value.print(self)?; + Ok((self, new_value)) + } + + pub fn pretty_in_binder(self, value: &ty::Binder) -> Result + where + T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, + { + let old_region_index = self.region_index; + let (new, new_value) = self.name_all_regions(value)?; + let mut inner = new_value.0.print(new)?; inner.region_index = old_region_index; inner.binder_depth -= 1; Ok(inner) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 27ea0039354e7..530844ceee11b 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -52,6 +52,13 @@ impl DiagnosticStyledString { pub fn push_highlighted>(&mut self, t: S) { self.0.push(StringPart::Highlighted(t.into())); } + pub fn push>(&mut self, t: S, highlight: bool) { + if highlight { + self.0.push(StringPart::Highlighted(t.into())); + } else { + self.0.push(StringPart::Normal(t.into())); + } + } pub fn normal>(t: S) -> DiagnosticStyledString { DiagnosticStyledString(vec![StringPart::Normal(t.into())]) } diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 421c57fc74a0f..4f86ffb2b79af 100644 --- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -22,8 +22,8 @@ error[E0308]: method not compatible with trait LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)` - found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)` + = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` + found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` note: the lifetime `'c` as defined on the method body at 27:24... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr index 3d1710648daa2..37953d6328f70 100644 --- a/src/test/ui/c-variadic/variadic-ffi-1.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr @@ -28,8 +28,8 @@ error[E0308]: mismatched types LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; | ^^^ expected non-variadic fn, found variadic function | - = note: expected fn pointer `unsafe extern "C" fn(isize, u8)` - found fn item `unsafe extern "C" fn(isize, u8, ...) {foo}` + = note: expected fn pointer `unsafe extern "C" fn(_, _)` + found fn item `unsafe extern "C" fn(_, _, ...) {foo}` error[E0308]: mismatched types --> $DIR/variadic-ffi-1.rs:20:54 @@ -37,8 +37,8 @@ error[E0308]: mismatched types LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; | ^^^ expected variadic fn, found non-variadic function | - = note: expected fn pointer `extern "C" fn(isize, u8, ...)` - found fn item `extern "C" fn(isize, u8) {bar}` + = note: expected fn pointer `extern "C" fn(_, _, ...)` + found fn item `extern "C" fn(_, _) {bar}` error[E0617]: can't pass `f32` to variadic function --> $DIR/variadic-ffi-1.rs:22:19 diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 8f61e35e492cf..8d221c7fa9ce5 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -21,8 +21,8 @@ error[E0308]: mismatched types LL | let _ = Checked::<{generic_arg::}>; | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `u32` | - = note: expected fn pointer `fn(usize) -> bool` - found fn item `fn(u32) -> bool {generic_arg::}` + = note: expected fn pointer `fn(usize) -> _` + found fn item `fn(u32) -> _ {generic_arg::}` error[E0282]: type annotations needed --> $DIR/fn-const-param-infer.rs:22:23 diff --git a/src/test/ui/fn/fn-item-type.rs b/src/test/ui/fn/fn-item-type.rs index 18146d52551f9..68b75c18a43dc 100644 --- a/src/test/ui/fn/fn-item-type.rs +++ b/src/test/ui/fn/fn-item-type.rs @@ -12,8 +12,8 @@ impl Foo for T { /* `foo` is still default here */ } fn main() { eq(foo::, bar::); //~^ ERROR mismatched types - //~| expected fn item `fn(isize) -> isize {foo::}` - //~| found fn item `fn(isize) -> isize {bar::}` + //~| expected fn item `fn(_) -> _ {foo::}` + //~| found fn item `fn(_) -> _ {bar::}` //~| expected fn item, found a different fn item eq(foo::, foo::); @@ -22,8 +22,8 @@ fn main() { eq(bar::, bar::>); //~^ ERROR mismatched types - //~| expected fn item `fn(isize) -> isize {bar::}` - //~| found fn item `fn(isize) -> isize {bar::>}` + //~| expected fn item `fn(_) -> _ {bar::}` + //~| found fn item `fn(_) -> _ {bar::>}` //~| expected struct `std::string::String`, found struct `std::vec::Vec` // Make sure we distinguish between trait methods correctly. diff --git a/src/test/ui/fn/fn-item-type.stderr b/src/test/ui/fn/fn-item-type.stderr index e25e9c21c9fbc..4cce25c43c485 100644 --- a/src/test/ui/fn/fn-item-type.stderr +++ b/src/test/ui/fn/fn-item-type.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | eq(foo::, bar::); | ^^^^^^^^^ expected fn item, found a different fn item | - = note: expected fn item `fn(isize) -> isize {foo::}` - found fn item `fn(isize) -> isize {bar::}` + = note: expected fn item `fn(_) -> _ {foo::}` + found fn item `fn(_) -> _ {bar::}` error[E0308]: mismatched types --> $DIR/fn-item-type.rs:19:19 @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | eq(foo::, foo::); | ^^^^^^^^^ expected `u8`, found `i8` | - = note: expected fn item `fn(isize) -> isize {foo::}` - found fn item `fn(isize) -> isize {foo::}` + = note: expected fn item `fn(_) -> _ {foo::}` + found fn item `fn(_) -> _ {foo::}` error[E0308]: mismatched types --> $DIR/fn-item-type.rs:23:23 @@ -22,8 +22,8 @@ error[E0308]: mismatched types LL | eq(bar::, bar::>); | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found struct `std::vec::Vec` | - = note: expected fn item `fn(isize) -> isize {bar::}` - found fn item `fn(isize) -> isize {bar::>}` + = note: expected fn item `fn(_) -> _ {bar::}` + found fn item `fn(_) -> _ {bar::>}` error[E0308]: mismatched types --> $DIR/fn-item-type.rs:30:26 diff --git a/src/test/ui/issues/issue-15094.stderr b/src/test/ui/issues/issue-15094.stderr index 7b392fe1ac71b..2dcdaba170ac7 100644 --- a/src/test/ui/issues/issue-15094.stderr +++ b/src/test/ui/issues/issue-15094.stderr @@ -4,8 +4,8 @@ error[E0053]: method `call_once` has an incompatible type for trait LL | fn call_once(self, _args: ()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "Rust" fn | - = note: expected fn pointer `extern "rust-call" fn(Debuger, ())` - found fn pointer `fn(Debuger, ())` + = note: expected fn pointer `extern "rust-call" fn(Debuger<_>, ())` + found fn pointer `fn(Debuger<_>, ())` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-35869.stderr b/src/test/ui/issues/issue-35869.stderr index be21569315b72..66e89998e1db1 100644 --- a/src/test/ui/issues/issue-35869.stderr +++ b/src/test/ui/issues/issue-35869.stderr @@ -31,8 +31,8 @@ LL | fn baz(_: (u8, u16)); LL | fn baz(_: (u16, u16)) {} | ^^^^^^^^^^ expected `u8`, found `u16` | - = note: expected fn pointer `fn((u8, u16))` - found fn pointer `fn((u16, u16))` + = note: expected fn pointer `fn((u8, _))` + found fn pointer `fn((u16, _))` error[E0053]: method `qux` has an incompatible type for trait --> $DIR/issue-35869.rs:17:17 diff --git a/src/test/ui/issues/issue-37884.stderr b/src/test/ui/issues/issue-37884.stderr index 61cb3d7c58f38..703cdf0854808 100644 --- a/src/test/ui/issues/issue-37884.stderr +++ b/src/test/ui/issues/issue-37884.stderr @@ -9,8 +9,8 @@ LL | | Some(&mut self.0) LL | | } | |_____^ lifetime mismatch | - = note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> std::option::Option<&mut T>` - found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> std::option::Option<&mut T>` + = note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> std::option::Option<_>` + found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> std::option::Option<_>` note: the anonymous lifetime #1 defined on the method body at 6:5... --> $DIR/issue-37884.rs:6:5 | diff --git a/src/test/ui/issues/issue-9575.stderr b/src/test/ui/issues/issue-9575.stderr index 6203c2fa84ef7..3e3678a23f74c 100644 --- a/src/test/ui/issues/issue-9575.stderr +++ b/src/test/ui/issues/issue-9575.stderr @@ -4,8 +4,8 @@ error[E0308]: start function has wrong type LL | fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters | - = note: expected fn pointer `fn(isize, *const *const u8) -> isize` - found fn pointer `fn(isize, *const *const u8, *const u8) -> isize` + = note: expected fn pointer `fn(isize, *const *const u8) -> _` + found fn pointer `fn(isize, *const *const u8, *const u8) -> _` error: aborting due to previous error diff --git a/src/test/ui/unsafe/unsafe-subtyping.stderr b/src/test/ui/unsafe/unsafe-subtyping.stderr index b3e789cc0d91d..19f5ef463cef2 100644 --- a/src/test/ui/unsafe/unsafe-subtyping.stderr +++ b/src/test/ui/unsafe/unsafe-subtyping.stderr @@ -6,8 +6,8 @@ LL | fn foo(x: Option) -> Option { LL | x | ^ expected unsafe fn, found normal fn | - = note: expected enum `std::option::Option` - found enum `std::option::Option` + = note: expected enum `std::option::Option` + found enum `std::option::Option` error: aborting due to previous error diff --git a/src/test/ui/unsafe/unsafe-trait-impl.rs b/src/test/ui/unsafe/unsafe-trait-impl.rs index 97ee97cb5c0df..03a251be1a914 100644 --- a/src/test/ui/unsafe/unsafe-trait-impl.rs +++ b/src/test/ui/unsafe/unsafe-trait-impl.rs @@ -7,8 +7,8 @@ trait Foo { impl Foo for u32 { fn len(&self) -> u32 { *self } //~^ ERROR method `len` has an incompatible type for trait - //~| expected fn pointer `unsafe fn(&u32) -> u32` - //~| found fn pointer `fn(&u32) -> u32` + //~| expected fn pointer `unsafe fn(&u32) -> _` + //~| found fn pointer `fn(&u32) -> _` } fn main() { } diff --git a/src/test/ui/unsafe/unsafe-trait-impl.stderr b/src/test/ui/unsafe/unsafe-trait-impl.stderr index 567be27555cf1..1c3d057cbc9ce 100644 --- a/src/test/ui/unsafe/unsafe-trait-impl.stderr +++ b/src/test/ui/unsafe/unsafe-trait-impl.stderr @@ -7,8 +7,8 @@ LL | unsafe fn len(&self) -> u32; LL | fn len(&self) -> u32 { *self } | ^^^^^^^^^^^^^^^^^^^^ expected unsafe fn, found normal fn | - = note: expected fn pointer `unsafe fn(&u32) -> u32` - found fn pointer `fn(&u32) -> u32` + = note: expected fn pointer `unsafe fn(&u32) -> _` + found fn pointer `fn(&u32) -> _` error: aborting due to previous error diff --git a/src/test/ui/wrong-mul-method-signature.stderr b/src/test/ui/wrong-mul-method-signature.stderr index c0888b3b9d4d5..31f5a3f698161 100644 --- a/src/test/ui/wrong-mul-method-signature.stderr +++ b/src/test/ui/wrong-mul-method-signature.stderr @@ -22,8 +22,8 @@ error[E0053]: method `mul` has an incompatible type for trait LL | fn mul(self, s: f64) -> f64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `f64` | - = note: expected fn pointer `fn(Vec3, f64) -> i32` - found fn pointer `fn(Vec3, f64) -> f64` + = note: expected fn pointer `fn(Vec3, _) -> i32` + found fn pointer `fn(Vec3, _) -> f64` error[E0308]: mismatched types --> $DIR/wrong-mul-method-signature.rs:63:45 From 9d7774c64fcbe9f535f649b51add9a701f459526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 23 Nov 2019 18:36:33 -0800 Subject: [PATCH 2/2] review comments: remove unnecessary `&str` to `String` conversions --- src/librustc/infer/error_reporting/mod.rs | 40 +++++++++++------------ src/librustc_errors/diagnostic.rs | 4 +-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 7d7e7da1def63..f8f69936021f3 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -898,8 +898,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^^^^^^ - values.0.push(sig1.unsafety.prefix_str().to_string(), sig1.unsafety != sig2.unsafety); - values.1.push(sig2.unsafety.prefix_str().to_string(), sig1.unsafety != sig2.unsafety); + values.0.push(sig1.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety); + values.1.push(sig2.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety); // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^^^^^^^^^^ @@ -918,8 +918,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^^^ - values.0.push_normal("fn(".to_string()); - values.1.push_normal("fn(".to_string()); + values.0.push_normal("fn("); + values.1.push_normal("fn("); // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^^^^^ @@ -936,34 +936,34 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { for (i, l) in sig1.inputs().iter().enumerate() { values.0.push_highlighted(l.to_string()); if i != len1 - 1 { - values.0.push_highlighted(", ".to_string()); + values.0.push_highlighted(", "); } } for (i, r) in sig2.inputs().iter().enumerate() { values.1.push_highlighted(r.to_string()); if i != len2 - 1 { - values.1.push_highlighted(", ".to_string()); + values.1.push_highlighted(", "); } } } if sig1.c_variadic { if len1 > 0 { - values.0.push_normal(", ".to_string()); + values.0.push_normal(", "); } - values.0.push("...".to_string(), !sig2.c_variadic); + values.0.push("...", !sig2.c_variadic); } if sig2.c_variadic { if len2 > 0 { - values.1.push_normal(", ".to_string()); + values.1.push_normal(", "); } - values.1.push("...".to_string(), !sig1.c_variadic); + values.1.push("...", !sig1.c_variadic); } // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^ - values.0.push_normal(")".to_string()); - values.1.push_normal(")".to_string()); + values.0.push_normal(")"); + values.1.push_normal(")"); // unsafe extern "C" for<'a> fn(&'a T) -> &'a T // ^^^^^^^^ @@ -971,11 +971,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let output2 = sig2.output(); let (x1, x2) = self.cmp(output1, output2); if !output1.is_unit() { - values.0.push_normal(" -> ".to_string()); + values.0.push_normal(" -> "); (values.0).0.extend(x1.0); } if !output2.is_unit() { - values.1.push_normal(" -> ".to_string()); + values.1.push_normal(" -> "); (values.1).0.extend(x2.0); } values @@ -1240,8 +1240,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // When encountering tuples of the same size, highlight only the differing types (&ty::Tuple(substs1), &ty::Tuple(substs2)) if substs1.len() == substs2.len() => { let mut values = ( - DiagnosticStyledString::normal("(".to_string()), - DiagnosticStyledString::normal("(".to_string()), + DiagnosticStyledString::normal("("), + DiagnosticStyledString::normal("("), ); let len = substs1.len(); for (i, (left, right)) in substs1.types().zip(substs2.types()).enumerate() { @@ -1251,11 +1251,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.push_comma(&mut values.0, &mut values.1, len, i); } if len == 1 { // Keep the output for single element tuples as `(ty,)`. - values.0.push_normal(",".to_string()); - values.1.push_normal(",".to_string()); + values.0.push_normal(","); + values.1.push_normal(","); } - values.0.push_normal(")".to_string()); - values.1.push_normal(")".to_string()); + values.0.push_normal(")"); + values.1.push_normal(")"); values } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 530844ceee11b..abec979054e16 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -54,9 +54,9 @@ impl DiagnosticStyledString { } pub fn push>(&mut self, t: S, highlight: bool) { if highlight { - self.0.push(StringPart::Highlighted(t.into())); + self.push_highlighted(t); } else { - self.0.push(StringPart::Normal(t.into())); + self.push_normal(t); } } pub fn normal>(t: S) -> DiagnosticStyledString {