Skip to content

Commit

Permalink
Rewrite check_pat_enum, split it into check_pat_tuple_struct and chec…
Browse files Browse the repository at this point in the history
…k_pat_path

Update definitions in def_map for associated types written in unqualified form (like `Self::Output`)
Cleanup finish_resolving_def_to_ty/resolve_ty_and_def_ufcs
Make VariantDef's available through constructor IDs
  • Loading branch information
petrochenkov committed Jul 8, 2016
1 parent eb32440 commit 2cdd9f1
Show file tree
Hide file tree
Showing 17 changed files with 230 additions and 328 deletions.
9 changes: 0 additions & 9 deletions src/librustc/hir/def.rs
Expand Up @@ -137,15 +137,6 @@ impl Def {
}
}

pub fn variant_def_ids(&self) -> Option<(DefId, DefId)> {
match *self {
Def::Variant(enum_id, var_id) => {
Some((enum_id, var_id))
}
_ => None
}
}

pub fn kind_name(&self) -> &'static str {
match *self {
Def::Fn(..) => "function",
Expand Down
19 changes: 0 additions & 19 deletions src/librustc/hir/pat_util.rs
Expand Up @@ -12,15 +12,12 @@ use hir::def::*;
use hir::def_id::DefId;
use hir::{self, PatKind};
use ty::TyCtxt;
use util::nodemap::FnvHashMap;
use syntax::ast;
use syntax::codemap::Spanned;
use syntax_pos::{Span, DUMMY_SP};

use std::iter::{Enumerate, ExactSizeIterator};

pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>;

pub struct EnumerateAndAdjust<I> {
enumerate: Enumerate<I>,
gap_pos: usize,
Expand Down Expand Up @@ -97,22 +94,6 @@ pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
}
}

// Same as above, except that partially-resolved defs cause `false` to be
// returned instead of a panic.
pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Path(..) | PatKind::QPath(..) => {
match dm.get(&pat.id)
.and_then(|d| if d.depth == 0 { Some(d.base_def) }
else { None } ) {
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
_ => false
}
}
_ => false
}
}

/// Call `f` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub fn pat_bindings<F>(pat: &hir::Pat, mut f: F)
Expand Down
12 changes: 8 additions & 4 deletions src/librustc/ty/context.rs
Expand Up @@ -591,17 +591,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.global_interners.arenas.trait_defs.alloc(def)
}

pub fn insert_adt_def(self, did: DefId, adt_def: ty::AdtDefMaster<'gcx>) {
// this will need a transmute when reverse-variance is removed
if let Some(prev) = self.adt_defs.borrow_mut().insert(did, adt_def) {
bug!("Tried to overwrite interned AdtDef: {:?}", prev)
}
}

pub fn intern_adt_def(self,
did: DefId,
kind: ty::AdtKind,
variants: Vec<ty::VariantDefData<'gcx, 'gcx>>)
-> ty::AdtDefMaster<'gcx> {
let def = ty::AdtDefData::new(self, did, kind, variants);
let interned = self.global_interners.arenas.adt_defs.alloc(def);
// this will need a transmute when reverse-variance is removed
if let Some(prev) = self.adt_defs.borrow_mut().insert(did, interned) {
bug!("Tried to overwrite interned AdtDef: {:?}", prev)
}
self.insert_adt_def(did, interned);
interned
}

Expand Down
14 changes: 14 additions & 0 deletions src/librustc/ty/mod.rs
Expand Up @@ -2454,6 +2454,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.def_map.borrow().get(&id).map(|resolution| resolution.full_def())
}

// Returns `ty::VariantDef` if `def` refers to a struct,
// or variant or their constructors, panics otherwise.
pub fn expect_variant_def(self, def: Def) -> VariantDef<'tcx> {
match def {
Def::Variant(enum_did, did) => {
self.lookup_adt_def(enum_did).variant_with_id(did)
}
Def::Struct(did) => {
self.lookup_adt_def(did).struct_variant()
}
_ => bug!("expect_variant_def used with unexpected def {:?}", def)
}
}

pub fn def_key(self, id: DefId) -> ast_map::DefKey {
if id.is_local() {
self.map.def_key(id)
Expand Down
14 changes: 10 additions & 4 deletions src/librustc_metadata/decoder.rs
Expand Up @@ -471,23 +471,29 @@ pub fn get_adt_def<'a, 'tcx>(intr: &IdentInterner,

let doc = cdata.lookup_item(item_id);
let did = DefId { krate: cdata.cnum, index: item_id };
let mut ctor_did = None;
let (kind, variants) = match item_family(doc) {
Enum => {
(ty::AdtKind::Enum,
get_enum_variants(intr, cdata, doc))
}
Struct(..) => {
let ctor_did =
reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).
map_or(did, |ctor_doc| translated_def_id(cdata, ctor_doc));
// Use separate constructor id for unit/tuple structs and reuse did for braced structs.
ctor_did = reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).map(|ctor_doc| {
translated_def_id(cdata, ctor_doc)
});
(ty::AdtKind::Struct,
vec![get_struct_variant(intr, cdata, doc, ctor_did)])
vec![get_struct_variant(intr, cdata, doc, ctor_did.unwrap_or(did))])
}
_ => bug!("get_adt_def called on a non-ADT {:?} - {:?}",
item_family(doc), did)
};

