Tidying up and reformatting

This commit is contained in:
Nick Cameron 2015-03-30 12:21:20 +13:00
parent a5479622ea
commit 0dd0925f57
5 changed files with 155 additions and 117 deletions

View file

@ -65,7 +65,7 @@ pub enum Def {
/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~
/// base_def depth = 2
#[derive(Copy, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct PathResolution {
pub base_def: Def,
pub last_private: LastPrivate,
@ -85,6 +85,17 @@ pub fn full_def(&self) -> Def {
pub fn def_id(&self) -> ast::DefId {
self.full_def().def_id()
}
pub fn new(base_def: Def,
last_private: LastPrivate,
depth: usize)
-> PathResolution {
PathResolution {
base_def: base_def,
last_private: last_private,
depth: depth,
}
}
}
// Definition mapping

View file

@ -32,7 +32,7 @@
/// reexporting a public struct doesn't inline the doc).
pub type PublicItems = NodeSet;
#[derive(Copy, Debug)]
#[derive(Copy, Clone, Debug)]
pub enum LastPrivate {
LastMod(PrivateDep),
// `use` directives (imports) can refer to two separate definitions in the
@ -46,14 +46,14 @@ pub enum LastPrivate {
type_used: ImportUse},
}
#[derive(Copy, Debug)]
#[derive(Copy, Clone, Debug)]
pub enum PrivateDep {
AllPublic,
DependsOn(ast::DefId),
}
// How an import is used.
#[derive(Copy, PartialEq, Debug)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ImportUse {
Unused, // The import is not used.
Used, // The import is used.

View file

@ -162,9 +162,12 @@ fn is_unbound(&self) -> bool {
}
enum NameDefinition {
NoNameDefinition, //< The name was unbound.
ChildNameDefinition(Def, LastPrivate), //< The name identifies an immediate child.
ImportNameDefinition(Def, LastPrivate) //< The name identifies an import.
// The name was unbound.
NoNameDefinition,
// The name identifies an immediate child.
ChildNameDefinition(Def, LastPrivate),
// The name identifies an import.
ImportNameDefinition(Def, LastPrivate),
}
impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
@ -795,11 +798,6 @@ pub struct Resolver<'a, 'tcx:'a> {
// The current self type if inside an impl (used for better errors).
current_self_type: Option<Ty>,
// The ident for the keyword "self".
self_name: Name,
// The ident for the non-keyword "Self".
type_self_name: Name,
// The idents for the primitive types.
primitive_type_table: PrimitiveTypeTable,
@ -869,9 +867,6 @@ fn new(session: &'a Session,
current_trait_ref: None,
current_self_type: None,
self_name: special_names::self_,
type_self_name: special_names::type_self,
primitive_type_table: PrimitiveTypeTable::new(),
def_map: RefCell::new(NodeMap()),
@ -1822,7 +1817,7 @@ fn resolve_item(&mut self, item: &Item) {
let mut self_type_rib = Rib::new(ItemRibKind);
// plain insert (no renaming, types are not currently hygienic....)
let name = self.type_self_name;
let name = special_names::type_self;
self_type_rib.bindings.insert(name, DlDef(DefSelfTy(item.id)));
self.type_ribs.push(self_type_rib);
@ -2047,8 +2042,9 @@ fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
fn with_optional_trait_ref<T, F>(&mut self,
opt_trait_ref: Option<&TraitRef>,
f: F) -> T where
F: FnOnce(&mut Resolver) -> T,
f: F)
-> T
where F: FnOnce(&mut Resolver) -> T,
{
let mut new_val = None;
if let Some(trait_ref) = opt_trait_ref {
@ -2585,11 +2581,7 @@ fn resolve_path(&mut self,
let span = path.span;
let segments = &path.segments[..path.segments.len()-path_depth];
let mk_res = |(def, lp)| PathResolution {
base_def: def,
last_private: lp,
depth: path_depth
};
let mk_res = |(def, lp)| PathResolution::new(def, lp, path_depth);
if path.global {
let def = self.resolve_crate_relative_path(span, segments, namespace);
@ -2603,25 +2595,25 @@ fn resolve_path(&mut self,
check_ribs,
span);
if segments.len() > 1 {
let def = self.resolve_module_relative_path(span, segments, namespace);
match (def, unqualified_def) {
(Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
self.session
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
id, span,
"unnecessary qualification".to_string());
}
_ => ()
}
def.map(mk_res)
} else {
unqualified_def.map(mk_res)
if segments.len() <= 1 {
return unqualified_def.map(mk_res);
}
let def = self.resolve_module_relative_path(span, segments, namespace);
match (def, unqualified_def) {
(Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
self.session
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
id, span,
"unnecessary qualification".to_string());
}
_ => {}
}
def.map(mk_res)
}
// resolve a single identifier (used as a varref)
// Resolve a single identifier.
fn resolve_identifier(&mut self,
identifier: Ident,
namespace: Namespace,
@ -2662,8 +2654,7 @@ fn resolve_definition_of_name_in_module(&mut self,
match child_name_bindings.def_for_namespace(namespace) {
Some(def) => {
// Found it. Stop the search here.
let p = child_name_bindings.defined_in_public_namespace(
namespace);
let p = child_name_bindings.defined_in_public_namespace(namespace);
let lp = if p {LastMod(AllPublic)} else {
LastMod(DependsOn(def.def_id()))
};
@ -2734,8 +2725,8 @@ fn resolve_module_relative_path(&mut self,
let containing_module;
let last_private;
let module = self.current_module.clone();
match self.resolve_module_path(module,
let current_module = self.current_module.clone();
match self.resolve_module_path(current_module,
&module_path[..],
UseLexicalScope,
span,
@ -2858,8 +2849,7 @@ fn resolve_identifier_in_local_ribs(&mut self,
match search_result {
Some(DlDef(def)) => {
debug!("(resolving path in local ribs) resolved `{}` to \
local: {:?}",
debug!("(resolving path in local ribs) resolved `{}` to local: {:?}",
token::get_ident(ident),
def);
Some(def)
@ -2904,15 +2894,13 @@ fn resolve_item_by_name_in_lexical_scope(&mut self,
panic!("unexpected indeterminate result");
}
Failed(err) => {
match err {
Some((span, msg)) =>
self.resolve_error(span, &format!("failed to resolve. {}",
msg)),
None => ()
}
debug!("(resolving item path by identifier in lexical scope) \
failed to resolve {}", token::get_name(name));
if let Some((span, msg)) = err {
self.resolve_error(span, &format!("failed to resolve. {}", msg))
}
return None;
}
}
@ -2964,10 +2952,10 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
}
} else {
match this.resolve_module_path(root,
&name_path[..],
UseLexicalScope,
span,
PathSearch) {
&name_path[..],
UseLexicalScope,
span,
PathSearch) {
Success((module, _)) => Some(module),
_ => None
}
@ -3203,8 +3191,8 @@ fn resolve_expr(&mut self, expr: &Expr) {
false // Stop advancing
});
if method_scope && &token::get_name(self.self_name)[..]
== path_name {
if method_scope &&
&token::get_name(special_names::self_)[..] == path_name {
self.resolve_error(
expr.span,
"`self` is not available \

View file

@ -140,13 +140,7 @@ fn projected_ty(&self,
span: Span,
_trait_ref: Rc<ty::TraitRef<'tcx>>,
_item_name: ast::Name)
-> Ty<'tcx>
{
span_err!(self.tcx().sess, span, E0213,
"associated types are not accepted in this context");
self.tcx().types.err
}
-> Ty<'tcx>;
}
pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
@ -924,9 +918,12 @@ fn ast_path_to_ty<'tcx>(
}
};
let substs = ast_path_substs_for_ty(this, rscope,
span, param_mode,
&generics, item_segment);
let substs = ast_path_substs_for_ty(this,
rscope,
span,
param_mode,
&generics,
item_segment);
// FIXME(#12938): This is a hack until we have full support for DST.
if Some(did) == this.tcx().lang_items.owned_box() {
@ -1044,6 +1041,12 @@ fn report_ambiguous_associated_type(tcx: &ty::ctxt,
type_str, trait_str, name);
}
// Create a type from a a path to an associated type.
// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
// and item_segment is the path segment for D. We return a type and a def for
// the whole path.
// Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
// parameter or Self.
fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
span: Span,
ty: Ty<'tcx>,
@ -1052,35 +1055,43 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
-> (Ty<'tcx>, def::Def)
{
let tcx = this.tcx();
check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
let assoc_name = item_segment.identifier.name;
let is_param = match (&ty.sty, ty_path_def) {
debug!("associated_path_def_to_ty: {}::{}", ty.repr(tcx), token::get_name(assoc_name));
check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
// Check that the path prefix given by ty/ty_path_def is a type parameter/Self.
match (&ty.sty, ty_path_def) {
(&ty::ty_param(_), def::DefTyParam(..)) |
(&ty::ty_param(_), def::DefSelfTy(_)) => true,
_ => false
};
let ty_param_node_id = if is_param {
ty_path_def.local_node_id()
} else {
report_ambiguous_associated_type(
tcx, span, &ty.user_string(tcx), "Trait", &token::get_name(assoc_name));
return (tcx.types.err, ty_path_def);
};
(&ty::ty_param(_), def::DefSelfTy(_)) => {}
_ => {
report_ambiguous_associated_type(tcx,
span,
&ty.user_string(tcx),
"Trait",
&token::get_name(assoc_name));
return (tcx.types.err, ty_path_def);
}
}
let ty_param_node_id = ty_path_def.local_node_id();
let ty_param_name = tcx.ty_param_defs.borrow().get(&ty_param_node_id).unwrap().name;
let bounds = match this.get_type_parameter_bounds(span, ty_param_node_id) {
Ok(v) => v,
Err(ErrorReported) => { return (tcx.types.err, ty_path_def); }
Err(ErrorReported) => {
return (tcx.types.err, ty_path_def);
}
};
// ensure the super predicates and stop if we encountered an error
// Ensure the super predicates and stop if we encountered an error.
if bounds.iter().any(|b| this.ensure_super_predicates(span, b.def_id()).is_err()) {
return (this.tcx().types.err, ty_path_def);
}
// Check that there is exactly one way to find an associated type with the
// correct name.
let mut suitable_bounds: Vec<_> =
traits::transitive_bounds(tcx, &bounds)
.filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
@ -1118,7 +1129,8 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
// by type collection, which may be in progress at this point.
match this.tcx().map.expect_item(trait_did.node).node {
ast::ItemTrait(_, _, _, ref trait_items) => {
let item = trait_items.iter().find(|i| i.ident.name == assoc_name)
let item = trait_items.iter()
.find(|i| i.ident.name == assoc_name)
.expect("missing associated type");
ast_util::local_def(item.id)
}
@ -1129,6 +1141,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
let item = trait_items.iter().find(|i| i.name() == assoc_name);
item.expect("missing associated type").def_id()
};
(ty, def::DefAssociatedTy(trait_did, item_did))
}
@ -1150,8 +1163,11 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
ty
} else {
let path_str = ty::item_path_str(tcx, trait_def_id);
report_ambiguous_associated_type(
tcx, span, "Type", &path_str, &token::get_ident(item_segment.identifier));
report_ambiguous_associated_type(tcx,
span,
"Type",
&path_str,
&token::get_ident(item_segment.identifier));
return tcx.types.err;
};
@ -1204,13 +1220,15 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
}
}
// Note that both base_segments and assoc_segments may be empty, although not at
// the same time.
pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
def: &mut def::Def,
def: &def::Def,
opt_self_ty: Option<Ty<'tcx>>,
segments: &[ast::PathSegment],
base_segments: &[ast::PathSegment],
assoc_segments: &[ast::PathSegment])
-> Ty<'tcx> {
let tcx = this.tcx();
@ -1226,52 +1244,64 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
span,
param_mode,
trait_def_id,
segments.last().unwrap(),
base_segments.last().unwrap(),
&mut projection_bounds);
check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
trait_ref_to_object_type(this, rscope, span, trait_ref,
projection_bounds, &[])
check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS);
trait_ref_to_object_type(this,
rscope,
span,
trait_ref,
projection_bounds,
&[])
}
def::DefTy(did, _) | def::DefStruct(did) => {
check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS);
ast_path_to_ty(this, rscope, span,
param_mode, did,
segments.last().unwrap())
base_segments.last().unwrap())
}
def::DefTyParam(space, index, _, name) => {
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
ty::mk_param(tcx, space, index, name)
}
def::DefSelfTy(_) => {
// n.b.: resolve guarantees that the this type only appears in a
// N.b.: resolve guarantees that the this type only appears in a
// trait, which we rely upon in various places when creating
// substs
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
// substs.
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
ty::mk_self_type(tcx)
}
def::DefAssociatedTy(trait_did, _) => {
check_path_args(tcx, &segments[..segments.len()-2], NO_TPS | NO_REGIONS);
qpath_to_ty(this, rscope, span, param_mode,
opt_self_ty, trait_did,
&segments[segments.len()-2],
segments.last().unwrap())
check_path_args(tcx, &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS);
qpath_to_ty(this,
rscope,
span,
param_mode,
opt_self_ty,
trait_did,
&base_segments[base_segments.len()-2],
base_segments.last().unwrap())
}
def::DefMod(id) => {
// Used as sentinel by callers to indicate the `<T>::A::B::C` form.
// FIXME(#22519) This part of the resolution logic should be
// avoided entirely for that form, once we stop needed a Def
// for `associated_path_def_to_ty`.
if segments.is_empty() {
opt_self_ty.expect("missing T in <T>::a::b::c")
} else {
span_err!(tcx.sess, span, E0247, "found module name used as a type: {}",
if !base_segments.is_empty() {
span_err!(tcx.sess,
span,
E0247,
"found module name used as a type: {}",
tcx.map.node_to_string(id.node));
return this.tcx().types.err;
}
opt_self_ty.expect("missing T in <T>::a::b::c")
}
def::DefPrimTy(prim_ty) => {
prim_ty_to_ty(tcx, segments, prim_ty)
prim_ty_to_ty(tcx, base_segments, prim_ty)
}
_ => {
span_err!(tcx.sess, span, E0248,
@ -1282,15 +1312,19 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
// If any associated type segments remain, attempt to resolve them.
let mut ty = base_ty;
let mut def = *def;
for segment in assoc_segments {
if ty.sty == ty::ty_err {
break;
}
// This is pretty bad (it will fail except for T::A and Self::A).
let (a_ty, a_def) = associated_path_def_to_ty(this, span,
ty, *def, segment);
let (a_ty, a_def) = associated_path_def_to_ty(this,
span,
ty,
def,
segment);
ty = a_ty;
*def = a_def;
def = a_def;
}
ty
}
@ -1378,13 +1412,16 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
tcx.sess.span_bug(ast_ty.span,
&format!("unbound path {}", ast_ty.repr(tcx)))
};
let mut def = path_res.base_def;
let def = path_res.base_def;
let base_ty_end = path.segments.len() - path_res.depth;
let opt_self_ty = maybe_qself.as_ref().map(|qself| {
ast_ty_to_ty(this, rscope, &qself.ty)
});
let ty = finish_resolving_def_to_ty(this, rscope, ast_ty.span,
PathParamMode::Explicit, &mut def,
let ty = finish_resolving_def_to_ty(this,
rscope,
ast_ty.span,
PathParamMode::Explicit,
&def,
opt_self_ty,
&path.segments[..base_ty_end],
&path.segments[base_ty_end..]);

View file

@ -3329,7 +3329,7 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
&format!("unbound path {}", expr.repr(tcx)))
};
let mut def = path_res.base_def;
let def = path_res.base_def;
if path_res.depth == 0 {
let (scheme, predicates) =
type_scheme_and_predicates_for_def(fcx, expr.span, def);
@ -3339,9 +3339,11 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
} else {
let ty_segments = path.segments.init();
let base_ty_end = path.segments.len() - path_res.depth;
let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span,
let ty = astconv::finish_resolving_def_to_ty(fcx,
fcx,
expr.span,
PathParamMode::Optional,
&mut def,
&def,
opt_self_ty,
&ty_segments[..base_ty_end],
&ty_segments[base_ty_end..]);