Skip to content

Commit

Permalink
Auto merge of #49885 - spastorino:fn_ref_unsound, r=nikomatsakis
Browse files Browse the repository at this point in the history
Fix unsoundness bug in functions input references

Fixes #48803

r? @nikomatsakis
  • Loading branch information
bors committed Apr 15, 2018
2 parents 56109db + 55fb12c commit 602b395
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 20 deletions.
55 changes: 35 additions & 20 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<Item = ty::Predicate<'tcx>>,
location: Location,
) {
let mut predicates_iter = predicates.into_iter();

debug!(
"prove_predicates(predicates={:?}, location={:?})",
predicates, location
predicates_iter.by_ref().collect::<Vec<_>>(),
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: (),
Expand Down
25 changes: 25 additions & 0 deletions src/test/ui/issue-48803.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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"
}
15 changes: 15 additions & 0 deletions src/test/ui/issue-48803.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 602b395

Please sign in to comment.