Autoderef privacy for fields
This commit is contained in:
parent
d5a91e6958
commit
62d181f474
|
@ -2938,9 +2938,8 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
base: &'tcx hir::Expr,
|
||||
field: &Spanned<ast::Name>) {
|
||||
check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
|
||||
let expr_t = structurally_resolved_type(fcx, expr.span,
|
||||
fcx.expr_ty(base));
|
||||
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
|
||||
let expr_t = structurally_resolved_type(fcx, expr.span, fcx.expr_ty(base));
|
||||
let mut private_candidate = None;
|
||||
let (_, autoderefs, field_ty) = autoderef(fcx,
|
||||
expr.span,
|
||||
expr_t,
|
||||
|
@ -2948,15 +2947,17 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
UnresolvedTypeAction::Error,
|
||||
lvalue_pref,
|
||||
|base_t, _| {
|
||||
match base_t.sty {
|
||||
ty::TyStruct(base_def, substs) => {
|
||||
debug!("struct named {:?}", base_t);
|
||||
base_def.struct_variant()
|
||||
.find_field_named(field.node)
|
||||
.map(|f| fcx.field_ty(expr.span, f, substs))
|
||||
if let ty::TyStruct(base_def, substs) = base_t.sty {
|
||||
debug!("struct named {:?}", base_t);
|
||||
if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
|
||||
let field_ty = fcx.field_ty(expr.span, field, substs);
|
||||
if field.vis == hir::Public || fcx.private_item_is_visible(base_def.did) {
|
||||
return Some(field_ty);
|
||||
}
|
||||
private_candidate = Some((base_def.did, field_ty));
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
None
|
||||
});
|
||||
match field_ty {
|
||||
Some(field_ty) => {
|
||||
|
@ -2967,12 +2968,14 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
None => {}
|
||||
}
|
||||
|
||||
if field.node == special_idents::invalid.name {
|
||||
if let Some((did, field_ty)) = private_candidate {
|
||||
let struct_path = fcx.tcx().item_path_str(did);
|
||||
let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path);
|
||||
fcx.tcx().sess.span_err(expr.span, &msg);
|
||||
fcx.write_ty(expr.id, field_ty);
|
||||
} else if field.node == special_idents::invalid.name {
|
||||
fcx.write_error(expr.id);
|
||||
return;
|
||||
}
|
||||
|
||||
if method::exists(fcx, field.span, field.node, expr_t, expr.id) {
|
||||
} else if method::exists(fcx, field.span, field.node, expr_t, expr.id) {
|
||||
fcx.type_error_struct(field.span,
|
||||
|actual| {
|
||||
format!("attempted to take value of method `{}` on type \
|
||||
|
@ -2983,6 +2986,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
"maybe a `()` to call it is missing? \
|
||||
If not, try an anonymous function")
|
||||
.emit();
|
||||
fcx.write_error(expr.id);
|
||||
} else {
|
||||
let mut err = fcx.type_error_struct(
|
||||
expr.span,
|
||||
|
@ -2998,9 +3002,8 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
suggest_field_names(&mut err, def.struct_variant(), field, vec![]);
|
||||
}
|
||||
err.emit();
|
||||
fcx.write_error(expr.id);
|
||||
}
|
||||
|
||||
fcx.write_error(expr.id);
|
||||
}
|
||||
|
||||
// displays hints about the closest matches in field names
|
||||
|
@ -3035,10 +3038,9 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
base: &'tcx hir::Expr,
|
||||
idx: codemap::Spanned<usize>) {
|
||||
check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
|
||||
let expr_t = structurally_resolved_type(fcx, expr.span,
|
||||
fcx.expr_ty(base));
|
||||
let expr_t = structurally_resolved_type(fcx, expr.span, fcx.expr_ty(base));
|
||||
let mut private_candidate = None;
|
||||
let mut tuple_like = false;
|
||||
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
|
||||
let (_, autoderefs, field_ty) = autoderef(fcx,
|
||||
expr.span,
|
||||
expr_t,
|
||||
|
@ -3046,25 +3048,27 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
UnresolvedTypeAction::Error,
|
||||
lvalue_pref,
|
||||
|base_t, _| {
|
||||
match base_t.sty {
|
||||
ty::TyStruct(base_def, substs) => {
|
||||
tuple_like = base_def.struct_variant().is_tuple_struct();
|
||||
if tuple_like {
|
||||
debug!("tuple struct named {:?}", base_t);
|
||||
base_def.struct_variant()
|
||||
.fields
|
||||
.get(idx.node)
|
||||
.map(|f| fcx.field_ty(expr.span, f, substs))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
let (base_def, substs) = match base_t.sty {
|
||||
ty::TyStruct(base_def, substs) => (base_def, substs),
|
||||
ty::TyTuple(ref v) => {
|
||||
tuple_like = true;
|
||||
if idx.node < v.len() { Some(v[idx.node]) } else { None }
|
||||
return if idx.node < v.len() { Some(v[idx.node]) } else { None }
|
||||
}
|
||||
_ => None
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
tuple_like = base_def.struct_variant().is_tuple_struct();
|
||||
if !tuple_like { return None }
|
||||
|
||||
debug!("tuple struct named {:?}", base_t);
|
||||
if let Some(field) = base_def.struct_variant().fields.get(idx.node) {
|
||||
let field_ty = fcx.field_ty(expr.span, field, substs);
|
||||
if field.vis == hir::Public || fcx.private_item_is_visible(base_def.did) {
|
||||
return Some(field_ty);
|
||||
}
|
||||
private_candidate = Some((base_def.did, field_ty));
|
||||
}
|
||||
None
|
||||
});
|
||||
match field_ty {
|
||||
Some(field_ty) => {
|
||||
|
@ -3074,6 +3078,15 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
if let Some((did, field_ty)) = private_candidate {
|
||||
let struct_path = fcx.tcx().item_path_str(did);
|
||||
let msg = format!("field `{}` of struct `{}` is private", idx.node, struct_path);
|
||||
fcx.tcx().sess.span_err(expr.span, &msg);
|
||||
fcx.write_ty(expr.id, field_ty);
|
||||
return;
|
||||
}
|
||||
|
||||
fcx.type_error_message(
|
||||
expr.span,
|
||||
|actual| {
|
||||
|
|
Loading…
Reference in New Issue