Skip to content

Commit 602b395

Browse files
committed
Auto merge of #49885 - spastorino:fn_ref_unsound, r=nikomatsakis
Fix unsoundness bug in functions input references Fixes #48803 r? @nikomatsakis
2 parents 56109db + 55fb12c commit 602b395

File tree

3 files changed

+75
-20
lines changed

3 files changed

+75
-20
lines changed

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+35-20
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@
1414
use borrow_check::nll::region_infer::Cause;
1515
use borrow_check::nll::region_infer::ClosureRegionRequirementsExt;
1616
use borrow_check::nll::universal_regions::UniversalRegions;
17+
use dataflow::move_paths::MoveData;
1718
use dataflow::FlowAtLocation;
1819
use dataflow::MaybeInitializedPlaces;
19-
use dataflow::move_paths::MoveData;
2020
use rustc::hir::def_id::DefId;
21-
use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult};
2221
use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
23-
use rustc::traits::{self, Normalized, TraitEngine};
22+
use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult};
23+
use rustc::mir::tcx::PlaceTy;
24+
use rustc::mir::visit::{PlaceContext, Visitor};
25+
use rustc::mir::*;
2426
use rustc::traits::query::NoSolution;
27+
use rustc::traits::{self, Normalized, TraitEngine};
2528
use rustc::ty::error::TypeError;
2629
use rustc::ty::fold::TypeFoldable;
2730
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
28-
use rustc::mir::*;
29-
use rustc::mir::tcx::PlaceTy;
30-
use rustc::mir::visit::{PlaceContext, Visitor};
3131
use std::fmt;
3232
use syntax::ast;
3333
use syntax_pos::{Span, DUMMY_SP};
@@ -61,8 +61,8 @@ macro_rules! span_mirbug_and_err {
6161
})
6262
}
6363

64-
mod liveness;
6564
mod input_output;
65+
mod liveness;
6666

6767
/// Type checks the given `mir` in the context of the inference
6868
/// context `infcx`. Returns any region constraints that have yet to
@@ -275,7 +275,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
275275
tcx.predicates_of(def_id).instantiate(tcx, substs);
276276
let predicates =
277277
type_checker.normalize(&instantiated_predicates.predicates, location);
278-
type_checker.prove_predicates(&predicates, location);
278+
type_checker.prove_predicates(predicates.iter().cloned(), location);
279279
}
280280

281281
value.ty
@@ -763,9 +763,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
763763
}
764764
StatementKind::UserAssertTy(ref c_ty, ref local) => {
765765
let local_ty = mir.local_decls()[*local].ty;
766-
let (ty, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
767-
stmt.source_info.span, c_ty);
768-
debug!("check_stmt: user_assert_ty ty={:?} local_ty={:?}", ty, local_ty);
766+
let (ty, _) = self.infcx
767+
.instantiate_canonical_with_fresh_inference_vars(stmt.source_info.span, c_ty);
768+
debug!(
769+
"check_stmt: user_assert_ty ty={:?} local_ty={:?}",
770+
ty, local_ty
771+
);
769772
if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) {
770773
span_mirbug!(
771774
self,
@@ -895,6 +898,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
895898
let sig = self.normalize(&sig, term_location);
896899
self.check_call_dest(mir, term, &sig, destination, term_location);
897900

901+
self.prove_predicates(
902+
sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
903+
term_location,
904+
);
905+
898906
// The ordinary liveness rules will ensure that all
899907
// regions in the type of the callee are live here. We
900908
// then further constrain the late-bound regions that
@@ -1508,28 +1516,35 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
15081516

15091517
let predicates = self.normalize(&instantiated_predicates.predicates, location);
15101518
debug!("prove_aggregate_predicates: predicates={:?}", predicates);
1511-
self.prove_predicates(&predicates, location);
1519+
self.prove_predicates(predicates.iter().cloned(), location);
15121520
}
15131521

15141522
fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) {
15151523
self.prove_predicates(
1516-
&[
1517-
ty::Predicate::Trait(trait_ref.to_poly_trait_ref().to_poly_trait_predicate()),
1518-
],
1524+
[ty::Predicate::Trait(
1525+
trait_ref.to_poly_trait_ref().to_poly_trait_predicate(),
1526+
)].iter()
1527+
.cloned(),
15191528
location,
15201529
);
15211530
}
15221531

1523-
fn prove_predicates(&mut self, predicates: &[ty::Predicate<'tcx>], location: Location) {
1532+
fn prove_predicates(
1533+
&mut self,
1534+
predicates: impl IntoIterator<Item = ty::Predicate<'tcx>>,
1535+
location: Location,
1536+
) {
1537+
let mut predicates_iter = predicates.into_iter();
1538+
15241539
debug!(
15251540
"prove_predicates(predicates={:?}, location={:?})",
1526-
predicates, location
1541+
predicates_iter.by_ref().collect::<Vec<_>>(),
1542+
location
15271543
);
15281544
self.fully_perform_op(location.at_self(), |this| {
15291545
let cause = this.misc(this.last_span);
1530-
let obligations = predicates
1531-
.iter()
1532-
.map(|&p| traits::Obligation::new(cause.clone(), this.param_env, p))
1546+
let obligations = predicates_iter
1547+
.map(|p| traits::Obligation::new(cause.clone(), this.param_env, p))
15331548
.collect();
15341549
Ok(InferOk {
15351550
value: (),

src/test/ui/issue-48803.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(nll)]
12+
13+
fn flatten<'a, 'b, T>(x: &'a &'b T) -> &'a T {
14+
x
15+
}
16+
17+
fn main() {
18+
let mut x = "original";
19+
let y = &x;
20+
let z = &y;
21+
let w = flatten(z);
22+
x = "modified";
23+
//~^ ERROR cannot assign to `x` because it is borrowed [E0506]
24+
println!("{}", w); // prints "modified"
25+
}

src/test/ui/issue-48803.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0506]: cannot assign to `x` because it is borrowed
2+
--> $DIR/issue-48803.rs:22:5
3+
|
4+
LL | let y = &x;
5+
| -- borrow of `x` occurs here
6+
...
7+
LL | x = "modified";
8+
| ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
9+
LL | //~^ ERROR cannot assign to `x` because it is borrowed [E0506]
10+
LL | println!("{}", w); // prints "modified"
11+
| - borrow later used here
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0506`.

0 commit comments

Comments
 (0)