Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

borrowck: consolidate mut suggestions #40841

Merged
merged 2 commits into from
Mar 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,13 @@ impl<'a> LoweringContext<'a> {
FunctionRetTy::Default(span) => hir::DefaultReturn(span),
},
variadic: decl.variadic,
has_implicit_self: decl.inputs.get(0).map_or(false, |arg| {
match arg.ty.node {
TyKind::ImplicitSelf => true,
TyKind::Rptr(_, ref mt) => mt.ty.node == TyKind::ImplicitSelf,
_ => false
}
})
})
}

Expand Down
3 changes: 3 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,9 @@ pub struct FnDecl {
pub inputs: HirVec<P<Ty>>,
pub output: FunctionRetTy,
pub variadic: bool,
/// True if this function has an `self`, `&self` or `&mut self` receiver
/// (but not a `self: Xxx` one).
pub has_implicit_self: bool,
}

#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
Expand Down
140 changes: 61 additions & 79 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,76 +194,75 @@ pub struct cmt_<'tcx> {

pub type cmt<'tcx> = Rc<cmt_<'tcx>>;

pub enum ImmutabilityBlame<'tcx> {
ImmLocal(ast::NodeId),
ClosureEnv(ast::NodeId),
LocalDeref(ast::NodeId),
AdtFieldDeref(&'tcx ty::AdtDef, &'tcx ty::FieldDef)
}

