Change:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code with : I expected to see only warning without error, like this: Instead, this happened (extra error E0521 emitted, which is incorrect): If I add in line 3, it compiles without any error or warning: So the E0521 error emitted by the compiler is incorrect. The test code using should only produce warnings without an error. It most recently worked on: 1.63.0-nightly ( 2022-05-18) </p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --
labels:+T-compiler
label A-diagnostics
labels: +regression-from-stable-to-nightly
label -regression-untriaged Bisection: regressed nightly: nightly-2022-06-23 searched commit range: regressed commit: that’s , cc
Seems like, possibly, the code without the explicit (incorrectly) desugars to rather than Edit: Or perhaps it incorrectly desugars to
Here’s another kind of code example that reproduces the issue Which does confirm the idea that this appears to be interpreted like , rather than which would be correct.
WG-prioritization assigning priority (). label -I-prioritize +P-critical

Discussion:
param_mode: ParamMode, itctx: ImplTraitContext, ) -> hir::Ty<'hir> { <ins> // 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() }; } </ins> 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)

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); <ins> // 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; } </ins> } TyKind::ImplicitSelf => { let self_ty = Ident::with_dummy_span(kw::SelfUpper);

<ins> #![allow(bare_trait_objects)] // check-pass pub struct FormatWith<'a, I, F> { sep: &'a str, /// FormatWith uses interior mutability because Display::fmt takes &self. inner: RefCell<Option<(I, F)>>, } use std::cell::RefCell; use std::fmt; struct Layout; pub fn new_format<'a, I, F>(iter: I, separator: &'a str, f: F) -> FormatWith<'a, I, F> where I: Iterator, F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result, { FormatWith { sep: separator, inner: RefCell::new(Some((iter, f))) } } fn main() { let _ = new_format(0..32, " | ", |i, f| f(&format_args!("0x{:x}", i))); } </ins>

<ins> // 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])) fn next_u32(fill_buf: &mut FnMut(&mut [u8])) { let mut buf: [u8; 4] = [0; 4]; fill_buf(&mut buf); } fn explicit(fill_buf: &mut dyn FnMut(&mut [u8])) { let mut buf: [u8; 4] = [0; 4]; fill_buf(&mut buf); } fn main() { let _: fn(&mut FnMut(&mut [u8])) = next_u32; let _: &dyn Fn(&mut FnMut(&mut [u8])) = &next_u32; let _: fn(&mut FnMut(&mut [u8])) = explicit; 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; let _: fn(&mut dyn FnMut(&mut [u8])) = explicit; let _: &dyn Fn(&mut dyn FnMut(&mut [u8])) = &explicit; } </ins>