Address review comments + fix rebase
This commit is contained in:
parent
e783a0a5e3
commit
6d7b35bd98
7 changed files with 51 additions and 167 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
@ -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:
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
|
||||
|
|
@ -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));
|
||||
|
|
@ -440,7 +439,7 @@ 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)
|
||||
|
|
@ -448,7 +447,7 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
|||
ResolutionError::PatPathUnexpected(expected_what, found_what, path) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0420,
|
||||
E0532,
|
||||
"expected {}, found {} `{}`",
|
||||
expected_what,
|
||||
found_what,
|
||||
|
|
@ -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(
|
||||
|
|
@ -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 \
|
||||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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 \
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue