Skip to content

Commit f97070d

Browse files
committed
Forbid lifetime elision in let position impl Trait
This is consistent with types.
1 parent 4201fd2 commit f97070d

File tree

9 files changed

+95
-52
lines changed

9 files changed

+95
-52
lines changed

src/librustc_ast_lowering/lib.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,15 +1619,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16191619
visitor.visit_ty(ty);
16201620
}
16211621
}
1622-
let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
16231622
let ty = l.ty.as_ref().map(|t| {
16241623
self.lower_ty(
16251624
t,
16261625
if self.sess.features_untracked().impl_trait_in_bindings {
1627-
ImplTraitContext::OpaqueTy(
1628-
Some(parent_def_id.to_def_id()),
1629-
hir::OpaqueTyOrigin::Misc,
1630-
)
1626+
ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Binding)
16311627
} else {
16321628
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
16331629
},

src/librustc_hir/hir.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2018,7 +2018,9 @@ pub enum OpaqueTyOrigin {
20182018
FnReturn,
20192019
/// `async fn`
20202020
AsyncFn,
2021-
/// Impl trait in bindings, consts, statics, bounds.
2021+
/// `let _: impl Trait = ...`
2022+
Binding,
2023+
/// Impl trait in type aliases, consts, statics, bounds.
20222024
Misc,
20232025
}
20242026

src/librustc_resolve/late/lifetimes.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ enum Elide {
258258
Exact(Region),
259259
/// Less or more than one lifetime were found, error on unspecified.
260260
Error(Vec<ElisionFailureInfo>),
261+
/// Forbid lifetime elision inside of a larger scope that does. For
262+
/// example, in let position impl trait.
263+
Forbid,
261264
}
262265

263266
#[derive(Clone, Debug)]
@@ -566,7 +569,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
566569
// This arm is for `impl Trait` in the types of statics, constants and locals.
567570
hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => {
568571
intravisit::walk_ty(self, ty);
569-
intravisit::walk_item(this, opaque_ty);
572+
573+
// Elided lifetimes are not allowed in non-return
574+
// position impl Trait
575+
let scope = Scope::Elision { elide: Elide::Forbid, s: self.scope };
576+
self.with(scope, |_, this| {
577+
intravisit::walk_item(this, opaque_ty);
578+
});
579+
570580
return;
571581
}
572582
// RPIT (return position impl trait)
@@ -2332,6 +2342,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23322342
}
23332343
break Some(e);
23342344
}
2345+
Elide::Forbid => break None,
23352346
};
23362347
for lifetime_ref in lifetime_refs {
23372348
self.insert_lifetime(lifetime_ref, lifetime);

src/librustc_trait_selection/opaque_types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
413413
}
414414
// These opaque type inherit all lifetime parameters from their
415415
// parent.
416-
hir::OpaqueTyOrigin::Misc => 0,
416+
hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => 0,
417417
};
418418

419419
let span = tcx.def_span(def_id);
@@ -569,7 +569,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
569569
hir::OpaqueTyOrigin::AsyncFn => return false,
570570

571571
// Otherwise, generate the label we'll use in the error message.
572-
hir::OpaqueTyOrigin::TypeAlias
572+
hir::OpaqueTyOrigin::Binding
573573
| hir::OpaqueTyOrigin::FnReturn
574574
| hir::OpaqueTyOrigin::Misc => "impl Trait",
575575
};

src/librustc_typeck/collect/type_of.rs

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -100,26 +100,17 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
100100
let substs = InternalSubsts::identity_for_item(tcx, def_id);
101101
tcx.mk_adt(def, substs)
102102
}
103+
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::Binding, .. }) => {
104+
let_position_impl_trait_type(tcx, def_id.expect_local())
105+
}
103106
ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
104107
find_opaque_ty_constraints(tcx, def_id.expect_local())
105108
}
106109
// Opaque types desugared from `impl Trait`.
107-
ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), origin, .. }) => {
108-
let concrete_types = match origin {
109-
OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => {
110-
&tcx.mir_borrowck(owner.expect_local()).concrete_opaque_types
111-
}
112-
OpaqueTyOrigin::Misc => {
113-
// We shouldn't leak borrowck results through impl trait in bindings.
114-
// For example, we shouldn't be able to tell if `x` in
115-
// `let x: impl Sized + 'a = &()` has type `&'static ()` or `&'a ()`.
116-
&tcx.typeck_tables_of(owner.expect_local()).concrete_opaque_types
117-
}
118-
OpaqueTyOrigin::TypeAlias => {
119-
span_bug!(item.span, "Type alias impl trait shouldn't have an owner")
120-
}
121-
};
122-
let concrete_ty = concrete_types
110+
ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => {
111+
let concrete_ty = tcx
112+
.mir_borrowck(owner.expect_local())
113+
.concrete_opaque_types
123114
.get(&def_id)
124115
.map(|opaque| opaque.concrete_type)
125116
.unwrap_or_else(|| {
@@ -148,13 +139,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
148139
}
149140
});
150141
debug!("concrete_ty = {:?}", concrete_ty);
151-
if concrete_ty.has_erased_regions() {
152-
// FIXME(impl_trait_in_bindings) Handle this case.
153-
tcx.sess.span_fatal(
154-
item.span,
155-
"lifetimes in impl Trait types in bindings are not currently supported",
156-
);
157-
}
158142
concrete_ty
159143
}
160144
ItemKind::Trait(..)
@@ -589,6 +573,50 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
589573
}
590574
}
591575

