Skip to content

Commit

Permalink
Address review comments + fix rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Jun 9, 2016
1 parent e783a0a commit 6d7b35b
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 167 deletions.
15 changes: 4 additions & 11 deletions src/librustc/middle/mem_categorization.rs
Expand Up @@ -1105,17 +1105,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {

(*op)(self, cmt.clone(), pat);

// This function can be used during region checking when not all paths are fully
// resolved. Partially resolved paths in patterns can only legally refer to
// associated constants which don't require categorization.
let opt_def = if let Some(path_res) = self.tcx().def_map.borrow().get(&pat.id) {
if path_res.depth != 0 || path_res.base_def == Def::Err {
return Err(());
}
Some(path_res.full_def())
} else {
None
};
let opt_def = self.tcx().expect_def_or_none(pat.id);
if opt_def == Some(Def::Err) {
return Err(());
}

// Note: This goes up here (rather than within the PatKind::TupleStruct arm
// alone) because struct patterns can refer to struct types or
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/hair/cx/pattern.rs
Expand Up @@ -162,7 +162,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
}

PatKind::Binding(bm, ref ident, ref sub) => {
let id = self.cx.tcx.def_map.borrow()[&pat.id].full_def().var_id();
let id = self.cx.tcx.expect_def(pat.id).var_id();
let var_ty = self.cx.tcx.node_id_to_type(pat.id);
let region = match var_ty.sty {
ty::TyRef(&r, _) => Some(r),
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_passes/consts.rs
Expand Up @@ -584,7 +584,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
}
}
hir::ExprStruct(..) => {
if v.tcx.expect_def(e.id).def_id() == v.tcx.lang_items.unsafe_cell_type().unwrap() {
// unsafe_cell_type doesn't necessarily exist with no_core
if Some(v.tcx.expect_def(e.id).def_id()) == v.tcx.lang_items.unsafe_cell_type() {
v.add_qualif(ConstQualif::MUTABLE_MEM);
}
}
Expand Down
142 changes: 16 additions & 126 deletions src/librustc_resolve/diagnostics.rs
Expand Up @@ -677,100 +677,6 @@ fn foo<T>(x: T) {} // ok!
```
"##,

E0413: r##"
A declaration shadows an enum variant or unit-like struct in scope. Example of
erroneous code:
```compile_fail
struct Foo;
let Foo = 12i32; // error: declaration of `Foo` shadows an enum variant or
// unit-like struct in scope
```
To fix this error, rename the variable such that it doesn't shadow any enum
variable or structure in scope. Example:
```
struct Foo;
let foo = 12i32; // ok!
```
Or:
```
struct FooStruct;
let Foo = 12i32; // ok!
```
The goal here is to avoid a conflict of names.
"##,

E0414: r##"
A variable binding in an irrefutable pattern is shadowing the name of a
constant. Example of erroneous code:
```compile_fail
const FOO: u8 = 7;
let FOO = 5; // error: variable bindings cannot shadow constants
// or
fn bar(FOO: u8) { // error: variable bindings cannot shadow constants
}
// or
for FOO in bar {
}
```
Introducing a new variable in Rust is done through a pattern. Thus you can have
`let` bindings like `let (a, b) = ...`. However, patterns also allow constants
in them, e.g. if you want to match over a constant:
```ignore
const FOO: u8 = 1;
match (x,y) {
(3, 4) => { .. }, // it is (3,4)
(FOO, 1) => { .. }, // it is (1,1)
(foo, 1) => { .. }, // it is (anything, 1)
// call the value in the first slot "foo"
_ => { .. } // it is anything
}
```
Here, the second arm matches the value of `x` against the constant `FOO`,
whereas the third arm will accept any value of `x` and call it `foo`.
This works for `match`, however in cases where an irrefutable pattern is
required, constants can't be used. An irrefutable pattern is one which always
matches, whose purpose is only to bind variable names to values. These are
required by let, for, and function argument patterns.
Refutable patterns in such a situation do not make sense, for example:
```ignore
let Some(x) = foo; // what if foo is None, instead?
let (1, x) = foo; // what if foo.0 is not 1?
let (SOME_CONST, x) = foo; // what if foo.0 is not SOME_CONST?
let SOME_CONST = foo; // what if foo is not SOME_CONST?
```
Thus, an irrefutable variable binding can't contain a constant.
To fix this error, just give the marked variable a different name.
"##,

E0415: r##"
More than one function parameter have the same name. Example of erroneous code:
Expand Down Expand Up @@ -814,34 +720,6 @@ match (A, B, C) {
```
"##,

E0417: r##"
A static variable was referenced in a pattern. Example of erroneous code:
```compile_fail
static FOO : i32 = 0;
match 0 {
FOO => {} // error: static variables cannot be referenced in a
// pattern, use a `const` instead
_ => {}
}
```
The compiler needs to know the value of the pattern at compile time;
compile-time patterns can defined via const or enum items. Please verify
that the identifier is spelled correctly, and if so, use a const instead
of static to define it. Example:
```
const FOO : i32 = 0;
match 0 {
FOO => {} // ok!
_ => {}
}
```
"##,

E0422: r##"
You are trying to use an identifier that is either undefined or not a struct.
For instance:
Expand Down Expand Up @@ -1221,11 +1099,23 @@ impl Foo for i32 {}
}

