about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-08-24 14:55:31 -0400
committerMichael Goulet <michael@errs.io>2024-08-24 14:55:31 -0400
commit147bb17f51b521269929f348b4b2a27afad8a273 (patch)
tree107207335e2adf71517393be57c48d0c16b3e8a0
parentf167efad2f51088d86180ee89177b3d7c9e7c2f5 (diff)
downloadrust-147bb17f51b521269929f348b4b2a27afad8a273.tar.gz
rust-147bb17f51b521269929f348b4b2a27afad8a273.zip
Rework how we emit errors for unresolved object lifetimes
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs32
3 files changed, 25 insertions, 16 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index f75954c9edf..9e6c431a6e6 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -392,7 +392,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
     }
 
     fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
-        if let RegionInferReason::BorrowedObjectLifetimeDefault = reason {
+        if let RegionInferReason::ObjectLifetimeDefault = reason {
             let e = struct_span_code_err!(
                 self.dcx(),
                 span,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 5c8ecf254a5..73baa05bce6 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -85,10 +85,9 @@ pub enum PredicateFilter {
 
 #[derive(Debug)]
 pub enum RegionInferReason<'a> {
-    /// Lifetime on a trait object behind a reference.
-    /// This allows inferring information from the reference.
-    BorrowedObjectLifetimeDefault,
-    /// A trait object's lifetime.
+    /// Lifetime on a trait object that is spelled explicitly, e.g. `+ 'a` or `+ '_`.
+    ExplicitObjectLifetime,
+    /// A trait object's lifetime when it is elided, e.g. `dyn Any`.
     ObjectLifetimeDefault,
     /// Generic lifetime parameter
     Param(&'a ty::GenericParamDef),
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
index 31d1750f33d..082fbb2c418 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
@@ -30,7 +30,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         hir_id: hir::HirId,
         hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)],
         lifetime: &hir::Lifetime,
-        borrowed: bool,
+        _borrowed: bool,
         representation: DynKind,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
@@ -325,22 +325,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         v.dedup();
         let existential_predicates = tcx.mk_poly_existential_predicates(&v);
 
-        // Use explicitly-specified region bound.
+        // Use explicitly-specified region bound, unless the bound is missing.
         let region_bound = if !lifetime.is_elided() {
-            self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault)
+            self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
         } else {
             self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
+                // Curiously, we prefer object lifetime default for `+ '_`...
                 if tcx.named_bound_var(lifetime.hir_id).is_some() {
-                    self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault)
+                    self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
                 } else {
-                    self.re_infer(
-                        span,
-                        if borrowed {
-                            RegionInferReason::ObjectLifetimeDefault
+                    let reason =
+                        if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res {
+                            if let hir::Node::Ty(hir::Ty {
+                                kind: hir::TyKind::Ref(parent_lifetime, _),
+                                ..
+                            }) = tcx.parent_hir_node(hir_id)
+                                && tcx.named_bound_var(parent_lifetime.hir_id).is_none()
+                            {
+                                // Parent lifetime must have failed to resolve. Don't emit a redundant error.
+                                RegionInferReason::ExplicitObjectLifetime
+                            } else {
+                                RegionInferReason::ObjectLifetimeDefault
+                            }
                         } else {
-                            RegionInferReason::BorrowedObjectLifetimeDefault
-                        },
-                    )
+                            RegionInferReason::ExplicitObjectLifetime
+                        };
+                    self.re_infer(span, reason)
                 }
             })
         };