576+
fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
577+
let scope = tcx.hir().get_defining_scope(tcx.hir().as_local_hir_id(opaque_ty_id));
578+
let scope_def_id = tcx.hir().local_def_id(scope);
579+
580+
let opaque_ty_def_id = opaque_ty_id.to_def_id();
581+
582+
let owner_tables = tcx.typeck_tables_of(scope_def_id);
583+
let concrete_ty = owner_tables
584+
.concrete_opaque_types
585+
.get(&opaque_ty_def_id)
586+
.map(|opaque| opaque.concrete_type)
587+
.unwrap_or_else(|| {
588+
tcx.sess.delay_span_bug(
589+
DUMMY_SP,
590+
&format!(
591+
"owner {:?} has no opaque type for {:?} in its tables",
592+
scope_def_id, opaque_ty_id
593+
),
594+
);
595+
if let Some(ErrorReported) = owner_tables.tainted_by_errors {
596+
// Some error in the owner fn prevented us from populating the
597+
// `concrete_opaque_types` table.
598+
tcx.types.err
599+
} else {
600+
// We failed to resolve the opaque type or it resolves to
601+
// itself. Return the non-revealed type, which should result in
602+
// E0720.
603+
tcx.mk_opaque(
604+
opaque_ty_def_id,
605+
InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
606+
)
607+
}
608+
});
609+
debug!("concrete_ty = {:?}", concrete_ty);
610+
if concrete_ty.has_erased_regions() {
611+
// FIXME(impl_trait_in_bindings) Handle this case.
612+
tcx.sess.span_fatal(
613+
tcx.hir().span(tcx.hir().as_local_hir_id(opaque_ty_id)),
614+
"lifetimes in impl Trait types in bindings are not currently supported",
615+
);
616+
}
617+
concrete_ty
618+
}
619+
592620
fn infer_placeholder_type(
593621
tcx: TyCtxt<'_>,
594622
def_id: LocalDefId,

src/test/ui/impl-trait/issue-60473.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55

66
struct A<'a>(&'a ());
77

8-
trait Trait<T> {
9-
}
8+
trait Trait<T> {}
109

11-
impl<T> Trait<T> for () {
12-
}
10+
impl<T> Trait<T> for () {}
1311

1412
fn main() {
15-
let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
16-
//~^ ERROR: opaque type expands to a recursive type
13+
let x: impl Trait<A> = ();
14+
//~^ ERROR: missing lifetime specifier
1715
}
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
error[E0720]: opaque type expands to a recursive type
2-
--> $DIR/issue-60473.rs:15:12
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/issue-60473.rs:13:23
33
|
4-
LL | let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
5-
| ^^^^^^^^^^^^^ expands to a recursive type
4+
LL | let x: impl Trait<A> = ();
5+
| ^ expected named lifetime parameter
6+
|
7+
help: consider introducing a named lifetime parameter
8+
|
9+
LL | fn main<'a>() {
10+
LL | let x: impl Trait<A<'a>> = ();
611
|
7-
= note: type resolves to itself
812

913
error: aborting due to previous error
1014

11-
For more information about this error, try `rustc --explain E0720`.
15+
For more information about this error, try `rustc --explain E0106`.

src/test/ui/impl-trait/issue-67166.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
#![allow(incomplete_features)]
55

66
pub fn run() {
7-
let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
8-
//~^ ERROR: opaque type expands to a recursive type
7+
let _foo: Box<impl Copy + '_> = Box::new(());
8+
//~^ ERROR: missing lifetime specifier
99
}
1010

1111
fn main() {}
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
error[E0720]: opaque type expands to a recursive type
2-
--> $DIR/issue-67166.rs:7:19
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/issue-67166.rs:7:31
33
|
4-
LL | let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
5-
| ^^^^^^^^^^^^^^ expands to a recursive type
4+
LL | let _foo: Box<impl Copy + '_> = Box::new(());
5+
| ^^ expected named lifetime parameter
6+
|
7+
help: consider introducing a named lifetime parameter
8+
|
9+
LL | pub fn run<'a>() {
10+
LL | let _foo: Box<impl Copy + 'a> = Box::new(());
611
|
7-
= note: type resolves to itself
812

913
error: aborting due to previous error
1014

11-
For more information about this error, try `rustc --explain E0720`.
15+
For more information about this error, try `rustc --explain E0106`.

0 commit comments

Comments
 (0)