Handle fresh lifetimes on bare trait objects.
This commit is contained in:
parent
d5354eb48e
commit
21a12e8ab7
6 changed files with 53 additions and 71 deletions
|
@ -1174,6 +1174,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
param_mode: ParamMode,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::Ty<'hir> {
|
||||
// Check whether we should interpret this as a bare trait object.
|
||||
// This check mirrors the one in late resolution. We only introduce this special case in
|
||||
// the rare occurence we need to lower `Fresh` anonymous lifetimes.
|
||||
// The other cases when a qpath should be opportunistically made a trait object are handled
|
||||
// by `ty_path`.
|
||||
if qself.is_none()
|
||||
&& let Some(partial_res) = self.resolver.get_partial_res(t.id)
|
||||
&& partial_res.unresolved_segments() == 0
|
||||
&& let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
|
||||
{
|
||||
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
|
||||
let bound = this.lower_poly_trait_ref(
|
||||
&PolyTraitRef {
|
||||
bound_generic_params: vec![],
|
||||
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
|
||||
span: t.span
|
||||
},
|
||||
itctx,
|
||||
);
|
||||
let bounds = this.arena.alloc_from_iter([bound]);
|
||||
let lifetime_bound = this.elided_dyn_bound(t.span);
|
||||
(bounds, lifetime_bound)
|
||||
});
|
||||
let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None);
|
||||
return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };
|
||||
}
|
||||
|
||||
let id = self.lower_node_id(t.id);
|
||||
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
|
||||
self.ty_path(id, t.span, qpath)
|
||||
|
|
|
@ -611,6 +611,30 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
TyKind::Path(ref qself, ref path) => {
|
||||
self.diagnostic_metadata.current_type_path = Some(ty);
|
||||
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
|
||||
|
||||
// Check whether we should interpret this as a bare trait object.
|
||||
if qself.is_none()
|
||||
&& let Some(partial_res) = self.r.partial_res_map.get(&ty.id)
|
||||
&& partial_res.unresolved_segments() == 0
|
||||
&& let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
|
||||
{
|
||||
// This path is actually a bare trait object. In case of a bare `Fn`-trait
|
||||
// object with anonymous lifetimes, we need this rib to correctly place the
|
||||
// synthetic lifetimes.
|
||||
let span = ty.span.shrink_to_lo().to(path.span.shrink_to_lo());
|
||||
self.with_generic_param_rib(
|
||||
&[],
|
||||
NormalRibKind,
|
||||
LifetimeRibKind::Generics {
|
||||
binder: ty.id,
|
||||
kind: LifetimeBinderKind::PolyTrait,
|
||||
span,
|
||||
},
|
||||
|this| this.visit_path(&path, ty.id),
|
||||
);
|
||||
self.diagnostic_metadata.current_type_path = prev_ty;
|
||||
return;
|
||||
}
|
||||
}
|
||||
TyKind::ImplicitSelf => {
|
||||
let self_ty = Ident::with_dummy_span(kw::SelfUpper);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(bare_trait_objects)]
|
||||
|
||||
// check-pass
|
||||
pub struct FormatWith<'a, I, F> {
|
||||
sep: &'a str,
|
||||
/// FormatWith uses interior mutability because Display::fmt takes &self.
|
||||
|
@ -21,7 +21,4 @@ where
|
|||
|
||||
fn main() {
|
||||
let _ = new_format(0..32, " | ", |i, f| f(&format_args!("0x{:x}", i)));
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
//~| ERROR temporary value dropped while borrowed
|
||||
//~| ERROR `i` does not live long enough
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/bare-trait-object-borrowck.rs:23:48
|
||||
|
|
||||
LL | let _ = new_format(0..32, " | ", |i, f| f(&format_args!("0x{:x}", i)));
|
||||
| - ---^^^^^^^^^^^^^^^^^^^^^^^^^-
|
||||
| | | | |
|
||||
| | | | temporary value is freed at the end of this statement
|
||||
| | | creates a temporary which is freed while still in use
|
||||
| | argument requires that borrow lasts for `'1`
|
||||
| has type `&mut dyn FnMut(&'1 (dyn std::fmt::Display + '1)) -> Result<(), std::fmt::Error>`
|
||||
|
|
||||
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/bare-trait-object-borrowck.rs:23:48
|
||||
|
|
||||
LL | let _ = new_format(0..32, " | ", |i, f| f(&format_args!("0x{:x}", i)));
|
||||
| - ---^^^^^^^^^^^^^^^^^^^^^^^^^-
|
||||
| | | | |
|
||||
| | | | temporary value is freed at the end of this statement
|
||||
| | | creates a temporary which is freed while still in use
|
||||
| | argument requires that borrow lasts for `'1`
|
||||
| has type `&mut dyn FnMut(&'1 (dyn std::fmt::Display + '1)) -> Result<(), std::fmt::Error>`
|
||||
|
|
||||
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0597]: `i` does not live long enough
|
||||
--> $DIR/bare-trait-object-borrowck.rs:23:71
|
||||
|
|
||||
LL | let _ = new_format(0..32, " | ", |i, f| f(&format_args!("0x{:x}", i)));
|
||||
| - --------------------------^--
|
||||
| | | | |
|
||||
| | | | `i` dropped here while still borrowed
|
||||
| | | borrowed value does not live long enough
|
||||
| | argument requires that `i` is borrowed for `'1`
|
||||
| has type `&mut dyn FnMut(&'1 (dyn std::fmt::Display + '1)) -> Result<(), std::fmt::Error>`
|
||||
|
|
||||
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0597, E0716.
|
||||
For more information about an error, try `rustc --explain E0597`.
|
|
@ -1,5 +1,5 @@
|
|||
// Verify that lifetime resolution correctly accounts for `Fn` bare trait objects.
|
||||
|
||||
// check-pass
|
||||
#![allow(bare_trait_objects)]
|
||||
|
||||
// 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])) {
|
|||
|
||||
fn main() {
|
||||
let _: fn(&mut FnMut(&mut [u8])) = next_u32;
|
||||
//~^ ERROR mismatched types
|
||||
let _: &dyn Fn(&mut FnMut(&mut [u8])) = &next_u32;
|
||||
let _: fn(&mut FnMut(&mut [u8])) = explicit;
|
||||
//~^ ERROR mismatched types
|
||||
let _: &dyn Fn(&mut FnMut(&mut [u8])) = &explicit;
|
||||
let _: fn(&mut dyn FnMut(&mut [u8])) = next_u32;
|
||||
let _: &dyn Fn(&mut dyn FnMut(&mut [u8])) = &next_u32;
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/bare-trait-object.rs:17:40
|
||||
|
|
||||
LL | let _: fn(&mut FnMut(&mut [u8])) = next_u32;
|
||||
| ^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's> fn(&'r mut (dyn for<'s> FnMut(&'s mut [u8]) + 'r))`
|
||||
found fn item `for<'r> fn(&'r mut (dyn for<'r> FnMut(&'r mut [u8]) + 'r)) {next_u32}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bare-trait-object.rs:20:40
|
||||
|
|
||||
LL | let _: fn(&mut FnMut(&mut [u8])) = explicit;
|
||||
| ^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's> fn(&'r mut (dyn for<'s> FnMut(&'s mut [u8]) + 'r))`
|
||||
found fn item `for<'r> fn(&'r mut (dyn for<'r> FnMut(&'r mut [u8]) + 'r)) {explicit}`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue