-
-
Notifications
You must be signed in to change notification settings - Fork 14.5k
Description
If we fail to deduce a trait object lifetime default in an item signature1 we generally emit an error for that. More specifically, we generally do that if TyCtxt::named_bound_var returns None. For context, named_bound_var actually returns None iff RBV didn't register a mapping from a given hir::Lifetime to a ResolvedArg. Now, since RBV doesn't actually map unresolved lifetimes to ResolvedArg::Error, we ultimately emit two errors in certain cases (1st: unresolved lifetime, 2nd: indeterminate trait object lifetime bound).
I'm not super familiar with the early resolution of lifetimes. Therefore, I don't know if we map unresolved lifetimes to LifetimeRes::Error in rustc_resolve or not (I have a hunch we don't (possibly a remnant of the now removed feature inband lifetimes?)). In any case, ideally we would map unresolved lifetimes to ResolvedArg::Error(_) in RBV which would automatically suppress the "indeterminate trait object lifetime bound" error.
Between AST lowering, name resolution and HIR ty lowering, we have LifetimeRes::Error, hir::LifetimeKind::Error, ResolvedArg::Error(ErrorGuaranteed) & ty::RegionKind::Error(ErrorGuaranteed) but none or only some are actually used for unresolved lifetimes IINM (they're mainly used for other early lifetime issues). Ideally, we'd use these for unresolved lifetimes, too, I guess (for that, ideally LifetimeRes and LifetimeKind::Error would carry an ErrorGuaranteed).
I've used the word "generally" a few times above, that's because in the special case of &'undefined dyn Trait (i.e., trait object type passed to a reference type constructor), we manually suppress the follow-up error. However, if we were to implement the scheme I'm describing above that would become unnecessary allowing us to remove this minor hack in HIR ty lowering:
rust/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
Lines 454 to 464 in f60a0f1
| 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 | |
| } |
Example Reproducer
fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {}error[E0261]: use of undeclared lifetime name `'undefined`
--> src/lib.rs:1:24
|
1 | fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {}
| ^^^^^^^^^^ undeclared lifetime
|
help: consider introducing lifetime `'undefined` here
|
1 | fn f<'undefined>(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {}
| ++++++++++++
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
--> src/lib.rs:1:36
|
1 | fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {}
| ^^^^^^^^^^^^^^^^^^^
Footnotes
-
aka item ctxt aka non-body ↩