Skip to content

Commit 21a12e8

Browse files
committed
Handle fresh lifetimes on bare trait objects.
1 parent d5354eb commit 21a12e8

File tree

6 files changed

+53
-71
lines changed

6 files changed

+53
-71
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11741174
param_mode: ParamMode,
11751175
itctx: ImplTraitContext,
11761176
) -> hir::Ty<'hir> {
1177+
// Check whether we should interpret this as a bare trait object.
1178+
// This check mirrors the one in late resolution. We only introduce this special case in
1179+
// the rare occurence we need to lower `Fresh` anonymous lifetimes.
1180+
// The other cases when a qpath should be opportunistically made a trait object are handled
1181+
// by `ty_path`.
1182+
if qself.is_none()
1183+
&& let Some(partial_res) = self.resolver.get_partial_res(t.id)
1184+
&& partial_res.unresolved_segments() == 0
1185+
&& let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
1186+
{
1187+
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
1188+
let bound = this.lower_poly_trait_ref(
1189+
&PolyTraitRef {
1190+
bound_generic_params: vec![],
1191+
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
1192+
span: t.span
1193+
},
1194+
itctx,
1195+
);
1196+
let bounds = this.arena.alloc_from_iter([bound]);
1197+
let lifetime_bound = this.elided_dyn_bound(t.span);
1198+
(bounds, lifetime_bound)
1199+
});
1200+
let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None);
1201+
return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };
1202+
}
1203+
11771204
let id = self.lower_node_id(t.id);
11781205
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
11791206
self.ty_path(id, t.span, qpath)

compiler/rustc_resolve/src/late.rs

+24
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,30 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
611611
TyKind::Path(ref qself, ref path) => {
612612
self.diagnostic_metadata.current_type_path = Some(ty);
613613
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
614+
615+
// Check whether we should interpret this as a bare trait object.
616+
if qself.is_none()
617+
&& let Some(partial_res) = self.r.partial_res_map.get(&ty.id)
618+
&& partial_res.unresolved_segments() == 0
619+
&& let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
620+
{
621+
// This path is actually a bare trait object. In case of a bare `Fn`-trait
622+
// object with anonymous lifetimes, we need this rib to correctly place the
623+
// synthetic lifetimes.
624+
let span = ty.span.shrink_to_lo().to(path.span.shrink_to_lo());
625+
self.with_generic_param_rib(
626+
&[],
627+
NormalRibKind,
628+
LifetimeRibKind::Generics {
629+
binder: ty.id,
630+
kind: LifetimeBinderKind::PolyTrait,
631+
span,
632+
},
633+
|this| this.visit_path(&path, ty.id),
634+
);
635+
self.diagnostic_metadata.current_type_path = prev_ty;
636+
return;
637+
}
614638
}
615639
TyKind::ImplicitSelf => {
616640
let self_ty = Ident::with_dummy_span(kw::SelfUpper);

src/test/ui/lifetimes/bare-trait-object-borrowck.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![allow(bare_trait_objects)]
2-
2+
// check-pass
33
pub struct FormatWith<'a, I, F> {
44
sep: &'a str,
55
/// FormatWith uses interior mutability because Display::fmt takes &self.
@@ -21,7 +21,4 @@ where
2121

2222
fn main() {
2323
let _ = new_format(0..32, " | ", |i, f| f(&format_args!("0x{:x}", i)));
24-
//~^ ERROR temporary value dropped while borrowed
25-
//~| ERROR temporary value dropped while borrowed
26-
//~| ERROR `i` does not live long enough
2724
}

src/test/ui/lifetimes/bare-trait-object-borrowck.stderr

-43
This file was deleted.

src/test/ui/lifetimes/bare-trait-object.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Verify that lifetime resolution correctly accounts for `Fn` bare trait objects.
2-
2+
// check-pass
33
#![allow(bare_trait_objects)]
44

55
// This should work as: fn next_u32(fill_buf: &mut dyn FnMut(&mut [u8]))
@@ -15,10 +15,8 @@ fn explicit(fill_buf: &mut dyn FnMut(&mut [u8])) {
1515

1616
fn main() {
1717
let _: fn(&mut FnMut(&mut [u8])) = next_u32;
18-
//~^ ERROR mismatched types
1918
let _: &dyn Fn(&mut FnMut(&mut [u8])) = &next_u32;
2019
let _: fn(&mut FnMut(&mut [u8])) = explicit;
21-
//~^ ERROR mismatched types
2220
let _: &dyn Fn(&mut FnMut(&mut [u8])) = &explicit;
2321
let _: fn(&mut dyn FnMut(&mut [u8])) = next_u32;
2422
let _: &dyn Fn(&mut dyn FnMut(&mut [u8])) = &next_u32;

src/test/ui/lifetimes/bare-trait-object.stderr

-21
This file was deleted.

0 commit comments

Comments
 (0)