Skip to content

Commit a63b1df

Browse files
authored
Rollup merge of #40841 - arielb1:immutable-blame, r=pnkfelix
borrowck: consolidate `mut` suggestions This converts all of borrowck's `mut` suggestions to a new `mc::ImmutabilityBlame` API instead of the current mix of various hacks. Fixes #35937. Fixes #40823. Fixes #40859. cc @estebank r? @pnkfelix
2 parents 96dd9a9 + 39011f8 commit a63b1df

23 files changed

+427
-225
lines changed

src/librustc/hir/lowering.rs

+7
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,13 @@ impl<'a> LoweringContext<'a> {
907907
FunctionRetTy::Default(span) => hir::DefaultReturn(span),
908908
},
909909
variadic: decl.variadic,
910+
has_implicit_self: decl.inputs.get(0).map_or(false, |arg| {
911+
match arg.ty.node {
912+
TyKind::ImplicitSelf => true,
913+
TyKind::Rptr(_, ref mt) => mt.ty.node == TyKind::ImplicitSelf,
914+
_ => false
915+
}
916+
})
910917
})
911918
}
912919

src/librustc/hir/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,9 @@ pub struct FnDecl {
13831383
pub inputs: HirVec<P<Ty>>,
13841384
pub output: FunctionRetTy,
13851385
pub variadic: bool,
1386+
/// True if this function has an `self`, `&self` or `&mut self` receiver
1387+
/// (but not a `self: Xxx` one).
1388+
pub has_implicit_self: bool,
13861389
}
13871390

13881391
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]

src/librustc/middle/mem_categorization.rs

+61-79
Original file line numberDiff line numberDiff line change
@@ -194,76 +194,75 @@ pub struct cmt_<'tcx> {
194194

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