let adt = tcx.intern_adt_def(did, kind, variants);
if let Some(ctor_did) = ctor_did {
// Make adt definition available through constructor id as well.
tcx.insert_adt_def(ctor_did, adt);
}

// this needs to be done *after* the variant is interned,
// to support recursive structures
Expand Down
80 changes: 40 additions & 40 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -53,7 +53,7 @@ use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
use rustc_const_eval::EvalHint::UncheckedExprHint;
use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
use hir::{self, SelfKind};
use hir::def::{self, Def};
use hir::def::{Def, PathResolution};
use hir::def_id::DefId;
use hir::print as pprust;
use middle::resolve_lifetime as rl;
Expand Down Expand Up @@ -1327,7 +1327,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
};

if self.ensure_super_predicates(span, trait_did).is_err() {
return (tcx.types.err, ty_path_def);
return (tcx.types.err, Def::Err);
}

let candidates: Vec<ty::PolyTraitRef> =
Expand All @@ -1341,7 +1341,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
&assoc_name.as_str(),
span) {
Ok(bound) => bound,
Err(ErrorReported) => return (tcx.types.err, ty_path_def),
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
(&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
Expand All @@ -1351,7 +1351,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
assoc_name,
span) {
Ok(bound) => bound,
Err(ErrorReported) => return (tcx.types.err, ty_path_def),
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
(&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
Expand All @@ -1361,15 +1361,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
assoc_name,
span) {
Ok(bound) => bound,
Err(ErrorReported) => return (tcx.types.err, ty_path_def),
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
_ => {
self.report_ambiguous_associated_type(span,
&ty.to_string(),
"Trait",
&assoc_name.as_str());
return (tcx.types.err, ty_path_def);
return (tcx.types.err, Def::Err);
}
};

Expand Down Expand Up @@ -1574,45 +1574,46 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
}

// Note that both base_segments and assoc_segments may be empty, although not at
// the same time.
// Resolve possibly associated type path into a type and final definition.
// Note that both base_segments and assoc_segments may be empty, although not at same time.
pub fn finish_resolving_def_to_ty(&self,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
mut def: Def,
base_def: Def,
opt_self_ty: Option<Ty<'tcx>>,
base_path_ref_id: ast::NodeId,
base_segments: &[hir::PathSegment],
assoc_segments: &[hir::PathSegment])
-> (Ty<'tcx>, Def) {
debug!("finish_resolving_def_to_ty(def={:?}, \
// Convert the base type.
debug!("finish_resolving_def_to_ty(base_def={:?}, \
base_segments={:?}, \
assoc_segments={:?})",
def,
base_def,
base_segments,
assoc_segments);
let mut ty = self.base_def_to_ty(rscope,
span,
param_mode,
def,
opt_self_ty,
base_path_ref_id,
base_segments);
debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", ty);
let base_ty = self.base_def_to_ty(rscope,
span,
param_mode,
base_def,
opt_self_ty,
base_path_ref_id,
base_segments);
debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);

// If any associated type segments remain, attempt to resolve them.
let (mut ty, mut def) = (base_ty, base_def);
for segment in assoc_segments {
debug!("finish_resolving_def_to_ty: segment={:?}", segment);
if ty.sty == ty::TyError {
// This is pretty bad (it will fail except for T::A and Self::A).
let (new_ty, new_def) = self.associated_path_def_to_ty(span, ty, def, segment);
ty = new_ty;
def = new_def;

if def == Def::Err {
break;
}
// This is pretty bad (it will fail except for T::A and Self::A).
let (a_ty, a_def) = self.associated_path_def_to_ty(span,
ty,
def,
segment);
ty = a_ty;
def = a_def;
}
(ty, def)
}
Expand Down Expand Up @@ -1719,23 +1720,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
hir::TyPath(ref maybe_qself, ref path) => {
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
let path_res = tcx.expect_resolution(ast_ty.id);
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| {
self.ast_ty_to_ty(rscope, &qself.ty)
});
let (ty, _def) = self.finish_resolving_def_to_ty(rscope,
ast_ty.span,
PathParamMode::Explicit,
def,
opt_self_ty,
ast_ty.id,
&path.segments[..base_ty_end],
&path.segments[base_ty_end..]);

if path_res.depth != 0 && ty.sty != ty::TyError {
// Write back the new resolution.
tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution::new(def));
let (ty, def) = self.finish_resolving_def_to_ty(rscope,
ast_ty.span,
PathParamMode::Explicit,
path_res.base_def,
opt_self_ty,
ast_ty.id,
&path.segments[..base_ty_end],
&path.segments[base_ty_end..]);

// Write back the new resolution.
if path_res.depth != 0 {
tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
}

ty
Expand Down

0 comments on commit 2cdd9f1

Please sign in to comment.