diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 544cb5eefc886..faa382738b06f 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -14,20 +14,20 @@ use borrow_check::nll::region_infer::Cause; use borrow_check::nll::region_infer::ClosureRegionRequirementsExt; use borrow_check::nll::universal_regions::UniversalRegions; +use dataflow::move_paths::MoveData; use dataflow::FlowAtLocation; use dataflow::MaybeInitializedPlaces; -use dataflow::move_paths::MoveData; use rustc::hir::def_id::DefId; -use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; use rustc::infer::region_constraints::{GenericKind, RegionConstraintData}; -use rustc::traits::{self, Normalized, TraitEngine}; +use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; +use rustc::mir::tcx::PlaceTy; +use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::*; use rustc::traits::query::NoSolution; +use rustc::traits::{self, Normalized, TraitEngine}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants}; -use rustc::mir::*; -use rustc::mir::tcx::PlaceTy; -use rustc::mir::visit::{PlaceContext, Visitor}; use std::fmt; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; @@ -61,8 +61,8 @@ macro_rules! span_mirbug_and_err { }) } -mod liveness; mod input_output; +mod liveness; /// Type checks the given `mir` in the context of the inference /// context `infcx`. Returns any region constraints that have yet to @@ -275,7 +275,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { tcx.predicates_of(def_id).instantiate(tcx, substs); let predicates = type_checker.normalize(&instantiated_predicates.predicates, location); - type_checker.prove_predicates(&predicates, location); + type_checker.prove_predicates(predicates.iter().cloned(), location); } value.ty @@ -763,9 +763,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } StatementKind::UserAssertTy(ref c_ty, ref local) => { let local_ty = mir.local_decls()[*local].ty; - let (ty, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( - stmt.source_info.span, c_ty); - debug!("check_stmt: user_assert_ty ty={:?} local_ty={:?}", ty, local_ty); + let (ty, _) = self.infcx + .instantiate_canonical_with_fresh_inference_vars(stmt.source_info.span, c_ty); + debug!( + "check_stmt: user_assert_ty ty={:?} local_ty={:?}", + ty, local_ty + ); if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) { span_mirbug!( self, @@ -895,6 +898,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let sig = self.normalize(&sig, term_location); self.check_call_dest(mir, term, &sig, destination, term_location); + self.prove_predicates( + sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)), + term_location, + ); + // The ordinary liveness rules will ensure that all // regions in the type of the callee are live here. We // then further constrain the late-bound regions that @@ -1508,28 +1516,35 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let predicates = self.normalize(&instantiated_predicates.predicates, location); debug!("prove_aggregate_predicates: predicates={:?}", predicates); - self.prove_predicates(&predicates, location); + self.prove_predicates(predicates.iter().cloned(), location); } 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()), - ], + [ty::Predicate::Trait( + trait_ref.to_poly_trait_ref().to_poly_trait_predicate(), + )].iter() + .cloned(), location, ); } - fn prove_predicates(&mut self, predicates: &[ty::Predicate<'tcx>], location: Location) { + fn prove_predicates( + &mut self, + predicates: impl IntoIterator>, + location: Location, + ) { + let mut predicates_iter = predicates.into_iter(); + debug!( "prove_predicates(predicates={:?}, location={:?})", - predicates, location + predicates_iter.by_ref().collect::>(), + 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)) + let obligations = predicates_iter + .map(|p| traits::Obligation::new(cause.clone(), this.param_env, p)) .collect(); Ok(InferOk { value: (), diff --git a/src/test/ui/issue-48803.rs b/src/test/ui/issue-48803.rs new file mode 100644 index 0000000000000..c6d14ace8b344 --- /dev/null +++ b/src/test/ui/issue-48803.rs @@ -0,0 +1,25 @@ +// Copyright 2018 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. + +#![feature(nll)] + +fn flatten<'a, 'b, T>(x: &'a &'b T) -> &'a T { + x +} + +fn main() { + let mut x = "original"; + let y = &x; + let z = &y; + let w = flatten(z); + x = "modified"; + //~^ ERROR cannot assign to `x` because it is borrowed [E0506] + println!("{}", w); // prints "modified" +} diff --git a/src/test/ui/issue-48803.stderr b/src/test/ui/issue-48803.stderr new file mode 100644 index 0000000000000..b37e2c07d23d7 --- /dev/null +++ b/src/test/ui/issue-48803.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/issue-48803.rs:22:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +... +LL | x = "modified"; + | ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here +LL | //~^ ERROR cannot assign to `x` because it is borrowed [E0506] +LL | println!("{}", w); // prints "modified" + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`.