197+
pub enum ImmutabilityBlame<'tcx> {
198+
ImmLocal(ast::NodeId),
199+
ClosureEnv(ast::NodeId),
200+
LocalDeref(ast::NodeId),
201+
AdtFieldDeref(&'tcx ty::AdtDef, &'tcx ty::FieldDef)
202+
}
203+
197204
impl<'tcx> cmt_<'tcx> {
198-
pub fn get_def(&self) -> Option<ast::NodeId> {
199-
match self.cat {
200-
Categorization::Deref(ref cmt, ..) |
201-
Categorization::Interior(ref cmt, _) |
202-
Categorization::Downcast(ref cmt, _) => {
203-
if let Categorization::Local(nid) = cmt.cat {
204-
Some(nid)
205-
} else {
206-
None
207-
}
205+
fn resolve_field(&self, field_name: FieldName) -> (&'tcx ty::AdtDef, &'tcx ty::FieldDef)
206+
{
207+
let adt_def = self.ty.ty_adt_def().unwrap_or_else(|| {
208+
bug!("interior cmt {:?} is not an ADT", self)
209+
});
210+
let variant_def = match self.cat {
211+
Categorization::Downcast(_, variant_did) => {
212+
adt_def.variant_with_id(variant_did)
208213
}
209-
_ => None
210-
}
214+
_ => {
215+
assert!(adt_def.is_univariant());
216+
&adt_def.variants[0]
217+
}
218+
};
219+
let field_def = match field_name {
220+
NamedField(name) => variant_def.field_named(name),
221+
PositionalField(idx) => &variant_def.fields[idx]
222+
};
223+
(adt_def, field_def)
211224
}
212225

213-
pub fn get_field(&self, name: ast::Name) -> Option<DefId> {
226+
pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'tcx>> {
214227
match self.cat {
215-
Categorization::Deref(ref cmt, ..) |
216-
Categorization::Interior(ref cmt, _) |
217-
Categorization::Downcast(ref cmt, _) => {
218-
if let Categorization::Local(_) = cmt.cat {
219-
if let ty::TyAdt(def, _) = self.ty.sty {
220-
if def.is_struct() {
221-
return def.struct_variant().find_field_named(name).map(|x| x.did);
228+
Categorization::Deref(ref base_cmt, _, BorrowedPtr(ty::ImmBorrow, _)) |
229+
Categorization::Deref(ref base_cmt, _, Implicit(ty::ImmBorrow, _)) => {
230+
// try to figure out where the immutable reference came from
231+
match base_cmt.cat {
232+
Categorization::Local(node_id) =>
233+
Some(ImmutabilityBlame::LocalDeref(node_id)),
234+
Categorization::Interior(ref base_cmt, InteriorField(field_name)) => {
235+
let (adt_def, field_def) = base_cmt.resolve_field(field_name);
236+
Some(ImmutabilityBlame::AdtFieldDeref(adt_def, field_def))
237+
}
238+
Categorization::Upvar(Upvar { id, .. }) => {
239+
if let NoteClosureEnv(..) = self.note {
240+
Some(ImmutabilityBlame::ClosureEnv(id.closure_expr_id))
241+
} else {
242+
None
222243
}
223244
}
224-
None
225-
} else {
226-
cmt.get_field(name)
245+
_ => None
227246
}
228247
}
229-
_ => None
230-
}
231-
}
232-
233-
pub fn get_field_name(&self) -> Option<ast::Name> {
234-
match self.cat {
235-
Categorization::Interior(_, ref ik) => {
236-
if let InteriorKind::InteriorField(FieldName::NamedField(name)) = *ik {
237-
Some(name)
238-
} else {
239-
None
240-
}
248+
Categorization::Local(node_id) => {
249+
Some(ImmutabilityBlame::ImmLocal(node_id))
241250
}
242-
Categorization::Deref(ref cmt, ..) |
243-
Categorization::Downcast(ref cmt, _) => {
244-
cmt.get_field_name()
251+
Categorization::Rvalue(..) |
252+
Categorization::Upvar(..) |
253+
Categorization::Deref(.., UnsafePtr(..)) => {
254+
// This should not be reachable up to inference limitations.
255+
None
245256
}
246-
_ => None,
247-
}
248-
}
249-
250-
pub fn get_arg_if_immutable(&self, map: &hir_map::Map) -> Option<ast::NodeId> {
251-
match self.cat {
252-
Categorization::Deref(ref cmt, ..) |
253-
Categorization::Interior(ref cmt, _) |
254-
Categorization::Downcast(ref cmt, _) => {
255-
if let Categorization::Local(nid) = cmt.cat {
256-
if let ty::TyAdt(_, _) = self.ty.sty {
257-
if let ty::TyRef(_, ty::TypeAndMut{mutbl: MutImmutable, ..}) = cmt.ty.sty {
258-
return Some(nid);
259-
}
260-
}
261-
None
262-
} else {
263-
cmt.get_arg_if_immutable(map)
264-
}
257+
Categorization::Interior(ref base_cmt, _) |
258+
Categorization::Downcast(ref base_cmt, _) |
259+
Categorization::Deref(ref base_cmt, _, _) => {
260+
base_cmt.immutability_blame()
261+
}
262+
Categorization::StaticItem => {
263+
// Do we want to do something here?
264+
None
265265
}
266-
_ => None
267266
}
268267
}
269268
}
@@ -1282,9 +1281,6 @@ pub enum Aliasability {
12821281
#[derive(Copy, Clone, Debug)]
12831282
pub enum AliasableReason {
12841283
AliasableBorrowed,
1285-
AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env
1286-
AliasableOther,
1287-
UnaliasableImmutable, // Created as needed upon seeing ImmutableUnique
12881284
AliasableStatic,
12891285
AliasableStaticMut,
12901286
}
@@ -1324,23 +1320,13 @@ impl<'tcx> cmt_<'tcx> {
13241320
Categorization::Deref(ref b, _, Implicit(ty::MutBorrow, _)) |
13251321
Categorization::Deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
13261322
Categorization::Deref(ref b, _, Implicit(ty::UniqueImmBorrow, _)) |
1323+
Categorization::Deref(ref b, _, Unique) |
13271324
Categorization::Downcast(ref b, _) |
13281325
Categorization::Interior(ref b, _) => {
13291326
// Aliasability depends on base cmt
13301327
b.freely_aliasable()
13311328
}
13321329

1333-
Categorization::Deref(ref b, _, Unique) => {
1334-
let sub = b.freely_aliasable();
1335-
if b.mutbl.is_mutable() {
1336-
// Aliasability depends on base cmt alone
1337-
sub
1338-
} else {
1339-
// Do not allow mutation through an immutable box.
1340-
ImmutableUnique(Box::new(sub))
1341-
}
1342-
}
1343-
13441330
Categorization::Rvalue(..) |
13451331
Categorization::Local(..) |
13461332
Categorization::Upvar(..) |
@@ -1356,13 +1342,9 @@ impl<'tcx> cmt_<'tcx> {
13561342
}
13571343
}
13581344

1359-
Categorization::Deref(ref base, _, BorrowedPtr(ty::ImmBorrow, _)) |
1360-
Categorization::Deref(ref base, _, Implicit(ty::ImmBorrow, _)) => {
1361-
match base.cat {
1362-
Categorization::Upvar(Upvar{ id, .. }) =>
1363-
FreelyAliasable(AliasableClosure(id.closure_expr_id)),
1364-
_ => FreelyAliasable(AliasableBorrowed)
1365-
}
1345+
Categorization::Deref(_, _, BorrowedPtr(ty::ImmBorrow, _)) |
1346+
Categorization::Deref(_, _, Implicit(ty::ImmBorrow, _)) => {
1347+
FreelyAliasable(AliasableBorrowed)
13661348
}
13671349
}
13681350
}

src/librustc_borrowck/borrowck/gather_loans/mod.rs

-9
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,6 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
188188
// user knows what they're doing in these cases.
189189
Ok(())
190190
}
191-
(mc::Aliasability::ImmutableUnique(_), ty::MutBorrow) => {
192-
bccx.report_aliasability_violation(
193-
borrow_span,
194-
loan_cause,
195-
mc::AliasableReason::UnaliasableImmutable,
196-
cmt);
197-
Err(())
198-
}
199191
(mc::Aliasability::FreelyAliasable(alias_cause), ty::UniqueImmBorrow) |
200192
(mc::Aliasability::FreelyAliasable(alias_cause), ty::MutBorrow) => {
201193
bccx.report_aliasability_violation(
@@ -510,4 +502,3 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
510502
self.move_error_collector.report_potential_errors(self.bccx);
511503
}
512504
}
513-

0 commit comments

Comments
 (0)