Skip to content

Commit 83ef304

Browse files
committed
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`.
1 parent 429d9cc commit 83ef304

File tree

13 files changed

+149
-77
lines changed

13 files changed

+149
-77
lines changed

src/librustc/lint/builtin.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,15 +1612,11 @@ impl LintPass for MissingCopyImplementations {
16121612
}
16131613
_ => return,
16141614
};
1615-
let parameter_environment = ty::empty_parameter_environment();
1616-
if !ty::type_moves_by_default(cx.tcx,
1617-
ty,
1618-
&parameter_environment) {
1615+
let parameter_environment = ty::empty_parameter_environment(cx.tcx);
1616+
if !ty::type_moves_by_default(&parameter_environment, item.span, ty) {
16191617
return
16201618
}
1621-
if ty::can_type_implement_copy(cx.tcx,
1622-
ty,
1623-
&parameter_environment).is_ok() {
1619+
if ty::can_type_implement_copy(&parameter_environment, item.span, ty).is_ok() {
16241620
cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
16251621
item.span,
16261622
"type could implement `Copy`; consider adding `impl \

src/librustc/middle/check_match.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,9 +1032,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
10321032
match p.node {
10331033
ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
10341034
let pat_ty = ty::node_id_to_type(tcx, p.id);
1035-
if ty::type_moves_by_default(tcx,
1036-
pat_ty,
1037-
&cx.param_env) {
1035+
if ty::type_moves_by_default(&cx.param_env, pat.span, pat_ty) {
10381036
check_move(p, sub.as_ref().map(|p| &**p));
10391037
}
10401038
}

src/librustc/middle/check_rvalues.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
6060
cmt: mc::cmt<'tcx>,
6161
_: euv::ConsumeMode) {
6262
debug!("consume; cmt: {}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty));
63-
if !ty::type_is_sized(self.tcx, cmt.ty, self.param_env) {
63+
if !ty::type_is_sized(self.param_env, span, cmt.ty) {
6464
span_err!(self.tcx.sess, span, E0161,
6565
"cannot move a value of type {0}: the size of {0} cannot be statically determined",
6666
ty_to_string(self.tcx, cmt.ty));

src/librustc/middle/expr_use_visitor.rs

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
367367
consume_id: ast::NodeId,
368368
consume_span: Span,
369369
cmt: mc::cmt<'tcx>) {
370-
let mode = copy_or_move(self.tcx(),
371-
cmt.ty,
372-
self.param_env,
373-
DirectRefMove);
370+
let mode = copy_or_move(self.typer, &cmt, DirectRefMove);
374371
self.delegate.consume(consume_id, consume_span, cmt, mode);
375372
}
376373

@@ -1020,10 +1017,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
10201017
ast::PatIdent(ast::BindByRef(_), _, _) =>
10211018
mode.lub(BorrowingMatch),
10221019
ast::PatIdent(ast::BindByValue(_), _, _) => {
1023-
match copy_or_move(tcx,
1024-
cmt_pat.ty,
1025-
self.param_env,
1026-
PatBindingMove) {
1020+
match copy_or_move(self.typer, &cmt_pat, PatBindingMove) {
10271021
Copy => mode.lub(CopyingMatch),
10281022
Move(_) => mode.lub(MovingMatch),
10291023
}
@@ -1085,10 +1079,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
10851079
r, bk, RefBinding);
10861080
}
10871081
ast::PatIdent(ast::BindByValue(_), _, _) => {
1088-
let mode = copy_or_move(typer.tcx(),
1089-
cmt_pat.ty,
1090-
param_env,
1091-
PatBindingMove);
1082+
let mode = copy_or_move(typer, &cmt_pat, PatBindingMove);
10921083
debug!("walk_pat binding consuming pat");
10931084
delegate.consume_pat(pat, cmt_pat, mode);
10941085
}
@@ -1303,12 +1294,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
13031294
}
13041295
}
13051296

1306-
fn copy_or_move<'tcx>(tcx: &ty::ctxt<'tcx>,
1307-
ty: Ty<'tcx>,
1308-
param_env: &ParameterEnvironment<'tcx>,
1297+
fn copy_or_move<'tcx>(typer: &mc::Typer<'tcx>,
1298+
cmt: &mc::cmt<'tcx>,
13091299
move_reason: MoveReason)
1310-
-> ConsumeMode {
1311-
if ty::type_moves_by_default(tcx, ty, param_env) {
1300+
-> ConsumeMode
1301+
{
1302+
if typer.type_moves_by_default(cmt.span, cmt.ty) {
13121303
Move(move_reason)
13131304
} else {
13141305
Copy

src/librustc/middle/intrinsicck.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
170170

171171
let mut substs = param_env.free_substs.clone();
172172
self.with_each_combination(
173+
span,
173174
param_env,
174175
param_env.free_substs.types.iter_enumerated(),
175176
&mut substs,
@@ -187,7 +188,8 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
187188
}
188189

189190
fn with_each_combination(&self,
190-
param_env: &ty::ParameterEnvironment<'tcx>,
191+
span: Span,
192+
param_env: &ty::ParameterEnvironment<'a,'tcx>,
191193
mut types_in_scope: EnumeratedItems<Ty<'tcx>>,
192194
substs: &mut Substs<'tcx>,
193195
callback: &mut FnMut(&Substs<'tcx>))
@@ -210,15 +212,17 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
210212
debug!("with_each_combination: space={}, index={}, param_ty={}",
211213
space, index, param_ty.repr(self.tcx));
212214

213-
if !ty::type_is_sized(self.tcx, param_ty, param_env) {
215+
if !ty::type_is_sized(param_env, span, param_ty) {
214216
debug!("with_each_combination: param_ty is not known to be sized");
215217

216218
substs.types.get_mut_slice(space)[index] = self.dummy_unsized_ty;
217-
self.with_each_combination(param_env, types_in_scope.clone(), substs, callback);
219+
self.with_each_combination(span, param_env, types_in_scope.clone(),
220+
substs, callback);
218221
}
219222

220223
substs.types.get_mut_slice(space)[index] = self.dummy_sized_ty;
221-
self.with_each_combination(param_env, types_in_scope, substs, callback);
224+
self.with_each_combination(span, param_env, types_in_scope,
225+
substs, callback);
222226
}
223227
}
224228
}

src/librustc/middle/traits/error_reporting.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
7777
"overflow evaluating the requirement `{}`",
7878
predicate.user_string(infcx.tcx)).as_slice());
7979

80-
suggest_new_overflow_limit(infcx, obligation.cause.span);
80+
suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
8181

8282
note_obligation_cause(infcx, obligation);
8383
}
@@ -332,10 +332,10 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
332332
}
333333
}
334334