register_diagnostics! {
// E0153, unused error code
// E0157, unused error code
E0254, // import conflicts with imported crate in this module
// E0257,
// E0258,
E0402, // cannot use an outer type parameter in this context
E0406, // undeclared associated type
E0418, // X bindings cannot shadow Ys
E0419, // unresolved pattern path kind `name`
E0420, // expected pattern path kind, found another pattern path kind
E0427, // cannot use `ref` binding mode with ...
// E0410, merged into 408
// E0413, merged into 530
// E0414, merged into 530
// E0417, merged into 532
// E0418, merged into 532
// E0419, merged into 531
// E0420, merged into 532
// E0421, merged into 531
E0530, // X bindings cannot shadow Ys
E0531, // unresolved pattern path kind `name`
E0532, // expected pattern path kind, found another pattern path kind
// E0427, merged into 530
}
50 changes: 25 additions & 25 deletions src/librustc_resolve/lib.rs
Expand Up @@ -155,11 +155,11 @@ enum ResolutionError<'a> {
CannotCaptureDynamicEnvironmentInFnItem,
/// error E0435: attempt to use a non-constant value in a constant
AttemptToUseNonConstantValueInConstant,
/// error E0418: X bindings cannot shadow Ys
/// error E0530: X bindings cannot shadow Ys
BindingShadowsSomethingUnacceptable(&'a str, &'a str, Name),
/// error E0419: unresolved pattern path kind `name`
/// error E0531: unresolved pattern path kind `name`
PatPathUnresolved(&'a str, &'a Path),
/// error E0420: expected pattern path kind, found another pattern path kind
/// error E0532: expected pattern path kind, found another pattern path kind
PatPathUnexpected(&'a str, &'a str, &'a Path),
}

