Skip to content

Commit 6f6010b

Browse files
committed
Auto merge of rust-lang#102254 - matthiaskrgr:rollup-gitu6li, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - rust-lang#102016 (implied_bounds: deal with inference vars) - rust-lang#102161 (Resolve async fn signature even without body (e.g., in trait)) - rust-lang#102216 (rustdoc: Stabilize --diagnostic-width) - rust-lang#102240 (rustdoc: remove unused CSS `#main-content > .line-numbers`) - rust-lang#102242 (rustdoc: remove unused CSS `.summary`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 8e9c93d + c6870cc commit 6f6010b

File tree

11 files changed

+187
-80
lines changed

11 files changed

+187
-80
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub struct OutlivesEnvironment<'tcx> {
5353
}
5454

5555
/// Builder of OutlivesEnvironment.
56+
#[derive(Debug)]
5657
struct OutlivesEnvironmentBuilder<'tcx> {
5758
param_env: ty::ParamEnv<'tcx>,
5859
region_relation: TransitiveRelationBuilder<Region<'tcx>>,
@@ -109,6 +110,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
109110

110111
impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
111112
#[inline]
113+
#[instrument(level = "debug")]
112114
fn build(self) -> OutlivesEnvironment<'tcx> {
113115
OutlivesEnvironment {
114116
param_env: self.param_env,

compiler/rustc_resolve/src/late.rs

+37-36
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
805805
sig.decl.has_self(),
806806
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
807807
&sig.decl.output,
808-
)
808+
);
809+
810+
this.record_lifetime_params_for_async(
811+
fn_id,
812+
sig.header.asyncness.opt_return_id(),
813+
);
809814
},
810815
);
811816
return;
@@ -847,41 +852,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
847852
},
848853
);
849854

850-
// Construct the list of in-scope lifetime parameters for async lowering.
851-
// We include all lifetime parameters, either named or "Fresh".
852-
// The order of those parameters does not matter, as long as it is
853-
// deterministic.
854-
if let Some((async_node_id, _)) = async_node_id {
855-
let mut extra_lifetime_params = this
856-
.r
857-
.extra_lifetime_params_map
858-
.get(&fn_id)
859-
.cloned()
860-
.unwrap_or_default();
861-
for rib in this.lifetime_ribs.iter().rev() {
862-
extra_lifetime_params.extend(
863-
rib.bindings
864-
.iter()
865-
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
866-
);
867-
match rib.kind {
868-
LifetimeRibKind::Item => break,
869-
LifetimeRibKind::AnonymousCreateParameter {
870-
binder, ..
871-
} => {
872-
if let Some(earlier_fresh) =
873-
this.r.extra_lifetime_params_map.get(&binder)
874-
{
875-
extra_lifetime_params.extend(earlier_fresh);
876-
}
877-
}
878-
_ => {}
879-
}
880-
}
881-
this.r
882-
.extra_lifetime_params_map
883-
.insert(async_node_id, extra_lifetime_params);
884-
}
855+
this.record_lifetime_params_for_async(fn_id, async_node_id);
885856

886857
if let Some(body) = body {
887858
// Ignore errors in function bodies if this is rustdoc
@@ -3926,6 +3897,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
39263897
Some((ident.name, ns)),
39273898
)
39283899
}
3900+
3901+
/// Construct the list of in-scope lifetime parameters for async lowering.
3902+
/// We include all lifetime parameters, either named or "Fresh".
3903+
/// The order of those parameters does not matter, as long as it is
3904+
/// deterministic.
3905+
fn record_lifetime_params_for_async(
3906+
&mut self,
3907+
fn_id: NodeId,
3908+
async_node_id: Option<(NodeId, Span)>,
3909+
) {
3910+
if let Some((async_node_id, _)) = async_node_id {
3911+
let mut extra_lifetime_params =
3912+
self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
3913+
for rib in self.lifetime_ribs.iter().rev() {
3914+
extra_lifetime_params.extend(
3915+
rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)),
3916+
);
3917+
match rib.kind {
3918+
LifetimeRibKind::Item => break,
3919+
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
3920+
if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
3921+
extra_lifetime_params.extend(earlier_fresh);
3922+
}
3923+
}
3924+
_ => {}
3925+
}
3926+
}
3927+
self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
3928+
}
3929+
}
39293930
}
39303931

