From 0dd0925f5777122460ee84acf0b6dae76b58b25a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 30 Mar 2015 12:21:20 +1300 Subject: [PATCH] Tidying up and reformatting --- src/librustc/middle/def.rs | 13 ++- src/librustc/middle/privacy.rs | 6 +- src/librustc_resolve/lib.rs | 94 +++++++++---------- src/librustc_typeck/astconv.rs | 149 +++++++++++++++++++------------ src/librustc_typeck/check/mod.rs | 8 +- 5 files changed, 154 insertions(+), 116 deletions(-) diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 1a054c0f464aa..c60bb229be142 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -65,7 +65,7 @@ pub enum Def { /// ::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 @@ impl PathResolution { 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 diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 3a253735f925b..d8efb5655aaab 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -32,7 +32,7 @@ pub type ExternalExports = DefIdSet; /// 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. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ff635a6c46b22..ece83b578d257 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -162,9 +162,12 @@ impl NamespaceResult { } 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, - // 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn with_optional_trait_ref(&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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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()); - } - _ => () - } + if segments.len() <= 1 { + return unqualified_def.map(mk_res); + } - def.map(mk_res) - } else { - 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } 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 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { 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 \ diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0d6ca7430d38e..939142cff1c32 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -140,13 +140,7 @@ pub trait AstConv<'tcx> { span: Span, _trait_ref: Rc>, _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) { - (&ty::ty_param(_), def::DefTyParam(..)) | - (&ty::ty_param(_), def::DefSelfTy(_)) => true, - _ => false - }; + debug!("associated_path_def_to_ty: {}::{}", ty.repr(tcx), token::get_name(assoc_name)); - 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); - }; + 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(_)) => {} + _ => { + 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>, - 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 `::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 ::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 ::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..]); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 16501ec280791..3854d85181039 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3329,7 +3329,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(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_expr_with_unifier<'a, 'tcx, F>(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..]);