335-
pub fn suggest_new_overflow_limit(infcx: &InferCtxt, span: Span) {
336-
let current_limit = infcx.tcx.sess.recursion_limit.get();
335+
pub fn suggest_new_overflow_limit(tcx: &ty::ctxt, span: Span) {
336+
let current_limit = tcx.sess.recursion_limit.get();
337337
let suggested_limit = current_limit * 2;
338-
infcx.tcx.sess.span_note(
338+
tcx.sess.span_note(
339339
span,
340340
format!(
341341
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",

src/librustc/middle/traits/mod.rs

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ pub use self::FulfillmentErrorCode::*;
1515
pub use self::Vtable::*;
1616
pub use self::ObligationCauseCode::*;
1717

18+
use middle::mem_categorization::Typer;
1819
use middle::subst;
1920
use middle::ty::{mod, Ty};
2021
use middle::infer::InferCtxt;
2122
use std::slice::Iter;
2223
use std::rc::Rc;
2324
use syntax::ast;
2425
use syntax::codemap::{Span, DUMMY_SP};
25-
use util::ppaux::Repr;
26+
use util::ppaux::{Repr, UserString};
2627

2728
pub use self::error_reporting::report_fulfillment_errors;
29+
pub use self::error_reporting::suggest_new_overflow_limit;
2830
pub use self::coherence::orphan_check;
2931
pub use self::coherence::OrphanCheckErr;
3032
pub use self::fulfill::{FulfillmentContext, RegionObligation};
@@ -288,29 +290,62 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
288290
/// `bound` or is not known to meet bound (note that this is
289291
/// conservative towards *no impl*, which is the opposite of the
290292
/// `evaluate` methods).
291-
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
292-
param_env: &ty::ParameterEnvironment<'tcx>,
293-
ty: Ty<'tcx>,
294-
bound: ty::BuiltinBound)
295-
-> bool
293+
pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
294+
typer: &ty::UnboxedClosureTyper<'tcx>,
295+
ty: Ty<'tcx>,
296+
bound: ty::BuiltinBound,
297+
span: Span)
298+
-> SelectionResult<'tcx, ()>
296299
{
297300
debug!("type_known_to_meet_builtin_bound(ty={}, bound={})",
298301
ty.repr(infcx.tcx),
299302
bound);
300303

301304
let mut fulfill_cx = FulfillmentContext::new();
302305

303-
// We can use dummy values here because we won't report any errors
304-
// that result nor will we pay any mind to region obligations that arise
305-
// (there shouldn't really be any anyhow).
306-
let cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);
306+
// We can use a dummy node-id here because we won't pay any mind
307+
// to region obligations that arise (there shouldn't really be any
308+
// anyhow).
309+
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
307310

308311
fulfill_cx.register_builtin_bound(infcx, ty, bound, cause);
309312

310313
// Note: we only assume something is `Copy` if we can
311314
// *definitively* show that it implements `Copy`. Otherwise,
312315
// assume it is move; linear is always ok.
313-
let result = fulfill_cx.select_all_or_error(infcx, param_env, infcx.tcx).is_ok();
316+
let result = match fulfill_cx.select_all_or_error(infcx, typer) {
317+
Ok(()) => Ok(Some(())), // Success, we know it implements Copy.
318+
Err(errors) => {
319+
// Check if overflow occurred anywhere and propagate that.
320+
if errors.iter().any(
321+
|err| match err.code { CodeSelectionError(Overflow) => true, _ => false })
322+
{
323+
return Err(Overflow);
324+
}
325+
326+
// Otherwise, if there were any hard errors, propagate an
327+
// arbitrary one of those. If no hard errors at all,
328+
// report ambiguity.
329+
let sel_error =
330+
errors.iter()
331+
.filter_map(|err| {
332+
match err.code {
333+
CodeAmbiguity => None,
334+
CodeSelectionError(ref e) => Some(e.clone()),
335+
CodeProjectionError(_) => {
336+
infcx.tcx.sess.span_bug(
337+
span,
338+
"projection error while selecting?")
339+
}
340+
}
341+
})
342+
.next();
343+
match sel_error {
344+
None => { Ok(None) }
345+
Some(e) => { Err(e) }
346+
}
347+
}
348+
};
314349

315350
debug!("type_known_to_meet_builtin_bound: ty={} bound={} result={}",
316351
ty.repr(infcx.tcx),
@@ -320,6 +355,40 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
320355
result
321356
}
322357

358+
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
359+
typer: &ty::UnboxedClosureTyper<'tcx>,
360+
ty: Ty<'tcx>,
361+
bound: ty::BuiltinBound,
362+
span: Span)
363+
-> bool
364+
{
365+
match evaluate_builtin_bound(infcx, typer, ty, bound, span) {
366+
Ok(Some(())) => {
367+
// definitely impl'd
368+
true
369+
}
370+
Ok(None) => {
371+
// ambiguous: if coherence check was successful, shouldn't
372+
// happen, but we might have reported an error and been
373+
// soldering on, so just treat this like not implemented
374+
false
375+
}
376+
Err(Overflow) => {
377+
infcx.tcx.sess.span_err(
378+
span,
379+
format!("overflow evaluating whether `{}` is `{}`",
380+
ty.user_string(infcx.tcx),
381+
bound.user_string(infcx.tcx))[]);
382+
suggest_new_overflow_limit(infcx.tcx, span);
383+
false
384+
}
385+
Err(_) => {
386+
// other errors: not implemented.
387+
false
388+
}
389+
}
390+
}
391+
323392
impl<'tcx,O> Obligation<'tcx,O> {
324393
pub fn new(cause: ObligationCause<'tcx>,
325394
trait_ref: O)

src/librustc/middle/ty.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3548,11 +3548,12 @@ fn type_impls_bound<'tcx>(cx: &ctxt<'tcx>,
35483548
}
35493549
}
35503550

3551-
let infcx = infer::new_infer_ctxt(cx);
3552-
let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound);
3551+
let infcx = infer::new_infer_ctxt(param_env.tcx);
3552+
3553+
let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound, span);
35533554

35543555
debug!("type_impls_bound({}, {}) = {}",
3555-
ty_to_string(cx, ty),
3556+
ty.repr(param_env.tcx),
35563557
bound,
35573558
is_impld);
35583559

@@ -3564,20 +3565,22 @@ fn type_impls_bound<'tcx>(cx: &ctxt<'tcx>,
35643565
is_impld
35653566
}
35663567

3567-
pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>,
3568-
ty: Ty<'tcx>,
3569-
param_env: &ParameterEnvironment<'tcx>)
3570-
-> bool
3568+
pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
3569+
span: Span,
3570+
ty: Ty<'tcx>)
3571+
-> bool
35713572
{
3572-
!type_impls_bound(cx, &cx.type_impls_copy_cache, param_env, ty, ty::BoundCopy)
3573+
let tcx = param_env.tcx;
3574+
!type_impls_bound(param_env, &tcx.type_impls_copy_cache, ty, ty::BoundCopy, span)
35733575
}
35743576

3575-
pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>,
3576-
ty: Ty<'tcx>,
3577-
param_env: &ParameterEnvironment<'tcx>)
3578-
-> bool
3577+
pub fn type_is_sized<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
3578+
span: Span,
3579+
ty: Ty<'tcx>)
3580+
-> bool
35793581
{
3580-
type_impls_bound(cx, &cx.type_impls_sized_cache, param_env, ty, ty::BoundSized)
3582+
let tcx = param_env.tcx;
3583+
type_impls_bound(param_env, &tcx.type_impls_sized_cache, ty, ty::BoundSized, span)
35813584
}
35823585

