about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-09-25 09:33:57 +0000
committerbors <bors@rust-lang.org>2022-09-25 09:33:57 +0000
commit6f6010b08bd5e5dd0d03d4abf35a3acc4d2433a2 (patch)
tree336160a858e310de9df5845078d9cfec9e266f12
parent8e9c93df464b7ada3fc7a1c8ccddd9dcb24ee0a0 (diff)
parentc6870ccc5ce454aef260fe63ef76d8b9eab86ac0 (diff)
downloadrust-6f6010b08bd5e5dd0d03d4abf35a3acc4d2433a2.tar.gz
rust-6f6010b08bd5e5dd0d03d4abf35a3acc4d2433a2.zip
Auto merge of #102254 - matthiaskrgr:rollup-gitu6li, r=matthiaskrgr
Rollup of 5 pull requests

Successful merges:

 - #102016 (implied_bounds: deal with inference vars)
 - #102161 (Resolve async fn signature even without body (e.g., in trait))
 - #102216 (rustdoc: Stabilize --diagnostic-width)
 - #102240 (rustdoc: remove unused CSS `#main-content > .line-numbers`)
 - #102242 (rustdoc: remove unused CSS `.summary`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_infer/src/infer/outlives/env.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs73
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs3
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs69
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs1
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css8
-rw-r--r--src/librustdoc/lib.rs2
-rw-r--r--src/test/rustdoc-ui/diagnostic-width.rs2
-rw-r--r--src/test/ui/async-await/in-trait/issue-102138.rs46
-rw-r--r--src/test/ui/implied-bounds/issue-101951.rs50
-rw-r--r--src/test/ui/resolve/name-collision-in-trait-fn-sig.rs11
11 files changed, 187 insertions, 80 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index 872886da362..9922b156ebf 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -53,6 +53,7 @@ pub struct OutlivesEnvironment<'tcx> {
 }
 
 /// Builder of OutlivesEnvironment.
+#[derive(Debug)]
 struct OutlivesEnvironmentBuilder<'tcx> {
     param_env: ty::ParamEnv<'tcx>,
     region_relation: TransitiveRelationBuilder<Region<'tcx>>,
@@ -109,6 +110,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
 
 impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
     #[inline]
+    #[instrument(level = "debug")]
     fn build(self) -> OutlivesEnvironment<'tcx> {
         OutlivesEnvironment {
             param_env: self.param_env,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 0aea90bb5aa..558db003867 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -805,7 +805,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                             sig.decl.has_self(),
                             sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
                             &sig.decl.output,
-                        )
+                        );
+
+                        this.record_lifetime_params_for_async(
+                            fn_id,
+                            sig.header.asyncness.opt_return_id(),
+                        );
                     },
                 );
                 return;
@@ -847,41 +852,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                             },
                         );
 
-                        // Construct the list of in-scope lifetime parameters for async lowering.
-                        // We include all lifetime parameters, either named or "Fresh".
-                        // The order of those parameters does not matter, as long as it is
-                        // deterministic.
-                        if let Some((async_node_id, _)) = async_node_id {
-                            let mut extra_lifetime_params = this
-                                .r
-                                .extra_lifetime_params_map
-                                .get(&fn_id)
-                                .cloned()
-                                .unwrap_or_default();
-                            for rib in this.lifetime_ribs.iter().rev() {
-                                extra_lifetime_params.extend(
-                                    rib.bindings
-                                        .iter()
-                                        .map(|(&ident, &(node_id, res))| (ident, node_id, res)),
-                                );
-                                match rib.kind {
-                                    LifetimeRibKind::Item => break,
-                                    LifetimeRibKind::AnonymousCreateParameter {
-                                        binder, ..
-                                    } => {
-                                        if let Some(earlier_fresh) =
-                                            this.r.extra_lifetime_params_map.get(&binder)
-                                        {
-                                            extra_lifetime_params.extend(earlier_fresh);
-                                        }
-                                    }
-                                    _ => {}
-                                }
-                            }
-                            this.r
-                                .extra_lifetime_params_map
-                                .insert(async_node_id, extra_lifetime_params);
-                        }
+                        this.record_lifetime_params_for_async(fn_id, async_node_id);
 
                         if let Some(body) = body {
                             // Ignore errors in function bodies if this is rustdoc
@@ -3926,6 +3897,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             Some((ident.name, ns)),
         )
     }
