Skip to content

Commit

Permalink
Move the hack with fake partial resolution for <A>::B from typeck to …
Browse files Browse the repository at this point in the history
…resolve
  • Loading branch information
petrochenkov committed Jun 9, 2016
1 parent 91b9dab commit 4c30f64
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 105 deletions.
2 changes: 1 addition & 1 deletion src/librustc/hir/lowering.rs
Expand Up @@ -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,
Expand Down
120 changes: 37 additions & 83 deletions src/librustc_resolve/lib.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -2477,7 +2445,7 @@ impl<'a> Resolver<'a> {
}
});
}
ResolveAttempt(resolution)
resolution
}

/// Skips `path_depth` trailing segments, which is also reflected in the
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 0 additions & 6 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -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)
};
Expand Down
9 changes: 1 addition & 8 deletions src/librustc_typeck/check/_match.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 1 addition & 7 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -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)
};

Expand Down

0 comments on commit 4c30f64

Please sign in to comment.