35833586
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> {
65626565
-> ast::CaptureClause {
65636566
self.capture_modes.borrow()[closure_expr_id].clone()
65646567
}
6568+
6569+
fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
6570+
type_moves_by_default(self, span, ty)
6571+
}
65656572
}
65666573

65676574
impl<'tcx> UnboxedClosureTyper<'tcx> for ty::ctxt<'tcx> {
@@ -6944,15 +6951,18 @@ pub enum CopyImplementationError {
69446951
TypeIsStructural,
69456952
}
69466953

6947-
pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>,
6948-
self_type: Ty<'tcx>,
6949-
param_env: &ParameterEnvironment<'tcx>)
6950-
-> Result<(),CopyImplementationError> {
6954+
pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tcx>,
6955+
span: Span,
6956+
self_type: Ty<'tcx>)
6957+
-> Result<(),CopyImplementationError>
6958+
{
6959+
let tcx = param_env.tcx;
6960+
69516961
match self_type.sty {
69526962
ty::ty_struct(struct_did, substs) => {
69536963
let fields = ty::struct_fields(tcx, struct_did, substs);
69546964
for field in fields.iter() {
6955-
if type_moves_by_default(tcx, field.mt.ty, param_env) {
6965+
if type_moves_by_default(param_env, span, field.mt.ty) {
69566966
return Err(FieldDoesNotImplementCopy(field.name))
69576967
}
69586968
}
@@ -6963,9 +6973,7 @@ pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>,
69636973
for variant_arg_type in variant.args.iter() {
69646974
let substd_arg_type =
69656975
variant_arg_type.subst(tcx, substs);
6966-
if type_moves_by_default(tcx,
6967-
substd_arg_type,
6968-
param_env) {
6976+
if type_moves_by_default(param_env, span, substd_arg_type) {
69696977
return Err(VariantDoesNotImplementCopy(variant.name))
69706978
}
69716979
}

src/librustc_trans/trans/_match.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,9 +1327,8 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
13271327
let trmode;
13281328
match bm {
13291329
ast::BindByValue(_)
1330-
if !ty::type_moves_by_default(tcx,
1331-
variable_ty,
1332-
&param_env) || reassigned => {
1330+
if !ty::type_moves_by_default(&param_env, span, variable_ty) || reassigned =>
1331+
{
13331332
llmatch = alloca_no_lifetime(bcx,
13341333
llvariable_ty.ptr_to(),
13351334
"__llmatch");

0 commit comments

Comments
 (0)