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,
|
depth: depth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn kind_name(&self) -> &'static str {
|
||||||
|
if self.depth != 0 {
|
||||||
|
"associated item"
|
||||||
|
} else {
|
||||||
|
self.base_def.kind_name()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Definition mapping
|
// Definition mapping
|
||||||
|
@ -161,8 +169,8 @@ impl Def {
|
||||||
Def::Struct(..) => "struct",
|
Def::Struct(..) => "struct",
|
||||||
Def::Trait(..) => "trait",
|
Def::Trait(..) => "trait",
|
||||||
Def::Method(..) => "method",
|
Def::Method(..) => "method",
|
||||||
Def::Const(..) => "const",
|
Def::Const(..) => "constant",
|
||||||
Def::AssociatedConst(..) => "associated const",
|
Def::AssociatedConst(..) => "associated constant",
|
||||||
Def::TyParam(..) => "type parameter",
|
Def::TyParam(..) => "type parameter",
|
||||||
Def::PrimTy(..) => "builtin type",
|
Def::PrimTy(..) => "builtin type",
|
||||||
Def::Local(..) => "local variable",
|
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##"
|
E0422: r##"
|
||||||
You are trying to use an identifier that is either undefined or not a struct.
|
You are trying to use an identifier that is either undefined or not a struct.
|
||||||
For instance:
|
For instance:
|
||||||
|
@ -1247,16 +1221,11 @@ impl Foo for i32 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
register_diagnostics! {
|
register_diagnostics! {
|
||||||
// E0153, unused error code
|
|
||||||
// E0157, unused error code
|
|
||||||
E0254, // import conflicts with imported crate in this module
|
E0254, // import conflicts with imported crate in this module
|
||||||
// E0257,
|
|
||||||
// E0258,
|
|
||||||
E0402, // cannot use an outer type parameter in this context
|
E0402, // cannot use an outer type parameter in this context
|
||||||
E0406, // undeclared associated type
|
E0406, // undeclared associated type
|
||||||
// E0410, merged into 408
|
E0418, // X bindings cannot shadow Ys
|
||||||
E0418, // is not an enum variant, struct or const
|
E0419, // unresolved pattern path kind `name`
|
||||||
E0420, // is not an associated const
|
E0420, // expected pattern path kind, found another pattern path kind
|
||||||
E0421, // unresolved associated const
|
|
||||||
E0427, // cannot use `ref` binding mode with ...
|
E0427, // cannot use `ref` binding mode with ...
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ extern crate arena;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc;
|
extern crate rustc;
|
||||||
|
|
||||||
use self::PatternBindingMode::*;
|
|
||||||
use self::Namespace::*;
|
use self::Namespace::*;
|
||||||
use self::ResolveResult::*;
|
use self::ResolveResult::*;
|
||||||
use self::FallbackSuggestion::*;
|
use self::FallbackSuggestion::*;
|
||||||
|
@ -40,7 +39,6 @@ use self::RibKind::*;
|
||||||
use self::UseLexicalScopeFlag::*;
|
use self::UseLexicalScopeFlag::*;
|
||||||
use self::ModulePrefixResult::*;
|
use self::ModulePrefixResult::*;
|
||||||
use self::AssocItemResolveResult::*;
|
use self::AssocItemResolveResult::*;
|
||||||
use self::BareIdentifierPatternResolution::*;
|
|
||||||
use self::ParentLink::*;
|
use self::ParentLink::*;
|
||||||
|
|
||||||
use rustc::hir::map::Definitions;
|
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::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
||||||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
|
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
|
||||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||||
use syntax::ast::{Local, Pat, PatKind, Path};
|
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
|
||||||
use syntax::ast::{PathSegment, PathParameters, TraitItemKind, TraitRef, Ty, TyKind};
|
use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
@ -123,24 +121,10 @@ enum ResolutionError<'a> {
|
||||||
SelfUsedOutsideImplOrTrait,
|
SelfUsedOutsideImplOrTrait,
|
||||||
/// error E0412: use of undeclared
|
/// error E0412: use of undeclared
|
||||||
UseOfUndeclared(&'a str, &'a str, SuggestedCandidates),
|
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
|
/// error E0415: identifier is bound more than once in this parameter list
|
||||||
IdentifierBoundMoreThanOnceInParameterList(&'a str),
|
IdentifierBoundMoreThanOnceInParameterList(&'a str),
|
||||||
/// error E0416: identifier is bound more than once in the same pattern
|
/// error E0416: identifier is bound more than once in the same pattern
|
||||||
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
|
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
|
/// error E0422: does not name a struct
|
||||||
DoesNotNameAStruct(&'a str),
|
DoesNotNameAStruct(&'a str),
|
||||||
/// error E0423: is a struct variant name, but this expression uses it like a function name
|
/// 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
|
/// error E0426: use of undeclared label
|
||||||
UndeclaredLabel(&'a str),
|
UndeclaredLabel(&'a str),
|
||||||
/// error E0427: cannot use `ref` binding mode with ...
|
|
||||||
CannotUseRefBindingModeWith(&'a str),
|
|
||||||
/// error E0429: `self` imports are only allowed within a { } list
|
/// error E0429: `self` imports are only allowed within a { } list
|
||||||
SelfImportsOnlyAllowedWithin,
|
SelfImportsOnlyAllowedWithin,
|
||||||
/// error E0430: `self` import can only appear once in the list
|
/// error E0430: `self` import can only appear once in the list
|
||||||
|
@ -174,6 +156,12 @@ enum ResolutionError<'a> {
|
||||||
CannotCaptureDynamicEnvironmentInFnItem,
|
CannotCaptureDynamicEnvironmentInFnItem,
|
||||||
/// error E0435: attempt to use a non-constant value in a constant
|
/// error E0435: attempt to use a non-constant value in a constant
|
||||||
AttemptToUseNonConstantValueInConstant,
|
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.
|
/// 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.span_label(span, &format!("undefined or not in scope"));
|
||||||
err
|
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) => {
|
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
|
||||||
let mut err = struct_span_err!(resolver.session,
|
let mut err = struct_span_err!(resolver.session,
|
||||||
span,
|
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.span_label(span, &format!("used in a pattern more than once"));
|
||||||
err
|
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) => {
|
ResolutionError::DoesNotNameAStruct(name) => {
|
||||||
struct_span_err!(resolver.session,
|
struct_span_err!(resolver.session,
|
||||||
span,
|
span,
|
||||||
|
@ -455,13 +380,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
||||||
"use of undeclared label `{}`",
|
"use of undeclared label `{}`",
|
||||||
name)
|
name)
|
||||||
}
|
}
|
||||||
ResolutionError::CannotUseRefBindingModeWith(descr) => {
|
|
||||||
struct_span_err!(resolver.session,
|
|
||||||
span,
|
|
||||||
E0427,
|
|
||||||
"cannot use `ref` binding mode with {}",
|
|
||||||
descr)
|
|
||||||
}
|
|
||||||
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
||||||
struct_span_err!(resolver.session,
|
struct_span_err!(resolver.session,
|
||||||
span,
|
span,
|
||||||
|
@ -506,6 +424,37 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
||||||
E0435,
|
E0435,
|
||||||
"attempt to use a non-constant value in a constant")
|
"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.
|
// Map from the name in a pattern to its binding mode.
|
||||||
type BindingMap = HashMap<Name, BindingInfo>;
|
type BindingMap = HashMap<Name, BindingInfo>;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
enum PatternBindingMode {
|
enum PatternSource {
|
||||||
RefutableMode,
|
Match,
|
||||||
LocalIrrefutableMode,
|
IfLet,
|
||||||
ArgumentIrrefutableMode,
|
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)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
@ -709,13 +680,6 @@ enum AssocItemResolveResult {
|
||||||
ResolveAttempt(Option<PathResolution>),
|
ResolveAttempt(Option<PathResolution>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
enum BareIdentifierPatternResolution<'a> {
|
|
||||||
FoundStructOrEnumVariant(Def),
|
|
||||||
FoundConst(&'a NameBinding<'a>, Name),
|
|
||||||
BareIdentifierPatternUnresolved,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// One local scope.
|
/// One local scope.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Rib<'a> {
|
struct Rib<'a> {
|
||||||
|
@ -1814,7 +1778,7 @@ impl<'a> Resolver<'a> {
|
||||||
// Add each argument to the rib.
|
// Add each argument to the rib.
|
||||||
let mut bindings_list = HashMap::new();
|
let mut bindings_list = HashMap::new();
|
||||||
for argument in &declaration.inputs {
|
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);
|
self.visit_ty(&argument.ty);
|
||||||
|
|
||||||
|
@ -2055,7 +2019,7 @@ impl<'a> Resolver<'a> {
|
||||||
walk_list!(self, visit_expr, &local.init);
|
walk_list!(self, visit_expr, &local.init);
|
||||||
|
|
||||||
// Resolve the pattern.
|
// 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.
|
// build a map from pattern identifiers to binding-info's.
|
||||||
|
@ -2124,7 +2088,7 @@ impl<'a> Resolver<'a> {
|
||||||
|
|
||||||
let mut bindings_list = HashMap::new();
|
let mut bindings_list = HashMap::new();
|
||||||
for pattern in &arm.pats {
|
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
|
// 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
|
// This is a path in the type namespace. Walk through scopes
|
||||||
// looking for it.
|
// looking for it.
|
||||||
if let Some(def) = resolution {
|
if let Some(def) = resolution {
|
||||||
// Write the result into the def map.
|
match def.base_def {
|
||||||
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
|
Def::Mod(..) => {
|
||||||
path_names_to_string(path, 0), ty.id, def);
|
self.session.span_err(path.span, "expected type, found module");
|
||||||
self.record_def(ty.id, def);
|
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 {
|
} else {
|
||||||
self.record_def(ty.id, err_path_resolution());
|
self.record_def(ty.id, err_path_resolution());
|
||||||
|
|
||||||
|
@ -2246,312 +2218,230 @@ impl<'a> Resolver<'a> {
|
||||||
visit::walk_ty(self, ty);
|
visit::walk_ty(self, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_pattern(&mut self,
|
fn fresh_binding(&mut self,
|
||||||
pattern: &Pat,
|
ident: &ast::SpannedIdent,
|
||||||
mode: PatternBindingMode,
|
pat_id: NodeId,
|
||||||
// Maps idents to the node ID for the (outermost)
|
outer_pat_id: NodeId,
|
||||||
// pattern that binds them
|
pat_src: PatternSource,
|
||||||
bindings_list: &mut HashMap<Name, NodeId>) {
|
bindings_list: &mut HashMap<Name, NodeId>)
|
||||||
let pat_id = pattern.id;
|
-> PathResolution {
|
||||||
pattern.walk(&mut |pattern| {
|
// Add the binding to the local ribs, if it
|
||||||
match pattern.node {
|
// doesn't already exist in the bindings list. (We
|
||||||
PatKind::Ident(binding_mode, ref path1, ref at_rhs) => {
|
// must not add it if it's in the bindings list
|
||||||
// The meaning of PatKind::Ident with no type parameters
|
// because that breaks the assumptions later
|
||||||
// depends on whether an enum variant or unit-like struct
|
// passes make about or-patterns.)
|
||||||
// with that name is in scope. The probing lookup has to
|
let renamed = mtwt::resolve(ident.node);
|
||||||
// be careful not to emit spurious errors. Only matching
|
let def = match bindings_list.get(&renamed).cloned() {
|
||||||
// patterns (match) can match nullary variants or
|
Some(id) if id == outer_pat_id => {
|
||||||
// unit-like structs. For binding patterns (let
|
// `Variant(a, a)`, error
|
||||||
// and the LHS of @-patterns), matching such a value is
|
resolve_error(
|
||||||
// simply disallowed (since it's rarely what you want).
|
self,
|
||||||
let const_ok = mode == RefutableMode && at_rhs.is_none();
|
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;
|
PathResolution { base_def: def, depth: 0 }
|
||||||
let renamed = mtwt::resolve(ident);
|
}
|
||||||
|
|
||||||
match self.resolve_bare_identifier_pattern(ident, pattern.span) {
|
fn resolve_pattern_path<ExpectedFn>(&mut self,
|
||||||
FoundStructOrEnumVariant(def) if const_ok => {
|
pat_id: NodeId,
|
||||||
debug!("(resolving pattern) resolving `{}` to struct or enum variant",
|
qself: Option<&QSelf>,
|
||||||
renamed);
|
path: &Path,
|
||||||
|
namespace: Namespace,
|
||||||
self.enforce_default_binding_mode(pattern,
|
expected_fn: ExpectedFn,
|
||||||
binding_mode,
|
expected_what: &'static str)
|
||||||
"an enum variant");
|
where ExpectedFn: FnOnce(Def) -> bool
|
||||||
self.record_def(pattern.id,
|
{
|
||||||
PathResolution {
|
let resolution = match self.resolve_possibly_assoc_item(pat_id, qself, path, namespace) {
|
||||||
base_def: def,
|
ResolveAttempt(resolution) => {
|
||||||
depth: 0,
|
if let Some(resolution) = resolution {
|
||||||
});
|
if resolution.depth == 0 {
|
||||||
}
|
if expected_fn(resolution.base_def) {
|
||||||
FoundStructOrEnumVariant(..) => {
|
resolution
|
||||||
resolve_error(
|
} else {
|
||||||
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.
|
|
||||||
resolve_error(
|
resolve_error(
|
||||||
self,
|
self,
|
||||||
path.span,
|
path.span,
|
||||||
ResolutionError::UnresolvedEnumVariantStructOrConst(
|
ResolutionError::PatPathUnexpected(expected_what,
|
||||||
&path.segments.last().unwrap().identifier.name.as_str())
|
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) => {
|
PatKind::QPath(ref qself, ref path) => {
|
||||||
// Associated constants only.
|
self.resolve_pattern_path(pat.id, Some(qself), path, ValueNS, |def| {
|
||||||
let resolution = match self.resolve_possibly_assoc_item(pat_id,
|
match def {
|
||||||
Some(qself),
|
Def::AssociatedConst(..) | Def::Err => true,
|
||||||
path,
|
_ => false,
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
ResolveAttempt(resolution) => resolution,
|
}, "associated constant");
|
||||||
};
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Struct(ref path, _, _) => {
|
PatKind::Struct(ref path, _, _) => {
|
||||||
match self.resolve_path(pat_id, path, 0, TypeNS) {
|
self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| {
|
||||||
Ok(definition) => {
|
match def {
|
||||||
self.record_def(pattern.id, definition);
|
Def::Struct(..) | Def::Variant(..) |
|
||||||
|
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::Err => true,
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
Err(true) => self.record_def(pattern.id, err_path_resolution()),
|
}, "variant, struct or type alias");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Lit(_) | PatKind::Range(..) => {
|
_ => {}
|
||||||
visit::walk_pat(self, pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
// Nothing to do.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_bare_identifier_pattern(&mut self, ident: ast::Ident, span: Span)
|
visit::walk_pat(self, pat);
|
||||||
-> 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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles paths that may refer to associated items
|
/// Handles paths that may refer to associated items
|
||||||
fn resolve_possibly_assoc_item(&mut self,
|
fn resolve_possibly_assoc_item(&mut self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
maybe_qself: Option<&ast::QSelf>,
|
maybe_qself: Option<&QSelf>,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
namespace: Namespace)
|
namespace: Namespace)
|
||||||
-> AssocItemResolveResult {
|
-> AssocItemResolveResult {
|
||||||
|
@ -2579,13 +2469,14 @@ impl<'a> Resolver<'a> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self.with_no_errors(|this| {
|
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)
|
ResolveAttempt(resolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3171,7 +3062,7 @@ impl<'a> Resolver<'a> {
|
||||||
self.visit_expr(subexpression);
|
self.visit_expr(subexpression);
|
||||||
|
|
||||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
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.visit_block(if_block);
|
||||||
self.value_ribs.pop();
|
self.value_ribs.pop();
|
||||||
|
|
||||||
|
@ -3181,7 +3072,7 @@ impl<'a> Resolver<'a> {
|
||||||
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
|
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
|
||||||
self.visit_expr(subexpression);
|
self.visit_expr(subexpression);
|
||||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
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);
|
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) => {
|
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => {
|
||||||
self.visit_expr(subexpression);
|
self.visit_expr(subexpression);
|
||||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
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);
|
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 {
|
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
||||||
let (path, id) = match *vis {
|
let (path, id) = match *vis {
|
||||||
ast::Visibility::Public => return ty::Visibility::Public,
|
ast::Visibility::Public => return ty::Visibility::Public,
|
||||||
|
|
|
@ -23,5 +23,5 @@ mod bar1 {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert_eq!(1, bar1::Foo::ID);
|
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() {
|
fn main() {
|
||||||
let bar = 5;
|
let bar = 5;
|
||||||
//~^ ERROR cannot be named the same
|
//~^ ERROR let bindings cannot shadow structs
|
||||||
use foo::bar;
|
use foo::bar;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ use foo::d; //~ NOTE is imported here
|
||||||
const a: u8 = 2; //~ NOTE is defined here
|
const a: u8 = 2; //~ NOTE is defined here
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = 4; //~ ERROR let variables cannot
|
let a = 4; //~ ERROR let bindings cannot shadow constants
|
||||||
//~^ NOTE cannot be named the same as a const variable
|
//~^ NOTE cannot be named the same as a constant
|
||||||
let c = 4; //~ ERROR let variables cannot
|
let c = 4; //~ ERROR let bindings cannot shadow constants
|
||||||
//~^ NOTE cannot be named the same as a const variable
|
//~^ NOTE cannot be named the same as a constant
|
||||||
let d = 4; //~ ERROR let variables cannot
|
let d = 4; //~ ERROR let bindings cannot shadow constants
|
||||||
//~^ NOTE cannot be named the same as a const variable
|
//~^ NOTE cannot be named the same as a constant
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ fn main() {
|
||||||
// XEmpty1() => () // ERROR unresolved enum variant, struct or const `XEmpty1`
|
// XEmpty1() => () // ERROR unresolved enum variant, struct or const `XEmpty1`
|
||||||
// }
|
// }
|
||||||
match e1 {
|
match e1 {
|
||||||
Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1`
|
Empty1(..) => () //~ ERROR unresolved variant or struct `Empty1`
|
||||||
}
|
}
|
||||||
match xe1 {
|
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);
|
struct hello(isize);
|
||||||
|
|
||||||
fn main() {
|
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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//error-pattern:unresolved enum variant
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// a bug in the parser is allowing this:
|
let a(1) = 13; //~ ERROR unresolved variant or struct `a`
|
||||||
let a(1) = 13;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ fn foo(_: usize) -> Foo { Foo(false) }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match Foo(true) {
|
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() {
|
fn main() {
|
||||||
match () {
|
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() {
|
fn main() {
|
||||||
let boolValue = match 42 {
|
let boolValue = match 42 {
|
||||||
externalValue => true,
|
externalValue => true,
|
||||||
//~^ ERROR static variables cannot be referenced in a pattern
|
//~^ ERROR match bindings cannot shadow statics
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ enum Foo {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match Foo::Bar(1) {
|
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;
|
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::{
|
use other::{
|
||||||
FOO,
|
FOO,
|
||||||
BAR, //~ ERROR: const `BAR` is private
|
BAR, //~ ERROR: constant `BAR` is private
|
||||||
FOO2,
|
FOO2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ const A3: usize = 1;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match 1 {
|
match 1 {
|
||||||
A1 => {} //~ ERROR: static variables cannot be referenced in a pattern
|
A1 => {} //~ ERROR: match bindings cannot shadow statics
|
||||||
A2 => {} //~ ERROR: static variables cannot be referenced in a pattern
|
A2 => {} //~ ERROR: match bindings cannot shadow statics
|
||||||
A3 => {}
|
A3 => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub static X: usize = 1;
|
||||||
fn main() {
|
fn main() {
|
||||||
match 1 {
|
match 1 {
|
||||||
self::X => { },
|
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.
|
// except according to those terms.
|
||||||
|
|
||||||
static foo: i32 = 0;
|
static foo: i32 = 0;
|
||||||
//~^ NOTE static variable defined here
|
//~^ NOTE a static `foo` is defined here
|
||||||
|
|
||||||
fn bar(foo: i32) {}
|
fn bar(foo: i32) {}
|
||||||
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
//~^ ERROR function parameters cannot shadow statics
|
||||||
//~| static variable used in pattern
|
//~| cannot be named the same as a static
|
||||||
|
|
||||||
mod submod {
|
mod submod {
|
||||||
pub static answer: i32 = 42;
|
pub static answer: i32 = 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
use self::submod::answer;
|
use self::submod::answer;
|
||||||
//~^ NOTE static variable imported here
|
//~^ NOTE a static `answer` is imported here
|
||||||
|
|
||||||
fn question(answer: i32) {}
|
fn question(answer: i32) {}
|
||||||
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
//~^ ERROR function parameters cannot shadow statics
|
||||||
//~| static variable used in pattern
|
//~| cannot be named the same as a static
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
match 'a' {
|
match 'a' {
|
||||||
char{ch} => true
|
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() {
|
fn main() {
|
||||||
match Some(1) {
|
match Some(1) {
|
||||||
None @ _ => {} //~ ERROR cannot be named the same
|
None @ _ => {} //~ ERROR match bindings cannot shadow variants
|
||||||
};
|
};
|
||||||
const C: u8 = 1;
|
const C: u8 = 1;
|
||||||
match 1 {
|
match 1 {
|
||||||
C @ 2 => { //~ ERROR cannot be named the same
|
C @ 2 => { //~ ERROR match bindings cannot shadow constant
|
||||||
println!("{}", C);
|
println!("{}", C);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -14,7 +14,9 @@ fn main() {
|
||||||
let u = A { x: 1 }; //~ ERROR `A` does not name a structure
|
let u = A { x: 1 }; //~ ERROR `A` does not name a structure
|
||||||
let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure
|
let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure
|
||||||
match () {
|
match () {
|
||||||
A { x: 1 } => {} //~ ERROR `A` does not name a struct
|
A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A`
|
||||||
u32 { x: 1 } => {} //~ ERROR `u32` does not name a struct
|
//~^ 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() {
|
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
|
if let S::C2(..) = 0 {} //~ ERROR `S::C2` does not name a tuple variant or a tuple struct
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let z = match 3 {
|
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`
|
//~^ ERROR unresolved name `x`
|
||||||
};
|
};
|
||||||
assert!(z == 3);
|
assert!(z == 3);
|
||||||
|
|
|
@ -19,6 +19,6 @@ impl MyTrait for Foo {}
|
||||||
fn main() {
|
fn main() {
|
||||||
match 0u32 {
|
match 0u32 {
|
||||||
<Foo as MyTrait>::trait_bar => {}
|
<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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// error-pattern:cannot be named the same
|
|
||||||
use std::option::*;
|
use std::option::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let None: isize = 42;
|
let None: isize = 42; //~ ERROR let bindings cannot shadow variants
|
||||||
log(debug, None);
|
log(debug, None);
|
||||||
|
//~^ ERROR unresolved name `debug`
|
||||||
|
//~| ERROR unresolved name `log`
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
struct foo(usize);
|
struct foo(usize);
|
||||||
|
|
||||||
fn main() {
|
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() {
|
fn main() {
|
||||||
match 10 {
|
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
|
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
|
// instead of spitting out a custom error about some identifier collisions
|
||||||
// (we should allow shadowing)
|
// (we should allow shadowing)
|
||||||
match 4 {
|
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) }) {
|
match (Foo { bar: Some(Direction::North), baz: NewBool(true) }) {
|
||||||
Foo { bar: None, baz: NewBool(true) } => (),
|
Foo { bar: None, baz: NewBool(true) } => (),
|
||||||
STATIC_MUT_FOO => (),
|
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(Direction::South), .. } => (),
|
||||||
Foo { bar: Some(EAST), .. } => (),
|
Foo { bar: Some(EAST), .. } => (),
|
||||||
Foo { bar: Some(Direction::North), baz: NewBool(true) } => (),
|
Foo { bar: Some(Direction::North), baz: NewBool(true) } => (),
|
||||||
|
|
|
@ -14,7 +14,7 @@ mod a {
|
||||||
trait 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() {
|
fn main() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue