Skip to content

Commit 08e2d46

Browse files
committed
Auto merge of rust-lang#73905 - matthewjasper:projection-bounds-2, r=nikomatsakis
Separate projection bounds and predicates Follow up to rust-lang#72788. - Rename `projection_predicates` to `item_bounds` - Separate bounds on associated types (the things after the `:` in `type X: ...`) and opaque types (the things after `impl`) from predicates. - Projection candidates now have the correct nested obligations - Trait object candidates now check that the associated types on the trait object satisfy their bounds as nested obligations - Type alias impl trait types are now checked (rust-lang#73035) - `feature(generic_associated_types)` no longer changes how we handle bounds (rust-lang#73816) Opening for a perf and crater runs. r? `@nikomatsakis`
2 parents 5849a7e + 69fc6d8 commit 08e2d46

File tree

259 files changed

+3604
-2336
lines changed

Some content is hidden

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

259 files changed

+3604
-2336
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -432,17 +432,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
432432
self.with_catch_scope(body.id, |this| {
433433
let mut block = this.lower_block_noalloc(body, true);
434434

435-
let try_span = this.mark_span_with_reason(
436-
DesugaringKind::TryBlock,
437-
body.span,
438-
this.allow_try_trait.clone(),
439-
);
440-
441435
// Final expression of the block (if present) or `()` with span at the end of block
442-
let tail_expr = block
443-
.expr
444-
.take()
445-
.unwrap_or_else(|| this.expr_unit(this.sess.source_map().end_point(try_span)));
436+
let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {
437+
(
438+
this.mark_span_with_reason(
439+
DesugaringKind::TryBlock,
440+
expr.span,
441+
this.allow_try_trait.clone(),
442+
),
443+
expr,
444+
)
445+
} else {
446+
let try_span = this.mark_span_with_reason(
447+
DesugaringKind::TryBlock,
448+
this.sess.source_map().end_point(body.span),
449+
this.allow_try_trait.clone(),
450+
);
451+
452+
(try_span, this.expr_unit(try_span))
453+
};
446454

447455
let ok_wrapped_span =
448456
this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
@@ -1553,7 +1561,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
15531561
hir::LangItem::TryFromError,
15541562
unstable_span,
15551563
from_expr,
1556-
try_span,
1564+
unstable_span,
15571565
);
15581566
let thin_attrs = ThinVec::from(attrs);
15591567
let catch_scope = self.catch_scopes.last().copied();

compiler/rustc_error_codes/src/error_codes/E0284.md

+15-23
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,29 @@ as the `collect` method for `Iterator`s.
55
For example:
66

77
```compile_fail,E0284
8-
fn foo() -> Result<bool, ()> {
9-
let results = [Ok(true), Ok(false), Err(())].iter().cloned();
10-
let v: Vec<bool> = results.collect()?;
11-
// Do things with v...
12-
Ok(true)
8+
fn main() {
9+
let n: u32 = 1;
10+
let mut d: u64 = 2;
11+
d = d + n.into();
1312
}
1413
```
1514

16-
Here we have an iterator `results` over `Result<bool, ()>`.
17-
Hence, `results.collect()` can return any type implementing
18-
`FromIterator<Result<bool, ()>>`. On the other hand, the
19-
`?` operator can accept any type implementing `Try`.
15+
Here we have an addition of `d` and `n.into()`. Hence, `n.into()` can return
16+
any type `T` where `u64: Add<T>`. On the other hand, the `into` method can
17+
return any type where `u32: Into<T>`.
2018

21-
The author of this code probably wants `collect()` to return a
22-
`Result<Vec<bool>, ()>`, but the compiler can't be sure
23-
that there isn't another type `T` implementing both `Try` and
24-
`FromIterator<Result<bool, ()>>` in scope such that
25-
`T::Ok == Vec<bool>`. Hence, this code is ambiguous and an error
26-
is returned.
19+
The author of this code probably wants `into()` to return a `u64`, but the
20+
compiler can't be sure that there isn't another type `T` where both
21+
`u32: Into<T>` and `u64: Add<T>`.
2722

2823
To resolve this error, use a concrete type for the intermediate expression:
2924

3025
```
31-
fn foo() -> Result<bool, ()> {
32-
let results = [Ok(true), Ok(false), Err(())].iter().cloned();
33-
let v = {
34-
let temp: Result<Vec<bool>, ()> = results.collect();
35-
temp?
36-
};
37-
// Do things with v...
38-
Ok(true)
26+
fn main() {
27+
let n: u32 = 1;
28+
let mut d: u64 = 2;
29+
let m: u64 = n.into();
30+
d = d + m;
3931
}
4032
```
4133

compiler/rustc_infer/src/infer/higher_ranked/mod.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! the end of the file for details.
33
44
use super::combine::CombineFields;
5-
use super::{HigherRankedType, InferCtxt, PlaceholderMap};
5+
use super::{HigherRankedType, InferCtxt};
66

77
use crate::infer::CombinedSnapshot;
88
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
@@ -33,7 +33,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
3333
self.infcx.commit_if_ok(|_| {
3434
// First, we instantiate each bound region in the supertype with a
3535
// fresh placeholder region.
36-
let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(&b);
36+
let b_prime = self.infcx.replace_bound_vars_with_placeholders(&b);
3737

3838
// Next, we instantiate each bound region in the subtype
3939
// with a fresh region variable. These region variables --
@@ -66,10 +66,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
6666
/// the [rustc dev guide].
6767
///
6868
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
69-
pub fn replace_bound_vars_with_placeholders<T>(
70-
&self,
71-
binder: &ty::Binder<T>,
72-
) -> (T, PlaceholderMap<'tcx>)
69+
pub fn replace_bound_vars_with_placeholders<T>(&self, binder: &ty::Binder<T>) -> T
7370
where
7471
T: TypeFoldable<'tcx>,
7572
{
@@ -122,7 +119,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
122119
next_universe, binder, result, map,
123120
);
124121

125-
(result, map)
122+
result
126123
}
127124

128125
/// See `infer::region_constraints::RegionConstraintCollector::leak_check`.

compiler/rustc_infer/src/infer/mod.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -351,11 +351,6 @@ pub struct InferCtxt<'a, 'tcx> {
351351
universe: Cell<ty::UniverseIndex>,
352352
}
353353

354-
/// A map returned by `replace_bound_vars_with_placeholders()`
355-
/// indicating the placeholder region that each late-bound region was
356-
/// replaced with.
357-
pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
358-
359354
/// See the `error_reporting` module for more details.
360355
#[derive(Clone, Debug, PartialEq, Eq, TypeFoldable)]
361356
pub enum ValuePairs<'tcx> {
@@ -992,7 +987,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
992987
}
993988

994989
Some(self.commit_if_ok(|_snapshot| {
995-
let (ty::SubtypePredicate { a_is_expected, a, b }, _) =
990+
let ty::SubtypePredicate { a_is_expected, a, b } =
996991
self.replace_bound_vars_with_placeholders(&predicate);
997992

998993
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
@@ -1007,7 +1002,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10071002
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
10081003
) -> UnitResult<'tcx> {
10091004
self.commit_if_ok(|_snapshot| {
1010-
let (ty::OutlivesPredicate(r_a, r_b), _) =
1005+
let ty::OutlivesPredicate(r_a, r_b) =
10111006
self.replace_bound_vars_with_placeholders(&predicate);
10121007
let origin = SubregionOrigin::from_obligation_cause(cause, || {
10131008
RelateRegionParamBound(cause.span)

compiler/rustc_infer/src/infer/outlives/verify.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
328328
assoc_item_def_id: DefId,
329329
) -> impl Iterator<Item = ty::Region<'tcx>> {
330330
let tcx = self.tcx;
331-
let predicates = tcx.projection_predicates(assoc_item_def_id);
332-
predicates
331+
let bounds = tcx.item_bounds(assoc_item_def_id);
332+
bounds
333333
.into_iter()
334334
.filter_map(|p| p.to_opt_type_outlives())
335335
.filter_map(|p| p.no_bound_vars())

compiler/rustc_infer/src/traits/util.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation};
44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_middle::ty::outlives::Component;
66
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
7-
use rustc_span::Span;
87

98
pub fn anonymize_predicate<'tcx>(
109
tcx: TyCtxt<'tcx>,
@@ -94,7 +93,11 @@ pub fn elaborate_predicates<'tcx>(
9493
tcx: TyCtxt<'tcx>,
9594
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
9695
) -> Elaborator<'tcx> {
97-
let obligations = predicates.map(|predicate| predicate_obligation(predicate, None)).collect();
96+
let obligations = predicates
97+
.map(|predicate| {
98+
predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy())
99+
})
100+
.collect();
98101
elaborate_obligations(tcx, obligations)
99102
}
100103

@@ -109,15 +112,10 @@ pub fn elaborate_obligations<'tcx>(
109112

110113
fn predicate_obligation<'tcx>(
111114
predicate: ty::Predicate<'tcx>,
112-
span: Option<Span>,
115+
param_env: ty::ParamEnv<'tcx>,
116+
cause: ObligationCause<'tcx>,
113117
) -> PredicateObligation<'tcx> {
114-
let cause = if let Some(span) = span {
115-
ObligationCause::dummy_with_span(span)
116-
} else {
117-
ObligationCause::dummy()
118-
};
119-
120-
Obligation { cause, param_env: ty::ParamEnv::empty(), recursion_depth: 0, predicate }
118+
Obligation { cause, param_env, recursion_depth: 0, predicate }
121119
}
122120

123121
impl Elaborator<'tcx> {
@@ -133,10 +131,11 @@ impl Elaborator<'tcx> {
133131
// Get predicates declared on the trait.
134132
let predicates = tcx.super_predicates_of(data.def_id());
135133

136-
let obligations = predicates.predicates.iter().map(|&(pred, span)| {
134+
let obligations = predicates.predicates.iter().map(|&(pred, _)| {
137135
predicate_obligation(
138136
pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)),
139-
Some(span),
137+
obligation.param_env,
138+
obligation.cause.clone(),
140139
)
141140
});
142141
debug!("super_predicates: data={:?}", data);
@@ -233,7 +232,13 @@ impl Elaborator<'tcx> {
233232
})
234233
.map(|predicate_kind| predicate_kind.to_predicate(tcx))
235234
.filter(|&predicate| visited.insert(predicate))
236-
.map(|predicate| predicate_obligation(predicate, None)),
235+
.map(|predicate| {
236+
predicate_obligation(
237+
predicate,
238+
obligation.param_env,
239+
obligation.cause.clone(),
240+
)
241+
}),
237242
);
238243
}
239244
ty::PredicateAtom::TypeWellFormedFromEnv(..) => {

compiler/rustc_lint/src/unused.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
200200
ty::Adt(def, _) => check_must_use_def(cx, def.did, span, descr_pre, descr_post),
201201
ty::Opaque(def, _) => {
202202
let mut has_emitted = false;
203-
for (predicate, _) in cx.tcx.predicates_of(def).predicates {
203+
for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
204204
// We only look at the `DefId`, so it is safe to skip the binder here.
205205
if let ty::PredicateAtom::Trait(ref poly_trait_predicate, _) =
206206
predicate.skip_binders()

compiler/rustc_metadata/src/rmeta/decoder.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
937937
.tables
938938
.inferred_outlives
939939
.get(self, item_id)
940-
.map(|predicates| predicates.decode((self, tcx)))
940+
.map(|predicates| tcx.arena.alloc_from_iter(predicates.decode((self, tcx))))
941941
.unwrap_or_default()
942942
}
943943

@@ -949,6 +949,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
949949
self.root.tables.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
950950
}
951951

952+
fn get_explicit_item_bounds(
953+
&self,
954+
item_id: DefIndex,
955+
tcx: TyCtxt<'tcx>,
956+
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
957+
self.root
958+
.tables
959+
.explicit_item_bounds
960+
.get(self, item_id)
961+
.map(|bounds| tcx.arena.alloc_from_iter(bounds.decode((self, tcx))))
962+
.unwrap_or_default()
963+
}
964+
952965
fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
953966
self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess))
954967
}

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
8989
explicit_predicates_of => { cdata.get_explicit_predicates(def_id.index, tcx) }
9090
inferred_outlives_of => { cdata.get_inferred_outlives(def_id.index, tcx) }
9191
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
92+
explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) }
9293
trait_def => { cdata.get_trait_def(def_id.index, tcx.sess) }
9394
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
9495
adt_destructor => {

compiler/rustc_metadata/src/rmeta/encoder.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,14 @@ impl EncodeContext<'a, 'tcx> {
965965
record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
966966
}
967967

968+
fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
969+
debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
970+
let bounds = self.tcx.explicit_item_bounds(def_id);
971+
if !bounds.is_empty() {
972+
record!(self.tables.explicit_item_bounds[def_id] <- bounds);
973+
}
974+
}
975+
968976
fn encode_info_for_trait_item(&mut self, def_id: DefId) {
969977
debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
970978
let tcx = self.tcx;
@@ -1017,7 +1025,10 @@ impl EncodeContext<'a, 'tcx> {
10171025
has_self: trait_item.fn_has_self_parameter,
10181026
}))
10191027
}
1020-
ty::AssocKind::Type => EntryKind::AssocType(container),
1028+
ty::AssocKind::Type => {
1029+
self.encode_explicit_item_bounds(def_id);
1030+
EntryKind::AssocType(container)
1031+
}
10211032
});
10221033
record!(self.tables.visibility[def_id] <- trait_item.vis);
10231034
record!(self.tables.span[def_id] <- ast_item.span);
@@ -1255,7 +1266,10 @@ impl EncodeContext<'a, 'tcx> {
12551266
hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
12561267
hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
12571268
hir::ItemKind::TyAlias(..) => EntryKind::Type,
1258-
hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy,
1269+
hir::ItemKind::OpaqueTy(..) => {
1270+
self.encode_explicit_item_bounds(def_id);
1271+
EntryKind::OpaqueTy
1272+
}
12591273
hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr),
12601274
hir::ItemKind::Struct(ref struct_def, _) => {
12611275
let adt_def = self.tcx.adt_def(def_id);

compiler/rustc_metadata/src/rmeta/mod.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,11 @@ define_tables! {
295295
generics: Table<DefIndex, Lazy<ty::Generics>>,
296296
explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
297297
expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
298-
// FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate`
299-
// doesn't handle shorthands in its own (de)serialization impls,
300-
// as it's an `enum` for which we want to derive (de)serialization,
301-
// so the `ty::codec` APIs handle the whole `&'tcx [...]` at once.
302-
// Also, as an optimization, a missing entry indicates an empty `&[]`.
303-
inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
298+
// As an optimization, a missing entry indicates an empty `&[]`.
299+
inferred_outlives: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
304300
super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
301+
// As an optimization, a missing entry indicates an empty `&[]`.
302+
explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
305303
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
306304
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
307305
mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,

0 commit comments

Comments
 (0)