Modify type_known_to_meet_builtin_bound
so that it doesn't suppress overflow,
which should always result in an error. NB. Some of the hunks in this commit rely on a later commit which adds `tcx` into `param_env` and modifies `ParameterEnvironment` to implement `Typer`.
This commit is contained in:
parent
429d9cce1b
commit
83ef3042de
13 changed files with 149 additions and 77 deletions
|
@ -1612,15 +1612,11 @@ impl LintPass for MissingCopyImplementations {
|
||||||
}
|
}
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let parameter_environment = ty::empty_parameter_environment();
|
let parameter_environment = ty::empty_parameter_environment(cx.tcx);
|
||||||
if !ty::type_moves_by_default(cx.tcx,
|
if !ty::type_moves_by_default(¶meter_environment, item.span, ty) {
|
||||||
ty,
|
|
||||||
¶meter_environment) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ty::can_type_implement_copy(cx.tcx,
|
if ty::can_type_implement_copy(¶meter_environment, item.span, ty).is_ok() {
|
||||||
ty,
|
|
||||||
¶meter_environment).is_ok() {
|
|
||||||
cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
|
cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
|
||||||
item.span,
|
item.span,
|
||||||
"type could implement `Copy`; consider adding `impl \
|
"type could implement `Copy`; consider adding `impl \
|
||||||
|
|
|
@ -1032,9 +1032,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
|
||||||
match p.node {
|
match p.node {
|
||||||
ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
|
ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
|
||||||
let pat_ty = ty::node_id_to_type(tcx, p.id);
|
let pat_ty = ty::node_id_to_type(tcx, p.id);
|
||||||
if ty::type_moves_by_default(tcx,
|
if ty::type_moves_by_default(&cx.param_env, pat.span, pat_ty) {
|
||||||
pat_ty,
|
|
||||||
&cx.param_env) {
|
|
||||||
check_move(p, sub.as_ref().map(|p| &**p));
|
check_move(p, sub.as_ref().map(|p| &**p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
|
||||||
cmt: mc::cmt<'tcx>,
|
cmt: mc::cmt<'tcx>,
|
||||||
_: euv::ConsumeMode) {
|
_: euv::ConsumeMode) {
|
||||||
debug!("consume; cmt: {}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty));
|
debug!("consume; cmt: {}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty));
|
||||||
if !ty::type_is_sized(self.tcx, cmt.ty, self.param_env) {
|
if !ty::type_is_sized(self.param_env, span, cmt.ty) {
|
||||||
span_err!(self.tcx.sess, span, E0161,
|
span_err!(self.tcx.sess, span, E0161,
|
||||||
"cannot move a value of type {0}: the size of {0} cannot be statically determined",
|
"cannot move a value of type {0}: the size of {0} cannot be statically determined",
|
||||||
ty_to_string(self.tcx, cmt.ty));
|
ty_to_string(self.tcx, cmt.ty));
|
||||||
|
|
|
@ -367,10 +367,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
consume_id: ast::NodeId,
|
consume_id: ast::NodeId,
|
||||||
consume_span: Span,
|
consume_span: Span,
|
||||||
cmt: mc::cmt<'tcx>) {
|
cmt: mc::cmt<'tcx>) {
|
||||||
let mode = copy_or_move(self.tcx(),
|
let mode = copy_or_move(self.typer, &cmt, DirectRefMove);
|
||||||
cmt.ty,
|
|
||||||
self.param_env,
|
|
||||||
DirectRefMove);
|
|
||||||
self.delegate.consume(consume_id, consume_span, cmt, mode);
|
self.delegate.consume(consume_id, consume_span, cmt, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,10 +1017,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
ast::PatIdent(ast::BindByRef(_), _, _) =>
|
ast::PatIdent(ast::BindByRef(_), _, _) =>
|
||||||
mode.lub(BorrowingMatch),
|
mode.lub(BorrowingMatch),
|
||||||
ast::PatIdent(ast::BindByValue(_), _, _) => {
|
ast::PatIdent(ast::BindByValue(_), _, _) => {
|
||||||
match copy_or_move(tcx,
|
match copy_or_move(self.typer, &cmt_pat, PatBindingMove) {
|
||||||
cmt_pat.ty,
|
|
||||||
self.param_env,
|
|
||||||
PatBindingMove) {
|
|
||||||
Copy => mode.lub(CopyingMatch),
|
Copy => mode.lub(CopyingMatch),
|
||||||
Move(_) => mode.lub(MovingMatch),
|
Move(_) => mode.lub(MovingMatch),
|
||||||
}
|
}
|
||||||
|
@ -1085,10 +1079,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
r, bk, RefBinding);
|
r, bk, RefBinding);
|
||||||
}
|
}
|
||||||
ast::PatIdent(ast::BindByValue(_), _, _) => {
|
ast::PatIdent(ast::BindByValue(_), _, _) => {
|
||||||
let mode = copy_or_move(typer.tcx(),
|
let mode = copy_or_move(typer, &cmt_pat, PatBindingMove);
|
||||||
cmt_pat.ty,
|
|
||||||
param_env,
|
|
||||||
PatBindingMove);
|
|
||||||
debug!("walk_pat binding consuming pat");
|
debug!("walk_pat binding consuming pat");
|
||||||
delegate.consume_pat(pat, cmt_pat, mode);
|
delegate.consume_pat(pat, cmt_pat, mode);
|
||||||
}
|
}
|
||||||
|
@ -1303,12 +1294,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_or_move<'tcx>(tcx: &ty::ctxt<'tcx>,
|
fn copy_or_move<'tcx>(typer: &mc::Typer<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
cmt: &mc::cmt<'tcx>,
|
||||||
param_env: &ParameterEnvironment<'tcx>,
|
|
||||||
move_reason: MoveReason)
|
move_reason: MoveReason)
|
||||||
-> ConsumeMode {
|
-> ConsumeMode
|
||||||
if ty::type_moves_by_default(tcx, ty, param_env) {
|
{
|
||||||
|
if typer.type_moves_by_default(cmt.span, cmt.ty) {
|
||||||
Move(move_reason)
|
Move(move_reason)
|
||||||
} else {
|
} else {
|
||||||
Copy
|
Copy
|
||||||
|
|
|
@ -170,6 +170,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
let mut substs = param_env.free_substs.clone();
|
let mut substs = param_env.free_substs.clone();
|
||||||
self.with_each_combination(
|
self.with_each_combination(
|
||||||
|
span,
|
||||||
param_env,
|
param_env,
|
||||||
param_env.free_substs.types.iter_enumerated(),
|
param_env.free_substs.types.iter_enumerated(),
|
||||||
&mut substs,
|
&mut substs,
|
||||||
|
@ -187,7 +188,8 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_each_combination(&self,
|
fn with_each_combination(&self,
|
||||||
param_env: &ty::ParameterEnvironment<'tcx>,
|
span: Span,
|
||||||
|
param_env: &ty::ParameterEnvironment<'a,'tcx>,
|
||||||
mut types_in_scope: EnumeratedItems<Ty<'tcx>>,
|
mut types_in_scope: EnumeratedItems<Ty<'tcx>>,
|
||||||
substs: &mut Substs<'tcx>,
|
substs: &mut Substs<'tcx>,
|
||||||
callback: &mut FnMut(&Substs<'tcx>))
|
callback: &mut FnMut(&Substs<'tcx>))
|
||||||
|
@ -210,15 +212,17 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
|
||||||
debug!("with_each_combination: space={}, index={}, param_ty={}",
|
debug!("with_each_combination: space={}, index={}, param_ty={}",
|
||||||
space, index, param_ty.repr(self.tcx));
|
space, index, param_ty.repr(self.tcx));
|
||||||
|
|
||||||
if !ty::type_is_sized(self.tcx, param_ty, param_env) {
|
if !ty::type_is_sized(param_env, span, param_ty) {
|
||||||
debug!("with_each_combination: param_ty is not known to be sized");
|
debug!("with_each_combination: param_ty is not known to be sized");
|
||||||
|
|
||||||
substs.types.get_mut_slice(space)[index] = self.dummy_unsized_ty;
|
substs.types.get_mut_slice(space)[index] = self.dummy_unsized_ty;
|
||||||
self.with_each_combination(param_env, types_in_scope.clone(), substs, callback);
|
self.with_each_combination(span, param_env, types_in_scope.clone(),
|
||||||
|
substs, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
substs.types.get_mut_slice(space)[index] = self.dummy_sized_ty;
|
substs.types.get_mut_slice(space)[index] = self.dummy_sized_ty;
|
||||||
self.with_each_combination(param_env, types_in_scope, substs, callback);
|
self.with_each_combination(span, param_env, types_in_scope,
|
||||||
|
substs, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||||
"overflow evaluating the requirement `{}`",
|
"overflow evaluating the requirement `{}`",
|
||||||
predicate.user_string(infcx.tcx)).as_slice());
|
predicate.user_string(infcx.tcx)).as_slice());
|
||||||
|
|
||||||
suggest_new_overflow_limit(infcx, obligation.cause.span);
|
suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
|
||||||
|
|
||||||
note_obligation_cause(infcx, obligation);
|
note_obligation_cause(infcx, obligation);
|
||||||
}
|
}
|
||||||
|
@ -332,10 +332,10 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn suggest_new_overflow_limit(infcx: &InferCtxt, span: Span) {
|
pub fn suggest_new_overflow_limit(tcx: &ty::ctxt, span: Span) {
|
||||||
let current_limit = infcx.tcx.sess.recursion_limit.get();
|
let current_limit = tcx.sess.recursion_limit.get();
|
||||||
let suggested_limit = current_limit * 2;
|
let suggested_limit = current_limit * 2;
|
||||||
infcx.tcx.sess.span_note(
|
tcx.sess.span_note(
|
||||||
span,
|
span,
|
||||||
format!(
|
format!(
|
||||||
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
|
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub use self::FulfillmentErrorCode::*;
|
||||||
pub use self::Vtable::*;
|
pub use self::Vtable::*;
|
||||||
pub use self::ObligationCauseCode::*;
|
pub use self::ObligationCauseCode::*;
|
||||||
|
|
||||||
|
use middle::mem_categorization::Typer;
|
||||||
use middle::subst;
|
use middle::subst;
|
||||||
use middle::ty::{mod, Ty};
|
use middle::ty::{mod, Ty};
|
||||||
use middle::infer::InferCtxt;
|
use middle::infer::InferCtxt;
|
||||||
|
@ -22,9 +23,10 @@ use std::slice::Iter;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::{Span, DUMMY_SP};
|
use syntax::codemap::{Span, DUMMY_SP};
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::{Repr, UserString};
|
||||||
|
|
||||||
pub use self::error_reporting::report_fulfillment_errors;
|
pub use self::error_reporting::report_fulfillment_errors;
|
||||||
|
pub use self::error_reporting::suggest_new_overflow_limit;
|
||||||
pub use self::coherence::orphan_check;
|
pub use self::coherence::orphan_check;
|
||||||
pub use self::coherence::OrphanCheckErr;
|
pub use self::coherence::OrphanCheckErr;
|
||||||
pub use self::fulfill::{FulfillmentContext, RegionObligation};
|
pub use self::fulfill::{FulfillmentContext, RegionObligation};
|
||||||
|
@ -288,11 +290,12 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
/// `bound` or is not known to meet bound (note that this is
|
/// `bound` or is not known to meet bound (note that this is
|
||||||
/// conservative towards *no impl*, which is the opposite of the
|
/// conservative towards *no impl*, which is the opposite of the
|
||||||
/// `evaluate` methods).
|
/// `evaluate` methods).
|
||||||
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
||||||
param_env: &ty::ParameterEnvironment<'tcx>,
|
typer: &ty::UnboxedClosureTyper<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
bound: ty::BuiltinBound)
|
bound: ty::BuiltinBound,
|
||||||
-> bool
|
span: Span)
|
||||||
|
-> SelectionResult<'tcx, ()>
|
||||||
{
|
{
|
||||||
debug!("type_known_to_meet_builtin_bound(ty={}, bound={})",
|
debug!("type_known_to_meet_builtin_bound(ty={}, bound={})",
|
||||||
ty.repr(infcx.tcx),
|
ty.repr(infcx.tcx),
|
||||||
|
@ -300,17 +303,49 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
||||||
|
|
||||||
let mut fulfill_cx = FulfillmentContext::new();
|
let mut fulfill_cx = FulfillmentContext::new();
|
||||||
|
|
||||||
// We can use dummy values here because we won't report any errors
|
// We can use a dummy node-id here because we won't pay any mind
|
||||||
// that result nor will we pay any mind to region obligations that arise
|
// to region obligations that arise (there shouldn't really be any
|
||||||
// (there shouldn't really be any anyhow).
|
// anyhow).
|
||||||
let cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);
|
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
|
||||||
|
|
||||||
fulfill_cx.register_builtin_bound(infcx, ty, bound, cause);
|
fulfill_cx.register_builtin_bound(infcx, ty, bound, cause);
|
||||||
|
|
||||||
// Note: we only assume something is `Copy` if we can
|
// Note: we only assume something is `Copy` if we can
|
||||||
// *definitively* show that it implements `Copy`. Otherwise,
|
// *definitively* show that it implements `Copy`. Otherwise,
|
||||||
// assume it is move; linear is always ok.
|
// assume it is move; linear is always ok.
|
||||||
let result = fulfill_cx.select_all_or_error(infcx, param_env, infcx.tcx).is_ok();
|
let result = match fulfill_cx.select_all_or_error(infcx, typer) {
|
||||||
|
Ok(()) => Ok(Some(())), // Success, we know it implements Copy.
|
||||||
|
Err(errors) => {
|
||||||
|
// Check if overflow occurred anywhere and propagate that.
|
||||||
|
if errors.iter().any(
|
||||||
|
|err| match err.code { CodeSelectionError(Overflow) => true, _ => false })
|
||||||
|
{
|
||||||
|
return Err(Overflow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, if there were any hard errors, propagate an
|
||||||
|
// arbitrary one of those. If no hard errors at all,
|
||||||
|
// report ambiguity.
|
||||||
|
let sel_error =
|
||||||
|
errors.iter()
|
||||||
|
.filter_map(|err| {
|
||||||
|
match err.code {
|
||||||
|
CodeAmbiguity => None,
|
||||||
|
CodeSelectionError(ref e) => Some(e.clone()),
|
||||||
|
CodeProjectionError(_) => {
|
||||||
|
infcx.tcx.sess.span_bug(
|
||||||
|
span,
|
||||||
|
"projection error while selecting?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.next();
|
||||||
|
match sel_error {
|
||||||
|
None => { Ok(None) }
|
||||||
|
Some(e) => { Err(e) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
debug!("type_known_to_meet_builtin_bound: ty={} bound={} result={}",
|
debug!("type_known_to_meet_builtin_bound: ty={} bound={} result={}",
|
||||||
ty.repr(infcx.tcx),
|
ty.repr(infcx.tcx),
|
||||||
|
@ -320,6 +355,40 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
||||||
|
typer: &ty::UnboxedClosureTyper<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
bound: ty::BuiltinBound,
|
||||||
|
span: Span)
|
||||||
|
-> bool
|
||||||
|
{
|
||||||
|
match evaluate_builtin_bound(infcx, typer, ty, bound, span) {
|
||||||
|
Ok(Some(())) => {
|
||||||
|
// definitely impl'd
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
// ambiguous: if coherence check was successful, shouldn't
|
||||||
|
// happen, but we might have reported an error and been
|
||||||
|
// soldering on, so just treat this like not implemented
|
||||||
|
false
|
||||||
|
}
|
||||||
|
Err(Overflow) => {
|
||||||
|
infcx.tcx.sess.span_err(
|
||||||
|
span,
|
||||||
|
format!("overflow evaluating whether `{}` is `{}`",
|
||||||
|
ty.user_string(infcx.tcx),
|
||||||
|
bound.user_string(infcx.tcx))[]);
|
||||||
|
suggest_new_overflow_limit(infcx.tcx, span);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// other errors: not implemented.
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx,O> Obligation<'tcx,O> {
|
impl<'tcx,O> Obligation<'tcx,O> {
|
||||||
pub fn new(cause: ObligationCause<'tcx>,
|
pub fn new(cause: ObligationCause<'tcx>,
|
||||||
trait_ref: O)
|
trait_ref: O)
|
||||||
|
|
|
@ -3548,11 +3548,12 @@ fn type_impls_bound<'tcx>(cx: &ctxt<'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let infcx = infer::new_infer_ctxt(cx);
|
let infcx = infer::new_infer_ctxt(param_env.tcx);
|
||||||
let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound);
|
|
||||||
|
let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound, span);
|
||||||
|
|
||||||
debug!("type_impls_bound({}, {}) = {}",
|
debug!("type_impls_bound({}, {}) = {}",
|
||||||
ty_to_string(cx, ty),
|
ty.repr(param_env.tcx),
|
||||||
bound,
|
bound,
|
||||||
is_impld);
|
is_impld);
|
||||||
|
|
||||||
|
@ -3564,20 +3565,22 @@ fn type_impls_bound<'tcx>(cx: &ctxt<'tcx>,
|
||||||
is_impld
|
is_impld
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>,
|
pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
|
||||||
ty: Ty<'tcx>,
|
span: Span,
|
||||||
param_env: &ParameterEnvironment<'tcx>)
|
ty: Ty<'tcx>)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
!type_impls_bound(cx, &cx.type_impls_copy_cache, param_env, ty, ty::BoundCopy)
|
let tcx = param_env.tcx;
|
||||||
|
!type_impls_bound(param_env, &tcx.type_impls_copy_cache, ty, ty::BoundCopy, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>,
|
pub fn type_is_sized<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
|
||||||
ty: Ty<'tcx>,
|
span: Span,
|
||||||
param_env: &ParameterEnvironment<'tcx>)
|
ty: Ty<'tcx>)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
type_impls_bound(cx, &cx.type_impls_sized_cache, param_env, ty, ty::BoundSized)
|
let tcx = param_env.tcx;
|
||||||
|
type_impls_bound(param_env, &tcx.type_impls_sized_cache, ty, ty::BoundSized, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
|
@ -6562,6 +6565,10 @@ impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> {
|
||||||
-> ast::CaptureClause {
|
-> ast::CaptureClause {
|
||||||
self.capture_modes.borrow()[closure_expr_id].clone()
|
self.capture_modes.borrow()[closure_expr_id].clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
|
||||||
|
type_moves_by_default(self, span, ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> UnboxedClosureTyper<'tcx> for ty::ctxt<'tcx> {
|
impl<'tcx> UnboxedClosureTyper<'tcx> for ty::ctxt<'tcx> {
|
||||||
|
@ -6944,15 +6951,18 @@ pub enum CopyImplementationError {
|
||||||
TypeIsStructural,
|
TypeIsStructural,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>,
|
pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tcx>,
|
||||||
self_type: Ty<'tcx>,
|
span: Span,
|
||||||
param_env: &ParameterEnvironment<'tcx>)
|
self_type: Ty<'tcx>)
|
||||||
-> Result<(),CopyImplementationError> {
|
-> Result<(),CopyImplementationError>
|
||||||
|
{
|
||||||
|
let tcx = param_env.tcx;
|
||||||
|
|
||||||
match self_type.sty {
|
match self_type.sty {
|
||||||
ty::ty_struct(struct_did, substs) => {
|
ty::ty_struct(struct_did, substs) => {
|
||||||
let fields = ty::struct_fields(tcx, struct_did, substs);
|
let fields = ty::struct_fields(tcx, struct_did, substs);
|
||||||
for field in fields.iter() {
|
for field in fields.iter() {
|
||||||
if type_moves_by_default(tcx, field.mt.ty, param_env) {
|
if type_moves_by_default(param_env, span, field.mt.ty) {
|
||||||
return Err(FieldDoesNotImplementCopy(field.name))
|
return Err(FieldDoesNotImplementCopy(field.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6963,9 +6973,7 @@ pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>,
|
||||||
for variant_arg_type in variant.args.iter() {
|
for variant_arg_type in variant.args.iter() {
|
||||||
let substd_arg_type =
|
let substd_arg_type =
|
||||||
variant_arg_type.subst(tcx, substs);
|
variant_arg_type.subst(tcx, substs);
|
||||||
if type_moves_by_default(tcx,
|
if type_moves_by_default(param_env, span, substd_arg_type) {
|
||||||
substd_arg_type,
|
|
||||||
param_env) {
|
|
||||||
return Err(VariantDoesNotImplementCopy(variant.name))
|
return Err(VariantDoesNotImplementCopy(variant.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1327,9 +1327,8 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
|
||||||
let trmode;
|
let trmode;
|
||||||
match bm {
|
match bm {
|
||||||
ast::BindByValue(_)
|
ast::BindByValue(_)
|
||||||
if !ty::type_moves_by_default(tcx,
|
if !ty::type_moves_by_default(¶m_env, span, variable_ty) || reassigned =>
|
||||||
variable_ty,
|
{
|
||||||
¶m_env) || reassigned => {
|
|
||||||
llmatch = alloca_no_lifetime(bcx,
|
llmatch = alloca_no_lifetime(bcx,
|
||||||
llvariable_ty.ptr_to(),
|
llvariable_ty.ptr_to(),
|
||||||
"__llmatch");
|
"__llmatch");
|
||||||
|
|
|
@ -625,6 +625,10 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
|
||||||
-> ast::CaptureClause {
|
-> ast::CaptureClause {
|
||||||
self.tcx().capture_modes.borrow()[closure_expr_id].clone()
|
self.tcx().capture_modes.borrow()[closure_expr_id].clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
|
||||||
|
self.param_env().type_moves_by_default(span, ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
|
impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
|
||||||
|
|
|
@ -543,8 +543,9 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> {
|
||||||
* affine values (since they must never be duplicated).
|
* affine values (since they must never be duplicated).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let param_env = ty::empty_parameter_environment();
|
assert!(!ty::type_moves_by_default(&ty::empty_parameter_environment(bcx.tcx()),
|
||||||
assert!(!ty::type_moves_by_default(bcx.tcx(), self.ty, ¶m_env));
|
DUMMY_SP,
|
||||||
|
self.ty));
|
||||||
self.shallow_copy_raw(bcx, dst)
|
self.shallow_copy_raw(bcx, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1462,7 +1462,7 @@ fn check_cast(fcx: &FnCtxt,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fcx.type_is_known_to_be_sized(t_1) {
|
if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
|
||||||
let tstr = fcx.infcx().ty_to_string(t_1);
|
let tstr = fcx.infcx().ty_to_string(t_1);
|
||||||
fcx.type_error_message(span, |actual| {
|
fcx.type_error_message(span, |actual| {
|
||||||
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
|
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
|
||||||
|
@ -1981,13 +1981,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_is_known_to_be_sized(&self,
|
pub fn type_is_known_to_be_sized(&self,
|
||||||
ty: Ty<'tcx>)
|
ty: Ty<'tcx>,
|
||||||
|
span: Span)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
traits::type_known_to_meet_builtin_bound(self.infcx(),
|
traits::type_known_to_meet_builtin_bound(self.infcx(),
|
||||||
self.param_env(),
|
self.param_env(),
|
||||||
ty,
|
ty,
|
||||||
ty::BoundSized)
|
ty::BoundSized,
|
||||||
|
span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_builtin_bound(&self,
|
pub fn register_builtin_bound(&self,
|
||||||
|
|
|
@ -482,7 +482,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||||
debug!("check_implementations_of_copy: self_type={} (free)",
|
debug!("check_implementations_of_copy: self_type={} (free)",
|
||||||
self_type.repr(tcx));
|
self_type.repr(tcx));
|
||||||
|
|
||||||
match ty::can_type_implement_copy(tcx, self_type, ¶m_env) {
|
match ty::can_type_implement_copy(¶m_env, span, self_type) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(ty::FieldDoesNotImplementCopy(name)) => {
|
Err(ty::FieldDoesNotImplementCopy(name)) => {
|
||||||
tcx.sess
|
tcx.sess
|
||||||
|
|
Loading…
Add table
Reference in a new issue