Move the hack with fake partial resolution for <A>::B from typeck to resolve

This commit is contained in:
Vadim Petrochenkov 2016-06-03 23:15:00 +03:00
parent 91b9dabdeb
commit 4c30f6405c
5 changed files with 40 additions and 105 deletions

View File

@ -1238,7 +1238,7 @@ impl<'a> LoweringContext<'a> {
position: position,
}
});
let rename = if path.segments.len() == 1 {
let rename = if qself.is_none() && path.segments.len() == 1 {
// Only local variables are renamed
match self.resolver.get_resolution(e.id).map(|d| d.full_def()) {
Some(Def::Local(..)) | Some(Def::Upvar(..)) => true,

View File

@ -38,7 +38,6 @@ use self::TypeParameters::*;
use self::RibKind::*;
use self::UseLexicalScopeFlag::*;
use self::ModulePrefixResult::*;
use self::AssocItemResolveResult::*;
use self::ParentLink::*;
use rustc::hir::map::Definitions;
@ -671,15 +670,6 @@ enum ModulePrefixResult<'a> {
PrefixFound(Module<'a>, usize),
}
#[derive(Copy, Clone)]
enum AssocItemResolveResult {
/// Syntax such as `<T>::item`, which can't be resolved until type
/// checking.
TypecheckRequired,
/// We should have been able to resolve the associated item.
ResolveAttempt(Option<PathResolution>),
}
/// One local scope.
#[derive(Debug)]
struct Rib<'a> {
@ -2131,24 +2121,12 @@ impl<'a> Resolver<'a> {
fn resolve_type(&mut self, ty: &Ty) {
match ty.node {
TyKind::Path(ref maybe_qself, ref path) => {
let resolution = match self.resolve_possibly_assoc_item(ty.id,
maybe_qself.as_ref(),
path,
TypeNS) {
// `<T>::a::b::c` is resolved by typeck alone.
TypecheckRequired => {
// Resolve embedded types.
visit::walk_ty(self, ty);
return;
}
ResolveAttempt(resolution) => resolution,
};
// This is a path in the type namespace. Walk through scopes
// looking for it.
if let Some(def) = resolution {
if let Some(def) = self.resolve_possibly_assoc_item(ty.id, maybe_qself.as_ref(),
path, TypeNS) {
match def.base_def {
Def::Mod(..) => {
Def::Mod(..) if def.depth == 0 => {
self.session.span_err(path.span, "expected type, found module");
self.record_def(ty.id, err_path_resolution());
}
@ -2281,54 +2259,40 @@ impl<'a> Resolver<'a> {
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::PatPathUnexpected(expected_what,
resolution.kind_name(), path)
);
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
}
let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id,
qself, path, namespace) {
if resolution.depth == 0 {
if expected_fn(resolution.base_def) {
resolution
} else {
if let Err(false) = self.resolve_path(pat_id, path, 0, namespace) {
resolve_error(
self,
path.span,
ResolutionError::PatPathUnresolved(expected_what, path)
);
}
resolve_error(
self,
path.span,
ResolutionError::PatPathUnexpected(expected_what,
resolution.kind_name(), 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.
} else {
// Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B`
// or `<T>::A::B`. If `B` 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;
resolution
}
} 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()
};
self.record_def(pat_id, resolution);
@ -2444,13 +2408,17 @@ impl<'a> Resolver<'a> {
maybe_qself: Option<&QSelf>,
path: &Path,
namespace: Namespace)
-> AssocItemResolveResult {
-> Option<PathResolution> {
let max_assoc_types;
match maybe_qself {
Some(qself) => {
if qself.position == 0 {
return TypecheckRequired;
// FIXME: Create some fake resolution that can't possibly be a type.
return Some(PathResolution {
base_def: Def::Mod(self.definitions.local_def_id(ast::CRATE_NODE_ID)),
depth: path.segments.len()
});
}
max_assoc_types = path.segments.len() - qself.position;
// Make sure the trait is valid.
@ -2477,7 +2445,7 @@ impl<'a> Resolver<'a> {
}
});
}
ResolveAttempt(resolution)
resolution
}
/// Skips `path_depth` trailing segments, which is also reflected in the
@ -2826,24 +2794,10 @@ impl<'a> Resolver<'a> {
// Next, resolve the node.
match expr.node {
ExprKind::Path(ref maybe_qself, ref path) => {
let resolution = match self.resolve_possibly_assoc_item(expr.id,
maybe_qself.as_ref(),
path,
ValueNS) {
// `<T>::a::b::c` is resolved by typeck alone.
TypecheckRequired => {
let method_name = path.segments.last().unwrap().identifier.name;
let traits = self.get_traits_containing_item(method_name);
self.trait_map.insert(expr.id, traits);
visit::walk_expr(self, expr);
return;
}
ResolveAttempt(resolution) => resolution,
};
// This is a local path in the value namespace. Walk through
// scopes looking for it.
if let Some(path_res) = resolution {
if let Some(path_res) = self.resolve_possibly_assoc_item(expr.id,
maybe_qself.as_ref(), path, ValueNS) {
// Check if struct variant
let is_struct_variant = if let Def::Variant(_, variant_id) = path_res.base_def {
self.structs.contains_key(&variant_id)

View File

@ -1723,12 +1723,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
d
} else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
// Create some fake resolution that can't possibly be a type.
def::PathResolution {
base_def: Def::Mod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
depth: path.segments.len()
}
} else {
span_bug!(ast_ty.span, "unbound path {:?}", ast_ty)
};

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use hir::def::{self, Def};
use hir::def::Def;
use rustc::infer::{self, InferOk, TypeOrigin};
use hir::pat_util::{PatIdMap, pat_id_map};
use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
@ -224,13 +224,6 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
return;
}
d
} else if qself.position == 0 {
// This is just a sentinel for finish_resolving_def_to_ty.
let sentinel = self.tcx.map.local_def_id(ast::CRATE_NODE_ID);
def::PathResolution {
base_def: Def::Mod(sentinel),
depth: path.segments.len()
}
} else {
debug!("unbound path {:?}", pat);
self.write_error(pat.id);

View File

@ -3352,13 +3352,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
d
} else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
// Create some fake resolution that can't possibly be a type.
def::PathResolution {
base_def: Def::Mod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
depth: path.segments.len()
}
} else {
} else {
span_bug!(expr.span, "unbound path {:?}", expr)
};