-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce a default object lifetime bound #599
Conversation
Acked-by: Niko Matsakis <niko@alum.mit.edu>
I wholeheartedly support this RFC. Besides the quantitative data presented here, I feel that these defaults closely match the intuitions I generally have about ownership and trait objects. The interaction with lifetime elision seems similar to the use of sugared I also support the idea of opt-in for "hidden reference" types -- that is, rather than making I wonder how much extra work such an opt-in would be? There's some urgency because, presumably, one cannot decide to have a type opt in after it has already been stabilized. Since we already have some reference-like types in |
@aturon Hmm, I hadn't considered the fact that we could allow types to opt-in. I thought of it as backwards compatible, but you're right. Doesn't seem like it should be that hard, we mostly need to devise a syntax. |
+1, |
proposed here, the result would be `Ref<'a, SomeTrait+'static>`. If | ||
this becomes a serious annoyance, in the future we could add the | ||
option for declaring on the struct `Ref` that objects which appear in | ||
type `T` should be defaulted with the lifetime `'a`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that this change would not be backwards compatible (it would change the bound from 'static to 'a).
So I think this needs to be implemented now or it must be an error to not specify a bound in any case where an additional rule is to be implemented in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding some opt-in mechanism to override the default would be backwards compatible, but it'd be incompatible to actually use that mechanism on an existing type. Regardless, there are types in the standard library for which we might want it, so it might be worth discussing now, as @aturon pointed out.
So as both @aturon and @bill-myers pointed out, it is perhaps a good idea to consider if we can adopt an extensible default scheme now. In the RFC I proposed (and rejected) building on the existing struct Ref<'a, T:'a> {
x: &'a T
} We could say that if the struct declaration specifies exactly one bound of the form Some examples:
In the future, we could potentially try to handle multiple bounds, but only if one of them is unambiguously "biggest". For example The advantage of this is that it is guided by the existing type annotations and tries to pick a type that best meets what the struct said is required. However, it is subtle and may be hard to explain. Moreover, if we do decide to infer the I'm mildly concerned that this matter of lifetime bounds is a kind of obscure concern. I simultaneously don't want to dedicate a big keyword to it (pro to this comment's proposal) but also don't want it to ride on some subtle bit of syntax that is so easily overlooked and maybe confusing (con to this comment's proposal). |
I'm normally suspicious of such inference, but this RFC seems remedy a situation where rustc helped you uncharacteristically little, so +1. After this, it will be more consistently magical. Less sure about the previous comment, bounds on parameters doing that just spooks me out. |
I'm in favor of this RFC in general, and also think it would be a good idea to generalize the defaulting behavior behind reference types as proposed in @nikomatsakis last comment. It feels more consistent if both the build-in and custom reference types behave the same in regard to the proposal. Otherwise, custom ones might feel a bit second-class due to added lifetime verbosity. |
Big 👍 from me here, this matches my intuitions as well. |
+1 from me (I do kind of like the inference idea as well). |
I'm in favour. Another way to make avoiding default (The precise |
@huonw I would very much like some sort of marker like that, and I've considered just that syntax. I actually think it fits ok -- that is, Anyway, the other use cases where I would like that in the compiler is this: fn foo<'a>(x: &SomeContext<'a,'tcx>, ...) Here I only need the fn foo(x: &SomeContext<'_,'tcx>, ...) This comes up fairly regularly in the compiler anyhow, and I suspect it will come up in other programs that are making aggressive use of lifetimes/arenas/etc. |
For the record, I continue to be worried about the subtle implicit sugar that Rust is growing. Hard to know what's going on. |
I adapted the text to describe driving defaults based on user annotations, as discussed in this comment. |
Looks great! I'm happy with this RFC. |
This RFC has received broad support, and is a blocker for |
…felix Implement rules described in rust-lang/rfcs#599. Fixes #22211. ~~Based atop PR #22182, so the first few commits (up to and including "Pacify the mercilous nrc") have already been reviewed.~~
Add a default lifetime bound for object types, so that it is no longer necessary to write things like
Box<Trait+'static>
or&'a (Trait+'a)
. The default will be based on the context in which the object type appears. Object types that appear underneath a reference take the lifetime of the innermost reference under which they appear, and otherwise the default is'static
.Examples:
&'a &'b SomeTrait
becomes&'a &'b (SomeTrait+'b)
&'a Box<SomeTrait>
becomes&'a Box<SomeTrait+'a>
Box<SomeTrait>
becomesBox<SomeTrait+'static>
Rc<SomeTrait>
becomesRc<SomeTrait+'static>
Cases where the lifetime bound is either given explicitly or can be inferred from the traits involved are naturally unaffected.
text/
rendereddraft rendered