39313932
struct LifetimeCountVisitor<'a, 'b> {

compiler/rustc_trait_selection/src/traits/outlives_bounds.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
4646
/// Note that this may cause outlives obligations to be injected
4747
/// into the inference context with this body-id.
4848
/// - `ty`, the type that we are supposed to assume is WF.
49-
#[instrument(level = "debug", skip(self, param_env, body_id))]
49+
#[instrument(level = "debug", skip(self, param_env, body_id), ret)]
5050
fn implied_outlives_bounds(
5151
&self,
5252
param_env: ty::ParamEnv<'tcx>,
@@ -71,6 +71,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
7171
let TypeOpOutput { output, constraints, .. } = result;
7272

7373
if let Some(constraints) = constraints {
74+
debug!(?constraints);
7475
// Instantiation may have produced new inference variables and constraints on those
7576
// variables. Process these constraints.
7677
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.tcx);

compiler/rustc_traits/src/implied_outlives_bounds.rs

+36-33
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ fn compute_implied_outlives_bounds<'tcx>(
4949
let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
5050
let mut wf_args = vec![ty.into()];
5151

52-
let mut implied_bounds = vec![];
52+
let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
53+
vec![];
5354

5455
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
5556

@@ -65,41 +66,28 @@ fn compute_implied_outlives_bounds<'tcx>(
6566
// than the ultimate set. (Note: normally there won't be
6667
// unresolved inference variables here anyway, but there might be
6768
// during typeck under some circumstances.)
69+
//
70+
// FIXME(@lcnr): It's not really "always fine", having fewer implied
71+
// bounds can be backward incompatible, e.g. #101951 was caused by
72+
// us not dealing with inference vars in `TypeOutlives` predicates.
6873
let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
6974
.unwrap_or_default();
7075

71-
// N.B., all of these predicates *ought* to be easily proven
72-
// true. In fact, their correctness is (mostly) implied by
73-
// other parts of the program. However, in #42552, we had
74-
// an annoying scenario where:
75-
//
76-
// - Some `T::Foo` gets normalized, resulting in a
77-
// variable `_1` and a `T: Trait<Foo=_1>` constraint
78-
// (not sure why it couldn't immediately get
79-
// solved). This result of `_1` got cached.
80-
// - These obligations were dropped on the floor here,
81-
// rather than being registered.
82-
// - Then later we would get a request to normalize
83-
// `T::Foo` which would result in `_1` being used from
84-
// the cache, but hence without the `T: Trait<Foo=_1>`
85-
// constraint. As a result, `_1` never gets resolved,
86-
// and we get an ICE (in dropck).
87-
//
88-
// Therefore, we register any predicates involving
89-
// inference variables. We restrict ourselves to those
90-
// involving inference variables both for efficiency and
91-
// to avoids duplicate errors that otherwise show up.
76+
// While these predicates should all be implied by other parts of
77+
// the program, they are still relevant as they may constrain
78+
// inference variables, which is necessary to add the correct
79+
// implied bounds in some cases, mostly when dealing with projections.
9280
fulfill_cx.register_predicate_obligations(
9381
infcx,
9482
obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(),
9583
);
9684

9785
// From the full set of obligations, just filter down to the
9886
// region relationships.
99-
implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
87+
outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| {
10088
assert!(!obligation.has_escaping_bound_vars());
10189
match obligation.predicate.kind().no_bound_vars() {
102-
None => vec![],
90+
None => None,
10391
Some(pred) => match pred {
10492
ty::PredicateKind::Trait(..)
10593
| ty::PredicateKind::Subtype(..)
@@ -109,21 +97,18 @@ fn compute_implied_outlives_bounds<'tcx>(
10997
| ty::PredicateKind::ObjectSafe(..)
11098
| ty::PredicateKind::ConstEvaluatable(..)
11199
| ty::PredicateKind::ConstEquate(..)
112-
| ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![],
100+
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
113101
ty::PredicateKind::WellFormed(arg) => {
114102
wf_args.push(arg);
115-
vec![]
103+
None
116104
}
117105

118106
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
119-
vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
107+
Some(ty::OutlivesPredicate(r_a.into(), r_b))
120108
}
121109

122110
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
123-
let ty_a = infcx.resolve_vars_if_possible(ty_a);
124-
let mut components = smallvec![];
125-
push_outlives_components(tcx, ty_a, &mut components);
126-
implied_bounds_from_components(r_b, components)
111+
Some(ty::OutlivesPredicate(ty_a.into(), r_b))
127112
}
128113
},
129114
}
@@ -133,9 +118,27 @@ fn compute_implied_outlives_bounds<'tcx>(
133118
// Ensure that those obligations that we had to solve
134119
// get solved *here*.
135120
match fulfill_cx.select_all_or_error(infcx).as_slice() {
136-
[] => Ok(implied_bounds),
137-
_ => Err(NoSolution),
121+
[] => (),
122+
_ => return Err(NoSolution),
138123
}
124+
125+
// We lazily compute the outlives components as
126+
// `select_all_or_error` constrains inference variables.
127+
let implied_bounds = outlives_bounds
128+
.into_iter()
129+
.flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
130+
ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
131+
ty::GenericArgKind::Type(ty_a) => {
132+
let ty_a = infcx.resolve_vars_if_possible(ty_a);
133+
let mut components = smallvec![];
134+
push_outlives_components(tcx, ty_a, &mut components);
135+
implied_bounds_from_components(r_b, components)
136+
}
137+
ty::GenericArgKind::Const(_) => unreachable!(),
138+
})
139+
.collect();
140+
141+
Ok(implied_bounds)
139142
}
140143