impl<'tcx> cmt_<'tcx> {
pub fn get_def(&self) -> Option<ast::NodeId> {
match self.cat {
Categorization::Deref(ref cmt, ..) |
Categorization::Interior(ref cmt, _) |
Categorization::Downcast(ref cmt, _) => {
if let Categorization::Local(nid) = cmt.cat {
Some(nid)
} else {
None
}
fn resolve_field(&self, field_name: FieldName) -> (&'tcx ty::AdtDef, &'tcx ty::FieldDef)
{
let adt_def = self.ty.ty_adt_def().unwrap_or_else(|| {
bug!("interior cmt {:?} is not an ADT", self)
});
let variant_def = match self.cat {
Categorization::Downcast(_, variant_did) => {
adt_def.variant_with_id(variant_did)
}
_ => None
}
_ => {
assert!(adt_def.is_univariant());
&adt_def.variants[0]
}
};
let field_def = match field_name {
NamedField(name) => variant_def.field_named(name),
PositionalField(idx) => &variant_def.fields[idx]
};
(adt_def, field_def)
}

pub fn get_field(&self, name: ast::Name) -> Option<DefId> {
pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'tcx>> {
match self.cat {
Categorization::Deref(ref cmt, ..) |
Categorization::Interior(ref cmt, _) |
Categorization::Downcast(ref cmt, _) => {
if let Categorization::Local(_) = cmt.cat {
if let ty::TyAdt(def, _) = self.ty.sty {
if def.is_struct() {
return def.struct_variant().find_field_named(name).map(|x| x.did);
Categorization::Deref(ref base_cmt, _, BorrowedPtr(ty::ImmBorrow, _)) |
Categorization::Deref(ref base_cmt, _, Implicit(ty::ImmBorrow, _)) => {
// try to figure out where the immutable reference came from
match base_cmt.cat {
Categorization::Local(node_id) =>
Some(ImmutabilityBlame::LocalDeref(node_id)),
Categorization::Interior(ref base_cmt, InteriorField(field_name)) => {
let (adt_def, field_def) = base_cmt.resolve_field(field_name);
Some(ImmutabilityBlame::AdtFieldDeref(adt_def, field_def))
}
Categorization::Upvar(Upvar { id, .. }) => {
if let NoteClosureEnv(..) = self.note {
Some(ImmutabilityBlame::ClosureEnv(id.closure_expr_id))
} else {
None
}
}
None
} else {
cmt.get_field(name)
_ => None
}
}
_ => None
}
}

pub fn get_field_name(&self) -> Option<ast::Name> {
match self.cat {
Categorization::Interior(_, ref ik) => {
if let InteriorKind::InteriorField(FieldName::NamedField(name)) = *ik {
Some(name)
} else {
None
}
Categorization::Local(node_id) => {
Some(ImmutabilityBlame::ImmLocal(node_id))
}
Categorization::Deref(ref cmt, ..) |
Categorization::Downcast(ref cmt, _) => {
cmt.get_field_name()
Categorization::Rvalue(..) |
Categorization::Upvar(..) |
Categorization::Deref(.., UnsafePtr(..)) => {
// This should not be reachable up to inference limitations.
None
}
_ => None,
}
}

pub fn get_arg_if_immutable(&self, map: &hir_map::Map) -> Option<ast::NodeId> {
match self.cat {
Categorization::Deref(ref cmt, ..) |
Categorization::Interior(ref cmt, _) |
Categorization::Downcast(ref cmt, _) => {
if let Categorization::Local(nid) = cmt.cat {
if let ty::TyAdt(_, _) = self.ty.sty {
if let ty::TyRef(_, ty::TypeAndMut{mutbl: MutImmutable, ..}) = cmt.ty.sty {
return Some(nid);
}
}
None
} else {
cmt.get_arg_if_immutable(map)
}
Categorization::Interior(ref base_cmt, _) |
Categorization::Downcast(ref base_cmt, _) |
Categorization::Deref(ref base_cmt, _, _) => {
base_cmt.immutability_blame()
}
Categorization::StaticItem => {
// Do we want to do something here?
None
}
_ => None
}
}
}
Expand Down Expand Up @@ -1282,9 +1281,6 @@ pub enum Aliasability {
#[derive(Copy, Clone, Debug)]
pub enum AliasableReason {
AliasableBorrowed,
AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env
AliasableOther,
UnaliasableImmutable, // Created as needed upon seeing ImmutableUnique
AliasableStatic,
AliasableStaticMut,
}
Expand Down Expand Up @@ -1324,23 +1320,13 @@ impl<'tcx> cmt_<'tcx> {
Categorization::Deref(ref b, _, Implicit(ty::MutBorrow, _)) |
Categorization::Deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
Categorization::Deref(ref b, _, Implicit(ty::UniqueImmBorrow, _)) |
Categorization::Deref(ref b, _, Unique) |
Categorization::Downcast(ref b, _) |
Categorization::Interior(ref b, _) => {
// Aliasability depends on base cmt
b.freely_aliasable()
}

Categorization::Deref(ref b, _, Unique) => {
let sub = b.freely_aliasable();
if b.mutbl.is_mutable() {
// Aliasability depends on base cmt alone
sub
} else {
// Do not allow mutation through an immutable box.
ImmutableUnique(Box::new(sub))
}
}

Categorization::Rvalue(..) |
Categorization::Local(..) |
Categorization::Upvar(..) |
Expand All @@ -1356,13 +1342,9 @@ impl<'tcx> cmt_<'tcx> {
}
}

Categorization::Deref(ref base, _, BorrowedPtr(ty::ImmBorrow, _)) |
Categorization::Deref(ref base, _, Implicit(ty::ImmBorrow, _)) => {
match base.cat {
Categorization::Upvar(Upvar{ id, .. }) =>
FreelyAliasable(AliasableClosure(id.closure_expr_id)),
_ => FreelyAliasable(AliasableBorrowed)
}
Categorization::Deref(_, _, BorrowedPtr(ty::ImmBorrow, _)) |
Categorization::Deref(_, _, Implicit(ty::ImmBorrow, _)) => {
FreelyAliasable(AliasableBorrowed)
}
}
}
Expand Down
9 changes: 0 additions & 9 deletions src/librustc_borrowck/borrowck/gather_loans/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,6 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
// user knows what they're doing in these cases.
Ok(())
}
(mc::Aliasability::ImmutableUnique(_), ty::MutBorrow) => {
bccx.report_aliasability_violation(
borrow_span,
loan_cause,
mc::AliasableReason::UnaliasableImmutable,
cmt);
Err(())
}
(mc::Aliasability::FreelyAliasable(alias_cause), ty::UniqueImmBorrow) |
(mc::Aliasability::FreelyAliasable(alias_cause), ty::MutBorrow) => {
bccx.report_aliasability_violation(
Expand Down Expand Up @@ -510,4 +502,3 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
self.move_error_collector.report_potential_errors(self.bccx);
}
}

Loading