Skip to content

Commit

Permalink
Merge branch 'shadowing' of https://github.com/nikomatsakis/rfcs into…
Browse files Browse the repository at this point in the history
… nikomatsakis-shadowing
  • Loading branch information
nrc committed Nov 29, 2014
2 parents 63535c1 + bfe83d6 commit 0647cda
Showing 1 changed file with 91 additions and 0 deletions.
91 changes: 91 additions & 0 deletions text/0459-disallow-shadowing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
- Start Date: 2014-11-29
- RFC PR: #459
- Rust Issue: [19390](https://github.com/rust-lang/rust/issues/19390)

# Summary

Disallow type/lifetime parameter shadowing.

# Motivation

Today we allow type and lifetime parameters to be shadowed. This is a
common source of bugs as well as confusing errors. An example of such a confusing case is:

```rust
struct Foo<'a> {
x: &'a int
}

impl<'a> Foo<'a> {
fn set<'a>(&mut self, v: &'a int) {
self.x = v;
}
}

fn main() { }
```

In this example, the lifetime parameter `'a` is shadowed on the method, leading to two
logically distinct lifetime parameters with the same name. This then leads to the error
message:

mismatched types: expected `&'a int`, found `&'a int` (lifetime mismatch)

which is obviously completely unhelpful.

Similar errors can occur with type parameters:

```rust
struct Foo<T> {
x: T
}

impl<T> Foo<T> {
fn set<T>(&mut self, v: T) {
self.x = v;
}
}

fn main() { }
```

Compiling this program yields:

mismatched types: expected `T`, found `T` (expected type parameter, found a different type parameter)

Here the error message was improved by [a recent PR][pr], but this is
still a somewhat confusing situation.

Anecdotally, this kind of accidental shadowing is fairly frequent
occurrence. It recently arose on [this discuss thread][dt], for
example.

[dt]: http://discuss.rust-lang.org/t/confused-by-lifetime-error-messages-tell-me-about-it/358/41?u=nikomatsakis
[pr]: https://github.com/rust-lang/rust/pull/18264

# Detailed design

Disallow shadowed type/lifetime parameter declarations. An error would
be reported by the resolve/resolve-lifetime passes in the compiler and
hence fairly early in the pipeline.

# Drawbacks

We otherwise allow shadowing, so it is inconsistent.

# Alternatives

We could use a lint instead. However, we'd want to ensure that the
lint error messages were printed *before* type-checking begins. We
could do this, perhaps, by running the lint printing pass multiple
times. This might be useful in any case as the placement of lints in
the compiler pipeline has proven problematic before.

We could also attempt to improve the error messages. Doing so for
lifetimes is definitely important in any case, but also somewhat
tricky due to the extensive inference. It is usually easier and more
reliable to help avoid the error in the first place.

# Unresolved questions

None.

0 comments on commit 0647cda

Please sign in to comment.