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

remove notion of Implicit derefs from mem-cat #51235

Merged
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
11 changes: 9 additions & 2 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,17 +837,24 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
/// 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);
debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat);

let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| {
if let PatKind::Binding(_, canonical_id, ..) = pat.node {
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
debug!(
"walk_pat: binding cmt_pat={:?} pat={:?} match_mode={:?}",
cmt_pat,
pat,
match_mode,
);
let bm = *mc.tables.pat_binding_modes().get(pat.hir_id)
.expect("missing binding mode");
debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);

// pat_ty: the type of the binding being produced.
let pat_ty = return_if_err!(mc.node_ty(pat.hir_id));
debug!("walk_pat: pat_ty={:?}", pat_ty);

// Each match binding is effectively an assignment to the
// binding being produced.
Expand Down
90 changes: 45 additions & 45 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub enum Categorization<'tcx> {
StaticItem,
Upvar(Upvar), // upvar referenced by closure env
Local(ast::NodeId), // local variable
Deref(cmt<'tcx>, PointerKind<'tcx>), // deref of a ptr
Deref(cmt<'tcx>, PointerKind<'tcx>), // deref of a ptr
Interior(cmt<'tcx>, InteriorKind), // something interior: field, tuple, etc
Downcast(cmt<'tcx>, DefId), // selects a particular enum variant (*1)

Expand All @@ -120,9 +120,6 @@ pub enum PointerKind<'tcx> {

/// `*T`
UnsafePtr(hir::Mutability),

/// Implicit deref of the `&T` that results from an overloaded index `[]`.
Implicit(ty::BorrowKind, ty::Region<'tcx>),
}

// We use the term "interior" to mean "something reachable from the
Expand Down Expand Up @@ -172,6 +169,7 @@ pub enum MutabilityCategory {
pub enum Note {
NoteClosureEnv(ty::UpvarId), // Deref through closure env
NoteUpvarRef(ty::UpvarId), // Deref through by-ref upvar
NoteIndex, // Deref as part of desugaring `x[]` into its two components
NoteNone // Nothing special
}

Expand Down Expand Up @@ -231,8 +229,7 @@ impl<'tcx> cmt_<'tcx> {

pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'tcx>> {
match self.cat {
Categorization::Deref(ref base_cmt, BorrowedPtr(ty::ImmBorrow, _)) |
Categorization::Deref(ref base_cmt, Implicit(ty::ImmBorrow, _)) => {
Categorization::Deref(ref base_cmt, BorrowedPtr(ty::ImmBorrow, _)) => {
// try to figure out where the immutable reference came from
match base_cmt.cat {
Categorization::Local(node_id) =>
Expand Down Expand Up @@ -328,7 +325,7 @@ impl MutabilityCategory {
Unique => {
base_mutbl.inherit()
}
BorrowedPtr(borrow_kind, _) | Implicit(borrow_kind, _) => {
BorrowedPtr(borrow_kind, _) => {
MutabilityCategory::from_borrow_kind(borrow_kind)
}
UnsafePtr(m) => {
Expand Down Expand Up @@ -617,7 +614,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
} else {
previous()?
});
self.cat_deref(expr, base, false)
self.cat_deref(expr, base, NoteNone)
}

adjustment::Adjust::NeverToAny |
Expand All @@ -640,10 +637,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
match expr.node {
hir::ExprUnary(hir::UnDeref, ref e_base) => {
if self.tables.is_method_call(expr) {
self.cat_overloaded_place(expr, e_base, false)
self.cat_overloaded_place(expr, e_base, NoteNone)
} else {
let base_cmt = Rc::new(self.cat_expr(&e_base)?);
self.cat_deref(expr, base_cmt, false)
self.cat_deref(expr, base_cmt, NoteNone)
}
}

Expand All @@ -664,7 +661,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// The call to index() returns a `&T` value, which
// is an rvalue. That is what we will be
// dereferencing.
self.cat_overloaded_place(expr, base, true)
self.cat_overloaded_place(expr, base, NoteIndex)
} else {
let base_cmt = Rc::new(self.cat_expr(&base)?);
self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index)
Expand Down Expand Up @@ -999,12 +996,18 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
ret
}

fn cat_overloaded_place(&self,
expr: &hir::Expr,
base: &hir::Expr,
implicit: bool)
-> McResult<cmt_<'tcx>> {
debug!("cat_overloaded_place: implicit={}", implicit);
fn cat_overloaded_place(
&self,
expr: &hir::Expr,
base: &hir::Expr,
note: Note,
) -> McResult<cmt_<'tcx>> {
debug!(
"cat_overloaded_place(expr={:?}, base={:?}, note={:?})",
expr,
base,
note,
);

// Reconstruct the output assuming it's a reference with the
// same region and mutability as the receiver. This holds for
Expand All @@ -1024,14 +1027,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
});

let base_cmt = Rc::new(self.cat_rvalue_node(expr.id, expr.span, ref_ty));
self.cat_deref(expr, base_cmt, implicit)
self.cat_deref(expr, base_cmt, note)
}

pub fn cat_deref<N:ast_node>(&self,
node: &N,
base_cmt: cmt<'tcx>,
implicit: bool)
-> McResult<cmt_<'tcx>> {
pub fn cat_deref(
&self,
node: &impl ast_node,
base_cmt: cmt<'tcx>,
note: Note,
) -> McResult<cmt_<'tcx>> {
debug!("cat_deref: base_cmt={:?}", base_cmt);

let base_cmt_ty = base_cmt.ty;
Expand All @@ -1049,7 +1053,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
ty::TyRef(r, _, mutbl) => {
let bk = ty::BorrowKind::from_mutbl(mutbl);
if implicit { Implicit(bk, r) } else { BorrowedPtr(bk, r) }
BorrowedPtr(bk, r)
}
ref ty => bug!("unexpected type in cat_deref: {:?}", ty)
};
Expand All @@ -1060,7 +1064,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
mutbl: MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
cat: Categorization::Deref(base_cmt, ptr),
ty: deref_ty,
note: NoteNone
note: note,
};
debug!("cat_deref ret {:?}", ret);
Ok(ret)
Expand Down Expand Up @@ -1193,7 +1197,7 @@ 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(pat={:?}, cmt={:?})", pat, cmt);

// If (pattern) adjustments are active for this pattern, adjust the `cmt` correspondingly.
// `cmt`s are constructed differently from patterns. For example, in
Expand Down Expand Up @@ -1231,10 +1235,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
.pat_adjustments()
.get(pat.hir_id)
.map(|v| v.len())
.unwrap_or(0) {
cmt = Rc::new(self.cat_deref(pat, cmt, true /* implicit */)?);
.unwrap_or(0)
{
debug!("cat_pattern: applying adjustment to cmt={:?}", cmt);
cmt = Rc::new(self.cat_deref(pat, cmt, NoteNone)?);
}
let cmt = cmt; // lose mutability
debug!("cat_pattern: applied adjustment derefs to get cmt={:?}", cmt);

// Invoke the callback, but only now, after the `cmt` has adjusted.
//
Expand Down Expand Up @@ -1330,7 +1337,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// box p1, &p1, &mut p1. we can ignore the mutability of
// PatKind::Ref since that information is already contained
// in the type.
let subcmt = Rc::new(self.cat_deref(pat, cmt, false)?);
let subcmt = Rc::new(self.cat_deref(pat, cmt, NoteNone)?);
self.cat_pattern_(subcmt, &subpat, op)?;
}

Expand Down Expand Up @@ -1391,7 +1398,6 @@ impl<'tcx> cmt_<'tcx> {
Categorization::Local(..) |
Categorization::Deref(_, UnsafePtr(..)) |
Categorization::Deref(_, BorrowedPtr(..)) |
Categorization::Deref(_, Implicit(..)) |
Categorization::Upvar(..) => {
(*self).clone()
}
Expand All @@ -1411,9 +1417,7 @@ impl<'tcx> cmt_<'tcx> {

match self.cat {
Categorization::Deref(ref b, BorrowedPtr(ty::MutBorrow, _)) |
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, _) => {
Expand All @@ -1436,8 +1440,7 @@ impl<'tcx> cmt_<'tcx> {
}
}

Categorization::Deref(_, BorrowedPtr(ty::ImmBorrow, _)) |
Categorization::Deref(_, Implicit(ty::ImmBorrow, _)) => {
Categorization::Deref(_, BorrowedPtr(ty::ImmBorrow, _)) => {
FreelyAliasable(AliasableBorrowed)
}
}
Expand All @@ -1460,7 +1463,7 @@ impl<'tcx> cmt_<'tcx> {
_ => bug!()
})
}
NoteNone => None
NoteIndex | NoteNone => None
}
}

Expand All @@ -1487,17 +1490,17 @@ impl<'tcx> cmt_<'tcx> {
Some(_) => bug!(),
None => {
match pk {
Implicit(..) => {
format!("indexed content")
}
Unique => {
format!("`Box` content")
}
UnsafePtr(..) => {
format!("dereference of raw pointer")
}
BorrowedPtr(..) => {
format!("borrowed content")
match self.note {
NoteIndex => format!("indexed content"),
_ => format!("borrowed content"),
}
}
}
}
Expand Down Expand Up @@ -1525,12 +1528,9 @@ impl<'tcx> cmt_<'tcx> {
pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
match ptr {
Unique => "Box",
BorrowedPtr(ty::ImmBorrow, _) |
Implicit(ty::ImmBorrow, _) => "&",
BorrowedPtr(ty::MutBorrow, _) |
Implicit(ty::MutBorrow, _) => "&mut",
BorrowedPtr(ty::UniqueImmBorrow, _) |
Implicit(ty::UniqueImmBorrow, _) => "&unique",
BorrowedPtr(ty::ImmBorrow, _) => "&",
BorrowedPtr(ty::MutBorrow, _) => "&mut",
BorrowedPtr(ty::UniqueImmBorrow, _) => "&unique",
UnsafePtr(_) => "*",
}
}
Expand Down
31 changes: 25 additions & 6 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,30 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
use self::ProjectionTyCandidateSet::*;
use self::ProjectionTyCandidate::*;

// This wacky variable is just used to try and
// make code readable and avoid confusing paths.
// It is assigned a "value" of `()` only on those
// paths in which we wish to convert `*self` to
// ambiguous (and return false, because the candidate
// was not used). On other paths, it is not assigned,
// and hence if those paths *could* reach the code that
// comes after the match, this fn would not compile.
let convert_to_ambigious;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hax!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed...though I thought it was sort of beautiful in its own way :)


match self {
None => {
*self = Single(candidate);
true
return true;
}

Single(current) => {
// Duplicates can happen inside ParamEnv. In the case, we
// perform a lazy deduplication.
if current == &candidate {
return false;
}

// Prefer where-clauses. As in select, if there are multiple
// candidates, we prefer where-clause candidates over impls. This
// may seem a bit surprising, since impls are the source of
Expand All @@ -156,17 +169,23 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
// clauses are the safer choice. See the comment on
// `select::SelectionCandidate` and #21974 for more details.
match (current, candidate) {
(ParamEnv(..), ParamEnv(..)) => { *self = Ambiguous; }
(ParamEnv(..), _) => {}
(ParamEnv(..), ParamEnv(..)) => convert_to_ambigious = (),
(ParamEnv(..), _) => return false,
(_, ParamEnv(..)) => { unreachable!(); }
(_, _) => { *self = Ambiguous; }
(_, _) => convert_to_ambigious = (),
}
false
}

Ambiguous | Error(..) => {
false
return false;
}
}

// We only ever get here when we moved from a single candidate
// to ambiguous.
let () = convert_to_ambigious;
*self = Ambiguous;
false
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
-> Option<mc::cmt_<'tcx>> {
match cmt.cat {
Categorization::Deref(_, mc::BorrowedPtr(..)) |
Categorization::Deref(_, mc::Implicit(..)) |
Categorization::Deref(_, mc::UnsafePtr(..)) |
Categorization::StaticItem => {
Some(cmt.clone())
Expand Down
4 changes: 1 addition & 3 deletions src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
Categorization::Local(..) | // L-Local
Categorization::Upvar(..) |
Categorization::Deref(_, mc::BorrowedPtr(..)) | // L-Deref-Borrowed
Categorization::Deref(_, mc::Implicit(..)) |
Categorization::Deref(_, mc::UnsafePtr(..)) => {
self.check_scope(self.scope(cmt))
}
Expand Down Expand Up @@ -122,8 +121,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
Categorization::Deref(_, mc::UnsafePtr(..)) => {
self.bccx.tcx.types.re_static
}
Categorization::Deref(_, mc::BorrowedPtr(_, r)) |
Categorization::Deref(_, mc::Implicit(_, r)) => {
Categorization::Deref(_, mc::BorrowedPtr(_, r)) => {
r
}
Categorization::Downcast(ref cmt, _) |
Expand Down
1 change: 0 additions & 1 deletion src/librustc_borrowck/borrowck/gather_loans/move_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>,
-> DiagnosticBuilder<'a> {
match move_from.cat {
Categorization::Deref(_, mc::BorrowedPtr(..)) |
Categorization::Deref(_, mc::Implicit(..)) |
Categorization::Deref(_, mc::UnsafePtr(..)) |
Categorization::StaticItem => {
bccx.cannot_move_out_of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
let result = self.restrict(&cmt_base);
self.extend(result, &cmt, LpDeref(pk))
}
mc::Implicit(bk, lt) | mc::BorrowedPtr(bk, lt) => {
mc::BorrowedPtr(bk, lt) => {
// R-Deref-[Mut-]Borrowed
if !self.bccx.is_subregion_of(self.loan_region, lt) {
self.bccx.report(
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
.borrow_mut()
.pat_binding_modes_mut()
.insert(pat.hir_id, bm);
debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
let typ = self.local_ty(pat.span, pat.id);
match bm {
ty::BindByReference(mutbl) => {
Expand Down
1 change: 0 additions & 1 deletion src/librustc_typeck/check/regionck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,6 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
borrow_kind,
borrow_cmt);
match borrow_cmt_cat {
Categorization::Deref(ref_cmt, mc::Implicit(ref_kind, ref_region)) |
Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => {
match self.link_reborrowed_region(span,
borrow_region, borrow_kind,
Expand Down
Loading