Turn some impossible definitions into ICEs

This commit is contained in:
Vadim Petrochenkov 2016-09-15 00:51:46 +03:00
parent 75d6522b9a
commit bd291ce21a
18 changed files with 162 additions and 239 deletions

View File

@ -25,29 +25,34 @@ pub enum CtorKind {
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
Fn(DefId),
SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
// Type namespace
Mod(DefId),
Static(DefId, bool /* is_mutbl */),
Const(DefId),
AssociatedConst(DefId),
Local(DefId),
Variant(DefId),
VariantCtor(DefId, CtorKind),
Struct(DefId), // DefId refers to NodeId of the struct itself
Union(DefId),
Enum(DefId),
Variant(DefId),
Trait(DefId),
TyAlias(DefId),
AssociatedTy(DefId),
Trait(DefId),
PrimTy(hir::PrimTy),
TyParam(DefId),
SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
// Value namespace
Fn(DefId),
Const(DefId),
Static(DefId, bool /* is_mutbl */),
StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
VariantCtor(DefId, CtorKind),
Method(DefId),
AssociatedConst(DefId),
Local(DefId),
Upvar(DefId, // def id of closed over local
usize, // index in the freevars list of the closure
ast::NodeId), // expr node that creates the closure
Struct(DefId), // DefId refers to NodeId of the struct itself
StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
Union(DefId),
Label(ast::NodeId),
Method(DefId),
// Both namespaces
Err,
}

View File

@ -44,8 +44,9 @@ use hir;
use hir::map::Definitions;
use hir::map::definitions::DefPathData;
use hir::def_id::{DefIndex, DefId};
use hir::def::{Def, PathResolution};
use hir::def::{Def, CtorKind, PathResolution};
use session::Session;
use lint;
use std::collections::BTreeMap;
use std::iter;
@ -855,10 +856,23 @@ impl<'a> LoweringContext<'a> {
})
}
PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
PatKind::TupleStruct(ref pth, ref pats, ddpos) => {
hir::PatKind::TupleStruct(self.lower_path(pth),
pats.iter().map(|x| self.lower_pat(x)).collect(),
ddpos)
PatKind::TupleStruct(ref path, ref pats, ddpos) => {
match self.resolver.get_resolution(p.id).map(|d| d.base_def) {
Some(def @ Def::StructCtor(_, CtorKind::Const)) |
Some(def @ Def::VariantCtor(_, CtorKind::Const)) => {
// Temporarily lower `UnitVariant(..)` into `UnitVariant`
// for backward compatibility.
let msg = format!("expected tuple struct/variant, found {} `{}`",
def.kind_name(), path);
self.sess.add_lint(
lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
p.id, p.span, msg
);
hir::PatKind::Path(None, self.lower_path(path))
}
_ => hir::PatKind::TupleStruct(self.lower_path(path),
pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
}
}
PatKind::Path(ref opt_qself, ref path) => {
let opt_qself = opt_qself.as_ref().map(|qself| {

View File

@ -58,7 +58,7 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
PatKind::Path(..) |
PatKind::Struct(..) => {
match dm.get(&pat.id).map(|d| d.full_def()) {
Some(Def::Variant(..)) => true,
Some(Def::Variant(..)) | Some(Def::VariantCtor(..)) => true,
_ => false
}
}
@ -173,11 +173,9 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::Struct(..) => {
match dm.get(&p.id) {
Some(&PathResolution { base_def: Def::Variant(id), .. }) |
Some(&PathResolution { base_def: Def::VariantCtor(id, ..), .. }) => {
variants.push(id);
}
match dm.get(&p.id).map(|d| d.full_def()) {
Some(Def::Variant(id)) |
Some(Def::VariantCtor(id, ..)) => variants.push(id),
_ => ()
}
}

View File

@ -106,8 +106,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
self.check_def_id(def.def_id());
}
_ if self.ignore_non_const_paths => (),
Def::PrimTy(_) => (),
Def::SelfTy(..) => (),
Def::PrimTy(..) | Def::SelfTy(..) => (),
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
if let Some(enum_id) = self.tcx.parent_def_id(variant_id) {
self.check_def_id(enum_id);

View File

@ -1021,7 +1021,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
delegate.matched_pat(pat, cmt_pat, match_mode);
}
_ => {}
None | Some(Def::Local(..)) |
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {}
def => bug!("unexpected definition: {:?}", def)
}
}));
}

View File

@ -74,7 +74,7 @@ use hir::def_id::DefId;
use hir::map as ast_map;
use infer::InferCtxt;
use middle::const_qualif::ConstQualif;
use hir::def::Def;
use hir::def::{Def, CtorKind};
use ty::adjustment;
use ty::{self, Ty, TyCtxt};
@ -524,22 +524,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
id, expr_ty, def);
match def {
Def::StructCtor(..) | Def::Union(..) | Def::VariantCtor(..) | Def::Const(..) |
Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
Ok(self.cat_rvalue_node(id, span, expr_ty))
}
Def::Mod(_) |
Def::Trait(_) | Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(_) |
Def::TyParam(..) |
Def::Label(_) | Def::SelfTy(..) |
Def::Variant(..) |
Def::Struct(..) |
Def::AssociatedTy(..) => {
span_bug!(span, "Unexpected definition in \
memory categorization: {:?}", def);
}
Def::Static(_, mutbl) => {
Ok(Rc::new(cmt_ {
id:id,
@ -600,7 +589,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}))
}
Def::Err => bug!("Def::Err in memory categorization")
def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
}
}
@ -1095,11 +1084,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
match pat.node {
PatKind::TupleStruct(_, ref subpats, ddpos) => {
let expected_len = match self.tcx().expect_def(pat.id) {
Def::VariantCtor(def_id, ..) => {
Def::VariantCtor(def_id, CtorKind::Fn) => {
let enum_def = self.tcx().parent_def_id(def_id).unwrap();
self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
}
Def::StructCtor(..) => {
Def::StructCtor(_, CtorKind::Fn) => {
match self.pat_ty(&pat)?.sty {
ty::TyAdt(adt_def, _) => {
adt_def.struct_variant().fields.len()

View File

@ -617,12 +617,8 @@ pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
&Option<DeprecationEntry>)) {
// Paths in import prefixes may have no resolution.
match tcx.expect_def_or_none(id) {
Some(Def::PrimTy(..)) => {}
Some(Def::SelfTy(..)) => {}
Some(def) => {
maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
}
None => {}
None | Some(Def::PrimTy(..)) | Some(Def::SelfTy(..)) => {}
Some(def) => maybe_do_stability_check(tcx, def.def_id(), path.span, cb)
}
}
@ -631,12 +627,7 @@ pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cb: &mut FnMut(DefId, Span,
&Option<&Stability>,
&Option<DeprecationEntry>)) {
match tcx.expect_def(item.node.id) {
Def::PrimTy(..) => {}
def => {
maybe_do_stability_check(tcx, def.def_id(), item.span, cb);
}
}
maybe_do_stability_check(tcx, tcx.expect_def(item.node.id).def_id(), item.span, cb);
}
pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,

View File

@ -913,10 +913,10 @@ pub fn specialize<'a, 'b, 'tcx>(
Def::Const(..) | Def::AssociatedConst(..) =>
span_bug!(pat_span, "const pattern should've \
been rewritten"),
Def::VariantCtor(id, ..) if *constructor != Variant(id) => None,
Def::VariantCtor(..) | Def::StructCtor(..) => Some(Vec::new()),
def => span_bug!(pat_span, "specialize: unexpected \
definition {:?}", def),
Def::VariantCtor(id, CtorKind::Const) if *constructor != Variant(id) => None,
Def::VariantCtor(_, CtorKind::Const) |
Def::StructCtor(_, CtorKind::Const) => Some(Vec::new()),
def => span_bug!(pat_span, "specialize: unexpected definition: {:?}", def),
}
}
@ -925,8 +925,9 @@ pub fn specialize<'a, 'b, 'tcx>(
Def::Const(..) | Def::AssociatedConst(..) =>
span_bug!(pat_span, "const pattern should've \
been rewritten"),
Def::VariantCtor(id, ..) if *constructor != Variant(id) => None,
Def::VariantCtor(..) | Def::StructCtor(..) => {
Def::VariantCtor(id, CtorKind::Fn) if *constructor != Variant(id) => None,
Def::VariantCtor(_, CtorKind::Fn) |
Def::StructCtor(_, CtorKind::Fn) => {
match ddpos {
Some(ddpos) => {
let mut pats: Vec<_> = args[..ddpos].iter().map(|p| {
@ -939,7 +940,7 @@ pub fn specialize<'a, 'b, 'tcx>(
None => Some(args.iter().map(|p| wpat(p)).collect())
}
}
_ => None
def => span_bug!(pat_span, "specialize: unexpected definition: {:?}", def),
}
}

View File

@ -19,7 +19,7 @@ use rustc::hir::map as ast_map;
use rustc::hir::map::blocks::FnLikeNode;
use rustc::middle::cstore::InlinedItem;
use rustc::traits;
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def::{Def, CtorKind, PathResolution};
use rustc::hir::def_id::DefId;
use rustc::hir::pat_util::def_to_path;
use rustc::ty::{self, Ty, TyCtxt};
@ -287,8 +287,8 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
entry.insert(PathResolution::new(def));
}
let path = match def {
Def::StructCtor(def_id, ..) => def_to_path(tcx, def_id),
Def::VariantCtor(variant_did, ..) => def_to_path(tcx, variant_did),
Def::StructCtor(def_id, CtorKind::Fn) |
Def::VariantCtor(def_id, CtorKind::Fn) => def_to_path(tcx, def_id),
Def::Fn(..) | Def::Method(..) => return Ok(P(hir::Pat {
id: expr.id,
node: PatKind::Lit(P(expr.clone())),
@ -326,7 +326,8 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
hir::ExprPath(_, ref path) => {
match tcx.expect_def(expr.id) {
Def::StructCtor(..) | Def::VariantCtor(..) => PatKind::Path(None, path.clone()),
Def::StructCtor(_, CtorKind::Const) |
Def::VariantCtor(_, CtorKind::Const) => PatKind::Path(None, path.clone()),
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
let substs = Some(tcx.node_id_item_substs(expr.id).substs);
let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap();

View File

@ -271,10 +271,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// Tuple-like ADTs are represented as ExprCall. We convert them here.
expr_ty.ty_adt_def().and_then(|adt_def|{
match cx.tcx.expect_def(fun.id) {
Def::VariantCtor(variant_id, ..) => {
Def::VariantCtor(variant_id, CtorKind::Fn) => {
Some((adt_def, adt_def.variant_index_with_id(variant_id)))
},
Def::StructCtor(..) => {
Def::StructCtor(_, CtorKind::Fn) => {
Some((adt_def, 0))
},
_ => None
@ -670,38 +670,25 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// Otherwise there may be def_map borrow conflicts
let def = cx.tcx.expect_def(expr.id);
let def_id = match def {
// A regular function.
Def::Fn(def_id) | Def::Method(def_id) => def_id,
// A regular function, constructor function or a constant.
Def::Fn(def_id) | Def::Method(def_id) |
Def::StructCtor(def_id, CtorKind::Fn) |
Def::VariantCtor(def_id, CtorKind::Fn) => def_id,
Def::StructCtor(_, CtorKind::Const) => match cx.tcx.node_id_to_type(expr.id).sty {
// A unit struct which is used as a value. We return a completely different ExprKind
// here to account for this special case.
Def::VariantCtor(def_id, CtorKind::Fn) |
Def::Const(def_id) | Def::AssociatedConst(def_id) => def_id,
Def::StructCtor(def_id, CtorKind::Const) |
Def::VariantCtor(def_id, CtorKind::Const) => match cx.tcx.node_id_to_type(expr.id).sty {
// A unit struct/variant which is used as a value.
// We return a completely different ExprKind here to account for this special case.
ty::TyAdt(adt_def, substs) => return ExprKind::Adt {
adt_def: adt_def,
variant_index: 0,
variant_index: adt_def.variant_index_with_id(def_id),
substs: substs,
fields: vec![],
base: None
base: None,
},
ref sty => bug!("unexpected sty: {:?}", sty)
},
Def::VariantCtor(def_id, CtorKind::Const) => match cx.tcx.node_id_to_type(expr.id).sty {
// A unit variant, similar special case to the struct case above.
ty::TyAdt(adt_def, substs) => {
let index = adt_def.variant_index_with_id(def_id);
return ExprKind::Adt {
adt_def: adt_def,
substs: substs,
variant_index: index,
fields: vec![],
base: None
};
},
ref sty => bug!("unexpected sty: {:?}", sty)
},
Def::Const(def_id) |
Def::AssociatedConst(def_id) => def_id,
Def::Static(node_id, _) => return ExprKind::StaticRef {
id: node_id,

View File

@ -14,7 +14,7 @@
use rustc::dep_graph::DepNode;
use rustc::hir::map as ast_map;
use rustc::session::{CompileResult, Session};
use rustc::hir::def::{Def, DefMap};
use rustc::hir::def::{Def, CtorKind, DefMap};
use rustc::util::nodemap::NodeMap;
use syntax::ast;
@ -272,7 +272,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
// affect the specific variant used, but we need to check
// the whole enum definition to see what expression that
// might be (if any).
Some(Def::VariantCtor(variant_id, ..)) => {
Some(Def::VariantCtor(variant_id, CtorKind::Const)) => {
if let Some(variant_id) = self.ast_map.as_local_node_id(variant_id) {
let variant = self.ast_map.expect_variant(variant_id);
let enum_id = self.ast_map.get_parent(variant_id);

View File

@ -28,7 +28,7 @@ extern crate syntax_pos;
use rustc::dep_graph::DepNode;
use rustc::hir::{self, PatKind};
use rustc::hir::def::{self, Def};
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, Visitor};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@ -454,36 +454,25 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
}
}
hir::ExprPath(..) => {
if let Def::StructCtor(..) = self.tcx.expect_def(expr.id) {
let expr_ty = self.tcx.expr_ty(expr);
let def = match expr_ty.sty {
ty::TyFnDef(.., &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
output: ty, ..
}), ..}) => ty,
_ => expr_ty
}.ty_adt_def().unwrap();
let private_indexes : Vec<_> = def.struct_variant().fields.iter().enumerate()
.filter(|&(_,f)| {
!f.vis.is_accessible_from(self.curitem, &self.tcx.map)
}).map(|(n,&_)|n).collect();
if let def @ Def::StructCtor(_, CtorKind::Fn) = self.tcx.expect_def(expr.id) {
let adt_def = self.tcx.expect_variant_def(def);
let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
!field.vis.is_accessible_from(self.curitem, &self.tcx.map)
}).map(|(i, _)| i).collect::<Vec<_>>();
if !private_indexes.is_empty() {
let mut error = struct_span_err!(self.tcx.sess, expr.span, E0450,
"cannot invoke tuple struct constructor \
with private fields");
with private fields");
error.span_label(expr.span,
&format!("cannot construct with a private field"));
if let Some(def_id) = self.tcx.map.as_local_node_id(def.did) {
if let Some(hir::map::NodeItem(node)) = self.tcx.map.find(def_id) {
if let hir::Item_::ItemStruct(ref tuple_data, _) = node.node {
for i in private_indexes {
error.span_label(tuple_data.fields()[i].span,
&format!("private field declared here"));
}
if let Some(node_id) = self.tcx.map.as_local_node_id(adt_def.did) {
let node = self.tcx.map.find(node_id);
if let Some(hir::map::NodeStructCtor(vdata)) = node {
for i in private_indexes {
error.span_label(vdata.fields()[i].span,
&format!("private field declared here"));
}
}
}

View File

@ -2786,8 +2786,7 @@ impl<'a> Resolver<'a> {
// Look for a field with the same name in the current self_type.
if let Some(resolution) = self.def_map.get(&node_id) {
match resolution.base_def {
Def::Enum(did) | Def::TyAlias(did) | Def::Union(did) |
Def::Struct(did) | Def::Variant(did) if resolution.depth == 0 => {
Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => {
if let Some(field_names) = self.field_names.get(&did) {
if field_names.iter().any(|&field_name| name == field_name) {
return Field;

View File

@ -271,12 +271,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
}
}
// looks up anything, not just a type
fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
self.tcx.expect_def_or_none(ref_id).and_then(|def| {
match def {
Def::PrimTy(..) => None,
Def::SelfTy(..) => None,
Def::PrimTy(..) | Def::SelfTy(..) => None,
def => Some(def.def_id()),
}
})
@ -303,11 +301,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
}.lower(self.tcx));
}
Def::Struct(..) |
Def::StructCtor(..) |
Def::Variant(..) |
Def::Union(..) |
Def::Enum(..) |
Def::TyAlias(..) |
Def::AssociatedTy(..) |
Def::Trait(_) => {
self.dumper.type_ref(TypeRefData {
span: sub_span.expect("No span found for type ref"),
@ -317,12 +314,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
}.lower(self.tcx));
}
Def::Static(..) |
Def::Const(_) |
Def::AssociatedConst(..) |
Def::Local(..) |
Def::Variant(..) |
Def::VariantCtor(..) |
Def::Upvar(..) => {
Def::Const(..) |
Def::StructCtor(..) |
Def::VariantCtor(..) => {
self.dumper.variable_ref(VariableRefData {
span: sub_span.expect("No span found for var ref"),
ref_id: def_id,
@ -337,10 +331,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
scope: scope
}.lower(self.tcx));
}
Def::Local(..) |
Def::Upvar(..) |
Def::SelfTy(..) |
Def::Label(_) |
Def::TyParam(..) |
Def::Method(..) |
Def::AssociatedTy(..) |
Def::AssociatedConst(..) |
Def::PrimTy(_) |
Def::Err => {
span_bug!(span,
@ -424,7 +422,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
None => {
if let Some(NodeItem(item)) = self.tcx.map.get_if_local(id) {
if let hir::ItemImpl(_, _, _, _, ref ty, _) = item.node {
trait_id = self.lookup_type_ref(ty.id);
trait_id = self.lookup_def_id(ty.id);
}
}
}
@ -807,7 +805,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
};
let trait_ref = &trait_ref.trait_ref;
if let Some(id) = self.lookup_type_ref(trait_ref.ref_id) {
if let Some(id) = self.lookup_def_id(trait_ref.ref_id) {
let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
if !self.span.filter_generated(sub_span, trait_ref.path.span) {
self.dumper.type_ref(TypeRefData {
@ -926,15 +924,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
}
}
}
Def::Local(..) |
Def::Static(..) |
Def::Fn(..) |
Def::Const(..) |
Def::AssociatedConst(..) |
Def::Struct(..) |
Def::Static(..) |
Def::StructCtor(..) |
Def::Variant(..) |
Def::VariantCtor(..) |
Def::Fn(..) => self.write_sub_paths_truncated(path, false),
Def::AssociatedConst(..) |
Def::Local(..) |
Def::Upvar(..) |
Def::Struct(..) |
Def::Union(..) |
Def::Variant(..) |
Def::TyAlias(..) |
Def::AssociatedTy(..) => self.write_sub_paths_truncated(path, false),
_ => {}
}
}
@ -1167,7 +1169,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
match use_item.node {
ast::ViewPathSimple(ident, ref path) => {
let sub_span = self.span.span_for_last_ident(path.span);
let mod_id = match self.lookup_type_ref(item.id) {
let mod_id = match self.lookup_def_id(item.id) {
Some(def_id) => {
let scope = self.cur_scope;
self.process_def_kind(item.id, path.span, sub_span, def_id, scope);
@ -1225,7 +1227,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
for plid in list {
let scope = self.cur_scope;
let id = plid.node.id;
if let Some(def_id) = self.lookup_type_ref(id) {
if let Some(def_id) = self.lookup_def_id(id) {
let span = plid.span;
self.process_def_kind(id, span, Some(span), def_id, scope);
}
@ -1320,7 +1322,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
self.process_macro_use(t.span, t.id);
match t.node {
ast::TyKind::Path(_, ref path) => {
if let Some(id) = self.lookup_type_ref(t.id) {
if let Some(id) = self.lookup_def_id(t.id) {
let sub_span = self.span.sub_span_for_type_name(t.span);
if !self.span.filter_generated(sub_span, t.span) {
self.dumper.type_ref(TypeRefData {
@ -1490,14 +1492,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
}.lower(self.tcx));
}
}
Def::Variant(..) | Def::VariantCtor(..) | Def::Enum(..) |
Def::TyAlias(..) | Def::Struct(..) | Def::StructCtor(..) => {
Def::StructCtor(..) | Def::VariantCtor(..) |
Def::Const(..) | Def::AssociatedConst(..) |
Def::Struct(..) | Def::Variant(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => {
paths_to_process.push((id, p.clone(), Some(ref_kind)))
}
// FIXME(nrc) what are these doing here?
Def::Static(..) |
Def::Const(..) |
Def::AssociatedConst(..) => {}
def => error!("unexpected definition kind when processing collected paths: {:?}",
def),
}

View File

@ -507,7 +507,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
Def::Static(..) |
Def::Const(..) |
Def::AssociatedConst(..) |
Def::Variant(..) |
Def::StructCtor(..) |
Def::VariantCtor(..) => {
Some(Data::VariableRefData(VariableRefData {
name: self.span_utils.snippet(sub_span.unwrap()),
@ -517,10 +517,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
}))
}
Def::Struct(def_id) |
Def::StructCtor(def_id, ..) |
Def::Variant(def_id, ..) |
Def::Union(def_id) |
Def::Enum(def_id) |
Def::TyAlias(def_id) |
Def::AssociatedTy(def_id) |
Def::Trait(def_id) |
Def::TyParam(def_id) => {
Some(Data::TypeRefData(TypeRefData {
@ -574,7 +575,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
qualname: String::new() // FIXME: generate the real qualname
}))
}
_ => None,
Def::PrimTy(..) |
Def::SelfTy(..) |
Def::Label(..) |
Def::Err => None,
}
}

View File

@ -14,7 +14,6 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator;
use rustc::infer::{self, InferOk, TypeOrigin};
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
use check::{FnCtxt, Expectation};
use lint;
use util::nodemap::FnvHashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
@ -557,17 +556,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.check_pat(&pat, tcx.types.err);
}
};
let report_unexpected_def = |def: Def, is_lint| {
let report_unexpected_def = |def: Def| {
let msg = format!("expected tuple struct/variant, found {} `{}`",
def.kind_name(), path);
if is_lint {
tcx.sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
pat.id, pat.span, msg);
} else {
struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
.span_label(pat.span, &format!("not a tuple variant or struct")).emit();
on_error();
}
struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
.span_label(pat.span, &format!("not a tuple variant or struct")).emit();
on_error();
};
// Resolve the path and check the definition for errors.
@ -579,15 +573,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
return tcx.types.err;
}
Def::AssociatedConst(..) | Def::Method(..) => {
report_unexpected_def(def, false);
report_unexpected_def(def);
return tcx.types.err;
}
Def::VariantCtor(_, ctor_kind) | Def::StructCtor(_, ctor_kind) => {
if ctor_kind == CtorKind::Const {
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
// is allowed for backward compatibility.
report_unexpected_def(def, true);
}
Def::VariantCtor(_, CtorKind::Fn) |
Def::StructCtor(_, CtorKind::Fn) => {
tcx.expect_variant_def(def)
}
_ => bug!("unexpected pattern definition: {:?}", def)
@ -595,13 +585,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Type check the path.
let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
let pat_ty = if pat_ty.is_fn() {
// Replace constructor type with constructed type for tuple struct patterns.
tcx.no_late_bound_regions(&pat_ty.fn_ret()).unwrap()
} else {
// Leave the type as is for unit structs (backward compatibility).
pat_ty
};
// Replace constructor type with constructed type for tuple struct patterns.
let pat_ty = tcx.no_late_bound_regions(&pat_ty.fn_ret()).expect("expected fn type");
self.demand_eqtype(pat.span, expected, pat_ty);
// Type check subpatterns.

View File

@ -3245,7 +3245,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Def::Struct(type_did) | Def::Union(type_did) => {
Some((type_did, self.tcx.expect_variant_def(def)))
}
Def::TyAlias(did) => {
Def::TyAlias(did) | Def::AssociatedTy(did) => {
match self.tcx.opt_lookup_item_type(did).map(|scheme| &scheme.ty.sty) {
Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => {
Some((did, adt.struct_variant()))
@ -4064,34 +4064,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
//
// There are basically four cases to consider:
//
// 1. Reference to a *type*, such as a struct or enum:
// 1. Reference to a constructor of enum variant or struct:
//
// mod a { struct Foo<T> { ... } }
//
// Because we don't allow types to be declared within one
// another, a path that leads to a type will always look like
// `a::b::Foo<T>` where `a` and `b` are modules. This implies
// that only the final segment can have type parameters, and
// they are located in the TypeSpace.
//
// *Note:* Generally speaking, references to types don't
// actually pass through this function, but rather the
// `ast_ty_to_ty` function in `astconv`. However, in the case
// of struct patterns (and maybe literals) we do invoke
// `instantiate_value_path` to get the general type of an instance of
// a struct. (In these cases, there are actually no type
// parameters permitted at present, but perhaps we will allow
// them in the future.)
//
// 1b. Reference to an enum variant or tuple-like struct:
//
// struct foo<T>(...)
// enum E<T> { foo(...) }
// struct Foo<T>(...)
// enum E<T> { Foo(...) }
//
// In these cases, the parameters are declared in the type
// space.
//
// 2. Reference to a *fn item*:
// 2. Reference to a fn item or a free constant:
//
// fn foo<T>() { }
//
@ -4100,7 +4081,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// type parameters. However, in this case, those parameters are
// declared on a value, and hence are in the `FnSpace`.
//
// 3. Reference to a *method*:
// 3. Reference to a method or an associated constant:
//
// impl<A> SomeStruct<A> {
// fn foo<B>(...)
@ -4112,15 +4093,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// `SomeStruct::<A>`, contains parameters in TypeSpace, and the
// final segment, `foo::<B>` contains parameters in fn space.
//
// 4. Reference to an *associated const*:
// 4. Reference to a local variable
//
// impl<A> AnotherStruct<A> {
// const FOO: B = BAR;
// }
//
// The path in this case will look like
// `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
// only will have parameters in TypeSpace.
// Local variables can't have any type parameters.
//
// The first step then is to categorize the segments appropriately.
@ -4130,14 +4105,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut type_segment = None;
let mut fn_segment = None;
match def {
// Case 1 and 1b. Reference to a *type* or *enum variant*.
// Case 1. Reference to a struct/variant constructor.
Def::StructCtor(def_id, ..) |
Def::Union(def_id) |
Def::VariantCtor(def_id, ..) |
Def::Enum(def_id) |
Def::TyAlias(def_id) |
Def::AssociatedTy(def_id) |
Def::Trait(def_id) => {
Def::VariantCtor(def_id, ..) => {
// Everything but the final segment should have no
// parameters at all.
let mut generics = self.tcx.lookup_generics(def_id);
@ -4180,19 +4150,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn_segment = Some((segments.last().unwrap(), generics));
}
// Other cases. Various nonsense that really shouldn't show up
// here. If they do, an error will have been reported
// elsewhere. (I hope)
Def::Mod(..) |
Def::PrimTy(..) |
Def::SelfTy(..) |
Def::TyParam(..) |
Def::Local(..) |
Def::Label(..) |
Def::Upvar(..) |
Def::Variant(..) |
Def::Struct(..) |
Def::Err => {}
// Case 4. Local variable, no generics.
Def::Local(..) | Def::Upvar(..) => {}
_ => bug!("unexpected definition: {:?}", def),
}
// In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but

View File

@ -17,7 +17,6 @@ use rustc::hir;
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def_id::DefId;
use rustc::hir::map::DefPathData;
use rustc::hir::print as pprust;
use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::FnvHashSet;
@ -81,9 +80,7 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
record_extern_fqn(cx, did, clean::TypeKind::Function);
clean::FunctionItem(build_external_function(cx, tcx, did))
}
Def::Struct(did)
// If this is a struct constructor, we skip it
if tcx.def_key(did).disambiguated_data.data != DefPathData::StructCtor => {
Def::Struct(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Struct);
ret.extend(build_impls(cx, tcx, did));
clean::StructItem(build_struct(cx, tcx, did))
@ -105,7 +102,10 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
// Assume that the enum type is reexported next to the variant, and
// variants don't show up in documentation specially.
Def::Variant(..) => return Some(Vec::new()),
// Similarly, consider that struct type is reexported next to its constructor.
Def::Variant(..) |
Def::VariantCtor(..) |
Def::StructCtor(..) => return Some(Vec::new()),
Def::Mod(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Module);
clean::ModuleItem(build_module(cx, tcx, did))
@ -114,7 +114,7 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
record_extern_fqn(cx, did, clean::TypeKind::Static);
clean::StaticItem(build_static(cx, tcx, did, mtbl))
}
Def::Const(did) | Def::AssociatedConst(did) => {
Def::Const(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Const);
clean::ConstantItem(build_const(cx, tcx, did))
}
@ -501,10 +501,8 @@ fn build_module<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
let def_id = item.def.def_id();
if tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
if !visited.insert(def_id) { continue }
if let Some(def) = tcx.sess.cstore.describe_def(def_id) {
if let Some(i) = try_inline_def(cx, tcx, def) {
items.extend(i)
}
if let Some(i) = try_inline_def(cx, tcx, item.def) {
items.extend(i)
}
}
}