Skip to content

Commit

Permalink
rename type_moves_by_default to type_is_copy_modulo_regions
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Jan 2, 2019
1 parent 4c8fd2e commit 8e89184
Show file tree
Hide file tree
Showing 15 changed files with 55 additions and 46 deletions.
7 changes: 4 additions & 3 deletions src/librustc/infer/mod.rs
Expand Up @@ -1400,18 +1400,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
.verify_generic_bound(origin, kind, a, bound);
}

pub fn type_moves_by_default(
pub fn type_is_copy_modulo_regions(
&self,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
span: Span,
) -> bool {
let ty = self.resolve_type_vars_if_possible(&ty);

// Even if the type may have no inference variables, during
// type-checking closure types are in local tables only.
if !self.in_progress_tables.is_some() || !ty.has_closure_types() {
if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
return ty.moves_by_default(self.tcx.global_tcx(), param_env, span);
return ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span);
}
}

Expand All @@ -1421,7 +1422,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// rightly refuses to work with inference variables, but
// moves_by_default has a cache, which we want to use in other
// cases.
!traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
}

/// Obtains the latest type of the given closure; this may be a
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/expr_use_visitor.rs
Expand Up @@ -976,7 +976,7 @@ fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx
move_reason: MoveReason)
-> ConsumeMode
{
if mc.type_moves_by_default(param_env, cmt.ty, cmt.span) {
if !mc.type_is_copy_modulo_regions(param_env, cmt.ty, cmt.span) {
Move(move_reason)
} else {
Copy
Expand Down
15 changes: 8 additions & 7 deletions src/librustc/middle/mem_categorization.rs
Expand Up @@ -443,15 +443,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
}

pub fn type_moves_by_default(&self,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
span: Span)
-> bool {
self.infcx.map(|infcx| infcx.type_moves_by_default(param_env, ty, span))
pub fn type_is_copy_modulo_regions(
&self,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
span: Span,
) -> bool {
self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span))
.or_else(|| {
self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| {
ty.moves_by_default(self.tcx.global_tcx(), param_env, span)
ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span)
})
})
.unwrap_or(true)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/query/mod.rs
Expand Up @@ -382,7 +382,7 @@ define_queries! { <'tcx>
/// might want to use `reveal_all()` method to change modes.
[] fn param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>,

/// Trait selection queries. These are best used by invoking `ty.moves_by_default()`,
/// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
/// `ty.is_copy()`, etc, since that will prune the environment where possible.
[] fn is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
[] fn is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
Expand Down
18 changes: 9 additions & 9 deletions src/librustc/ty/util.rs
Expand Up @@ -203,7 +203,7 @@ impl<'tcx> ty::ParamEnv<'tcx> {
let cause = ObligationCause { span, ..ObligationCause::dummy() };
let ctx = traits::FulfillmentContext::new();
match traits::fully_normalize(&infcx, ctx, cause, self, &ty) {
Ok(ty) => if infcx.type_moves_by_default(self, ty, span) {
Ok(ty) => if !infcx.type_is_copy_modulo_regions(self, ty, span) {
infringing.push(field);
}
Err(errors) => {
Expand Down Expand Up @@ -628,12 +628,12 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
/// does copies even when the type actually doesn't satisfy the
/// full requirements for the `Copy` trait (cc #29149) -- this
/// winds up being reported as an error during NLL borrow check.
pub fn moves_by_default(&'tcx self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span)
-> bool {
!tcx.at(span).is_copy_raw(param_env.and(self))
pub fn is_copy_modulo_regions(&'tcx self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span)
-> bool {
tcx.at(span).is_copy_raw(param_env.and(self))
}

/// Checks whether values of this type `T` have a size known at
Expand Down Expand Up @@ -947,11 +947,11 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// `ManuallyDrop` doesn't have a destructor regardless of field types.
ty::Adt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false,

// Issue #22536: We first query type_moves_by_default. It sees a
// Issue #22536: We first query `is_copy_modulo_regions`. It sees a
// normalized version of the type, and therefore will definitely
// know whether the type implements Copy (and thus needs no
// cleanup/drop/zeroing) ...
_ if !ty.moves_by_default(tcx, param_env, DUMMY_SP) => false,
_ if ty.is_copy_modulo_regions(tcx, param_env, DUMMY_SP) => false,

// ... (issue #22536 continued) but as an optimization, still use
// prior logic of asking for the structural "may drop".
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/builtin.rs
Expand Up @@ -540,7 +540,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
return;
}
let param_env = ty::ParamEnv::empty();
if !ty.moves_by_default(cx.tcx, param_env, item.span) {
if ty.is_copy_modulo_regions(cx.tcx, param_env, item.span) {
return;
}
if param_env.can_type_implement_copy(cx.tcx, ty).is_ok() {
Expand Down
18 changes: 11 additions & 7 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Expand Up @@ -503,13 +503,17 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]),
};

// In order to have a Copy operand, the type T of the value must be Copy. Note that we
// prove that T: Copy, rather than using the type_moves_by_default test. This is
// important because type_moves_by_default ignores the resulting region obligations and
// assumes they pass. This can result in bounds from Copy impls being unsoundly ignored
// (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds
// fully apply: in effect, the rule is that if a value of some type could implement
// Copy, then it must.
// In order to have a Copy operand, the type T of the
// value must be Copy. Note that we prove that T: Copy,
// rather than using the `is_copy_modulo_regions`
// test. This is important because
// `is_copy_modulo_regions` ignores the resulting region
// obligations and assumes they pass. This can result in
// bounds from Copy impls being unsoundly ignored (e.g.,
// #29149). Note that we decide to use Copy before knowing
// whether the bounds fully apply: in effect, the rule is
// that if a value of some type could implement Copy, then
// it must.
self.cx.prove_trait_ref(
trait_ref,
location.to_locations(),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/misc.rs
Expand Up @@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
let tcx = self.hir.tcx();
let ty = place.ty(&self.local_decls, tcx).to_ty(tcx);
if self.hir.type_moves_by_default(ty, DUMMY_SP) {
if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) {
Operand::Move(place)
} else {
Operand::Copy(place)
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/hair/cx/mod.rs
Expand Up @@ -223,8 +223,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
self.check_overflow
}

pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
self.infcx.type_moves_by_default(self.param_env, ty, span)
pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/hair/pattern/check_match.rs
Expand Up @@ -545,7 +545,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
match bm {
ty::BindByValue(..) => {
let pat_ty = cx.tables.node_id_to_type(p.hir_id);
if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) {
if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) {
check_move(p, sub.as_ref().map(|p| &**p), span_vec);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/shim.rs
Expand Up @@ -310,7 +310,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
debug!("build_clone_shim(def_id={:?})", def_id);

let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
let is_copy = !self_ty.moves_by_default(tcx, tcx.param_env(def_id), builder.span);
let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span);

let dest = Place::Local(RETURN_PLACE);
let src = Place::Local(Local::new(1+0)).deref();
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_mir/transform/check_unsafety.rs
Expand Up @@ -224,8 +224,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
"non-field projection {:?} from union?",
place)
};
if elem_ty.moves_by_default(self.tcx, self.param_env,
self.source_info.span) {
if !elem_ty.is_copy_modulo_regions(
self.tcx,
self.param_env,
self.source_info.span,
) {
self.require_unsafe(
"assignment to non-`Copy` union field",
"the previous content of the field will be dropped, which \
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_typeck/check/demand.rs
Expand Up @@ -353,9 +353,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

// Maybe add `*`? Only if `T: Copy`.
_ => {
if !self.infcx.type_moves_by_default(self.param_env,
checked,
sp) {
if self.infcx.type_is_copy_modulo_regions(self.param_env,
checked,
sp) {
// do not suggest if the span comes from a macro (#52783)
if let (Ok(code),
true) = (cm.span_to_snippet(sp), sp == expr.span) {
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_typeck/check/op.rs
Expand Up @@ -262,9 +262,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut suggested_deref = false;
if let Ref(_, mut rty, _) = lhs_ty.sty {
if {
!self.infcx.type_moves_by_default(self.param_env,
rty,
lhs_expr.span) &&
self.infcx.type_is_copy_modulo_regions(self.param_env,
rty,
lhs_expr.span) &&
self.lookup_op_method(rty,
&[rhs_ty],
Op::Binary(op, is_assign))
Expand Down Expand Up @@ -334,9 +334,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut suggested_deref = false;
if let Ref(_, mut rty, _) = lhs_ty.sty {
if {
!self.infcx.type_moves_by_default(self.param_env,
rty,
lhs_expr.span) &&
self.infcx.type_is_copy_modulo_regions(self.param_env,
rty,
lhs_expr.span) &&
self.lookup_op_method(rty,
&[rhs_ty],
Op::Binary(op, is_assign))
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/coherence/coherence-subtyping.stderr
Expand Up @@ -7,7 +7,7 @@ LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 {
LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
= note: this behavior recently changed as a result of a bug fix; see #XXX for details
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details

error: aborting due to previous error

Expand Down

0 comments on commit 8e89184

Please sign in to comment.