Change:
Generally speaking, is equivalent to "eliding" a lifetime completely. That is, and are equivalent, as are and (unfortunately). However, there are two cases where this is not true: -- the object-lifetime-defaulting rules are different, and needs to interact with them (same for , of course) -- same, but for different reasons pointed out that is not what we really want:
I find this fascinating. Who would have predicted prior to implementation that introducing would allow us to elide even more lifetimes?

Discussion:
use hir::def::Def; use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use hir::ItemLocalId; <ins> use hir::LifetimeName; </ins> use ty::{self, TyCtxt}; use std::cell::Cell;

for bound in bounds { self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); } <del> if lifetime.is_elided() { self.resolve_object_lifetime_default(lifetime) } else { self.visit_lifetime(lifetime); </del> <ins> match lifetime.name { LifetimeName::Implicit => { // If the user does not write *anything*, we // use the object lifetime defaulting // rules. So e.g. `Box<dyn Debug>` becomes // `Box<dyn Debug + 'static>`. self.resolve_object_lifetime_default(lifetime) } LifetimeName::Underscore => { // If the user writes `'_`, we use the *ordinary* elision // rules. So the `'_` in e.g. `Box<dyn Debug + '_>` will be // resolved the same as the `'_` in `&'_ Foo`. // // cc #48468 self.resolve_elided_lifetimes(slice::from_ref(lifetime), false) } LifetimeName::Static | LifetimeName::Name(_) => { // If the user wrote an explicit name, use that. self.visit_lifetime(lifetime); } </ins> } } hir::TyRptr(ref lifetime_ref, ref mt) => {

<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Check that the `'_` in `dyn Trait + '_` acts like ordinary elision, // and not like an object lifetime default. // // cc #48468 #![feature(dyn_trait)] #![feature(underscore_lifetimes)] fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> { //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime } fn b<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> { Box::new(items.iter()) // OK, equivalent to c } fn c<'a, T>(items: &'a [T]) -> Box<dyn Iterator<Item=&'a T> + 'a> { Box::new(items.iter()) // OK, equivalent to b } fn main() { } </ins>

<ins> error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements --> $DIR/dyn-trait-underscore.rs:21:20 | LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime |                    ^^^^ | note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 19:1... --> $DIR/dyn-trait-underscore.rs:19:1 | LL | / fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> { LL | |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime LL | | } | |_^ note: ...so that reference does not outlive borrowed content --> $DIR/dyn-trait-underscore.rs:21:14 | LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime |              ^^^^^ = note: but, the lifetime must be valid for the static lifetime... = note: ...so that the expression is assignable: expected std::boxed::Box<std::iter::Iterator<Item=&T> + 'static> found std::boxed::Box<std::iter::Iterator<Item=&T>> error: aborting due to previous error For more information about this error, try `rustc --explain E0495`. </ins>