Auto merge of #36338 - estebank:primitive-shadow, r=jseyfried

Be more specific when type parameter shadows primitive type

When a type parameter shadows a primitive type, the error message
was non obvious. For example, given the file `file.rs`:

```rust
trait Parser<T> {
    fn parse(text: &str) -> Option<T>;
}

impl<bool> Parser<bool> for bool {
    fn parse(text: &str) -> Option<bool> {
        Some(true)
    }
}

fn main() {
    println!("{}", bool::parse("ok").unwrap_or(false));
}
```

The output was:

```bash
% rustc file.rs
error[E0308]: mismatched types
 --> file.rs:7:14
  |
7 |         Some(true)
  |              ^^^^ expected type parameter, found bool a
  |
  = note: expected type `bool`
  = note:    found type `bool`

error: aborting due to previous error
```

We now show extra information about the type:

```bash
% rustc file.rs
error[E0308]: mismatched types
 --> file.rs:7:14
  |
7 |         Some(true)
  |              ^^^^ expected type parameter, found bool a
  |
  = note: expected type `bool` (type parameter)
  = note:    found type `bool` (bool)

error: aborting due to previous error
```

Fixes #35030
This commit is contained in:
bors 2016-09-16 00:39:27 -07:00 committed by GitHub
commit 89500e9341
5 changed files with 63 additions and 5 deletions

View File

@ -547,7 +547,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
};
if !is_simple_error {
diag.note_expected_found(&"type", &expected, &found);
if expected == found {
if let &TypeError::Sorts(ref values) = terr {
diag.note_expected_found_extra(
&"type", &expected, &found,
&format!(" ({})", values.expected.sort_string(self.tcx)),
&format!(" ({})", values.found.sort_string(self.tcx)));
} else {
diag.note_expected_found(&"type", &expected, &found);
}
} else {
diag.note_expected_found(&"type", &expected, &found);
}
}
}

View File

@ -210,7 +210,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
}
impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
match self.sty {
ty::TyBool | ty::TyChar | ty::TyInt(_) |
ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),

View File

@ -273,10 +273,21 @@ impl<'a> DiagnosticBuilder<'a> {
expected: &fmt::Display,
found: &fmt::Display)
-> &mut DiagnosticBuilder<'a>
{
self.note_expected_found_extra(label, expected, found, &"", &"")
}
pub fn note_expected_found_extra(&mut self,
label: &fmt::Display,
expected: &fmt::Display,
found: &fmt::Display,
expected_extra: &fmt::Display,
found_extra: &fmt::Display)
-> &mut DiagnosticBuilder<'a>
{
// For now, just attach these as notes
self.note(&format!("expected {} `{}`", label, expected));
self.note(&format!(" found {} `{}`", label, found));
self.note(&format!("expected {} `{}`{}", label, expected, expected_extra));
self.note(&format!(" found {} `{}`{}", label, found, found_extra));
self
}
@ -764,4 +775,4 @@ pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T where
Some(t) => t,
None => diag.bug(&msg()),
}
}
}

View File

@ -0,0 +1,25 @@
// Copyright 2016 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.
// rustc-env:RUST_NEW_ERROR_FORMAT
trait Parser<T> {
fn parse(text: &str) -> Option<T>;
}
impl<bool> Parser<bool> for bool {
fn parse(text: &str) -> Option<bool> {
Some(true)
}
}
fn main() {
println!("{}", bool::parse("ok").unwrap_or(false));
}

View File

@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/issue-35030.rs:19:14
|
19 | Some(true)
| ^^^^ expected type parameter, found bool
|
= note: expected type `bool` (type parameter)
= note: found type `bool` (bool)
error: aborting due to previous error