+
+    /// Construct the list of in-scope lifetime parameters for async lowering.
+    /// We include all lifetime parameters, either named or "Fresh".
+    /// The order of those parameters does not matter, as long as it is
+    /// deterministic.
+    fn record_lifetime_params_for_async(
+        &mut self,
+        fn_id: NodeId,
+        async_node_id: Option<(NodeId, Span)>,
+    ) {
+        if let Some((async_node_id, _)) = async_node_id {
+            let mut extra_lifetime_params =
+                self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
+            for rib in self.lifetime_ribs.iter().rev() {
+                extra_lifetime_params.extend(
+                    rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)),
+                );
+                match rib.kind {
+                    LifetimeRibKind::Item => break,
+                    LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
+                        if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
+                            extra_lifetime_params.extend(earlier_fresh);
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
+        }
+    }
 }
 
 struct LifetimeCountVisitor<'a, 'b> {
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index a4b54018228..3008dfcadde 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -46,7 +46,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
     ///   Note that this may cause outlives obligations to be injected
     ///   into the inference context with this body-id.
     /// - `ty`, the type that we are supposed to assume is WF.
-    #[instrument(level = "debug", skip(self, param_env, body_id))]
+    #[instrument(level = "debug", skip(self, param_env, body_id), ret)]
     fn implied_outlives_bounds(
         &self,
         param_env: ty::ParamEnv<'tcx>,
@@ -71,6 +71,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
         let TypeOpOutput { output, constraints, .. } = result;
 
         if let Some(constraints) = constraints {
+            debug!(?constraints);
             // Instantiation may have produced new inference variables and constraints on those
             // variables. Process these constraints.
             let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.tcx);
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index e3e78f70b15..691b79f1053 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -49,7 +49,8 @@ fn compute_implied_outlives_bounds<'tcx>(
     let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
     let mut wf_args = vec![ty.into()];
 
-    let mut implied_bounds = vec![];
+    let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
+        vec![];
 
     let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
 
@@ -65,30 +66,17 @@ fn compute_implied_outlives_bounds<'tcx>(
         // than the ultimate set. (Note: normally there won't be
         // unresolved inference variables here anyway, but there might be
         // during typeck under some circumstances.)
+        //
+        // FIXME(@lcnr): It's not really "always fine", having fewer implied
+        // bounds can be backward incompatible, e.g. #101951 was caused by
+        // us not dealing with inference vars in `TypeOutlives` predicates.
         let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
             .unwrap_or_default();
 
-        // N.B., all of these predicates *ought* to be easily proven
-        // true. In fact, their correctness is (mostly) implied by
-        // other parts of the program. However, in #42552, we had
-        // an annoying scenario where:
-        //
-        // - Some `T::Foo` gets normalized, resulting in a
-        //   variable `_1` and a `T: Trait<Foo=_1>` constraint
-        //   (not sure why it couldn't immediately get
-        //   solved). This result of `_1` got cached.
-        // - These obligations were dropped on the floor here,
-        //   rather than being registered.
-        // - Then later we would get a request to normalize
-        //   `T::Foo` which would result in `_1` being used from
-        //   the cache, but hence without the `T: Trait<Foo=_1>`
-        //   constraint. As a result, `_1` never gets resolved,
-        //   and we get an ICE (in dropck).
-        //
-        // Therefore, we register any predicates involving
-        // inference variables. We restrict ourselves to those
-        // involving inference variables both for efficiency and
-        // to avoids duplicate errors that otherwise show up.
+        // While these predicates should all be implied by other parts of
+        // the program, they are still relevant as they may constrain
+        // inference variables, which is necessary to add the correct
+        // implied bounds in some cases, mostly when dealing with projections.
         fulfill_cx.register_predicate_obligations(
             infcx,
             obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(),
@@ -96,10 +84,10 @@ fn compute_implied_outlives_bounds<'tcx>(
 
         // From the full set of obligations, just filter down to the
         // region relationships.
-        implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
+        outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| {
             assert!(!obligation.has_escaping_bound_vars());
             match obligation.predicate.kind().no_bound_vars() {
-                None => vec![],
+                None => None,
                 Some(pred) => match pred {
                     ty::PredicateKind::Trait(..)
                     | ty::PredicateKind::Subtype(..)
@@ -109,21 +97,18 @@ fn compute_implied_outlives_bounds<'tcx>(
                     | ty::PredicateKind::ObjectSafe(..)
                     | ty::PredicateKind::ConstEvaluatable(..)
                     | ty::PredicateKind::ConstEquate(..)
-                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![],
+                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
                     ty::PredicateKind::WellFormed(arg) => {
                         wf_args.push(arg);
-                        vec![]
+                        None
                     }
 
                     ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
-                        vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
+                        Some(ty::OutlivesPredicate(r_a.into(), r_b))
                     }
 
                     ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
-                        let ty_a = infcx.resolve_vars_if_possible(ty_a);
-                        let mut components = smallvec![];
-                        push_outlives_components(tcx, ty_a, &mut components);
-                        implied_bounds_from_components(r_b, components)
+                        Some(ty::OutlivesPredicate(ty_a.into(), r_b))
                     }
                 },
             }
@@ -133,9 +118,27 @@ fn compute_implied_outlives_bounds<'tcx>(
     // Ensure that those obligations that we had to solve
     // get solved *here*.
     match fulfill_cx.select_all_or_error(infcx).as_slice() {
-        [] => Ok(implied_bounds),
-        _ => Err(NoSolution),
+        [] => (),
+        _ => return Err(NoSolution),
     }
+
+    // We lazily compute the outlives components as
+    // `select_all_or_error` constrains inference variables.
+    let implied_bounds = outlives_bounds
+        .into_iter()
+        .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
+            ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
+            ty::GenericArgKind::Type(ty_a) => {
+                let ty_a = infcx.resolve_vars_if_possible(ty_a);
+                let mut components = smallvec![];
+                push_outlives_components(tcx, ty_a, &mut components);
+                implied_bounds_from_components(r_b, components)
+            }
+            ty::GenericArgKind::Const(_) => unreachable!(),
+        })
+        .collect();
+
+    Ok(implied_bounds)
 }
 
 /// When we have an implied bound that `T: 'a`, we can further break
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 7c0b815e42a..ae98a8f6209 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -140,6 +140,7 @@ pub(crate) fn compare_impl_method<'tcx>(
 ///
 /// Finally we register each of these predicates as an obligation and check that
 /// they hold.
