diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index f5595d07340bb..9788ec2a5e453 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1201,6 +1201,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// translate them into the form that the NLL solver /// understands. See the NLL module for mode details. pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> { + assert!(self.region_obligations.borrow().is_empty(), + "region_obligations not empty: {:#?}", + self.region_obligations.borrow()); + self.borrow_region_constraints().take_and_reset_data() } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 1a74f32700151..3599a3174f725 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -17,7 +17,7 @@ use rustc::infer::region_constraints::RegionConstraintData; use rustc::traits::{self, FulfillmentContext}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; -use rustc::ty::{self, Ty, TyCtxt, TypeVariants}; +use rustc::ty::{self, Ty, TyCtxt, TypeVariants, ToPolyTraitRef}; use rustc::middle::const_val::ConstVal; use rustc::mir::*; use rustc::mir::tcx::PlaceTy; @@ -545,6 +545,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { span_mirbug!(self, "", "errors selecting obligation: {:?}", e); } + self.infcx.process_registered_region_obligations( + &[], + None, + self.param_env, + self.body_id, + ); + let data = self.infcx.take_and_reset_region_constraints(); if !data.is_empty() { self.constraints @@ -1110,13 +1117,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { + let tcx = self.tcx(); + match rvalue { Rvalue::Aggregate(ak, ops) => { self.check_aggregate_rvalue(mir, rvalue, ak, ops, location) } + + Rvalue::Repeat(operand, const_usize) => { + if const_usize.as_u64() > 1 { + let operand_ty = operand.ty(mir, tcx); + + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().copy_trait().unwrap(), + substs: tcx.mk_substs_trait(operand_ty, &[]), + }; + + self.prove_trait_ref(trait_ref, location); + } + } + // FIXME: These other cases have to be implemented in future PRs Rvalue::Use(..) | - Rvalue::Repeat(..) | Rvalue::Ref(..) | Rvalue::Len(..) | Rvalue::Cast(..) | @@ -1205,6 +1227,31 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } + fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) { + self.prove_predicates( + &[ + ty::Predicate::Trait(trait_ref.to_poly_trait_ref().to_poly_trait_predicate()), + ], + location, + ); + } + + fn prove_predicates(&mut self, predicates: &[ty::Predicate<'tcx>], location: Location) { + self.fully_perform_op(location.at_self(), |this| { + let cause = this.misc(this.last_span); + let obligations = predicates + .iter() + .map(|&p| { + traits::Obligation::new(cause.clone(), this.param_env, p) + }) + .collect(); + Ok(InferOk { + value: (), + obligations, + }) + }).unwrap() + } + fn typeck_mir(&mut self, mir: &Mir<'tcx>) { self.last_span = mir.span; debug!("run_on_mir: {:?}", mir.span); @@ -1237,7 +1284,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { { self.fully_perform_op(location.at_self(), |this| { let mut selcx = traits::SelectionContext::new(this.infcx); - let cause = traits::ObligationCause::misc(this.last_span, ast::CRATE_NODE_ID); + let cause = this.misc(this.last_span); let traits::Normalized { value, obligations } = traits::normalize(&mut selcx, this.param_env, cause, value); Ok(InferOk { value, obligations }) diff --git a/src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs b/src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs new file mode 100644 index 0000000000000..aae0cd3fdb00a --- /dev/null +++ b/src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs @@ -0,0 +1,39 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z borrowck=mir -Z nll + +#![allow(warnings)] + +struct Foo { + t: T, +} + +impl Copy for Foo {} +impl Clone for Foo { + fn clone(&self) -> Self { + *self + } +} + +fn main() { + let mut x = 22; + + { + let p = &x; //~ ERROR borrowed value does not live long enough + let w = Foo { t: p }; + + let v = [w; 22]; + } + + x += 1; + //~^ ERROR cannot assign to `x` because it is borrowed [E0506] +} +//~^ ERROR borrowed value does not live long enough [E0597]