resolve: Rewrite resolve_pattern
This commit is contained in:
parent
ee00760a14
commit
91b9dabdeb
28 changed files with 347 additions and 491 deletions
|
@ -88,6 +88,14 @@ impl PathResolution {
|
|||
depth: depth,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind_name(&self) -> &'static str {
|
||||
if self.depth != 0 {
|
||||
"associated item"
|
||||
} else {
|
||||
self.base_def.kind_name()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Definition mapping
|
||||
|
@ -161,8 +169,8 @@ impl Def {
|
|||
Def::Struct(..) => "struct",
|
||||
Def::Trait(..) => "trait",
|
||||
Def::Method(..) => "method",
|
||||
Def::Const(..) => "const",
|
||||
Def::AssociatedConst(..) => "associated const",
|
||||
Def::Const(..) => "constant",
|
||||
Def::AssociatedConst(..) => "associated constant",
|
||||
Def::TyParam(..) => "type parameter",
|
||||
Def::PrimTy(..) => "builtin type",
|
||||
Def::Local(..) => "local variable",
|
||||
|
|
|
@ -842,32 +842,6 @@ match 0 {
|
|||
```
|
||||
"##,
|
||||
|
||||
E0419: r##"
|
||||
An unknown enum variant, struct or const was used. Example of erroneous code:
|
||||
|
||||
```compile_fail
|
||||
match 0 {
|
||||
Something::Foo => {} // error: unresolved enum variant, struct
|
||||
// or const `Foo`
|
||||
}
|
||||
```
|
||||
|
||||
Please verify you didn't misspell it and the enum variant, struct or const has
|
||||
been declared and imported into scope. Example:
|
||||
|
||||
```
|
||||
enum Something {
|
||||
Foo,
|
||||
NotFoo,
|
||||
}
|
||||
|
||||
match Something::NotFoo {
|
||||
Something::Foo => {} // ok!
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0422: r##"
|
||||
You are trying to use an identifier that is either undefined or not a struct.
|
||||
For instance:
|
||||
|
@ -1247,16 +1221,11 @@ 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
|
||||
// E0410, merged into 408
|
||||
E0418, // is not an enum variant, struct or const
|
||||
E0420, // is not an associated const
|
||||
E0421, // unresolved associated const
|
||||
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 ...
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ extern crate arena;
|
|||
#[macro_use]
|
||||
extern crate rustc;
|
||||
|
||||
use self::PatternBindingMode::*;
|
||||
use self::Namespace::*;
|
||||
use self::ResolveResult::*;
|
||||
use self::FallbackSuggestion::*;
|
||||
|
@ -40,7 +39,6 @@ use self::RibKind::*;
|
|||
use self::UseLexicalScopeFlag::*;
|
||||
use self::ModulePrefixResult::*;
|
||||
use self::AssocItemResolveResult::*;
|
||||
use self::BareIdentifierPatternResolution::*;
|
||||
use self::ParentLink::*;
|
||||
|
||||
use rustc::hir::map::Definitions;
|
||||
|
@ -66,8 +64,8 @@ use syntax::visit::{self, FnKind, Visitor};
|
|||
use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
||||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
|
||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||
use syntax::ast::{Local, Pat, PatKind, Path};
|
||||
use syntax::ast::{PathSegment, PathParameters, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
|
||||
use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
@ -123,24 +121,10 @@ enum ResolutionError<'a> {
|
|||
SelfUsedOutsideImplOrTrait,
|
||||
/// error E0412: use of undeclared
|
||||
UseOfUndeclared(&'a str, &'a str, SuggestedCandidates),
|
||||
/// error E0413: cannot be named the same as an enum variant or unit-like struct in scope
|
||||
DeclarationShadowsEnumVariantOrUnitLikeStruct(Name),
|
||||
/// error E0414: only irrefutable patterns allowed here
|
||||
ConstantForIrrefutableBinding(Name, &'a NameBinding<'a>),
|
||||
/// error E0415: identifier is bound more than once in this parameter list
|
||||
IdentifierBoundMoreThanOnceInParameterList(&'a str),
|
||||
/// error E0416: identifier is bound more than once in the same pattern
|
||||
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
|
||||
/// error E0417: static variables cannot be referenced in a pattern
|
||||
StaticVariableReference(&'a NameBinding<'a>),
|
||||
/// error E0418: is not an enum variant, struct or const
|
||||
NotAnEnumVariantStructOrConst(&'a str),
|
||||
/// error E0419: unresolved enum variant, struct or const
|
||||
UnresolvedEnumVariantStructOrConst(&'a str),
|
||||
/// error E0420: is not an associated const
|
||||
NotAnAssociatedConst(&'a str),
|
||||
/// error E0421: unresolved associated const
|
||||
UnresolvedAssociatedConst(&'a str),
|
||||
/// error E0422: does not name a struct
|
||||
DoesNotNameAStruct(&'a str),
|
||||
/// error E0423: is a struct variant name, but this expression uses it like a function name
|
||||
|
@ -158,8 +142,6 @@ enum ResolutionError<'a> {
|
|||
},
|
||||
/// error E0426: use of undeclared label
|
||||
UndeclaredLabel(&'a str),
|
||||
/// error E0427: cannot use `ref` binding mode with ...
|
||||
CannotUseRefBindingModeWith(&'a str),
|
||||
/// error E0429: `self` imports are only allowed within a { } list
|
||||
SelfImportsOnlyAllowedWithin,
|
||||
/// error E0430: `self` import can only appear once in the list
|
||||
|
@ -174,6 +156,12 @@ enum ResolutionError<'a> {
|
|||
CannotCaptureDynamicEnvironmentInFnItem,
|
||||
/// error E0435: attempt to use a non-constant value in a constant
|
||||
AttemptToUseNonConstantValueInConstant,
|
||||
/// error E0418: X bindings cannot shadow Ys
|
||||
BindingShadowsSomethingUnacceptable(&'a str, &'a str, Name),
|
||||
/// error E0419: unresolved pattern path kind `name`
|
||||
PatPathUnresolved(&'a str, &'a Path),
|
||||
/// error E0420: expected pattern path kind, found another pattern path kind
|
||||
PatPathUnexpected(&'a str, &'a str, &'a Path),
|
||||
}
|
||||
|
||||
/// Context of where `ResolutionError::UnresolvedName` arose.
|
||||
|
@ -306,28 +294,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
|||
err.span_label(span, &format!("undefined or not in scope"));
|
||||
err
|
||||
}
|
||||
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0413,
|
||||
"`{}` cannot be named the same as an enum variant \
|
||||
or unit-like struct in scope",
|
||||
name);
|
||||
err.span_label(span,
|
||||
&format!("has same name as enum variant or unit-like struct"));
|
||||
err
|
||||
}
|
||||
ResolutionError::ConstantForIrrefutableBinding(name, binding) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0414,
|
||||
"let variables cannot be named the same as const variables");
|
||||
err.span_label(span,
|
||||
&format!("cannot be named the same as a const variable"));
|
||||
let participle = if binding.is_import() { "imported" } else { "defined" };
|
||||
err.span_label(binding.span, &format!("a constant `{}` is {} here", name, participle));
|
||||
err
|
||||
}
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
|
@ -346,47 +312,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
|||
err.span_label(span, &format!("used in a pattern more than once"));
|
||||
err
|
||||
}
|
||||
ResolutionError::StaticVariableReference(binding) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0417,
|
||||
"static variables cannot be referenced in a \
|
||||
pattern, use a `const` instead");
|
||||
err.span_label(span, &format!("static variable used in pattern"));
|
||||
if binding.span != codemap::DUMMY_SP {
|
||||
let participle = if binding.is_import() { "imported" } else { "defined" };
|
||||
err.span_label(binding.span, &format!("static variable {} here", participle));
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::NotAnEnumVariantStructOrConst(name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0418,
|
||||
"`{}` is not an enum variant, struct or const",
|
||||
name)
|
||||
}
|
||||
ResolutionError::UnresolvedEnumVariantStructOrConst(name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0419,
|
||||
"unresolved enum variant, struct or const `{}`",
|
||||
name)
|
||||
}
|
||||
ResolutionError::NotAnAssociatedConst(name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0420,
|
||||
"`{}` is not an associated const",
|
||||
name)
|
||||
}
|
||||
ResolutionError::UnresolvedAssociatedConst(name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0421,
|
||||
"unresolved associated const `{}`",
|
||||
name)
|
||||
}
|
||||
ResolutionError::DoesNotNameAStruct(name) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
|
@ -455,13 +380,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
|||
"use of undeclared label `{}`",
|
||||
name)
|
||||
}
|
||||
ResolutionError::CannotUseRefBindingModeWith(descr) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0427,
|
||||
"cannot use `ref` binding mode with {}",
|
||||
descr)
|
||||
}
|
||||
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
|
@ -506,6 +424,37 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
|||
E0435,
|
||||
"attempt to use a non-constant value in a constant")
|
||||
}
|
||||
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, shadows_what, name) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0418,
|
||||
"{}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) {
|
||||
let participle = if binding.is_import() { "imported" } else { "defined" };
|
||||
err.span_label(binding.span, &format!("a {} `{}` is {} here",
|
||||
shadows_what, name, participle));
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::PatPathUnresolved(expected_what, path) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0419,
|
||||
"unresolved {} `{}`",
|
||||
expected_what,
|
||||
path.segments.last().unwrap().identifier)
|
||||
}
|
||||
ResolutionError::PatPathUnexpected(expected_what, found_what, path) => {
|
||||
struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0420,
|
||||
"expected {}, found {} `{}`",
|
||||
expected_what,
|
||||
found_what,
|
||||
path.segments.last().unwrap().identifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -518,11 +467,33 @@ struct BindingInfo {
|
|||
// Map from the name in a pattern to its binding mode.
|
||||
type BindingMap = HashMap<Name, BindingInfo>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
enum PatternBindingMode {
|
||||
RefutableMode,
|
||||
LocalIrrefutableMode,
|
||||
ArgumentIrrefutableMode,
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
enum PatternSource {
|
||||
Match,
|
||||
IfLet,
|
||||
WhileLet,
|
||||
Let,
|
||||
For,
|
||||
FnParam,
|
||||
}
|
||||
|
||||
impl PatternSource {
|
||||
fn is_refutable(self) -> bool {
|
||||
match self {
|
||||
PatternSource::Match | PatternSource::IfLet | PatternSource::WhileLet => true,
|
||||
PatternSource::Let | PatternSource::For | PatternSource::FnParam => false,
|
||||
}
|
||||
}
|
||||
fn descr(self) -> &'static str {
|
||||
match self {
|
||||
PatternSource::Match => "match binding",
|
||||
PatternSource::IfLet => "if let binding",
|
||||
PatternSource::WhileLet => "while let binding",
|
||||
PatternSource::Let => "let binding",
|
||||
PatternSource::For => "for binding",
|
||||
PatternSource::FnParam => "function parameter",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
|
@ -709,13 +680,6 @@ enum AssocItemResolveResult {
|
|||
ResolveAttempt(Option<PathResolution>),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum BareIdentifierPatternResolution<'a> {
|
||||
FoundStructOrEnumVariant(Def),
|
||||
FoundConst(&'a NameBinding<'a>, Name),
|
||||
BareIdentifierPatternUnresolved,
|
||||
}
|
||||
|
||||
/// One local scope.
|
||||
#[derive(Debug)]
|
||||
struct Rib<'a> {
|
||||
|
@ -1814,7 +1778,7 @@ impl<'a> Resolver<'a> {
|
|||
// Add each argument to the rib.
|
||||
let mut bindings_list = HashMap::new();
|
||||
for argument in &declaration.inputs {
|
||||
self.resolve_pattern(&argument.pat, ArgumentIrrefutableMode, &mut bindings_list);
|
||||
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
|
||||
|
||||
self.visit_ty(&argument.ty);
|
||||
|
||||
|
@ -2055,7 +2019,7 @@ impl<'a> Resolver<'a> {
|
|||
walk_list!(self, visit_expr, &local.init);
|
||||
|
||||
// Resolve the pattern.
|
||||
self.resolve_pattern(&local.pat, LocalIrrefutableMode, &mut HashMap::new());
|
||||
self.resolve_pattern(&local.pat, PatternSource::Let, &mut HashMap::new());
|
||||
}
|
||||
|
||||
// build a map from pattern identifiers to binding-info's.
|
||||
|
@ -2124,7 +2088,7 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
let mut bindings_list = HashMap::new();
|
||||
for pattern in &arm.pats {
|
||||
self.resolve_pattern(&pattern, RefutableMode, &mut bindings_list);
|
||||
self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list);
|
||||
}
|
||||
|
||||
// This has to happen *after* we determine which
|
||||
|
@ -2183,10 +2147,18 @@ impl<'a> Resolver<'a> {
|
|||
// This is a path in the type namespace. Walk through scopes
|
||||
// looking for it.
|
||||
if let Some(def) = resolution {
|
||||
// Write the result into the def map.
|
||||
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
|
||||
path_names_to_string(path, 0), ty.id, def);
|
||||
self.record_def(ty.id, def);
|
||||
match def.base_def {
|
||||
Def::Mod(..) => {
|
||||
self.session.span_err(path.span, "expected type, found module");
|
||||
self.record_def(ty.id, err_path_resolution());
|
||||
}
|
||||
_ => {
|
||||
// Write the result into the def map.
|
||||
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
|
||||
path_names_to_string(path, 0), ty.id, def);
|
||||
self.record_def(ty.id, def);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.record_def(ty.id, err_path_resolution());
|
||||
|
||||
|
@ -2246,312 +2218,230 @@ impl<'a> Resolver<'a> {
|
|||
visit::walk_ty(self, ty);
|
||||
}
|
||||
|
||||
fn resolve_pattern(&mut self,
|
||||
pattern: &Pat,
|
||||
mode: PatternBindingMode,
|
||||
// Maps idents to the node ID for the (outermost)
|
||||
// pattern that binds them
|
||||
bindings_list: &mut HashMap<Name, NodeId>) {
|
||||
let pat_id = pattern.id;
|
||||
pattern.walk(&mut |pattern| {
|
||||
match pattern.node {
|
||||
PatKind::Ident(binding_mode, ref path1, ref at_rhs) => {
|
||||
// The meaning of PatKind::Ident with no type parameters
|
||||
// depends on whether an enum variant or unit-like struct
|
||||
// with that name is in scope. The probing lookup has to
|
||||
// be careful not to emit spurious errors. Only matching
|
||||
// patterns (match) can match nullary variants or
|
||||
// unit-like structs. For binding patterns (let
|
||||
// and the LHS of @-patterns), matching such a value is
|
||||
// simply disallowed (since it's rarely what you want).
|
||||
let const_ok = mode == RefutableMode && at_rhs.is_none();
|
||||
fn fresh_binding(&mut self,
|
||||
ident: &ast::SpannedIdent,
|
||||
pat_id: NodeId,
|
||||
outer_pat_id: NodeId,
|
||||
pat_src: PatternSource,
|
||||
bindings_list: &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
|
||||
// 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() {
|
||||
Some(id) if id == outer_pat_id => {
|
||||
// `Variant(a, a)`, error
|
||||
resolve_error(
|
||||
self,
|
||||
ident.span,
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
|
||||
&ident.node.name.as_str())
|
||||
);
|
||||
Def::Err
|
||||
}
|
||||
Some(..) if pat_src == PatternSource::FnParam => {
|
||||
// `fn f(a: u8, a: u8)`, error
|
||||
resolve_error(
|
||||
self,
|
||||
ident.span,
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
|
||||
&ident.node.name.as_str())
|
||||
);
|
||||
Def::Err
|
||||
}
|
||||
Some(..) if pat_src == PatternSource::Match => {
|
||||
// `Varian1(a) | Varian2(a)`, ok
|
||||
Def::Local(self.definitions.local_def_id(pat_id), pat_id)
|
||||
}
|
||||
Some(..) => {
|
||||
span_bug!(ident.span, "two bindings with the same name from \
|
||||
unexpected pattern source {:?}", pat_src);
|
||||
}
|
||||
None => {
|
||||
// A completely fresh binding, add to the lists
|
||||
bindings_list.insert(renamed, outer_pat_id);
|
||||
let def = Def::Local(self.definitions.local_def_id(pat_id), pat_id);
|
||||
self.value_ribs.last_mut().unwrap().bindings.insert(renamed, def);
|
||||
def
|
||||
}
|
||||
};
|
||||
|
||||
let ident = path1.node;
|
||||
let renamed = mtwt::resolve(ident);
|
||||
PathResolution { base_def: def, depth: 0 }
|
||||
}
|
||||
|
||||
match self.resolve_bare_identifier_pattern(ident, pattern.span) {
|
||||
FoundStructOrEnumVariant(def) if const_ok => {
|
||||
debug!("(resolving pattern) resolving `{}` to struct or enum variant",
|
||||
renamed);
|
||||
|
||||
self.enforce_default_binding_mode(pattern,
|
||||
binding_mode,
|
||||
"an enum variant");
|
||||
self.record_def(pattern.id,
|
||||
PathResolution {
|
||||
base_def: def,
|
||||
depth: 0,
|
||||
});
|
||||
}
|
||||
FoundStructOrEnumVariant(..) => {
|
||||
resolve_error(
|
||||
self,
|
||||
pattern.span,
|
||||
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(
|
||||
renamed)
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
FoundConst(binding, _) if const_ok => {
|
||||
debug!("(resolving pattern) resolving `{}` to constant", renamed);
|
||||
|
||||
self.enforce_default_binding_mode(pattern, binding_mode, "a constant");
|
||||
self.record_def(pattern.id,
|
||||
PathResolution {
|
||||
base_def: binding.def().unwrap(),
|
||||
depth: 0,
|
||||
});
|
||||
}
|
||||
FoundConst(binding, name) => {
|
||||
resolve_error(
|
||||
self,
|
||||
pattern.span,
|
||||
ResolutionError::ConstantForIrrefutableBinding(name, binding)
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
BareIdentifierPatternUnresolved => {
|
||||
debug!("(resolving pattern) binding `{}`", renamed);
|
||||
|
||||
let def_id = self.definitions.local_def_id(pattern.id);
|
||||
let def = Def::Local(def_id, pattern.id);
|
||||
|
||||
// Record the definition so that later passes
|
||||
// will be able to distinguish variants from
|
||||
// locals in patterns.
|
||||
|
||||
self.record_def(pattern.id,
|
||||
PathResolution {
|
||||
base_def: def,
|
||||
depth: 0,
|
||||
});
|
||||
|
||||
// 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
|
||||
// because that breaks the assumptions later
|
||||
// passes make about or-patterns.)
|
||||
if !bindings_list.contains_key(&renamed) {
|
||||
let this = &mut *self;
|
||||
let last_rib = this.value_ribs.last_mut().unwrap();
|
||||
last_rib.bindings.insert(renamed, def);
|
||||
bindings_list.insert(renamed, pat_id);
|
||||
} else if mode == ArgumentIrrefutableMode &&
|
||||
bindings_list.contains_key(&renamed) {
|
||||
// Forbid duplicate bindings in the same
|
||||
// parameter list.
|
||||
resolve_error(
|
||||
self,
|
||||
pattern.span,
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
|
||||
&ident.name.as_str())
|
||||
);
|
||||
} else if bindings_list.get(&renamed) == Some(&pat_id) {
|
||||
// Then this is a duplicate variable in the
|
||||
// same disjunction, which is an error.
|
||||
resolve_error(
|
||||
self,
|
||||
pattern.span,
|
||||
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
|
||||
&ident.name.as_str())
|
||||
);
|
||||
}
|
||||
// Else, not bound in the same pattern: do
|
||||
// nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(ref path, _, _) | PatKind::Path(ref path) => {
|
||||
// This must be an enum variant, struct or const.
|
||||
let resolution = match self.resolve_possibly_assoc_item(pat_id,
|
||||
None,
|
||||
path,
|
||||
ValueNS) {
|
||||
// The below shouldn't happen because all
|
||||
// qualified paths should be in PatKind::QPath.
|
||||
TypecheckRequired =>
|
||||
span_bug!(path.span,
|
||||
"resolve_possibly_assoc_item claimed that a path \
|
||||
in PatKind::Path or PatKind::TupleStruct \
|
||||
requires typecheck to resolve, but qualified \
|
||||
paths should be PatKind::QPath"),
|
||||
ResolveAttempt(resolution) => resolution,
|
||||
};
|
||||
if let Some(path_res) = resolution {
|
||||
match path_res.base_def {
|
||||
Def::Struct(..) if path_res.depth == 0 => {
|
||||
self.record_def(pattern.id, path_res);
|
||||
}
|
||||
Def::Variant(..) | Def::Const(..) => {
|
||||
self.record_def(pattern.id, path_res);
|
||||
}
|
||||
Def::Static(..) => {
|
||||
let segments = &path.segments;
|
||||
let binding = if path.global {
|
||||
self.resolve_crate_relative_path(path.span, segments, ValueNS)
|
||||
} else {
|
||||
self.resolve_module_relative_path(path.span, segments, ValueNS)
|
||||
}.unwrap();
|
||||
|
||||
let error = ResolutionError::StaticVariableReference(binding);
|
||||
resolve_error(self, path.span, error);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
_ => {
|
||||
// If anything ends up here entirely resolved,
|
||||
// it's an error. If anything ends up here
|
||||
// partially resolved, that's OK, because it may
|
||||
// be a `T::CONST` that typeck will resolve.
|
||||
if path_res.depth == 0 {
|
||||
resolve_error(
|
||||
self,
|
||||
path.span,
|
||||
ResolutionError::NotAnEnumVariantStructOrConst(
|
||||
&path.segments
|
||||
.last()
|
||||
.unwrap()
|
||||
.identifier
|
||||
.name
|
||||
.as_str())
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
} else {
|
||||
let const_name = path.segments
|
||||
.last()
|
||||
.unwrap()
|
||||
.identifier
|
||||
.name;
|
||||
let traits = self.get_traits_containing_item(const_name);
|
||||
self.trait_map.insert(pattern.id, traits);
|
||||
self.record_def(pattern.id, path_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let Err(false) = self.resolve_path(pat_id, &path, 0, ValueNS) {
|
||||
// No error has been reported, so we need to do this ourselves.
|
||||
fn resolve_pattern_path<ExpectedFn>(&mut self,
|
||||
pat_id: NodeId,
|
||||
qself: Option<&QSelf>,
|
||||
path: &Path,
|
||||
namespace: Namespace,
|
||||
expected_fn: ExpectedFn,
|
||||
expected_what: &'static str)
|
||||
where ExpectedFn: FnOnce(Def) -> bool
|
||||
{
|
||||
let resolution = match self.resolve_possibly_assoc_item(pat_id, qself, path, namespace) {
|
||||
ResolveAttempt(resolution) => {
|
||||
if let Some(resolution) = resolution {
|
||||
if resolution.depth == 0 {
|
||||
if expected_fn(resolution.base_def) {
|
||||
resolution
|
||||
} else {
|
||||
resolve_error(
|
||||
self,
|
||||
path.span,
|
||||
ResolutionError::UnresolvedEnumVariantStructOrConst(
|
||||
&path.segments.last().unwrap().identifier.name.as_str())
|
||||
ResolutionError::PatPathUnexpected(expected_what,
|
||||
resolution.kind_name(), path)
|
||||
);
|
||||
err_path_resolution()
|
||||
}
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
} else {
|
||||
// Not fully resolved associated item `T::A::B::C` or
|
||||
// `<T as Tr>::A::B::C`. If `C` should be resolved in value
|
||||
// namespace then it needs to be added to the trait map.
|
||||
if namespace == ValueNS {
|
||||
let item_name = path.segments.last().unwrap().identifier.name;
|
||||
let traits = self.get_traits_containing_item(item_name);
|
||||
self.trait_map.insert(pat_id, traits);
|
||||
}
|
||||
resolution
|
||||
}
|
||||
visit::walk_path(self, path);
|
||||
} else {
|
||||
if let Err(false) = self.resolve_path(pat_id, path, 0, namespace) {
|
||||
resolve_error(
|
||||
self,
|
||||
path.span,
|
||||
ResolutionError::PatPathUnresolved(expected_what, path)
|
||||
);
|
||||
}
|
||||
err_path_resolution()
|
||||
}
|
||||
}
|
||||
TypecheckRequired => {
|
||||
// `<T>::A::B::C`, resolves exclusively during typechecking.
|
||||
// If `C` should be resolved in value namespace then it needs
|
||||
// to be added to the trait map.
|
||||
if namespace == ValueNS {
|
||||
let item_name = path.segments.last().unwrap().identifier.name;
|
||||
let traits = self.get_traits_containing_item(item_name);
|
||||
self.trait_map.insert(pat_id, traits);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
self.record_def(pat_id, resolution);
|
||||
}
|
||||
|
||||
fn resolve_pattern(&mut self,
|
||||
pat: &Pat,
|
||||
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.
|
||||
let outer_pat_id = pat.id;
|
||||
pat.walk(&mut |pat| {
|
||||
match pat.node {
|
||||
PatKind::Ident(bmode, ref ident, ref opt_pat) => {
|
||||
// First try to resolve the identifier as some existing
|
||||
// entity, then fall back to a fresh binding.
|
||||
let resolution = if let Ok(resolution) = self.resolve_path(pat.id,
|
||||
&Path::from_ident(ident.span, ident.node), 0, ValueNS) {
|
||||
let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
|
||||
bmode != BindingMode::ByValue(Mutability::Immutable);
|
||||
match resolution.base_def {
|
||||
// Def::Err => {
|
||||
// // Just pass it through, the error is already
|
||||
// // reported if it was necessary.
|
||||
// resolution
|
||||
// }
|
||||
Def::Struct(..) | Def::Variant(..) |
|
||||
Def::Const(..) | Def::AssociatedConst(..) if !always_binding => {
|
||||
// A constant, unit variant, etc pattern.
|
||||
resolution
|
||||
}
|
||||
Def::Struct(..) | Def::Variant(..) |
|
||||
Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => {
|
||||
// A fresh binding that shadows something unacceptable.
|
||||
resolve_error(
|
||||
self,
|
||||
ident.span,
|
||||
ResolutionError::BindingShadowsSomethingUnacceptable(
|
||||
pat_src.descr(), resolution.kind_name(), ident.node.name)
|
||||
);
|
||||
err_path_resolution()
|
||||
}
|
||||
Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => {
|
||||
// These entities are explicitly allowed
|
||||
// to be shadowed by fresh bindings.
|
||||
self.fresh_binding(ident, pat.id, outer_pat_id,
|
||||
pat_src, bindings_list)
|
||||
}
|
||||
def => {
|
||||
span_bug!(ident.span, "unexpected definition for an \
|
||||
identifier in pattern {:?}", def);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Fall back to a fresh binding.
|
||||
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings_list)
|
||||
};
|
||||
|
||||
self.record_def(pat.id, resolution);
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(ref path, _, _) => {
|
||||
self.resolve_pattern_path(pat.id, None, path, ValueNS, |def| {
|
||||
match def {
|
||||
Def::Struct(..) | Def::Variant(..) | Def::Err => true,
|
||||
_ => false,
|
||||
}
|
||||
}, "variant or struct");
|
||||
}
|
||||
|
||||
PatKind::Path(ref path) => {
|
||||
self.resolve_pattern_path(pat.id, None, path, ValueNS, |def| {
|
||||
match def {
|
||||
Def::Struct(..) | Def::Variant(..) |
|
||||
Def::Const(..) | Def::AssociatedConst(..) | Def::Err => true,
|
||||
_ => false,
|
||||
}
|
||||
}, "variant, struct or constant");
|
||||
}
|
||||
|
||||
PatKind::QPath(ref qself, ref path) => {
|
||||
// Associated constants only.
|
||||
let resolution = match self.resolve_possibly_assoc_item(pat_id,
|
||||
Some(qself),
|
||||
path,
|
||||
ValueNS) {
|
||||
TypecheckRequired => {
|
||||
// All `<T>::CONST` should end up here, and will
|
||||
// require use of the trait map to resolve
|
||||
// during typechecking.
|
||||
let const_name = path.segments
|
||||
.last()
|
||||
.unwrap()
|
||||
.identifier
|
||||
.name;
|
||||
let traits = self.get_traits_containing_item(const_name);
|
||||
self.trait_map.insert(pattern.id, traits);
|
||||
visit::walk_pat(self, pattern);
|
||||
return true;
|
||||
self.resolve_pattern_path(pat.id, Some(qself), path, ValueNS, |def| {
|
||||
match def {
|
||||
Def::AssociatedConst(..) | Def::Err => true,
|
||||
_ => false,
|
||||
}
|
||||
ResolveAttempt(resolution) => resolution,
|
||||
};
|
||||
if let Some(path_res) = resolution {
|
||||
match path_res.base_def {
|
||||
// All `<T as Trait>::CONST` should end up here, and
|
||||
// have the trait already selected.
|
||||
Def::AssociatedConst(..) => {
|
||||
self.record_def(pattern.id, path_res);
|
||||
}
|
||||
_ => {
|
||||
resolve_error(
|
||||
self,
|
||||
path.span,
|
||||
ResolutionError::NotAnAssociatedConst(
|
||||
&path.segments.last().unwrap().identifier.name.as_str()
|
||||
)
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resolve_error(self,
|
||||
path.span,
|
||||
ResolutionError::UnresolvedAssociatedConst(&path.segments
|
||||
.last()
|
||||
.unwrap()
|
||||
.identifier
|
||||
.name
|
||||
.as_str()));
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
visit::walk_pat(self, pattern);
|
||||
}, "associated constant");
|
||||
}
|
||||
|
||||
PatKind::Struct(ref path, _, _) => {
|
||||
match self.resolve_path(pat_id, path, 0, TypeNS) {
|
||||
Ok(definition) => {
|
||||
self.record_def(pattern.id, definition);
|
||||
self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| {
|
||||
match def {
|
||||
Def::Struct(..) | Def::Variant(..) |
|
||||
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::Err => true,
|
||||
_ => false,
|
||||
}
|
||||
Err(true) => self.record_def(pattern.id, err_path_resolution()),
|
||||
Err(false) => {
|
||||
resolve_error(
|
||||
self,
|
||||
path.span,
|
||||
ResolutionError::DoesNotNameAStruct(
|
||||
&path_names_to_string(path, 0))
|
||||
);
|
||||
self.record_def(pattern.id, err_path_resolution());
|
||||
}
|
||||
}
|
||||
visit::walk_path(self, path);
|
||||
}, "variant, struct or type alias");
|
||||
}
|
||||
|
||||
PatKind::Lit(_) | PatKind::Range(..) => {
|
||||
visit::walk_pat(self, pattern);
|
||||
}
|
||||
|
||||
_ => {
|
||||
// Nothing to do.
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
fn resolve_bare_identifier_pattern(&mut self, ident: ast::Ident, span: Span)
|
||||
-> BareIdentifierPatternResolution<'a> {
|
||||
let binding = match self.resolve_ident_in_lexical_scope(ident, ValueNS, true) {
|
||||
Some(LexicalScopeBinding::Item(binding)) => binding,
|
||||
_ => return BareIdentifierPatternUnresolved,
|
||||
};
|
||||
let def = binding.def().unwrap();
|
||||
|
||||
match def {
|
||||
Def::Variant(..) | Def::Struct(..) => FoundStructOrEnumVariant(def),
|
||||
Def::Const(..) | Def::AssociatedConst(..) => FoundConst(binding, ident.name),
|
||||
Def::Static(..) => {
|
||||
let error = ResolutionError::StaticVariableReference(binding);
|
||||
resolve_error(self, span, error);
|
||||
BareIdentifierPatternUnresolved
|
||||
}
|
||||
_ => BareIdentifierPatternUnresolved,
|
||||
}
|
||||
visit::walk_pat(self, pat);
|
||||
}
|
||||
|
||||
/// Handles paths that may refer to associated items
|
||||
fn resolve_possibly_assoc_item(&mut self,
|
||||
id: NodeId,
|
||||
maybe_qself: Option<&ast::QSelf>,
|
||||
maybe_qself: Option<&QSelf>,
|
||||
path: &Path,
|
||||
namespace: Namespace)
|
||||
-> AssocItemResolveResult {
|
||||
|
@ -2579,13 +2469,14 @@ impl<'a> Resolver<'a> {
|
|||
break;
|
||||
}
|
||||
self.with_no_errors(|this| {
|
||||
resolution = this.resolve_path(id, path, depth, TypeNS).ok();
|
||||
let partial_resolution = this.resolve_path(id, path, depth, TypeNS).ok();
|
||||
if let Some(Def::Mod(..)) = partial_resolution.map(|r| r.base_def) {
|
||||
// Modules cannot have associated items
|
||||
} else {
|
||||
resolution = partial_resolution;
|
||||
}
|
||||
});
|
||||
}
|
||||
if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) {
|
||||
// A module is not a valid type or value.
|
||||
resolution = None;
|
||||
}
|
||||
ResolveAttempt(resolution)
|
||||
}
|
||||
|
||||
|
@ -3171,7 +3062,7 @@ impl<'a> Resolver<'a> {
|
|||
self.visit_expr(subexpression);
|
||||
|
||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
||||
self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
|
||||
self.resolve_pattern(pattern, PatternSource::IfLet, &mut HashMap::new());
|
||||
self.visit_block(if_block);
|
||||
self.value_ribs.pop();
|
||||
|
||||
|
@ -3181,7 +3072,7 @@ impl<'a> Resolver<'a> {
|
|||
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
|
||||
self.visit_expr(subexpression);
|
||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
||||
self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
|
||||
self.resolve_pattern(pattern, PatternSource::WhileLet, &mut HashMap::new());
|
||||
|
||||
self.resolve_labeled_block(label.map(|l| l.node), expr.id, block);
|
||||
|
||||
|
@ -3191,7 +3082,7 @@ impl<'a> Resolver<'a> {
|
|||
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => {
|
||||
self.visit_expr(subexpression);
|
||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
||||
self.resolve_pattern(pattern, LocalIrrefutableMode, &mut HashMap::new());
|
||||
self.resolve_pattern(pattern, PatternSource::For, &mut HashMap::new());
|
||||
|
||||
self.resolve_labeled_block(label.map(|l| l.node), expr.id, block);
|
||||
|
||||
|
@ -3411,20 +3302,6 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn enforce_default_binding_mode(&mut self,
|
||||
pat: &Pat,
|
||||
pat_binding_mode: BindingMode,
|
||||
descr: &str) {
|
||||
match pat_binding_mode {
|
||||
BindingMode::ByValue(_) => {}
|
||||
BindingMode::ByRef(..) => {
|
||||
resolve_error(self,
|
||||
pat.span,
|
||||
ResolutionError::CannotUseRefBindingModeWith(descr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
||||
let (path, id) = match *vis {
|
||||
ast::Visibility::Public => return ty::Visibility::Public,
|
||||
|
|
|
@ -23,5 +23,5 @@ mod bar1 {
|
|||
|
||||
fn main() {
|
||||
assert_eq!(1, bar1::Foo::ID);
|
||||
//~^ERROR associated const `ID` is private
|
||||
//~^ERROR associated constant `ID` is private
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@ mod foo { pub struct bar; }
|
|||
|
||||
fn main() {
|
||||
let bar = 5;
|
||||
//~^ ERROR cannot be named the same
|
||||
//~^ ERROR let bindings cannot shadow structs
|
||||
use foo::bar;
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ use foo::d; //~ NOTE is imported here
|
|||
const a: u8 = 2; //~ NOTE is defined here
|
||||
|
||||
fn main() {
|
||||
let a = 4; //~ ERROR let variables cannot
|
||||
//~^ NOTE cannot be named the same as a const variable
|
||||
let c = 4; //~ ERROR let variables cannot
|
||||
//~^ NOTE cannot be named the same as a const variable
|
||||
let d = 4; //~ ERROR let variables cannot
|
||||
//~^ NOTE cannot be named the same as a const variable
|
||||
let a = 4; //~ ERROR let bindings cannot shadow constants
|
||||
//~^ NOTE cannot be named the same as a constant
|
||||
let c = 4; //~ ERROR let bindings cannot shadow constants
|
||||
//~^ NOTE cannot be named the same as a constant
|
||||
let d = 4; //~ ERROR let bindings cannot shadow constants
|
||||
//~^ NOTE cannot be named the same as a constant
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@ fn main() {
|
|||
// XEmpty1() => () // ERROR unresolved enum variant, struct or const `XEmpty1`
|
||||
// }
|
||||
match e1 {
|
||||
Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1`
|
||||
Empty1(..) => () //~ ERROR unresolved variant or struct `Empty1`
|
||||
}
|
||||
match xe1 {
|
||||
XEmpty1(..) => () //~ ERROR unresolved enum variant, struct or const `XEmpty1`
|
||||
XEmpty1(..) => () //~ ERROR unresolved variant or struct `XEmpty1`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,5 +11,5 @@
|
|||
struct hello(isize);
|
||||
|
||||
fn main() {
|
||||
let hello = 0; //~ERROR cannot be named the same
|
||||
let hello = 0; //~ERROR let bindings cannot shadow structs
|
||||
}
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//error-pattern:unresolved enum variant
|
||||
|
||||
fn main() {
|
||||
// a bug in the parser is allowing this:
|
||||
let a(1) = 13;
|
||||
let a(1) = 13; //~ ERROR unresolved variant or struct `a`
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ fn foo(_: usize) -> Foo { Foo(false) }
|
|||
|
||||
fn main() {
|
||||
match Foo(true) {
|
||||
foo(x) //~ ERROR `foo` is not an enum variant, struct or const
|
||||
foo(x) //~ ERROR expected variant or struct, found function `foo`
|
||||
=> ()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@ mod foo { pub fn bar() {} }
|
|||
|
||||
fn main() {
|
||||
match () {
|
||||
foo::bar => {} //~ ERROR `bar` is not an enum variant, struct or const
|
||||
foo::bar => {} //~ ERROR expected variant, struct or constant, found function `bar`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ extern {
|
|||
fn main() {
|
||||
let boolValue = match 42 {
|
||||
externalValue => true,
|
||||
//~^ ERROR static variables cannot be referenced in a pattern
|
||||
//~^ ERROR match bindings cannot shadow statics
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ enum Foo {
|
|||
|
||||
fn main() {
|
||||
match Foo::Bar(1) {
|
||||
Foo { i } => () //~ ERROR `Foo` does not name a struct or a struct variant
|
||||
Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo`
|
||||
//~^ ERROR `Foo` does not name a struct or a struct variant
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
|
||||
extern crate issue_17718_const_privacy as other;
|
||||
|
||||
use a::B; //~ ERROR: const `B` is private
|
||||
use a::B; //~ ERROR: constant `B` is private
|
||||
use other::{
|
||||
FOO,
|
||||
BAR, //~ ERROR: const `BAR` is private
|
||||
BAR, //~ ERROR: constant `BAR` is private
|
||||
FOO2,
|
||||
};
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ const A3: usize = 1;
|
|||
|
||||
fn main() {
|
||||
match 1 {
|
||||
A1 => {} //~ ERROR: static variables cannot be referenced in a pattern
|
||||
A2 => {} //~ ERROR: static variables cannot be referenced in a pattern
|
||||
A1 => {} //~ ERROR: match bindings cannot shadow statics
|
||||
A2 => {} //~ ERROR: match bindings cannot shadow statics
|
||||
A3 => {}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ pub static X: usize = 1;
|
|||
fn main() {
|
||||
match 1 {
|
||||
self::X => { },
|
||||
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
||||
//~^ ERROR expected variant, struct or constant, found static `X`
|
||||
_ => { },
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,21 +9,21 @@
|
|||
// except according to those terms.
|
||||
|
||||
static foo: i32 = 0;
|
||||
//~^ NOTE static variable defined here
|
||||
//~^ NOTE a static `foo` is defined here
|
||||
|
||||
fn bar(foo: i32) {}
|
||||
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
||||
//~| static variable used in pattern
|
||||
//~^ ERROR function parameters cannot shadow statics
|
||||
//~| cannot be named the same as a static
|
||||
|
||||
mod submod {
|
||||
pub static answer: i32 = 42;
|
||||
}
|
||||
|
||||
use self::submod::answer;
|
||||
//~^ NOTE static variable imported here
|
||||
//~^ NOTE a static `answer` is imported here
|
||||
|
||||
fn question(answer: i32) {}
|
||||
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
||||
//~| static variable used in pattern
|
||||
//~^ ERROR function parameters cannot shadow statics
|
||||
//~| cannot be named the same as a static
|
||||
fn main() {
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
fn main() {
|
||||
match 'a' {
|
||||
char{ch} => true
|
||||
//~^ ERROR `char` does not name a struct or a struct variant
|
||||
//~^ ERROR expected variant, struct or type alias, found builtin type `char`
|
||||
//~| ERROR `char` does not name a struct or a struct variant
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
|
||||
fn main() {
|
||||
match Some(1) {
|
||||
None @ _ => {} //~ ERROR cannot be named the same
|
||||
None @ _ => {} //~ ERROR match bindings cannot shadow variants
|
||||
};
|
||||
const C: u8 = 1;
|
||||
match 1 {
|
||||
C @ 2 => { //~ ERROR cannot be named the same
|
||||
C @ 2 => { //~ ERROR match bindings cannot shadow constant
|
||||
println!("{}", C);
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -14,7 +14,9 @@ fn main() {
|
|||
let u = A { x: 1 }; //~ ERROR `A` does not name a structure
|
||||
let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure
|
||||
match () {
|
||||
A { x: 1 } => {} //~ ERROR `A` does not name a struct
|
||||
u32 { x: 1 } => {} //~ ERROR `u32` does not name a struct
|
||||
A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A`
|
||||
//~^ ERROR `A` does not name a struct or a struct variant
|
||||
u32 { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found builtin type `u32
|
||||
//~^ ERROR `u32` does not name a struct or a struct variant
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@ impl S {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
if let C1(..) = 0 {} //~ ERROR `C1` does not name a tuple variant or a tuple struct
|
||||
if let C1(..) = 0 {} //~ ERROR expected variant or struct, found constant `C1`
|
||||
if let S::C2(..) = 0 {} //~ ERROR `S::C2` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
fn main() {
|
||||
let z = match 3 {
|
||||
x(1) => x(1) //~ ERROR unresolved enum variant
|
||||
x(1) => x(1) //~ ERROR unresolved variant or struct `x`
|
||||
//~^ ERROR unresolved name `x`
|
||||
};
|
||||
assert!(z == 3);
|
||||
|
|
|
@ -19,6 +19,6 @@ impl MyTrait for Foo {}
|
|||
fn main() {
|
||||
match 0u32 {
|
||||
<Foo as MyTrait>::trait_bar => {}
|
||||
//~^ ERROR `trait_bar` is not an associated const
|
||||
//~^ ERROR expected associated constant, found method `trait_bar`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,11 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:cannot be named the same
|
||||
use std::option::*;
|
||||
|
||||
fn main() {
|
||||
let None: isize = 42;
|
||||
let None: isize = 42; //~ ERROR let bindings cannot shadow variants
|
||||
log(debug, None);
|
||||
//~^ ERROR unresolved name `debug`
|
||||
//~| ERROR unresolved name `log`
|
||||
}
|
||||
|
|
|
@ -11,5 +11,5 @@
|
|||
struct foo(usize);
|
||||
|
||||
fn main() {
|
||||
let (foo, _) = (2, 3); //~ ERROR `foo` cannot be named the same as
|
||||
let (foo, _) = (2, 3); //~ ERROR let bindings cannot shadow structs
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ impl S {
|
|||
|
||||
fn main() {
|
||||
match 10 {
|
||||
<S as Tr>::A::f::<u8> => {} //~ ERROR `f` is not an associated const
|
||||
<S as Tr>::A::f::<u8> => {} //~ ERROR associated items in match patterns must be constants
|
||||
0 ... <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ fn main() {
|
|||
// instead of spitting out a custom error about some identifier collisions
|
||||
// (we should allow shadowing)
|
||||
match 4 {
|
||||
a => {} //~ ERROR static variables cannot be referenced in a pattern
|
||||
a => {} //~ ERROR match bindings cannot shadow statics
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ fn mutable_statics() {
|
|||
match (Foo { bar: Some(Direction::North), baz: NewBool(true) }) {
|
||||
Foo { bar: None, baz: NewBool(true) } => (),
|
||||
STATIC_MUT_FOO => (),
|
||||
//~^ ERROR static variables cannot be referenced in a pattern
|
||||
//~^ ERROR match bindings cannot shadow statics
|
||||
Foo { bar: Some(Direction::South), .. } => (),
|
||||
Foo { bar: Some(EAST), .. } => (),
|
||||
Foo { bar: Some(Direction::North), baz: NewBool(true) } => (),
|
||||
|
|
|
@ -14,7 +14,7 @@ mod a {
|
|||
trait A {
|
||||
}
|
||||
|
||||
impl A for a { //~ ERROR type name `a` is undefined or not in scope
|
||||
impl A for a { //~ ERROR expected type, found module
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
Loading…
Add table
Reference in a new issue