141144
/// When we have an implied bound that `T: 'a`, we can further break

compiler/rustc_typeck/src/check/compare_method.rs

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ pub(crate) fn compare_impl_method<'tcx>(
140140
///
141141
/// Finally we register each of these predicates as an obligation and check that
142142
/// they hold.
143+
#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
143144
fn compare_predicate_entailment<'tcx>(
144145
tcx: TyCtxt<'tcx>,
145146
impl_m: &AssocItem,

src/librustdoc/html/static/css/rustdoc.css

-8
Original file line numberDiff line numberDiff line change
@@ -1130,10 +1130,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
11301130
font-size: 1rem;
11311131
}
11321132

1133-
.summary {
1134-
padding-right: 0px;
1135-
}
1136-
11371133
pre.rust .question-mark {
11381134
font-weight: bold;
11391135
}
@@ -1917,10 +1913,6 @@ in storage.js plus the media query with (min-width: 701px)
19171913
border-bottom: 1px solid;
19181914
}
19191915

1920-
#main-content > .line-numbers {
1921-
margin-top: 0;
1922-
}
1923-
19241916
.notable-traits .notable-traits-tooltiptext {
19251917
left: 0;
19261918
top: 100%;

src/librustdoc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ fn opts() -> Vec<RustcOptGroup> {
461461
"human|json|short",
462462
)
463463
}),
464-
unstable("diagnostic-width", |o| {
464+
stable("diagnostic-width", |o| {
465465
o.optopt(
466466
"",
467467
"diagnostic-width",

src/test/rustdoc-ui/diagnostic-width.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// compile-flags: -Zunstable-options --diagnostic-width=10
1+
// compile-flags: --diagnostic-width=10
22
#![deny(rustdoc::bare_urls)]
33

44
/// This is a long line that contains a http://link.com
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// check-pass
2+
// edition:2021
3+
4+
#![feature(async_fn_in_trait)]
5+
#![allow(incomplete_features)]
6+
7+
use std::future::Future;
8+
9+
async fn yield_now() {}
10+
11+
trait AsyncIterator {
12+
type Item;
13+
async fn next(&mut self) -> Option<Self::Item>;
14+
}
15+
16+
struct YieldingRange {
17+
counter: u32,
18+
stop: u32,
19+
}
20+
21+
impl AsyncIterator for YieldingRange {
22+
type Item = u32;
23+
24+
async fn next(&mut self) -> Option<Self::Item> {
25+
if self.counter == self.stop {
26+
None
27+
} else {
28+
let c = self.counter;
29+
self.counter += 1;
30+
yield_now().await;
31+
Some(c)
32+
}
33+
}
34+
}
35+
36+
async fn async_main() {
37+
let mut x = YieldingRange { counter: 0, stop: 10 };
38+
39+
while let Some(v) = x.next().await {
40+
println!("Hi: {v}");
41+
}
42+
}
43+
44+
fn main() {
45+
let _ = async_main();
46+
}
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Taken directly from that issue.
2+
//
3+
// This test detected that we didn't correctly resolve
4+
// inference variables when computing implied bounds.
5+
//
6+
// check-pass
7+
pub trait BuilderFn<'a> {
8+
type Output;
9+
}
10+
11+
impl<'a, F, Out> BuilderFn<'a> for F
12+
where
13+
F: FnOnce(&'a mut ()) -> Out,
14+
{
15+
type Output = Out;
16+
}
17+
18+
pub trait ConstructionFirm {
19+
type Builder: for<'a> BuilderFn<'a>;
20+
}
21+
22+
pub trait Campus<T>
23+
where
24+
T: ConstructionFirm,
25+
{
26+
fn add_building(
27+
&mut self,
28+
building: &mut <<T as ConstructionFirm>::Builder as BuilderFn<'_>>::Output,
29+
);
30+
}
31+
32+
struct ArchitectsInc {}
33+
34+
impl ConstructionFirm for ArchitectsInc {
35+
type Builder = fn(&mut ()) -> PrettyCondo<'_>;
36+
}
37+
38+
struct PrettyCondo<'a> {
39+
_marker: &'a mut (),
40+
}
41+
42+
struct CondoEstate {}
43+
44+
impl Campus<ArchitectsInc> for CondoEstate {
45+
fn add_building(&mut self, _building: &mut PrettyCondo<'_>) {
46+
todo!()
47+
}
48+
}
49+
50+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// check-pass
2+
// This is currently stable behavior, which was almost accidentally made an
3+
// error in #102161 since there is no test exercising it. I am not sure if
4+
// this _should_ be the desired behavior, but at least we should know if it
5+
// changes.
6+
7+
fn main() {}
8+
9+
trait Foo {
10+
fn fn_with_type_named_same_as_local_in_param(b: i32, b: i32);
11+
}

0 commit comments

Comments
 (0)