Skip to content

Commit aec6535

Browse files
authoredFeb 21, 2018
Rollup merge of rust-lang#47833 - Aaron1011:final_auto_trait, r=GuillaumeGomez
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. ![Auto trait implementations for Cloned](https://i.imgur.com/XtTV6IJ.png) On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. ![Auto trait implementors for Send](https://i.imgur.com/3GRBpTy.png) Synthesized impls for a particular auto trait ('synthetic impls') take generic bounds into account. For example, a type ```rust struct Foo<T>(T) ``` will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: ```rust struct Foo<T>(T) struct Wrapper<T>(Foo<T>) unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow ``` Then Wrapper will have the following impl generated: ```rust impl<T> Send for Wrapper<T> ``` reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls: ![A ridiculous demonstration type](https://i.imgur.com/TkZMWuN.png) However, if a type can *never* implement a particular auto trait (e.g. `struct MyStruct<T>(*const T)`), then a negative impl will be generated (in this case, `impl<T> !Send for MyStruct<T>`) All of this means that a user should be able to copy-paste a syntheticimpl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2 parents 2a32060 + 44d07df commit aec6535

File tree

28 files changed

+2496
-152
lines changed

28 files changed

+2496
-152
lines changed
 

‎src/librustc/hir/map/definitions.rs

+4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ impl DefPathTable {
7272
index
7373
}
7474

75+
pub fn next_id(&self, address_space: DefIndexAddressSpace) -> DefIndex {
76+
DefIndex::from_array_index(self.index_to_key[address_space.index()].len(), address_space)
77+
}
78+
7579
#[inline(always)]
7680
pub fn def_key(&self, index: DefIndex) -> DefKey {
7781
self.index_to_key[index.address_space().index()]

‎src/librustc/infer/mod.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
180180
// for each body-id in this map, which will process the
181181
// obligations within. This is expected to be done 'late enough'
182182
// that all type inference variables have been bound and so forth.
183-
region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
183+
pub region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
184184
}
185185

186186
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
@@ -1555,11 +1555,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
15551555
InferOk { value, obligations }
15561556
}
15571557

1558-
fn borrow_region_constraints(&self) -> RefMut<'_, RegionConstraintCollector<'tcx>> {
1558+
pub fn borrow_region_constraints(&self) -> RefMut<'_, RegionConstraintCollector<'tcx>> {
15591559
RefMut::map(
15601560
self.region_constraints.borrow_mut(),
15611561
|c| c.as_mut().expect("region constraints already solved"))
15621562
}
1563+
1564+
/// Clears the selection, evaluation, and projection cachesThis is useful when
1565+
/// repeatedly attemping to select an Obligation while changing only
1566+
/// its ParamEnv, since FulfillmentContext doesn't use 'probe'
1567+
pub fn clear_caches(&self) {
1568+
self.selection_cache.clear();
1569+
self.evaluation_cache.clear();
1570+
self.projection_cache.borrow_mut().clear();
1571+
}
15631572
}
15641573

15651574
impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> {

‎src/librustc/infer/region_constraints/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ pub type VarOrigins = IndexVec<RegionVid, RegionVariableOrigin>;
8282
/// Describes constraints between the region variables and other
8383
/// regions, as well as other conditions that must be verified, or
8484
/// assumptions that can be made.
85-
#[derive(Debug, Default)]
85+
#[derive(Debug, Default, Clone)]
8686
pub struct RegionConstraintData<'tcx> {
8787
/// Constraints of the form `A <= B`, where either `A` or `B` can
8888
/// be a region variable (or neither, as it happens).
@@ -142,7 +142,7 @@ pub enum Constraint<'tcx> {
142142
/// outlive `RS`. Therefore verify that `R <= RS[i]` for some
143143
/// `i`. Inference variables may be involved (but this verification
144144
/// step doesn't influence inference).
145-
#[derive(Debug)]
145+
#[derive(Debug, Clone)]
146146
pub struct Verify<'tcx> {
147147
pub kind: GenericKind<'tcx>,
148148
pub origin: SubregionOrigin<'tcx>,
@@ -159,7 +159,7 @@ pub enum GenericKind<'tcx> {
159159
/// When we introduce a verification step, we wish to test that a
160160
/// particular region (let's call it `'min`) meets some bound.
161161
/// The bound is described the by the following grammar:
162-
#[derive(Debug)]
162+
#[derive(Debug, Clone)]
163163
pub enum VerifyBound<'tcx> {
164164
/// B = exists {R} --> some 'r in {R} must outlive 'min
165165
///
@@ -288,6 +288,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
288288
&self.var_origins
289289
}
290290

291+
pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> {
292+
&self.data
293+
}
294+
291295
/// Once all the constraints have been gathered, extract out the final data.
292296
///
293297
/// Not legal during a snapshot.

‎src/librustc/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ use syntax_pos::{Span, DUMMY_SP};
3232
pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult};
3333
pub use self::fulfill::FulfillmentContext;
3434
pub use self::project::MismatchedProjectionTypes;
35-
pub use self::project::{normalize, normalize_projection_type, Normalized};
36-
pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal};
35+
pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type};
36+
pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal, Normalized};
3737
pub use self::object_safety::ObjectSafetyViolation;
3838
pub use self::object_safety::MethodViolationCode;
3939
pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};

‎src/librustc/traits/project.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,10 @@ impl<'tcx> ProjectionCache<'tcx> {
15961596
}
15971597
}
15981598

1599+
pub fn clear(&mut self) {
1600+
self.map.clear();
1601+
}
1602+
15991603
pub fn snapshot(&mut self) -> ProjectionCacheSnapshot {
16001604
ProjectionCacheSnapshot { snapshot: self.map.snapshot() }
16011605
}

‎src/librustc/traits/select.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
9393
inferred_obligations: SnapshotVec<InferredObligationsSnapshotVecDelegate<'tcx>>,
9494

9595
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
96+
97+
/// Controls whether or not to filter out negative impls when selecting.
98+
/// This is used in librustdoc to distinguish between the lack of an impl
99+
/// and a negative impl
100+
allow_negative_impls: bool
96101
}
97102

98103
#[derive(Clone, Debug)]
@@ -424,6 +429,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
424429
intercrate: None,
425430
inferred_obligations: SnapshotVec::new(),
426431
intercrate_ambiguity_causes: None,
432+
allow_negative_impls: false,
427433
}
428434
}
429435

@@ -436,6 +442,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
436442
intercrate: Some(mode),
437443
inferred_obligations: SnapshotVec::new(),
438444
intercrate_ambiguity_causes: None,
445+
allow_negative_impls: false,
446+
}
447+
}
448+
449+
pub fn with_negative(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
450+
allow_negative_impls: bool) -> SelectionContext<'cx, 'gcx, 'tcx> {
451+
debug!("with_negative({:?})", allow_negative_impls);
452+
SelectionContext {
453+
infcx,
454+
freshener: infcx.freshener(),
455+
intercrate: None,
456+
inferred_obligations: SnapshotVec::new(),
457+
intercrate_ambiguity_causes: None,
458+
allow_negative_impls,
439459
}
440460
}
441461

@@ -1086,7 +1106,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10861106
fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
10871107
-> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
10881108
if let ImplCandidate(def_id) = candidate {
1089-
if self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative {
1109+
if !self.allow_negative_impls &&
1110+
self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative {
10901111
return Err(Unimplemented)
10911112
}
10921113
}
@@ -3337,6 +3358,10 @@ impl<'tcx> SelectionCache<'tcx> {
33373358
hashmap: RefCell::new(FxHashMap())
33383359
}
33393360
}
3361+
3362+
pub fn clear(&self) {
3363+
*self.hashmap.borrow_mut() = FxHashMap()
3364+
}
33403365
}
33413366

33423367
impl<'tcx> EvaluationCache<'tcx> {
@@ -3345,6 +3370,10 @@ impl<'tcx> EvaluationCache<'tcx> {
33453370
hashmap: RefCell::new(FxHashMap())
33463371
}
33473372
}
3373+
3374+
pub fn clear(&self) {
3375+
*self.hashmap.borrow_mut() = FxHashMap()
3376+
}
33483377
}
33493378

33503379
impl<'o,'tcx> TraitObligationStack<'o,'tcx> {

‎src/librustc_data_structures/snapshot_map/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ impl<K, V> SnapshotMap<K, V>
4545
}
4646
}
4747

48+
pub fn clear(&mut self) {
49+
self.map.clear();
50+
self.undo_log.clear();
51+
}
52+
4853
pub fn insert(&mut self, key: K, value: V) -> bool {
4954
match self.map.insert(key.clone(), value) {
5055
None => {

0 commit comments

Comments
 (0)
Please sign in to comment.