Auto merge of #113229 - matthiaskrgr:rollup-gunqun4, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #113168 (fix(resolve): skip assertion judgment when NonModule is dummy) - #113174 (Better messages for next on a iterator inside for loops) - #113182 (Error when RPITITs' hidden types capture more lifetimes than their trait definitions) - #113196 (Fix associated items effective visibility calculation for type privacy lints) - #113226 (Fix try builds on the msvc builder) - #113227 (Update cargo) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5633798af6
@ -1,6 +1,5 @@
|
||||
use std::iter;
|
||||
|
||||
use either::Either;
|
||||
use hir::PatField;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::{
|
||||
@ -28,6 +27,7 @@
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
use std::iter;
|
||||
|
||||
use crate::borrow_set::TwoPhaseActivation;
|
||||
use crate::borrowck_errors;
|
||||
@ -992,6 +992,11 @@ pub(crate) fn report_conflicting_borrow(
|
||||
issued_borrow.borrowed_place,
|
||||
&issued_spans,
|
||||
);
|
||||
self.explain_iterator_advancement_in_for_loop_if_applicable(
|
||||
&mut err,
|
||||
span,
|
||||
&issued_spans,
|
||||
);
|
||||
err
|
||||
}
|
||||
|
||||
@ -1279,6 +1284,73 @@ fn suggest_slice_method_if_applicable(
|
||||
}
|
||||
}
|
||||
|
||||
/// Suggest using `while let` for call `next` on an iterator in a for loop.
|
||||
///
|
||||
/// For example:
|
||||
/// ```ignore (illustrative)
|
||||
///
|
||||
/// for x in iter {
|
||||
/// ...
|
||||
/// iter.next()
|
||||
/// }
|
||||
/// ```
|
||||
pub(crate) fn explain_iterator_advancement_in_for_loop_if_applicable(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
span: Span,
|
||||
issued_spans: &UseSpans<'tcx>,
|
||||
) {
|
||||
let issue_span = issued_spans.args_or_use();
|
||||
let tcx = self.infcx.tcx;
|
||||
let hir = tcx.hir();
|
||||
|
||||
let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
|
||||
let typeck_results = tcx.typeck(self.mir_def_id());
|
||||
|
||||
struct ExprFinder<'hir> {
|
||||
issue_span: Span,
|
||||
expr_span: Span,
|
||||
body_expr: Option<&'hir hir::Expr<'hir>>,
|
||||
loop_bind: Option<Symbol>,
|
||||
}
|
||||
impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
|
||||
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
|
||||
if let hir::ExprKind::Loop(hir::Block{ stmts: [stmt, ..], ..}, _, hir::LoopSource::ForLoop, _) = ex.kind &&
|
||||
let hir::StmtKind::Expr(hir::Expr{ kind: hir::ExprKind::Match(call, [_, bind, ..], _), ..}) = stmt.kind &&
|
||||
let hir::ExprKind::Call(path, _args) = call.kind &&
|
||||
let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _, _, )) = path.kind &&
|
||||
let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind &&
|
||||
let hir::QPath::LangItem(LangItem::OptionSome, _, _) = path &&
|
||||
let PatField { pat: hir::Pat{ kind: hir::PatKind::Binding(_, _, ident, ..), .. }, ..} = field &&
|
||||
self.issue_span.source_equal(call.span) {
|
||||
self.loop_bind = Some(ident.name);
|
||||
}
|
||||
|
||||
if let hir::ExprKind::MethodCall(body_call, _recv, ..) = ex.kind &&
|
||||
body_call.ident.name == sym::next && ex.span.source_equal(self.expr_span) {
|
||||
self.body_expr = Some(ex);
|
||||
}
|
||||
|
||||
hir::intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
let mut finder =
|
||||
ExprFinder { expr_span: span, issue_span, loop_bind: None, body_expr: None };
|
||||
finder.visit_expr(hir.body(body_id).value);
|
||||
|
||||
if let Some(loop_bind) = finder.loop_bind &&
|
||||
let Some(body_expr) = finder.body_expr &&
|
||||
let Some(def_id) = typeck_results.type_dependent_def_id(body_expr.hir_id) &&
|
||||
let Some(trait_did) = tcx.trait_of_item(def_id) &&
|
||||
tcx.is_diagnostic_item(sym::Iterator, trait_did) {
|
||||
err.note(format!(
|
||||
"a for loop advances the iterator for you, the result is stored in `{}`.",
|
||||
loop_bind
|
||||
));
|
||||
err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
|
||||
}
|
||||
}
|
||||
|
||||
/// Suggest using closure argument instead of capture.
|
||||
///
|
||||
/// For example:
|
||||
|
@ -1146,6 +1146,12 @@ fn explain_captures(
|
||||
// Avoid pointing to the same function in multiple different
|
||||
// error messages.
|
||||
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
|
||||
self.explain_iterator_advancement_in_for_loop_if_applicable(
|
||||
err,
|
||||
span,
|
||||
&move_spans,
|
||||
);
|
||||
|
||||
let func = tcx.def_path_str(method_did);
|
||||
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
|
||||
func,
|
||||
|
@ -19,7 +19,7 @@
|
||||
self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{
|
||||
@ -651,11 +651,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
let impl_sig = ocx.normalize(
|
||||
&norm_cause,
|
||||
param_env,
|
||||
infcx.instantiate_binder_with_fresh_vars(
|
||||
return_span,
|
||||
infer::HigherRankedType,
|
||||
tcx.fn_sig(impl_m.def_id).subst_identity(),
|
||||
),
|
||||
tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(impl_m.def_id).subst_identity()),
|
||||
);
|
||||
impl_sig.error_reported()?;
|
||||
let impl_return_ty = impl_sig.output();
|
||||
@ -665,9 +661,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
// them with inference variables.
|
||||
// We will use these inference variables to collect the hidden types of RPITITs.
|
||||
let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);
|
||||
let unnormalized_trait_sig = tcx
|
||||
.liberate_late_bound_regions(
|
||||
impl_m.def_id,
|
||||
let unnormalized_trait_sig = infcx
|
||||
.instantiate_binder_with_fresh_vars(
|
||||
return_span,
|
||||
infer::HigherRankedType,
|
||||
tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
|
||||
)
|
||||
.fold_with(&mut collector);
|
||||
@ -760,15 +757,17 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
|
||||
let mut collected_tys = FxHashMap::default();
|
||||
for (def_id, (ty, substs)) in collected_types {
|
||||
match infcx.fully_resolve(ty) {
|
||||
Ok(ty) => {
|
||||
match infcx.fully_resolve((ty, substs)) {
|
||||
Ok((ty, substs)) => {
|
||||
// `ty` contains free regions that we created earlier while liberating the
|
||||
// trait fn signature. However, projection normalization expects `ty` to
|
||||
// contains `def_id`'s early-bound regions.
|
||||
let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
debug!(?id_substs, ?substs);
|
||||
let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> =
|
||||
std::iter::zip(substs, id_substs).collect();
|
||||
let map: FxHashMap<_, _> = std::iter::zip(substs, id_substs)
|
||||
.skip(tcx.generics_of(trait_m.def_id).count())
|
||||
.filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
|
||||
.collect();
|
||||
debug!(?map);
|
||||
|
||||
// NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
|
||||
@ -793,25 +792,19 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
// same generics.
|
||||
let num_trait_substs = trait_to_impl_substs.len();
|
||||
let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
|
||||
let ty = tcx.fold_regions(ty, |region, _| {
|
||||
match region.kind() {
|
||||
// Remap all free regions, which correspond to late-bound regions in the function.
|
||||
ty::ReFree(_) => {}
|
||||
// Remap early-bound regions as long as they don't come from the `impl` itself.
|
||||
ty::ReEarlyBound(ebr) if tcx.parent(ebr.def_id) != impl_m.container_id(tcx) => {}
|
||||
_ => return region,
|
||||
}
|
||||
let Some(ty::ReEarlyBound(e)) = map.get(®ion.into()).map(|r| r.expect_region().kind())
|
||||
else {
|
||||
return ty::Region::new_error_with_message(tcx, return_span, "expected ReFree to map to ReEarlyBound")
|
||||
let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
|
||||
tcx,
|
||||
map,
|
||||
num_trait_substs,
|
||||
num_impl_substs,
|
||||
def_id,
|
||||
impl_def_id: impl_m.container_id(tcx),
|
||||
ty,
|
||||
return_span,
|
||||
}) {
|
||||
Ok(ty) => ty,
|
||||
Err(guar) => tcx.ty_error(guar),
|
||||
};
|
||||
ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion {
|
||||
def_id: e.def_id,
|
||||
name: e.name,
|
||||
index: (e.index as usize - num_trait_substs + num_impl_substs) as u32,
|
||||
})
|
||||
});
|
||||
debug!(%ty);
|
||||
collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
|
||||
}
|
||||
Err(err) => {
|
||||
@ -895,6 +888,97 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
struct RemapHiddenTyRegions<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
map: FxHashMap<ty::Region<'tcx>, ty::Region<'tcx>>,
|
||||
num_trait_substs: usize,
|
||||
num_impl_substs: usize,
|
||||
def_id: DefId,
|
||||
impl_def_id: DefId,
|
||||
ty: Ty<'tcx>,
|
||||
return_span: Span,
|
||||
}
|
||||
|
||||
impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
|
||||
type Error = ErrorGuaranteed;
|
||||
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||
if let ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = *t.kind() {
|
||||
let mut mapped_substs = Vec::with_capacity(substs.len());
|
||||
for (arg, v) in std::iter::zip(substs, self.tcx.variances_of(def_id)) {
|
||||
mapped_substs.push(match (arg.unpack(), v) {
|
||||
// Skip uncaptured opaque substs
|
||||
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
|
||||
_ => arg.try_fold_with(self)?,
|
||||
});
|
||||
}
|
||||
Ok(self.tcx.mk_opaque(def_id, self.tcx.mk_substs(&mapped_substs)))
|
||||
} else {
|
||||
t.try_super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fold_region(
|
||||
&mut self,
|
||||
region: ty::Region<'tcx>,
|
||||
) -> Result<ty::Region<'tcx>, Self::Error> {
|
||||
match region.kind() {
|
||||
// Remap all free regions, which correspond to late-bound regions in the function.
|
||||
ty::ReFree(_) => {}
|
||||
// Remap early-bound regions as long as they don't come from the `impl` itself,
|
||||
// in which case we don't really need to renumber them.
|
||||
ty::ReEarlyBound(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {}
|
||||
_ => return Ok(region),
|
||||
}
|
||||
|
||||
let e = if let Some(region) = self.map.get(®ion) {
|
||||
if let ty::ReEarlyBound(e) = region.kind() { e } else { bug!() }
|
||||
} else {
|
||||
let guar = match region.kind() {
|
||||
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. })
|
||||
| ty::ReFree(ty::FreeRegion {
|
||||
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
|
||||
..
|
||||
}) => {
|
||||
let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
|
||||
self.tcx.def_span(opaque_ty.def_id)
|
||||
} else {
|
||||
self.return_span
|
||||
};
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(
|
||||
return_span,
|
||||
"return type captures more lifetimes than trait definition",
|
||||
)
|
||||
.span_label(self.tcx.def_span(def_id), "this lifetime was captured")
|
||||
.span_note(
|
||||
self.tcx.def_span(self.def_id),
|
||||
"hidden type must only reference lifetimes captured by this impl trait",
|
||||
)
|
||||
.note(format!("hidden type inferred to be `{}`", self.ty))
|
||||
.emit()
|
||||
}
|
||||
_ => self.tcx.sess.delay_span_bug(DUMMY_SP, "should've been able to remap region"),
|
||||
};
|
||||
return Err(guar);
|
||||
};
|
||||
|
||||
Ok(ty::Region::new_early_bound(
|
||||
self.tcx,
|
||||
ty::EarlyBoundRegion {
|
||||
def_id: e.def_id,
|
||||
name: e.name,
|
||||
index: (e.index as usize - self.num_trait_substs + self.num_impl_substs) as u32,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn report_trait_method_mismatch<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
mut cause: ObligationCause<'tcx>,
|
||||
|
@ -2135,16 +2135,18 @@ pub fn check_item(&mut self, id: ItemId) {
|
||||
// lints shouldn't be emmited even if `from` effective visibility
|
||||
// is larger than `Priv` nominal visibility and if `Priv` can leak
|
||||
// in some scenarios due to type inference.
|
||||
let impl_ev = Some(EffectiveVisibility::of_impl::<false>(
|
||||
let impl_ev = EffectiveVisibility::of_impl::<false>(
|
||||
item.owner_id.def_id,
|
||||
tcx,
|
||||
self.effective_visibilities,
|
||||
));
|
||||
);
|
||||
|
||||
// check that private components do not appear in the generics or predicates of inherent impls
|
||||
// this check is intentionally NOT performed for impls of traits, per #90586
|
||||
if impl_.of_trait.is_none() {
|
||||
self.check(item.owner_id.def_id, impl_vis, impl_ev).generics().predicates();
|
||||
self.check(item.owner_id.def_id, impl_vis, Some(impl_ev))
|
||||
.generics()
|
||||
.predicates();
|
||||
}
|
||||
for impl_item_ref in impl_.items {
|
||||
let impl_item_vis = if impl_.of_trait.is_none() {
|
||||
@ -2159,8 +2161,9 @@ pub fn check_item(&mut self, id: ItemId) {
|
||||
|
||||
let impl_item_ev = if impl_.of_trait.is_none() {
|
||||
self.get(impl_item_ref.id.owner_id.def_id)
|
||||
.map(|ev| ev.min(impl_ev, self.tcx))
|
||||
} else {
|
||||
impl_ev
|
||||
Some(impl_ev)
|
||||
};
|
||||
|
||||
self.check_assoc_item(
|
||||
|
@ -370,7 +370,7 @@ pub(crate) fn resolve_ident_in_lexical_scope(
|
||||
/// expansion and import resolution (perhaps they can be merged in the future).
|
||||
/// The function is used for resolving initial segments of macro paths (e.g., `foo` in
|
||||
/// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
|
||||
#[instrument(level = "debug", skip(self, scope_set))]
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(crate) fn early_resolve_ident_in_lexical_scope(
|
||||
&mut self,
|
||||
orig_ident: Ident,
|
||||
|
@ -894,8 +894,9 @@ fn finalize_import(&mut self, import: &'a Import<'a>) -> Option<UnresolvedImport
|
||||
}
|
||||
return None;
|
||||
}
|
||||
PathResult::NonModule(_) => {
|
||||
if no_ambiguity {
|
||||
PathResult::NonModule(partial_res) => {
|
||||
if no_ambiguity && partial_res.full_res() != Some(Res::Err) {
|
||||
// Check if there are no ambiguities and the result is not dummy.
|
||||
assert!(import.imported_module.get().is_none());
|
||||
}
|
||||
// The error was already reported earlier.
|
||||
|
@ -128,7 +128,7 @@ enum Scope<'a> {
|
||||
/// with different restrictions when looking up the resolution.
|
||||
/// This enum is currently used only for early resolution (imports and macros),
|
||||
/// but not for late resolution yet.
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum ScopeSet<'a> {
|
||||
/// All scopes with the given namespace.
|
||||
All(Namespace),
|
||||
|
@ -1601,9 +1601,7 @@ fn filter(contents: &str, marker: &str) -> String {
|
||||
prepare("cargo");
|
||||
prepare("rust-analysis");
|
||||
prepare("rust-std");
|
||||
prepare("clippy");
|
||||
prepare("rust-analyzer");
|
||||
for tool in &["rust-docs", "rust-demangler", "miri"] {
|
||||
for tool in &["clippy", "rust-analyzer", "rust-docs", "rust-demangler", "miri"] {
|
||||
if built_tools.contains(tool) {
|
||||
prepare(tool);
|
||||
}
|
||||
@ -1689,6 +1687,7 @@ fn filter(contents: &str, marker: &str) -> String {
|
||||
.arg("-out")
|
||||
.arg(exe.join("StdGroup.wxs")),
|
||||
);
|
||||
if built_tools.contains("rust-analyzer") {
|
||||
builder.run(
|
||||
Command::new(&heat)
|
||||
.current_dir(&exe)
|
||||
@ -1706,6 +1705,8 @@ fn filter(contents: &str, marker: &str) -> String {
|
||||
.arg("-t")
|
||||
.arg(etc.join("msi/remove-duplicates.xsl")),
|
||||
);
|
||||
}
|
||||
if built_tools.contains("clippy") {
|
||||
builder.run(
|
||||
Command::new(&heat)
|
||||
.current_dir(&exe)
|
||||
@ -1723,6 +1724,7 @@ fn filter(contents: &str, marker: &str) -> String {
|
||||
.arg("-t")
|
||||
.arg(etc.join("msi/remove-duplicates.xsl")),
|
||||
);
|
||||
}
|
||||
if built_tools.contains("rust-demangler") {
|
||||
builder.run(
|
||||
Command::new(&heat)
|
||||
@ -1806,7 +1808,6 @@ fn filter(contents: &str, marker: &str) -> String {
|
||||
.arg("-dCargoDir=cargo")
|
||||
.arg("-dStdDir=rust-std")
|
||||
.arg("-dAnalysisDir=rust-analysis")
|
||||
.arg("-dClippyDir=clippy")
|
||||
.arg("-arch")
|
||||
.arg(&arch)
|
||||
.arg("-out")
|
||||
@ -1814,6 +1815,9 @@ fn filter(contents: &str, marker: &str) -> String {
|
||||
.arg(&input);
|
||||
add_env(builder, &mut cmd, target);
|
||||
|
||||
if built_tools.contains("clippy") {
|
||||
cmd.arg("-dClippyDir=clippy");
|
||||
}
|
||||
if built_tools.contains("rust-docs") {
|
||||
cmd.arg("-dDocsDir=rust-docs");
|
||||
}
|
||||
@ -1840,7 +1844,9 @@ fn filter(contents: &str, marker: &str) -> String {
|
||||
}
|
||||
candle("CargoGroup.wxs".as_ref());
|
||||
candle("StdGroup.wxs".as_ref());
|
||||
if built_tools.contains("clippy") {
|
||||
candle("ClippyGroup.wxs".as_ref());
|
||||
}
|
||||
if built_tools.contains("miri") {
|
||||
candle("MiriGroup.wxs".as_ref());
|
||||
}
|
||||
@ -1877,9 +1883,11 @@ fn filter(contents: &str, marker: &str) -> String {
|
||||
.arg("CargoGroup.wixobj")
|
||||
.arg("StdGroup.wixobj")
|
||||
.arg("AnalysisGroup.wixobj")
|
||||
.arg("ClippyGroup.wixobj")
|
||||
.current_dir(&exe);
|
||||
|
||||
if built_tools.contains("clippy") {
|
||||
cmd.arg("ClippyGroup.wixobj");
|
||||
}
|
||||
if built_tools.contains("miri") {
|
||||
cmd.arg("MiriGroup.wixobj");
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 03bc66b55c290324bd46eb22e369c8fae1908f91
|
||||
Subproject commit 5b377cece0e0dd0af686cf53ce4637d5d85c2a10
|
@ -5,7 +5,7 @@ LL | fn early<'late, T>(_: &'late ()) {}
|
||||
| - ^^^^^^^^^
|
||||
| | |
|
||||
| | expected type parameter `T`, found `()`
|
||||
| | help: change the parameter type to match the trait: `&'early T`
|
||||
| | help: change the parameter type to match the trait: `&T`
|
||||
| this type parameter
|
||||
|
|
||||
note: type in trait
|
||||
@ -13,8 +13,8 @@ note: type in trait
|
||||
|
|
||||
LL | fn early<'early, T>(x: &'early T) -> impl Sized;
|
||||
| ^^^^^^^^^
|
||||
= note: expected signature `fn(&'early T)`
|
||||
found signature `fn(&())`
|
||||
= note: expected signature `fn(&T)`
|
||||
found signature `fn(&'late ())`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,16 +1,61 @@
|
||||
error: `impl` item signature doesn't match `trait` item signature
|
||||
--> $DIR/signature-mismatch.rs:17:5
|
||||
error: return type captures more lifetimes than trait definition
|
||||
--> $DIR/signature-mismatch.rs:36:47
|
||||
|
|
||||
LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
||||
| -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type must only reference lifetimes captured by this impl trait
|
||||
--> $DIR/signature-mismatch.rs:17:40
|
||||
|
|
||||
LL | fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
|
||||
| ----------------------------------------------------------------- expected `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
|
||||
...
|
||||
LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
|
||||
|
||||
error: return type captures more lifetimes than trait definition
|
||||
--> $DIR/signature-mismatch.rs:41:57
|
||||
|
|
||||
= note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
|
||||
found signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
|
||||
= help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
|
||||
= help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
|
||||
LL | fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
||||
| -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type must only reference lifetimes captured by this impl trait
|
||||
--> $DIR/signature-mismatch.rs:18:57
|
||||
|
|
||||
LL | fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
|
||||
|
||||
error: aborting due to previous error
|
||||
error: return type captures more lifetimes than trait definition
|
||||
--> $DIR/signature-mismatch.rs:49:10
|
||||
|
|
||||
LL | fn async_fn_multiple<'a, 'b>(
|
||||
| -- this lifetime was captured
|
||||
...
|
||||
LL | ) -> impl Future<Output = Vec<u8>> + Captures2<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type must only reference lifetimes captured by this impl trait
|
||||
--> $DIR/signature-mismatch.rs:20:12
|
||||
|
|
||||
LL | -> impl Future<Output = Vec<u8>> + Captures<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + Captures2<'a, 'b>`
|
||||
|
||||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/signature-mismatch.rs:58:10
|
||||
|
|
||||
LL | ) -> impl Future<Output = Vec<u8>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `impl Future<Output = Vec<u8>>` will meet its required lifetime bounds...
|
||||
|
|
||||
note: ...that is required by this bound
|
||||
--> $DIR/signature-mismatch.rs:25:42
|
||||
|
|
||||
LL | ) -> impl Future<Output = Vec<u8>> + 'a;
|
||||
| ^^
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn async_fn_reduce_outlive<'a, 'b, T: 'a>(
|
||||
| ++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
|
@ -1,16 +1,61 @@
|
||||
error: `impl` item signature doesn't match `trait` item signature
|
||||
--> $DIR/signature-mismatch.rs:17:5
|
||||
error: return type captures more lifetimes than trait definition
|
||||
--> $DIR/signature-mismatch.rs:36:47
|
||||
|
|
||||
LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
||||
| -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type must only reference lifetimes captured by this impl trait
|
||||
--> $DIR/signature-mismatch.rs:17:40
|
||||
|
|
||||
LL | fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
|
||||
| ----------------------------------------------------------------- expected `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
|
||||
...
|
||||
LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
|
||||
|
||||
error: return type captures more lifetimes than trait definition
|
||||
--> $DIR/signature-mismatch.rs:41:57
|
||||
|
|
||||
= note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
|
||||
found signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
|
||||
= help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
|
||||
= help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
|
||||
LL | fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
||||
| -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type must only reference lifetimes captured by this impl trait
|
||||
--> $DIR/signature-mismatch.rs:18:57
|
||||
|
|
||||
LL | fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
|
||||
|
||||
error: aborting due to previous error
|
||||
error: return type captures more lifetimes than trait definition
|
||||
--> $DIR/signature-mismatch.rs:49:10
|
||||
|
|
||||
LL | fn async_fn_multiple<'a, 'b>(
|
||||
| -- this lifetime was captured
|
||||
...
|
||||
LL | ) -> impl Future<Output = Vec<u8>> + Captures2<'a, 'b> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: hidden type must only reference lifetimes captured by this impl trait
|
||||
--> $DIR/signature-mismatch.rs:20:12
|
||||
|
|
||||
LL | -> impl Future<Output = Vec<u8>> + Captures<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: hidden type inferred to be `impl Future<Output = Vec<u8>> + Captures2<'a, 'b>`
|
||||
|
||||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/signature-mismatch.rs:58:10
|
||||
|
|
||||
LL | ) -> impl Future<Output = Vec<u8>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `impl Future<Output = Vec<u8>>` will meet its required lifetime bounds...
|
||||
|
|
||||
note: ...that is required by this bound
|
||||
--> $DIR/signature-mismatch.rs:25:42
|
||||
|
|
||||
LL | ) -> impl Future<Output = Vec<u8>> + 'a;
|
||||
| ^^
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn async_fn_reduce_outlive<'a, 'b, T: 'a>(
|
||||
| ++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
|
@ -7,17 +7,70 @@
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
trait Captures<'a> {}
|
||||
impl<T> Captures<'_> for T {}
|
||||
|
||||
trait Captures2<'a, 'b> {}
|
||||
impl<T> Captures2<'_, '_> for T {}
|
||||
|
||||
pub trait AsyncTrait {
|
||||
fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
|
||||
fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>>;
|
||||
fn async_fn_multiple<'a>(&'a self, buff: &[u8])
|
||||
-> impl Future<Output = Vec<u8>> + Captures<'a>;
|
||||
fn async_fn_reduce_outlive<'a, T>(
|
||||
&'a self,
|
||||
buff: &[u8],
|
||||
t: T,
|
||||
) -> impl Future<Output = Vec<u8>> + 'a;
|
||||
fn async_fn_reduce<'a, T>(
|
||||
&'a self,
|
||||
buff: &[u8],
|
||||
t: T,
|
||||
) -> impl Future<Output = Vec<u8>> + Captures<'a>;
|
||||
}
|
||||
|
||||
pub struct Struct;
|
||||
|
||||
impl AsyncTrait for Struct {
|
||||
fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
||||
//~^ ERROR `impl` item signature doesn't match `trait` item signature
|
||||
//~^ ERROR return type captures more lifetimes than trait definition
|
||||
async move { buff.to_vec() }
|
||||
}
|
||||
|
||||
fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
|
||||
//~^ ERROR return type captures more lifetimes than trait definition
|
||||
async move { buff.to_vec() }
|
||||
}
|
||||
|
||||
fn async_fn_multiple<'a, 'b>(
|
||||
&'a self,
|
||||
buff: &'b [u8],
|
||||
) -> impl Future<Output = Vec<u8>> + Captures2<'a, 'b> {
|
||||
//~^ ERROR return type captures more lifetimes than trait definition
|
||||
async move { buff.to_vec() }
|
||||
}
|
||||
|
||||
fn async_fn_reduce_outlive<'a, 'b, T>(
|
||||
&'a self,
|
||||
buff: &'b [u8],
|
||||
t: T,
|
||||
) -> impl Future<Output = Vec<u8>> {
|
||||
//~^ ERROR the parameter type `T` may not live long enough
|
||||
async move {
|
||||
let _t = t;
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
// OK: We remove the `Captures<'a>`, providing a guarantee that we don't capture `'a`,
|
||||
// but we still fulfill the `Captures<'a>` trait bound.
|
||||
fn async_fn_reduce<'a, 'b, T>(&'a self, buff: &'b [u8], t: T) -> impl Future<Output = Vec<u8>> {
|
||||
async move {
|
||||
let _t = t;
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
6
tests/ui/imports/auxiliary/issue-85992-extern-1.rs
Normal file
6
tests/ui/imports/auxiliary/issue-85992-extern-1.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#[macro_export]
|
||||
macro_rules! m {
|
||||
() => {
|
||||
use issue_85992_extern_2::Outcome;
|
||||
}
|
||||
}
|
1
tests/ui/imports/auxiliary/issue-85992-extern-2.rs
Normal file
1
tests/ui/imports/auxiliary/issue-85992-extern-2.rs
Normal file
@ -0,0 +1 @@
|
||||
// nothing
|
11
tests/ui/imports/issue-85992.rs
Normal file
11
tests/ui/imports/issue-85992.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// edition: 2021
|
||||
// compile-flags: --extern issue_85992_extern_1 --extern issue_85992_extern_2
|
||||
// aux-build: issue-85992-extern-1.rs
|
||||
// aux-build: issue-85992-extern-2.rs
|
||||
|
||||
issue_85992_extern_1::m!();
|
||||
|
||||
use crate::issue_85992_extern_2;
|
||||
//~^ ERROR unresolved import `crate::issue_85992_extern_2`
|
||||
|
||||
fn main() {}
|
9
tests/ui/imports/issue-85992.stderr
Normal file
9
tests/ui/imports/issue-85992.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0432]: unresolved import `crate::issue_85992_extern_2`
|
||||
--> $DIR/issue-85992.rs:8:5
|
||||
|
|
||||
LL | use crate::issue_85992_extern_2;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `issue_85992_extern_2` in the root
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0432`.
|
16
tests/ui/suggestions/issue-102972.rs
Normal file
16
tests/ui/suggestions/issue-102972.rs
Normal file
@ -0,0 +1,16 @@
|
||||
fn test1() {
|
||||
let mut chars = "Hello".chars();
|
||||
for _c in chars.by_ref() {
|
||||
chars.next(); //~ ERROR cannot borrow `chars` as mutable more than once at a time
|
||||
}
|
||||
}
|
||||
|
||||
fn test2() {
|
||||
let v = vec![1, 2, 3];
|
||||
let mut iter = v.iter();
|
||||
for _i in iter {
|
||||
iter.next(); //~ ERROR borrow of moved value: `iter`
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
33
tests/ui/suggestions/issue-102972.stderr
Normal file
33
tests/ui/suggestions/issue-102972.stderr
Normal file
@ -0,0 +1,33 @@
|
||||
error[E0499]: cannot borrow `chars` as mutable more than once at a time
|
||||
--> $DIR/issue-102972.rs:4:9
|
||||
|
|
||||
LL | for _c in chars.by_ref() {
|
||||
| --------------
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
| first borrow later used here
|
||||
LL | chars.next();
|
||||
| ^^^^^^^^^^^^ second mutable borrow occurs here
|
||||
|
|
||||
= note: a for loop advances the iterator for you, the result is stored in `_c`.
|
||||
= help: if you want to call `next` on a iterator within the loop, consider using `while let`.
|
||||
|
||||
error[E0382]: borrow of moved value: `iter`
|
||||
--> $DIR/issue-102972.rs:12:9
|
||||
|
|
||||
LL | let mut iter = v.iter();
|
||||
| -------- move occurs because `iter` has type `std::slice::Iter<'_, i32>`, which does not implement the `Copy` trait
|
||||
LL | for _i in iter {
|
||||
| ---- `iter` moved due to this implicit call to `.into_iter()`
|
||||
LL | iter.next();
|
||||
| ^^^^^^^^^^^ value borrowed here after move
|
||||
|
|
||||
= note: a for loop advances the iterator for you, the result is stored in `_i`.
|
||||
= help: if you want to call `next` on a iterator within the loop, consider using `while let`.
|
||||
note: `into_iter` takes ownership of the receiver `self`, which moves `iter`
|
||||
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0382, E0499.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
Loading…
Reference in New Issue
Block a user