Skip to content

Commit 1b2de17

Browse files
author
Alexander Regueiro
committed
Applied suggestions from code review.
1 parent 51cb60c commit 1b2de17

File tree

4 files changed

+95
-94
lines changed

4 files changed

+95
-94
lines changed

src/librustc/traits/auto_trait.rs

+64-63
Original file line numberDiff line numberDiff line change
@@ -233,44 +233,45 @@ impl<'tcx> AutoTraitFinder<'tcx> {
233233
}
234234

235235
impl AutoTraitFinder<'tcx> {
236-
// The core logic responsible for computing the bounds for our synthesized impl.
237-
//
238-
// To calculate the bounds, we call `SelectionContext.select` in a loop. Like
239-
// `FulfillmentContext`, we recursively select the nested obligations of predicates we
240-
// encounter. However, whenever we encounter an `UnimplementedError` involving a type parameter,
241-
// we add it to our `ParamEnv`. Since our goal is to determine when a particular type implements
242-
// an auto trait, Unimplemented errors tell us what conditions need to be met.
243-
//
244-
// This method ends up working somewhat similarly to `FulfillmentContext`, but with a few key
245-
// differences. `FulfillmentContext` works under the assumption that it's dealing with concrete
246-
// user code. According, it considers all possible ways that a `Predicate` could be met, which
247-
// isn't always what we want for a synthesized impl. For example, given the predicate `T:
248-
// Iterator`, `FulfillmentContext` can end up reporting an Unimplemented error for `T:
249-
// IntoIterator` -- since there's an implementation of `Iterator` where `T: IntoIterator`,
250-
// `FulfillmentContext` will drive `SelectionContext` to consider that impl before giving up. If
251-
// we were to rely on `FulfillmentContext`'s decision, we might end up synthesizing an impl like
252-
// this:
253-
//
254-
// impl<T> Send for Foo<T> where T: IntoIterator
255-
//
256-
// While it might be technically true that Foo implements Send where `T: IntoIterator`,
257-
// the bound is overly restrictive - it's really only necessary that `T: Iterator`.
258-
//
259-
// For this reason, `evaluate_predicates` handles predicates with type variables specially. When
260-
// we encounter an `Unimplemented` error for a bound such as `T: Iterator`, we immediately add
261-
// it to our `ParamEnv`, and add it to our stack for recursive evaluation. When we later select
262-
// it, we'll pick up any nested bounds, without ever inferring that `T: IntoIterator` needs to
263-
// hold.
264-
//
265-
// One additional consideration is supertrait bounds. Normally, a `ParamEnv` is only ever
266-
// constructed once for a given type. As part of the construction process, the `ParamEnv` will
267-
// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo<T: Copy>`, the
268-
// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our
269-
// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or else
270-
// `SelectionContext` will choke on the missing predicates. However, this should never show up
271-
// in the final synthesized generics: we don't want our generated docs page to contain something
272-
// like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a separate
273-
// `user_env`, which only holds the predicates that will actually be displayed to the user.
236+
/// The core logic responsible for computing the bounds for our synthesized impl.
237+
///
238+
/// To calculate the bounds, we call `SelectionContext.select` in a loop. Like
239+
/// `FulfillmentContext`, we recursively select the nested obligations of predicates we
240+
/// encounter. However, whenever we encounter an `UnimplementedError` involving a type
241+
/// parameter, we add it to our `ParamEnv`. Since our goal is to determine when a particular
242+
/// type implements an auto trait, Unimplemented errors tell us what conditions need to be met.
243+
///
244+
/// This method ends up working somewhat similarly to `FulfillmentContext`, but with a few key
245+
/// differences. `FulfillmentContext` works under the assumption that it's dealing with concrete
246+
/// user code. According, it considers all possible ways that a `Predicate` could be met, which
247+
/// isn't always what we want for a synthesized impl. For example, given the predicate `T:
248+
/// Iterator`, `FulfillmentContext` can end up reporting an Unimplemented error for `T:
249+
/// IntoIterator` -- since there's an implementation of `Iterator` where `T: IntoIterator`,
250+
/// `FulfillmentContext` will drive `SelectionContext` to consider that impl before giving up.
251+
/// If we were to rely on `FulfillmentContext`s decision, we might end up synthesizing an impl
252+
/// like this:
253+
///
254+
/// impl<T> Send for Foo<T> where T: IntoIterator
255+
///
256+
/// While it might be technically true that Foo implements Send where `T: IntoIterator`,
257+
/// the bound is overly restrictive - it's really only necessary that `T: Iterator`.
258+
///
259+
/// For this reason, `evaluate_predicates` handles predicates with type variables specially.
260+
/// When we encounter an `Unimplemented` error for a bound such as `T: Iterator`, we immediately
261+
/// add it to our `ParamEnv`, and add it to our stack for recursive evaluation. When we later
262+
/// select it, we'll pick up any nested bounds, without ever inferring that `T: IntoIterator`
263+
/// needs to hold.
264+
///
265+
/// One additional consideration is supertrait bounds. Normally, a `ParamEnv` is only ever
266+
/// constructed once for a given type. As part of the construction process, the `ParamEnv` will
267+
/// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo<T: Copy>`, the
268+
/// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our
269+
/// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or
270+
/// else `SelectionContext` will choke on the missing predicates. However, this should never
271+
/// show up in the final synthesized generics: we don't want our generated docs page to contain
272+
/// something like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a
273+
/// separate `user_env`, which only holds the predicates that will actually be displayed to the
274+
/// user.
274275
fn evaluate_predicates(
275276
&self,
276277
infcx: &InferCtxt<'_, 'tcx>,
@@ -393,29 +394,29 @@ impl AutoTraitFinder<'tcx> {
393394
return Some((new_env, final_user_env));
394395
}
395396

396-
// This method is designed to work around the following issue:
397-
// When we compute auto trait bounds, we repeatedly call `SelectionContext.select`,
398-
// progressively building a `ParamEnv` based on the results we get.
399-
// However, our usage of `SelectionContext` differs from its normal use within the compiler,
400-
// in that we capture and re-reprocess predicates from `Unimplemented` errors.
401-
//
402-
// This can lead to a corner case when dealing with region parameters.
403-
// During our selection loop in `evaluate_predicates`, we might end up with
404-
// two trait predicates that differ only in their region parameters:
405-
// one containing a HRTB lifetime parameter, and one containing a 'normal'
406-
// lifetime parameter. For example:
407-
//
408-
// T as MyTrait<'a>
409-
// T as MyTrait<'static>
410-
//
411-
// If we put both of these predicates in our computed `ParamEnv`, we'll
412-
// confuse `SelectionContext`, since it will (correctly) view both as being applicable.
413-
//
414-
// To solve this, we pick the 'more strict' lifetime bound -- i.e., the HRTB
415-
// Our end goal is to generate a user-visible description of the conditions
416-
// under which a type implements an auto trait. A trait predicate involving
417-
// a HRTB means that the type needs to work with any choice of lifetime,
418-
// not just one specific lifetime (e.g., `'static`).
397+
/// This method is designed to work around the following issue:
398+
/// When we compute auto trait bounds, we repeatedly call `SelectionContext.select`,
399+
/// progressively building a `ParamEnv` based on the results we get.
400+
/// However, our usage of `SelectionContext` differs from its normal use within the compiler,
401+
/// in that we capture and re-reprocess predicates from `Unimplemented` errors.
402+
///
403+
/// This can lead to a corner case when dealing with region parameters.
404+
/// During our selection loop in `evaluate_predicates`, we might end up with
405+
/// two trait predicates that differ only in their region parameters:
406+
/// one containing a HRTB lifetime parameter, and one containing a 'normal'
407+
/// lifetime parameter. For example:
408+
///
409+
/// T as MyTrait<'a>
410+
/// T as MyTrait<'static>
411+
///
412+
/// If we put both of these predicates in our computed `ParamEnv`, we'll
413+
/// confuse `SelectionContext`, since it will (correctly) view both as being applicable.
414+
///
415+
/// To solve this, we pick the 'more strict' lifetime bound -- i.e., the HRTB
416+
/// Our end goal is to generate a user-visible description of the conditions
417+
/// under which a type implements an auto trait. A trait predicate involving
418+
/// a HRTB means that the type needs to work with any choice of lifetime,
419+
/// not just one specific lifetime (e.g., `'static`).
419420
fn add_user_pred<'c>(
420421
&self,
421422
user_computed_preds: &mut FxHashSet<ty::Predicate<'c>>,
@@ -506,8 +507,8 @@ impl AutoTraitFinder<'tcx> {
506507
}
507508
}
508509

509-
// This is very similar to `handle_lifetimes`. However, instead of matching `ty::Region`'s
510-
// to each other, we match `ty::RegionVid`'s to `ty::Region`'s.
510+
/// This is very similar to `handle_lifetimes`. However, instead of matching `ty::Region`s
511+
/// to each other, we match `ty::RegionVid`s to `ty::Region`s.
511512
fn map_vid_to_region<'cx>(
512513
&self,
513514
regions: &RegionConstraintData<'cx>,

src/librustc/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ pub enum ObligationCauseCode<'tcx> {
191191
/// Obligation incurred due to a coercion.
192192
Coercion { source: Ty<'tcx>, target: Ty<'tcx> },
193193

194-
// Various cases where expressions must be `Sized` / `Copy` / etc.
194+
/// Various cases where expressions must be `Sized` / `Copy` / etc.
195195
/// `L = X` implies that `L` is `Sized`.
196196
AssignmentLhsSized,
197197
/// `(x1, .., xn)` must be `Sized`.

src/librustc/traits/select.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -1198,26 +1198,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11981198
.insert(trait_ref, WithDepNode::new(dep_node, result));
11991199
}
12001200

1201-
// For various reasons, it's possible for a subobligation
1202-
// to have a *lower* recursion_depth than the obligation used to create it.
1203-
// Projection sub-obligations may be returned from the projection cache,
1204-
// which results in obligations with an 'old' `recursion_depth`.
1205-
// Additionally, methods like `ty::wf::obligations` and
1206-
// `InferCtxt.subtype_predicate` produce subobligations without
1207-
// taking in a 'parent' depth, causing the generated subobligations
1208-
// to have a `recursion_depth` of `0`.
1209-
//
1210-
// To ensure that obligation_depth never decreasees, we force all subobligations
1211-
// to have at least the depth of the original obligation.
1201+
/// For various reasons, it's possible for a subobligation
1202+
/// to have a *lower* recursion_depth than the obligation used to create it.
1203+
/// Projection sub-obligations may be returned from the projection cache,
1204+
/// which results in obligations with an 'old' `recursion_depth`.
1205+
/// Additionally, methods like `ty::wf::obligations` and
1206+
/// `InferCtxt.subtype_predicate` produce subobligations without
1207+
/// taking in a 'parent' depth, causing the generated subobligations
1208+
/// to have a `recursion_depth` of `0`.
1209+
///
1210+
/// To ensure that obligation_depth never decreasees, we force all subobligations
1211+
/// to have at least the depth of the original obligation.
12121212
fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(&self, it: I,
12131213
min_depth: usize) {
12141214
it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
12151215
}
12161216

1217-
// Checks that the recursion limit has not been exceeded.
1218-
//
1219-
// The weird return type of this function allows it to be used with the `try` (`?`)
1220-
// operator within certain functions.
1217+
/// Checks that the recursion limit has not been exceeded.
1218+
///
1219+
/// The weird return type of this function allows it to be used with the `try` (`?`)
1220+
/// operator within certain functions.
12211221
fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
12221222
&self,
12231223
obligation: &Obligation<'tcx, T>,

src/librustc_codegen_llvm/debuginfo/metadata.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,19 @@ pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
9191
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
9292
pub struct UniqueTypeId(ast::Name);
9393

94-
// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
95-
// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
96-
// faster lookup, also by `Ty`. The `TypeMap` is responsible for creating
97-
// `UniqueTypeId`s.
94+
/// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
95+
/// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
96+
/// faster lookup, also by `Ty`. The `TypeMap` is responsible for creating
97+
/// `UniqueTypeId`s.
9898
#[derive(Default)]
9999
pub struct TypeMap<'ll, 'tcx> {
100-
// The `UniqueTypeId`s created so far.
100+
/// The `UniqueTypeId`s created so far.
101101
unique_id_interner: Interner,
102-
// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
102+
/// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
103103
unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
104-
// A map from types to debuginfo metadata. This is an N:1 mapping.
104+
/// A map from types to debuginfo metadata. This is an N:1 mapping.
105105
type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
106-
// A map from types to `UniqueTypeId`. This is an N:1 mapping.
106+
/// A map from types to `UniqueTypeId`. This is an N:1 mapping.
107107
type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>
108108
}
109109

@@ -203,9 +203,9 @@ impl TypeMap<'ll, 'tcx> {
203203
return UniqueTypeId(key);
204204
}
205205

206-
// Get the `UniqueTypeId` for an enum variant. Enum variants are not really
207-
// types of their own, so they need special handling. We still need a
208-
// UniqueTypeId for them, since to debuginfo they *are* real types.
206+
/// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
207+
/// types of their own, so they need special handling. We still need a
208+
/// `UniqueTypeId` for them, since to debuginfo they *are* real types.
209209
fn get_unique_type_id_of_enum_variant<'a>(&mut self,
210210
cx: &CodegenCx<'a, 'tcx>,
211211
enum_type: Ty<'tcx>,
@@ -219,9 +219,9 @@ impl TypeMap<'ll, 'tcx> {
219219
UniqueTypeId(interner_key)
220220
}
221221

222-
// Get the unique type ID string for an enum variant part.
223-
// Variant parts are not types and shouldn't really have their own ID,
224-
// but it makes `set_members_of_composite_type()` simpler.
222+
/// Gets the unique type ID string for an enum variant part.
223+
/// Variant parts are not types and shouldn't really have their own ID,
224+
/// but it makes `set_members_of_composite_type()` simpler.
225225
fn get_unique_type_id_str_of_enum_variant_part(&mut self, enum_type_id: UniqueTypeId) -> &str {
226226
let variant_part_type_id = format!("{}_variant_part",
227227
self.get_unique_type_id_as_string(enum_type_id));
@@ -1027,7 +1027,7 @@ impl MetadataCreationResult<'ll> {
10271027
}
10281028
}
10291029

1030-
// Description of a type member, which can either be a regular field (as in
1030+
/// Description of a type member, which can either be a regular field (as in
10311031
/// structs or tuples) or an enum variant.
10321032
#[derive(Debug)]
10331033
struct MemberDescription<'ll> {

0 commit comments

Comments
 (0)