diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index d2a5cd7350331..d513af10b3618 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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 diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 89bd0fdf89760..1bc3954a5fe75 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -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), diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 774d19a06558b..75bfe7c0f2f95 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -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); } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index d3e2dd2a917e5..476b9a5447b07 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -677,100 +677,6 @@ fn foo(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 } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 13a3d53d49766..377863b016d85 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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) + bindings: &mut HashMap) -> 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(&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) { - // Visit all direct subpatterns of this pattern with the same PatternBindingMode. + bindings: &mut HashMap) { + // 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); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index bee0d6338d852..1cff392cf8338 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -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 { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4dee1e43d16ab..d9dd122d07376 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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};