+#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
 fn compare_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &AssocItem,
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 4136cb6cab3..c4da1e46009 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1130,10 +1130,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	font-size: 1rem;
 }
 
-.summary {
-	padding-right: 0px;
-}
-
 pre.rust .question-mark {
 	font-weight: bold;
 }
@@ -1917,10 +1913,6 @@ in storage.js plus the media query with (min-width: 701px)
 		border-bottom: 1px solid;
 	}
 
-	#main-content > .line-numbers {
-		margin-top: 0;
-	}
-
 	.notable-traits .notable-traits-tooltiptext {
 		left: 0;
 		top: 100%;
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 14d695582b0..23ad0c30f21 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -461,7 +461,7 @@ fn opts() -> Vec<RustcOptGroup> {
                 "human|json|short",
             )
         }),
-        unstable("diagnostic-width", |o| {
+        stable("diagnostic-width", |o| {
             o.optopt(
                 "",
                 "diagnostic-width",
diff --git a/src/test/rustdoc-ui/diagnostic-width.rs b/src/test/rustdoc-ui/diagnostic-width.rs
index 61961d5ec71..290d9db775b 100644
--- a/src/test/rustdoc-ui/diagnostic-width.rs
+++ b/src/test/rustdoc-ui/diagnostic-width.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Zunstable-options --diagnostic-width=10
+// compile-flags: --diagnostic-width=10
 #![deny(rustdoc::bare_urls)]
 
 /// This is a long line that contains a http://link.com
diff --git a/src/test/ui/async-await/in-trait/issue-102138.rs b/src/test/ui/async-await/in-trait/issue-102138.rs
new file mode 100644
index 00000000000..f61b34ed99e
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/issue-102138.rs
@@ -0,0 +1,46 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+async fn yield_now() {}
+
+trait AsyncIterator {
+    type Item;
+    async fn next(&mut self) -> Option<Self::Item>;
+}
+
+struct YieldingRange {
+    counter: u32,
+    stop: u32,
+}
+
+impl AsyncIterator for YieldingRange {
+    type Item = u32;
+
+    async fn next(&mut self) -> Option<Self::Item> {
+        if self.counter == self.stop {
+            None
+        } else {
+            let c = self.counter;
+            self.counter += 1;
+            yield_now().await;
+            Some(c)
+        }
+    }
+}
+
+async fn async_main() {
+    let mut x = YieldingRange { counter: 0, stop: 10 };
+
+    while let Some(v) = x.next().await {
+        println!("Hi: {v}");
+    }
+}
+
+fn main() {
+    let _ = async_main();
+}
diff --git a/src/test/ui/implied-bounds/issue-101951.rs b/src/test/ui/implied-bounds/issue-101951.rs
new file mode 100644
index 00000000000..108fef8a15f
--- /dev/null
+++ b/src/test/ui/implied-bounds/issue-101951.rs
@@ -0,0 +1,50 @@
+// Taken directly from that issue.
+//
+// This test detected that we didn't correctly resolve
+// inference variables when computing implied bounds.
+//
+// check-pass
+pub trait BuilderFn<'a> {
+    type Output;
+}
+
+impl<'a, F, Out> BuilderFn<'a> for F
+where
+    F: FnOnce(&'a mut ()) -> Out,
+{
+    type Output = Out;
+}
+
+pub trait ConstructionFirm {
+    type Builder: for<'a> BuilderFn<'a>;
+}
+
+pub trait Campus<T>
+where
+    T: ConstructionFirm,
+{
+    fn add_building(
+        &mut self,
+        building: &mut <<T as ConstructionFirm>::Builder as BuilderFn<'_>>::Output,
+    );
+}
+
+struct ArchitectsInc {}
+
+impl ConstructionFirm for ArchitectsInc {
+    type Builder = fn(&mut ()) -> PrettyCondo<'_>;
+}
+
+struct PrettyCondo<'a> {
+    _marker: &'a mut (),
+}
+
+struct CondoEstate {}
+
+impl Campus<ArchitectsInc> for CondoEstate {
+    fn add_building(&mut self, _building: &mut PrettyCondo<'_>) {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs b/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs
new file mode 100644
index 00000000000..fba4ffa1c6e
--- /dev/null
+++ b/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs
@@ -0,0 +1,11 @@
+// check-pass
+// This is currently stable behavior, which was almost accidentally made an
+// error in #102161 since there is no test exercising it. I am not sure if
+// this _should_ be the desired behavior, but at least we should know if it
+// changes.
+
+fn main() {}
+
+trait Foo {
+    fn fn_with_type_named_same_as_local_in_param(b: i32, b: i32);
+}