Skip to content

Commit e7261f3

Browse files
committed
Auto merge of #27641 - nikomatsakis:soundness-rfc-1214, r=nrc
This PR implements the majority of RFC 1214. In particular, it implements: - the new outlives relation - comprehensive WF checking For the most part, new code receives warnings, not errors, though 3 regressions were found via a crater run. There are some deviations from RFC 1214. Most notably: - we still consider implied bounds from fn ret; this intersects other soundness issues that I intend to address in detail in a follow-up RFC. Fixing this without breaking a lot of code probably requires rewriting compare-method somewhat (which is probably a good thing). - object types do not check trait bounds for fear of encountering `Self`; this was left as an unresolved question in RFC 1214, but ultimately feels inconsistent. Both of those two issues are highlighted in the tracking issue, #27579. #27579 also includes a testing matrix with new tests that I wrote -- these probably duplicate some existing tests, I tried to check but wasn't quite sure what to look for. I tried to be thorough in testing the WF relation, at least, but would welcome suggestions for missing tests. r? @nrc (or perhaps someone else?)
2 parents 0649b16 + 7f8942c commit e7261f3

File tree

155 files changed

+4732
-651
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

155 files changed

+4732
-651
lines changed

src/libcore/iter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2135,7 +2135,7 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F>
21352135
/// two `Step` objects.
21362136
#[unstable(feature = "step_trait",
21372137
reason = "likely to be replaced by finer-grained traits")]
2138-
pub trait Step: PartialOrd {
2138+
pub trait Step: PartialOrd+Sized {
21392139
/// Steps `self` if possible.
21402140
fn step(&self, by: &Self) -> Option<Self>;
21412141

src/libcore/marker.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub trait Sized {
5656
/// Types that can be "unsized" to a dynamically sized type.
5757
#[unstable(feature = "unsize")]
5858
#[lang="unsize"]
59-
pub trait Unsize<T> {
59+
pub trait Unsize<T: ?Sized> {
6060
// Empty.
6161
}
6262

src/libcore/num/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use char::CharExt;
1919
use cmp::{Eq, PartialOrd};
2020
use fmt;
2121
use intrinsics;
22-
use marker::Copy;
22+
use marker::{Copy, Sized};
2323
use mem::size_of;
2424
use option::Option::{self, Some, None};
2525
use result::Result::{self, Ok, Err};
@@ -1263,7 +1263,7 @@ pub enum FpCategory {
12631263
#[doc(hidden)]
12641264
#[unstable(feature = "core_float",
12651265
reason = "stable interface is via `impl f{32,64}` in later crates")]
1266-
pub trait Float {
1266+
pub trait Float: Sized {
12671267
/// Returns the NaN value.
12681268
fn nan() -> Self;
12691269
/// Returns the infinite value.

src/libcore/str/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use default::Default;
2525
use fmt;
2626
use iter::ExactSizeIterator;
2727
use iter::{Map, Iterator, DoubleEndedIterator};
28+
use marker::Sized;
2829
use mem;
2930
use ops::{Fn, FnMut, FnOnce};
3031
use option::Option::{self, None, Some};
@@ -37,7 +38,7 @@ pub mod pattern;
3738
/// A trait to abstract the idea of creating a new instance of a type from a
3839
/// string.
3940
#[stable(feature = "rust1", since = "1.0.0")]
40-
pub trait FromStr {
41+
pub trait FromStr: Sized {
4142
/// The associated error which can be returned from parsing.
4243
#[stable(feature = "rust1", since = "1.0.0")]
4344
type Err;

src/libgraphviz/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ pub type Edges<'a,E> = Cow<'a,[E]>;
561561
/// `Cow<[T]>` to leave implementers the freedom to create
562562
/// entirely new vectors or to pass back slices into internally owned
563563
/// vectors.
564-
pub trait GraphWalk<'a, N, E> {
564+
pub trait GraphWalk<'a, N: Clone, E: Clone> {
565565
/// Returns all the nodes in this graph.
566566
fn nodes(&'a self) -> Nodes<'a, N>;
567567
/// Returns all of the edges in this graph.

src/librand/distributions/range.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
// this is surprisingly complicated to be both generic & correct
1414

15+
use core::marker::Sized;
1516
use Rng;
1617
use distributions::{Sample, IndependentSample};
1718

@@ -57,7 +58,7 @@ impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
5758
/// uniformly between two values. This should not be used directly,
5859
/// and is only to facilitate `Range`.
5960
#[doc(hidden)]
60-
pub trait SampleRange {
61+
pub trait SampleRange: Sized {
6162
/// Construct the `Range` object that `sample_range`
6263
/// requires. This should not ever be called directly, only via
6364
/// `Range::new`, which will check that `low < high`, so this

src/librustc/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ pub mod middle {
129129
pub mod lang_items;
130130
pub mod liveness;
131131
pub mod mem_categorization;
132+
pub mod outlives;
132133
pub mod pat_util;
133134
pub mod privacy;
134135
pub mod reachable;
@@ -143,6 +144,7 @@ pub mod middle {
143144
pub mod ty_match;
144145
pub mod ty_relate;
145146
pub mod ty_walk;
147+
pub mod wf;
146148
pub mod weak_lang_items;
147149
}
148150

src/librustc/metadata/tydecode.rs

+6
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,12 @@ fn parse_predicate_<'a,'tcx, F>(st: &mut PState<'a, 'tcx>,
790790
'o' => ty::Binder(ty::OutlivesPredicate(parse_ty_(st, conv),
791791
parse_region_(st, conv))).to_predicate(),
792792
'p' => ty::Binder(parse_projection_predicate_(st, conv)).to_predicate(),
793+
'w' => ty::Predicate::WellFormed(parse_ty_(st, conv)),
794+
'O' => {
795+
let def_id = parse_def_(st, NominalType, conv);
796+
assert_eq!(next(st), '|');
797+
ty::Predicate::ObjectSafe(def_id)
798+
}
793799
c => panic!("Encountered invalid character in metadata: {}", c)
794800
}
795801
}

src/librustc/metadata/tyencode.rs

+7
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,13 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder,
457457
mywrite!(w, "p");
458458
enc_projection_predicate(w, cx, data)
459459
}
460+
ty::Predicate::WellFormed(data) => {
461+
mywrite!(w, "w");
462+
enc_ty(w, cx, data);
463+
}
464+
ty::Predicate::ObjectSafe(trait_def_id) => {
465+
mywrite!(w, "O{}|", (cx.ds)(trait_def_id));
466+
}
460467
}
461468
}
462469

src/librustc/middle/astencode.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
10611061
}
10621062
}
10631063

1064-
trait doc_decoder_helpers {
1064+
trait doc_decoder_helpers: Sized {
10651065
fn as_int(&self) -> isize;
10661066
fn opt_child(&self, tag: c::astencode_tag) -> Option<Self>;
10671067
}

src/librustc/middle/expr_use_visitor.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ impl OverloadedCallType {
239239
// supplies types from the tree. After type checking is complete, you
240240
// can just use the tcx as the typer.
241241

242-
pub struct ExprUseVisitor<'d,'t,'a: 't, 'tcx:'a> {
242+
pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d> {
243243
typer: &'t infer::InferCtxt<'a, 'tcx>,
244244
mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
245245
delegate: &'d mut (Delegate<'tcx>+'d),
@@ -273,7 +273,8 @@ enum PassArgs {
273273
impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
274274
pub fn new(delegate: &'d mut Delegate<'tcx>,
275275
typer: &'t infer::InferCtxt<'a, 'tcx>)
276-
-> ExprUseVisitor<'d,'t,'a, 'tcx> {
276+
-> ExprUseVisitor<'d,'t,'a,'tcx>
277+
{
277278
ExprUseVisitor {
278279
typer: typer,
279280
mc: mc::MemCategorizationContext::new(typer),

src/librustc/middle/free_region.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
//! This file defines
1212
13-
use middle::implicator::Implication;
13+
use middle::wf::ImpliedBound;
1414
use middle::ty::{self, FreeRegion};
1515
use util::common::can_reach;
1616
use util::nodemap::{FnvHashMap, FnvHashSet};
@@ -30,18 +30,19 @@ impl FreeRegionMap {
3030
FreeRegionMap { map: FnvHashMap(), statics: FnvHashSet() }
3131
}
3232

33-
pub fn relate_free_regions_from_implications<'tcx>(&mut self,
34-
implications: &[Implication<'tcx>])
33+
pub fn relate_free_regions_from_implied_bounds<'tcx>(&mut self,
34+
implied_bounds: &[ImpliedBound<'tcx>])
3535
{
36-
for implication in implications {
37-
debug!("implication: {:?}", implication);
38-
match *implication {
39-
Implication::RegionSubRegion(_, ty::ReFree(free_a), ty::ReFree(free_b)) => {
36+
debug!("relate_free_regions_from_implied_bounds()");
37+
for implied_bound in implied_bounds {
38+
debug!("implied bound: {:?}", implied_bound);
39+
match *implied_bound {
40+
ImpliedBound::RegionSubRegion(ty::ReFree(free_a), ty::ReFree(free_b)) => {
4041
self.relate_free_regions(free_a, free_b);
4142
}
42-
Implication::RegionSubRegion(..) |
43-
Implication::RegionSubGeneric(..) |
44-
Implication::Predicate(..) => {
43+
ImpliedBound::RegionSubRegion(..) |
44+
ImpliedBound::RegionSubParam(..) |
45+
ImpliedBound::RegionSubProjection(..) => {
4546
}
4647
}
4748
}
@@ -56,6 +57,8 @@ impl FreeRegionMap {
5657
ty::Predicate::Projection(..) |
5758
ty::Predicate::Trait(..) |
5859
ty::Predicate::Equate(..) |
60+
ty::Predicate::WellFormed(..) |
61+
ty::Predicate::ObjectSafe(..) |
5962
ty::Predicate::TypeOutlives(..) => {
6063
// No region bounds here
6164
}

src/librustc/middle/implicator.rs

+5-51
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use middle::infer::{InferCtxt, GenericKind};
1414
use middle::subst::Substs;
1515
use middle::traits;
16-
use middle::ty::{self, RegionEscape, ToPolyTraitRef, ToPredicate, Ty};
16+
use middle::ty::{self, RegionEscape, ToPredicate, Ty};
1717
use middle::ty_fold::{TypeFoldable, TypeFolder};
1818

1919
use syntax::ast;
@@ -278,9 +278,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
278278

279279
for predicate in predicates.predicates.as_slice() {
280280
match *predicate {
281-
ty::Predicate::Trait(ref data) => {
282-
self.accumulate_from_assoc_types_transitive(data);
283-
}
281+
ty::Predicate::Trait(..) => { }
284282
ty::Predicate::Equate(..) => { }
285283
ty::Predicate::Projection(..) => { }
286284
ty::Predicate::RegionOutlives(ref data) => {
@@ -301,6 +299,9 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
301299
}
302300
}
303301
}
302+
ty::Predicate::ObjectSafe(_) |
303+
ty::Predicate::WellFormed(_) => {
304+
}
304305
}
305306
}
306307

@@ -349,53 +350,6 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
349350
}
350351
}
351352

352-
/// Given that there is a requirement that `Foo<X> : 'a`, where
353-
/// `Foo` is declared like `struct Foo<T> where T : SomeTrait`,
354-
/// this code finds all the associated types defined in
355-
/// `SomeTrait` (and supertraits) and adds a requirement that `<X
356-
/// as SomeTrait>::N : 'a` (where `N` is some associated type
357-
/// defined in `SomeTrait`). This rule only applies to
358-
/// trait-bounds that are not higher-ranked, because we cannot
359-
/// project out of a HRTB. This rule helps code using associated
360-
/// types to compile, see Issue #22246 for an example.
361-
fn accumulate_from_assoc_types_transitive(&mut self,
362-
data: &ty::PolyTraitPredicate<'tcx>)
363-
{
364-
debug!("accumulate_from_assoc_types_transitive({:?})",
365-
data);
366-
367-
for poly_trait_ref in traits::supertraits(self.tcx(), data.to_poly_trait_ref()) {
368-
match self.tcx().no_late_bound_regions(&poly_trait_ref) {
369-
Some(trait_ref) => { self.accumulate_from_assoc_types(trait_ref); }
370-
None => { }
371-
}
372-
}
373-
}
374-
375-
fn accumulate_from_assoc_types(&mut self,
376-
trait_ref: ty::TraitRef<'tcx>)
377-
{
378-
debug!("accumulate_from_assoc_types({:?})",
379-
trait_ref);
380-
381-
let trait_def_id = trait_ref.def_id;
382-
let trait_def = self.tcx().lookup_trait_def(trait_def_id);
383-
let assoc_type_projections: Vec<_> =
384-
trait_def.associated_type_names
385-
.iter()
386-
.map(|&name| self.tcx().mk_projection(trait_ref.clone(), name))
387-
.collect();
388-
debug!("accumulate_from_assoc_types: assoc_type_projections={:?}",
389-
assoc_type_projections);
390-
let tys = match self.fully_normalize(&assoc_type_projections) {
391-
Ok(tys) => { tys }
392-
Err(ErrorReported) => { return; }
393-
};
394-
for ty in tys {
395-
self.accumulate_from_ty(ty);
396-
}
397-
}
398-
399353
fn accumulate_from_object_ty(&mut self,
400354
ty: Ty<'tcx>,
401355
region_bound: ty::Region,

0 commit comments

Comments
 (0)