Cleanup of some pattern related code
This commit is contained in:
parent
d3c94b25cb
commit
ba419a78f3
@ -945,52 +945,41 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
/// The core driver for walking a pattern; `match_mode` must be
|
||||
/// established up front, e.g. via `determine_pat_move_mode` (see
|
||||
/// also `walk_irrefutable_pat` for patterns that stand alone).
|
||||
fn walk_pat(&mut self,
|
||||
cmt_discr: mc::cmt<'tcx>,
|
||||
pat: &hir::Pat,
|
||||
match_mode: MatchMode) {
|
||||
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr,
|
||||
pat);
|
||||
fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
|
||||
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
|
||||
|
||||
let tcx = &self.tcx();
|
||||
let mc = &self.mc;
|
||||
let infcx = self.mc.infcx;
|
||||
let delegate = &mut self.delegate;
|
||||
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
|
||||
match pat.node {
|
||||
PatKind::Binding(bmode, _, _) => {
|
||||
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
|
||||
cmt_pat,
|
||||
pat,
|
||||
match_mode);
|
||||
if let PatKind::Binding(bmode, _, _) = pat.node {
|
||||
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
|
||||
|
||||
// pat_ty: the type of the binding being produced.
|
||||
let pat_ty = return_if_err!(infcx.node_ty(pat.id));
|
||||
// pat_ty: the type of the binding being produced.
|
||||
let pat_ty = return_if_err!(infcx.node_ty(pat.id));
|
||||
|
||||
// Each match binding is effectively an assignment to the
|
||||
// binding being produced.
|
||||
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
|
||||
tcx.expect_def(pat.id)) {
|
||||
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
|
||||
// Each match binding is effectively an assignment to the
|
||||
// binding being produced.
|
||||
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
|
||||
tcx.expect_def(pat.id)) {
|
||||
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
|
||||
}
|
||||
|
||||
// It is also a borrow or copy/move of the value being matched.
|
||||
match bmode {
|
||||
hir::BindByRef(m) => {
|
||||
if let ty::TyRef(&r, _) = pat_ty.sty {
|
||||
let bk = ty::BorrowKind::from_mutbl(m);
|
||||
delegate.borrow(pat.id, pat.span, cmt_pat, r, bk, RefBinding);
|
||||
}
|
||||
}
|
||||
|
||||
// It is also a borrow or copy/move of the value being matched.
|
||||
match bmode {
|
||||
hir::BindByRef(m) => {
|
||||
if let ty::TyRef(&r, _) = pat_ty.sty {
|
||||
let bk = ty::BorrowKind::from_mutbl(m);
|
||||
delegate.borrow(pat.id, pat.span, cmt_pat,
|
||||
r, bk, RefBinding);
|
||||
}
|
||||
}
|
||||
hir::BindByValue(..) => {
|
||||
let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
|
||||
debug!("walk_pat binding consuming pat");
|
||||
delegate.consume_pat(pat, cmt_pat, mode);
|
||||
}
|
||||
hir::BindByValue(..) => {
|
||||
let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
|
||||
debug!("walk_pat binding consuming pat");
|
||||
delegate.consume_pat(pat, cmt_pat, mode);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}));
|
||||
|
||||
@ -999,72 +988,23 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
// to the above loop's visit of than the bindings that form
|
||||
// the leaves of the pattern tree structure.
|
||||
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
|
||||
match pat.node {
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
match tcx.expect_def(pat.id) {
|
||||
Def::Variant(enum_did, variant_did) => {
|
||||
let downcast_cmt =
|
||||
if tcx.lookup_adt_def(enum_did).is_univariant() {
|
||||
cmt_pat
|
||||
} else {
|
||||
let cmt_pat_ty = cmt_pat.ty;
|
||||
mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
|
||||
};
|
||||
match tcx.expect_def_or_none(pat.id) {
|
||||
Some(Def::Variant(enum_did, variant_did)) => {
|
||||
let downcast_cmt = if tcx.lookup_adt_def(enum_did).is_univariant() {
|
||||
cmt_pat
|
||||
} else {
|
||||
let cmt_pat_ty = cmt_pat.ty;
|
||||
mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
|
||||
};
|
||||
|
||||
debug!("variant downcast_cmt={:?} pat={:?}",
|
||||
downcast_cmt,
|
||||
pat);
|
||||
|
||||
delegate.matched_pat(pat, downcast_cmt, match_mode);
|
||||
}
|
||||
|
||||
Def::Struct(..) | Def::TyAlias(..) => {
|
||||
// A struct (in either the value or type
|
||||
// namespace; we encounter the former on
|
||||
// e.g. patterns for unit structs).
|
||||
|
||||
debug!("struct cmt_pat={:?} pat={:?}",
|
||||
cmt_pat,
|
||||
pat);
|
||||
|
||||
delegate.matched_pat(pat, cmt_pat, match_mode);
|
||||
}
|
||||
|
||||
Def::Const(..) | Def::AssociatedConst(..) => {
|
||||
// This is a leaf (i.e. identifier binding
|
||||
// or constant value to match); thus no
|
||||
// `matched_pat` call.
|
||||
}
|
||||
|
||||
def => {
|
||||
// An enum type should never be in a pattern.
|
||||
// Remaining cases are e.g. Def::Fn, to
|
||||
// which identifiers within patterns
|
||||
// should not resolve. However, we do
|
||||
// encouter this when using the
|
||||
// expr-use-visitor during typeck. So just
|
||||
// ignore it, an error should have been
|
||||
// reported.
|
||||
|
||||
if !tcx.sess.has_errors() {
|
||||
span_bug!(pat.span,
|
||||
"Pattern has unexpected def: {:?} and type {:?}",
|
||||
def,
|
||||
cmt_pat.ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
|
||||
delegate.matched_pat(pat, downcast_cmt, match_mode);
|
||||
}
|
||||
|
||||
PatKind::Wild | PatKind::Tuple(..) | PatKind::Box(..) |
|
||||
PatKind::Ref(..) | PatKind::Lit(..) | PatKind::Range(..) |
|
||||
PatKind::Vec(..) | PatKind::Binding(..) => {
|
||||
// Each of these cases does not
|
||||
// correspond to an enum variant or struct, so we
|
||||
// do not do any `matched_pat` calls for these
|
||||
// cases either.
|
||||
Some(Def::Struct(..)) | Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => {
|
||||
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
|
||||
delegate.matched_pat(pat, cmt_pat, match_mode);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -1050,9 +1050,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// FIXME(#19596) This is a workaround, but there should be a better way to do this
|
||||
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
|
||||
-> McResult<()>
|
||||
where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat),
|
||||
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()>
|
||||
where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat)
|
||||
{
|
||||
// Here, `cmt` is the categorization for the value being
|
||||
// matched and pat is the pattern it is being matched against.
|
||||
@ -1099,21 +1098,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
// step out of sync again. So you'll see below that we always
|
||||
// get the type of the *subpattern* and use that.
|
||||
|
||||
debug!("cat_pattern: {:?} cmt={:?}",
|
||||
pat,
|
||||
cmt);
|
||||
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt);
|
||||
|
||||
(*op)(self, cmt.clone(), pat);
|
||||
|
||||
let opt_def = self.tcx().expect_def_or_none(pat.id);
|
||||
if opt_def == Some(Def::Err) {
|
||||
return Err(());
|
||||
}
|
||||
op(self, cmt.clone(), pat);
|
||||
|
||||
// Note: This goes up here (rather than within the PatKind::TupleStruct arm
|
||||
// alone) because struct patterns can refer to struct types or
|
||||
// to struct variants within enums.
|
||||
let cmt = match opt_def {
|
||||
// alone) because PatKind::Struct can also refer to variants.
|
||||
let cmt = match self.tcx().expect_def_or_none(pat.id) {
|
||||
Some(Def::Err) => return Err(()),
|
||||
Some(Def::Variant(enum_did, variant_did))
|
||||
// univariant enums do not need downcasts
|
||||
if !self.tcx().lookup_adt_def(enum_did).is_univariant() => {
|
||||
@ -1123,68 +1115,35 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
match pat.node {
|
||||
PatKind::Wild => {
|
||||
// _
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(_, ref subpats, ddpos) => {
|
||||
match opt_def {
|
||||
Some(Def::Variant(enum_def, def_id)) => {
|
||||
// variant(x, y, z)
|
||||
let expected_len = self.tcx().lookup_adt_def(enum_def)
|
||||
.variant_with_id(def_id).fields.len();
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
|
||||
|
||||
let subcmt =
|
||||
self.cat_imm_interior(
|
||||
pat, cmt.clone(), subpat_ty,
|
||||
InteriorField(PositionalField(i)));
|
||||
|
||||
self.cat_pattern_(subcmt, &subpat, op)?;
|
||||
}
|
||||
let expected_len = match self.tcx().expect_def(pat.id) {
|
||||
Def::Variant(enum_def, def_id) => {
|
||||
self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
|
||||
}
|
||||
Some(Def::Struct(..)) => {
|
||||
let expected_len = match self.pat_ty(&pat)?.sty {
|
||||
Def::Struct(..) => {
|
||||
match self.pat_ty(&pat)?.sty {
|
||||
ty::TyStruct(adt_def, _) => {
|
||||
adt_def.struct_variant().fields.len()
|
||||
}
|
||||
ref ty => {
|
||||
span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
def => {
|
||||
span_bug!(pat.span, "tuple struct pattern didn't resolve \
|
||||
to variant or struct {:?}", def);
|
||||
}
|
||||
};
|
||||
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
|
||||
let cmt_field =
|
||||
self.cat_imm_interior(
|
||||
pat, cmt.clone(), subpat_ty,
|
||||
InteriorField(PositionalField(i)));
|
||||
self.cat_pattern_(cmt_field, &subpat, op)?;
|
||||
}
|
||||
}
|
||||
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {
|
||||
for subpat in subpats {
|
||||
self.cat_pattern_(cmt.clone(), &subpat, op)?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_bug!(
|
||||
pat.span,
|
||||
"enum pattern didn't resolve to enum or struct {:?}",
|
||||
opt_def);
|
||||
}
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
|
||||
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
|
||||
InteriorField(PositionalField(i)));
|
||||
self.cat_pattern_(subcmt, &subpat, op)?;
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Path(..) | PatKind::QPath(..) | PatKind::Binding(_, _, None) => {
|
||||
// Lone constant, or unit variant or identifier: ignore
|
||||
}
|
||||
|
||||
PatKind::Binding(_, _, Some(ref subpat)) => {
|
||||
self.cat_pattern_(cmt, &subpat, op)?;
|
||||
}
|
||||
|
||||
PatKind::Struct(_, ref field_pats, _) => {
|
||||
// {f1: p1, ..., fN: pN}
|
||||
for fp in field_pats {
|
||||
@ -1194,6 +1153,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Binding(_, _, Some(ref subpat)) => {
|
||||
self.cat_pattern_(cmt, &subpat, op)?;
|
||||
}
|
||||
|
||||
PatKind::Tuple(ref subpats, ddpos) => {
|
||||
// (p1, ..., pN)
|
||||
let expected_len = match self.pat_ty(&pat)?.sty {
|
||||
@ -1202,10 +1165,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
|
||||
let subcmt =
|
||||
self.cat_imm_interior(
|
||||
pat, cmt.clone(), subpat_ty,
|
||||
InteriorField(PositionalField(i)));
|
||||
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
|
||||
InteriorField(PositionalField(i)));
|
||||
self.cat_pattern_(subcmt, &subpat, op)?;
|
||||
}
|
||||
}
|
||||
@ -1215,25 +1176,26 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
// PatKind::Ref since that information is already contained
|
||||
// in the type.
|
||||
let subcmt = self.cat_deref(pat, cmt, 0, None)?;
|
||||
self.cat_pattern_(subcmt, &subpat, op)?;
|
||||
self.cat_pattern_(subcmt, &subpat, op)?;
|
||||
}
|
||||
|
||||
PatKind::Vec(ref before, ref slice, ref after) => {
|
||||
let context = InteriorOffsetKind::Pattern;
|
||||
let elt_cmt = self.cat_index(pat, cmt, context)?;
|
||||
for before_pat in before {
|
||||
self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
|
||||
}
|
||||
if let Some(ref slice_pat) = *slice {
|
||||
self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
|
||||
}
|
||||
for after_pat in after {
|
||||
self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
|
||||
}
|
||||
let context = InteriorOffsetKind::Pattern;
|
||||
let elt_cmt = self.cat_index(pat, cmt, context)?;
|
||||
for before_pat in before {
|
||||
self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
|
||||
}
|
||||
if let Some(ref slice_pat) = *slice {
|
||||
self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
|
||||
}
|
||||
for after_pat in after {
|
||||
self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Lit(_) | PatKind::Range(_, _) => {
|
||||
/*always ok*/
|
||||
PatKind::Path(..) | PatKind::QPath(..) | PatKind::Binding(_, _, None) |
|
||||
PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
|
||||
// always ok
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -784,18 +784,14 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
|
||||
left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
|
||||
let pat = raw_pat(p);
|
||||
match pat.node {
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) =>
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(..) =>
|
||||
match cx.tcx.expect_def(pat.id) {
|
||||
Def::Const(..) | Def::AssociatedConst(..) =>
|
||||
span_bug!(pat.span, "const pattern should've \
|
||||
been rewritten"),
|
||||
Def::Struct(..) | Def::TyAlias(..) => vec![Single],
|
||||
Def::Variant(_, id) => vec![Variant(id)],
|
||||
def => span_bug!(pat.span, "pat_constructors: unexpected \
|
||||
definition {:?}", def),
|
||||
Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => vec![Single],
|
||||
Def::Const(..) | Def::AssociatedConst(..) =>
|
||||
span_bug!(pat.span, "const pattern should've been rewritten"),
|
||||
def => span_bug!(pat.span, "pat_constructors: unexpected definition {:?}", def),
|
||||
},
|
||||
PatKind::QPath(..) =>
|
||||
span_bug!(pat.span, "const pattern should've been rewritten"),
|
||||
PatKind::Lit(ref expr) =>
|
||||
vec![ConstantValue(eval_const_expr(cx.tcx, &expr))],
|
||||
PatKind::Range(ref lo, ref hi) =>
|
||||
@ -899,7 +895,7 @@ pub fn specialize<'a, 'b, 'tcx>(
|
||||
PatKind::Binding(..) | PatKind::Wild =>
|
||||
Some(vec![dummy_pat; arity]),
|
||||
|
||||
PatKind::Path(..) => {
|
||||
PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
match cx.tcx.expect_def(pat_id) {
|
||||
Def::Const(..) | Def::AssociatedConst(..) =>
|
||||
span_bug!(pat_span, "const pattern should've \
|
||||
@ -934,10 +930,6 @@ pub fn specialize<'a, 'b, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::QPath(_, _) => {
|
||||
span_bug!(pat_span, "const pattern should've been rewritten")
|
||||
}
|
||||
|
||||
PatKind::Struct(_, ref pattern_fields, _) => {
|
||||
let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
|
||||
let variant = constructor.variant_for_adt(adt);
|
||||
|
@ -13,7 +13,7 @@ use hair::cx::Cx;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
|
||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::mir::repr::*;
|
||||
use rustc::hir::{self, PatKind};
|
||||
@ -76,9 +76,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
PatternKind::Range { lo: lo, hi: hi }
|
||||
},
|
||||
|
||||
PatKind::Path(..) | PatKind::QPath(..)
|
||||
if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) =>
|
||||
{
|
||||
PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
match self.cx.tcx.expect_def(pat.id) {
|
||||
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
|
||||
let tcx = self.cx.tcx.global_tcx();
|
||||
@ -104,11 +102,9 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
def =>
|
||||
span_bug!(
|
||||
pat.span,
|
||||
"def not a constant: {:?}",
|
||||
def),
|
||||
_ => {
|
||||
self.variant_or_leaf(pat, vec![])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,10 +195,6 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Path(..) => {
|
||||
self.variant_or_leaf(pat, vec![])
|
||||
}
|
||||
|
||||
PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
|
||||
let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
let adt_def = match pat_ty.sty {
|
||||
@ -253,10 +245,6 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
|
||||
self.variant_or_leaf(pat, subpatterns)
|
||||
}
|
||||
|
||||
PatKind::QPath(..) => {
|
||||
span_bug!(pat.span, "unexpanded macro or bad constant etc");
|
||||
}
|
||||
};
|
||||
|
||||
Pattern {
|
||||
@ -325,7 +313,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
Def::Struct(..) | Def::TyAlias(..) => {
|
||||
Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => {
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
}
|
||||
|
||||
|
@ -436,7 +436,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
hir::ExprPath(..) => {
|
||||
|
||||
if let Def::Struct(..) = self.tcx.expect_def(expr.id) {
|
||||
let expr_ty = self.tcx.expr_ty(expr);
|
||||
let def = match expr_ty.sty {
|
||||
|
Loading…
x
Reference in New Issue
Block a user