Expand Down Expand Up @@ -426,11 +426,10 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, shadows_what, name) => {
let mut err = struct_span_err!(resolver.session,
span,
E0418,
E0530,
"{}s cannot shadow {}s", what_binding, shadows_what);
err.span_label(span, &format!("cannot be named the same as a {}", shadows_what));
if let Some(binding) = resolver.current_module
.resolve_name_in_lexical_scope(name, ValueNS) {
if let Success(binding) = resolver.current_module.resolve_name(name, ValueNS, true) {
let participle = if binding.is_import() { "imported" } else { "defined" };
err.span_label(binding.span, &format!("a {} `{}` is {} here",
shadows_what, name, participle));
Expand All @@ -440,15 +439,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
ResolutionError::PatPathUnresolved(expected_what, path) => {
struct_span_err!(resolver.session,
span,
E0419,
E0531,
"unresolved {} `{}`",
expected_what,
path.segments.last().unwrap().identifier)
}
ResolutionError::PatPathUnexpected(expected_what, found_what, path) => {
struct_span_err!(resolver.session,
span,
E0420,
E0532,
"expected {}, found {} `{}`",
expected_what,
found_what,
Expand Down Expand Up @@ -2201,15 +2200,15 @@ impl<'a> Resolver<'a> {
pat_id: NodeId,
outer_pat_id: NodeId,
pat_src: PatternSource,
bindings_list: &mut HashMap<Name, NodeId>)
bindings: &mut HashMap<Name, NodeId>)
-> PathResolution {
// Add the binding to the local ribs, if it
// doesn't already exist in the bindings list. (We
// must not add it if it's in the bindings list
// doesn't already exist in the bindings map. (We
// must not add it if it's in the bindings map
// because that breaks the assumptions later
// passes make about or-patterns.)
let renamed = mtwt::resolve(ident.node);
let def = match bindings_list.get(&renamed).cloned() {
let def = match bindings.get(&renamed).cloned() {
Some(id) if id == outer_pat_id => {
// `Variant(a, a)`, error
resolve_error(
Expand All @@ -2231,8 +2230,9 @@ impl<'a> Resolver<'a> {
Def::Err
}
Some(..) if pat_src == PatternSource::Match => {
// `Varian1(a) | Varian2(a)`, ok
Def::Local(self.definitions.local_def_id(pat_id), pat_id)
// `Variant1(a) | Variant2(a)`, ok
// Reuse definition from the first `a`.
self.value_ribs.last_mut().unwrap().bindings[&renamed]
}
Some(..) => {
span_bug!(ident.span, "two bindings with the same name from \
Expand All @@ -2244,7 +2244,7 @@ impl<'a> Resolver<'a> {
// define `Invalid` bindings as `Def::Local`, just don't add them to the lists.
let def = Def::Local(self.definitions.local_def_id(pat_id), pat_id);
if ident.node.name != keywords::Invalid.name() {
bindings_list.insert(renamed, outer_pat_id);
bindings.insert(renamed, outer_pat_id);
self.value_ribs.last_mut().unwrap().bindings.insert(renamed, def);
}
def
Expand All @@ -2255,12 +2255,12 @@ impl<'a> Resolver<'a> {
}

fn resolve_pattern_path<ExpectedFn>(&mut self,
pat_id: NodeId,
qself: Option<&QSelf>,
path: &Path,
namespace: Namespace,
expected_fn: ExpectedFn,
expected_what: &'static str)
pat_id: NodeId,
qself: Option<&QSelf>,
path: &Path,
namespace: Namespace,
expected_fn: ExpectedFn,
expected_what: &str)
where ExpectedFn: FnOnce(Def) -> bool
{
let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id,
Expand Down Expand Up @@ -2307,8 +2307,8 @@ impl<'a> Resolver<'a> {
pat_src: PatternSource,
// Maps idents to the node ID for the
// outermost pattern that binds them.
bindings_list: &mut HashMap<Name, NodeId>) {
// Visit all direct subpatterns of this pattern with the same PatternBindingMode.
bindings: &mut HashMap<Name, NodeId>) {
// Visit all direct subpatterns of this pattern.
let outer_pat_id = pat.id;
pat.walk(&mut |pat| {
match pat.node {
Expand Down Expand Up @@ -2340,7 +2340,7 @@ impl<'a> Resolver<'a> {
// These entities are explicitly allowed
// to be shadowed by fresh bindings.
self.fresh_binding(ident, pat.id, outer_pat_id,
pat_src, bindings_list)
pat_src, bindings)
}
def => {
span_bug!(ident.span, "unexpected definition for an \
Expand All @@ -2349,7 +2349,7 @@ impl<'a> Resolver<'a> {
}
} else {
// Fall back to a fresh binding.
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings_list)
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
};

self.record_def(pat.id, resolution);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/check/_match.rs
Expand Up @@ -151,7 +151,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// is good enough.
self.demand_suptype(pat.span, expected, const_ty);
}
PatKind::Binding(bm, ref path, ref sub) => {
PatKind::Binding(bm, _, ref sub) => {
let typ = self.local_ty(pat.span, pat.id);
match bm {
hir::BindByRef(mutbl) => {
Expand Down Expand Up @@ -180,7 +180,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

// if there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be
match tcx.def_map.borrow()[&pat.id].full_def() {
match tcx.expect_def(pat.id) {
Def::Err => {}
Def::Local(_, var_id) => {
if var_id != pat.id {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/mod.rs
Expand Up @@ -86,8 +86,8 @@ use fmt_macros::{Parser, Piece, Position};
use middle::cstore::LOCAL_CRATE;
use hir::def::{self, Def};
use hir::def_id::DefId;
use hir::pat_util;
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
use hir::pat_util::{self};
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
use rustc::traits::{self, ProjectionMode};
use rustc::ty::{GenericPredicates, TypeScheme};
Expand Down

0 comments on commit 6d7b35b

Please sign in to comment.