Auto merge of #103671 - matthiaskrgr:rollup-iuugpep, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #102642 (Add tests for static async functions in traits)
 - #103283 (Add suggestions for unsafe impl error codes)
 - #103523 (Fix unwanted merge of inline doc comments for impl blocks)
 - #103550 (diagnostics: do not suggest static candidates as traits to import)
 - #103641 (Don't carry MIR location in `ConstraintCategory::CallArgument`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-10-28 09:41:40 +00:00
commit a9ef10019f
62 changed files with 928 additions and 114 deletions

View File

@ -92,7 +92,7 @@ pub struct OutlivesConstraint<'tcx> {
pub span: Span,
/// What caused this constraint?
pub category: ConstraintCategory,
pub category: ConstraintCategory<'tcx>,
/// Variance diagnostic information
pub variance_info: VarianceDiagInfo<'tcx>,

View File

@ -983,7 +983,7 @@ fn suggest_using_local_if_applicable(
err: &mut Diagnostic,
location: Location,
issued_borrow: &BorrowData<'tcx>,
explanation: BorrowExplanation,
explanation: BorrowExplanation<'tcx>,
) {
let used_in_call = matches!(
explanation,
@ -1333,7 +1333,7 @@ fn report_local_value_does_not_live_long_enough(
borrow: &BorrowData<'tcx>,
drop_span: Span,
borrow_spans: UseSpans<'tcx>,
explanation: BorrowExplanation,
explanation: BorrowExplanation<'tcx>,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
debug!(
"report_local_value_does_not_live_long_enough(\
@ -1539,7 +1539,7 @@ fn report_temporary_value_does_not_live_long_enough(
drop_span: Span,
borrow_spans: UseSpans<'tcx>,
proper_span: Span,
explanation: BorrowExplanation,
explanation: BorrowExplanation<'tcx>,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
explanation
@ -1653,7 +1653,7 @@ fn try_report_cannot_return_reference_to_local(
borrow: &BorrowData<'tcx>,
borrow_span: Span,
return_span: Span,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
opt_place_desc: Option<&String>,
) -> Option<DiagnosticBuilder<'cx, ErrorGuaranteed>> {
let return_kind = match category {
@ -1748,7 +1748,7 @@ fn report_escaping_closure_capture(
use_span: UseSpans<'tcx>,
var_span: Span,
fr_name: &RegionName,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
constraint_span: Span,
captured_var: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {

View File

@ -21,7 +21,7 @@
use super::{find_use, RegionName, UseSpans};
#[derive(Debug)]
pub(crate) enum BorrowExplanation {
pub(crate) enum BorrowExplanation<'tcx> {
UsedLater(LaterUseKind, Span, Option<Span>),
UsedLaterInLoop(LaterUseKind, Span, Option<Span>),
UsedLaterWhenDropped {
@ -30,7 +30,7 @@ pub(crate) enum BorrowExplanation {
should_note_order: bool,
},
MustBeValidFor {
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
from_closure: bool,
span: Span,
region_name: RegionName,
@ -49,7 +49,7 @@ pub(crate) enum LaterUseKind {
Other,
}
impl<'tcx> BorrowExplanation {
impl<'tcx> BorrowExplanation<'tcx> {
pub(crate) fn is_explained(&self) -> bool {
!matches!(self, BorrowExplanation::Unexplained)
}
@ -284,7 +284,7 @@ pub(crate) fn add_explanation_to_diagnostic(
fn add_lifetime_bound_suggestion_to_diagnostic(
&self,
err: &mut Diagnostic,
category: &ConstraintCategory,
category: &ConstraintCategory<'tcx>,
span: Span,
region_name: &RegionName,
) {
@ -316,7 +316,7 @@ fn free_region_constraint_info(
&self,
borrow_region: RegionVid,
outlived_region: RegionVid,
) -> (ConstraintCategory, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) {
) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) {
let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint(
borrow_region,
NllRegionVariableOrigin::FreeRegion,
@ -348,7 +348,7 @@ pub(crate) fn explain_why_borrow_contains_point(
location: Location,
borrow: &BorrowData<'tcx>,
kind_place: Option<(WriteKind, Place<'tcx>)>,
) -> BorrowExplanation {
) -> BorrowExplanation<'tcx> {
let regioncx = &self.regioncx;
let body: &Body<'_> = &self.body;
let tcx = self.infcx.tcx;

View File

@ -161,7 +161,7 @@ pub(crate) fn collect_constraint(&mut self, fr: RegionVid, outlived_fr: RegionVi
pub(crate) fn intermediate_suggestion(
&mut self,
mbcx: &MirBorrowckCtxt<'_, '_>,
errci: &ErrorConstraintInfo,
errci: &ErrorConstraintInfo<'_>,
diag: &mut Diagnostic,
) {
// Emit an intermediate note.

View File

@ -2,7 +2,6 @@
#![deny(rustc::diagnostic_outside_of_impl)]
//! Error reporting machinery for lifetime errors.
use either::Either;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
use rustc_hir::def_id::DefId;
@ -17,7 +16,7 @@
NllRegionVariableOrigin, RelateParamBound,
};
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint, TerminatorKind};
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::Region;
use rustc_middle::ty::TypeVisitor;
@ -40,7 +39,7 @@
MirBorrowckCtxt,
};
impl ConstraintDescription for ConstraintCategory {
impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
fn description(&self) -> &'static str {
// Must end with a space. Allows for empty names to be provided.
match self {
@ -116,7 +115,7 @@ pub(crate) enum RegionErrorKind<'tcx> {
/// Information about the various region constraints involved in a borrow checker error.
#[derive(Clone, Debug)]
pub struct ErrorConstraintInfo {
pub struct ErrorConstraintInfo<'tcx> {
// fr: outlived_fr
pub(super) fr: RegionVid,
pub(super) fr_is_local: bool,
@ -124,7 +123,7 @@ pub struct ErrorConstraintInfo {
pub(super) outlived_fr_is_local: bool,
// Category and span for best blame constraint
pub(super) category: ConstraintCategory,
pub(super) category: ConstraintCategory<'tcx>,
pub(super) span: Span,
}
@ -499,7 +498,7 @@ pub(crate) fn report_region_error(
/// ```
fn report_fnmut_error(
&self,
errci: &ErrorConstraintInfo,
errci: &ErrorConstraintInfo<'tcx>,
kind: ReturnConstraint,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
@ -572,7 +571,7 @@ fn report_fnmut_error(
#[instrument(level = "debug", skip(self))]
fn report_escaping_data_error(
&self,
errci: &ErrorConstraintInfo,
errci: &ErrorConstraintInfo<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let ErrorConstraintInfo { span, category, .. } = errci;
@ -676,7 +675,7 @@ fn report_escaping_data_error(
/// ```
fn report_general_error(
&self,
errci: &ErrorConstraintInfo,
errci: &ErrorConstraintInfo<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let ErrorConstraintInfo {
fr,
@ -789,7 +788,7 @@ fn maybe_suggest_constrain_dyn_trait_impl(
diag: &mut Diagnostic,
f: Region<'tcx>,
o: Region<'tcx>,
category: &ConstraintCategory,
category: &ConstraintCategory<'tcx>,
) {
if !o.is_static() {
return;
@ -797,12 +796,7 @@ fn maybe_suggest_constrain_dyn_trait_impl(
let tcx = self.infcx.tcx;
let instance =
if let ConstraintCategory::CallArgument(location) = category
&& let Either::Right(term) = self.body.stmt_at(*location)
&& let TerminatorKind::Call { func, .. } = &term.kind
{
let func_ty = func.ty(self.body, tcx);
let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category {
let (fn_did, substs) = match func_ty.kind() {
ty::FnDef(fn_did, substs) => (fn_did, substs),
_ => return,

View File

@ -91,7 +91,7 @@ pub struct RegionInferenceContext<'tcx> {
/// Map closure bounds to a `Span` that should be used for error reporting.
closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
/// Map universe indexes to information on why we created it.
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
@ -267,7 +267,7 @@ pub(crate) fn new(
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
closure_bounds_mapping: FxHashMap<
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
>,
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>,
@ -1807,7 +1807,7 @@ pub(crate) fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bo
pub(crate) fn retrieve_closure_constraint_info(
&self,
constraint: OutlivesConstraint<'tcx>,
) -> Option<(ConstraintCategory, Span)> {
) -> Option<(ConstraintCategory<'tcx>, Span)> {
match constraint.locations {
Locations::All(_) => None,
Locations::Single(loc) => {
@ -1822,7 +1822,7 @@ pub(crate) fn find_outlives_blame_span(
fr1: RegionVid,
fr1_origin: NllRegionVariableOrigin,
fr2: RegionVid,
) -> (ConstraintCategory, ObligationCause<'tcx>) {
) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) {
let BlameConstraint { category, cause, .. } = self
.best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2))
.0;
@ -2362,7 +2362,7 @@ fn apply_requirements(
#[derive(Clone, Debug)]
pub struct BlameConstraint<'tcx> {
pub category: ConstraintCategory,
pub category: ConstraintCategory<'tcx>,
pub from_closure: bool,
pub cause: ObligationCause<'tcx>,
pub variance_info: ty::VarianceDiagInfo<'tcx>,

View File

@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
pub(super) fn fully_perform_op<R: fmt::Debug, Op>(
&mut self,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
op: Op,
) -> Fallible<R>
where
@ -85,7 +85,7 @@ pub(super) fn prove_trait_ref(
&mut self,
trait_ref: ty::TraitRef<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
self.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
@ -124,7 +124,7 @@ pub(super) fn prove_predicates(
&mut self,
predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
for predicate in predicates {
let predicate = predicate.to_predicate(self.tcx());
@ -139,7 +139,7 @@ pub(super) fn prove_predicate(
&mut self,
predicate: ty::Predicate<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
let param_env = self.param_env;
self.fully_perform_op(
@ -164,7 +164,7 @@ pub(super) fn normalize_with_category<T>(
&mut self,
value: T,
location: impl NormalizeLocation,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> T
where
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,

View File

@ -37,7 +37,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
span: Span,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
}
@ -50,7 +50,7 @@ pub(crate) fn new(
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
span: Span,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
) -> Self {
Self {
@ -175,7 +175,7 @@ fn add_outlives(
&mut self,
sup: ty::RegionVid,
sub: ty::RegionVid,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
let category = match self.category {
ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category,
@ -203,7 +203,7 @@ fn push_sub_region_constraint(
_origin: SubregionOrigin<'tcx>,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
constraint_category: ConstraintCategory,
constraint_category: ConstraintCategory<'tcx>,
) {
let b = self.to_region_vid(b);
let a = self.to_region_vid(a);

View File

@ -942,7 +942,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
pub(crate) closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
@ -1133,7 +1133,7 @@ fn check_user_type_annotations(&mut self) {
fn push_region_constraints(
&mut self,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
data: &QueryRegionConstraints<'tcx>,
) {
debug!("constraints generated: {:#?}", data);
@ -1158,7 +1158,7 @@ fn sub_types(
sub: Ty<'tcx>,
sup: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
// Use this order of parameters because the sup type is usually the
// "expected" type in diagnostics.
@ -1171,7 +1171,7 @@ fn eq_types(
expected: Ty<'tcx>,
found: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
}
@ -1183,7 +1183,7 @@ fn relate_type_and_user_type(
v: ty::Variance,
user_ty: &UserTypeProjection,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
@ -1618,12 +1618,19 @@ fn check_call_inputs(
span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
}
let func_ty = if let TerminatorKind::Call { func, .. } = &term.kind {
Some(func.ty(body, self.infcx.tcx))
} else {
None
};
debug!(?func_ty);
for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
let op_arg_ty = op_arg.ty(body, self.tcx());
let op_arg_ty = self.normalize(op_arg_ty, term_location);
let category = if from_hir_call {
ConstraintCategory::CallArgument(term_location)
ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
} else {
ConstraintCategory::Boring
};

View File

@ -28,7 +28,7 @@ pub(super) fn relate_types(
v: ty::Variance,
b: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
TypeRelating::new(
self.infcx,
@ -45,7 +45,7 @@ pub(super) fn eq_substs(
a: ty::SubstsRef<'tcx>,
b: ty::SubstsRef<'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
TypeRelating::new(
self.infcx,
@ -64,7 +64,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
locations: Locations,
/// What category do we assign the resulting `'a: 'b` relationships?
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
/// Information so that error reporting knows what types we are relating
/// when reporting a bound region error.
@ -75,7 +75,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
fn new(
type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
locations: Locations,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
universe_info: UniverseInfo<'tcx>,
) -> Self {
Self { type_checker, locations, category, universe_info }

View File

@ -26,6 +26,12 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"implementing the trait `{}` is not unsafe",
trait_ref.print_only_trait_path()
)
.span_suggestion_verbose(
item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)),
"remove `unsafe` from this trait implementation",
"",
rustc_errors::Applicability::MachineApplicable,
)
.emit();
}
@ -37,6 +43,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"the trait `{}` requires an `unsafe impl` declaration",
trait_ref.print_only_trait_path()
)
.note(format!(
"the trait `{}` enforces invariants that the compiler can't check. \
Review the trait documentation and make sure this implementation \
upholds those invariants before adding the `unsafe` keyword",
trait_ref.print_only_trait_path()
))
.span_suggestion_verbose(
item.span.shrink_to_lo(),
"add `unsafe` to this trait implementation",
"unsafe ",
rustc_errors::Applicability::MaybeIncorrect,
)
.emit();
}
@ -48,6 +66,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
attr_name
)
.note(format!(
"the trait `{}` enforces invariants that the compiler can't check. \
Review the trait documentation and make sure this implementation \
upholds those invariants before adding the `unsafe` keyword",
trait_ref.print_only_trait_path()
))
.span_suggestion_verbose(
item.span.shrink_to_lo(),
"add `unsafe` to this trait implementation",
"unsafe ",
rustc_errors::Applicability::MaybeIncorrect,
)
.emit();
}

View File

@ -106,7 +106,7 @@ pub fn report_method_error(
let report_candidates = |span: Span,
err: &mut Diagnostic,
mut sources: Vec<CandidateSource>,
sources: &mut Vec<CandidateSource>,
sugg_span: Span| {
sources.sort();
sources.dedup();
@ -248,7 +248,7 @@ pub fn report_method_error(
match error {
MethodError::NoMatch(NoMatchData {
static_candidates: static_sources,
static_candidates: mut static_sources,
unsatisfied_predicates,
out_of_scope_traits,
lev_candidate,
@ -422,9 +422,9 @@ pub fn report_method_error(
err.help(&format!("try with `{}::{}`", ty_str, item_name,));
}
report_candidates(span, &mut err, static_sources, sugg_span);
report_candidates(span, &mut err, &mut static_sources, sugg_span);
} else if static_sources.len() > 1 {
report_candidates(span, &mut err, static_sources, sugg_span);
report_candidates(span, &mut err, &mut static_sources, sugg_span);
}
let mut bound_spans = vec![];
@ -1007,6 +1007,7 @@ trait bound{s}",
source,
out_of_scope_traits,
&unsatisfied_predicates,
&static_sources,
unsatisfied_bounds,
);
}
@ -1079,7 +1080,7 @@ trait bound{s}",
return Some(err);
}
MethodError::Ambiguity(sources) => {
MethodError::Ambiguity(mut sources) => {
let mut err = struct_span_err!(
self.sess(),
item_name.span,
@ -1088,7 +1089,7 @@ trait bound{s}",
);
err.span_label(item_name.span, format!("multiple `{}` found", item_name));
report_candidates(span, &mut err, sources, sugg_span);
report_candidates(span, &mut err, &mut sources, sugg_span);
err.emit();
}
@ -2015,6 +2016,7 @@ fn suggest_traits_to_import(
Option<ty::Predicate<'tcx>>,
Option<ObligationCause<'tcx>>,
)],
static_candidates: &[CandidateSource],
unsatisfied_bounds: bool,
) {
let mut alt_rcvr_sugg = false;
@ -2128,6 +2130,16 @@ fn suggest_traits_to_import(
Some(attr) => attr.level.is_stable(),
None => true,
})
.filter(|info| {
// Static candidates are already implemented, and known not to work
// Do not suggest them again
static_candidates.iter().all(|sc| match *sc {
CandidateSource::Trait(def_id) => def_id != info.def_id,
CandidateSource::Impl(def_id) => {
self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
}
})
})
.filter(|info| {
// We approximate the coherence rules to only suggest
// traits that are legal to implement by requiring that

View File

@ -632,7 +632,7 @@ fn unify_canonical_vars(
/// creates query region constraints.
pub fn make_query_region_constraints<'tcx>(
tcx: TyCtxt<'tcx>,
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory)>,
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>,
region_constraints: &RegionConstraintData<'tcx>,
) -> QueryRegionConstraints<'tcx> {
let RegionConstraintData { constraints, verifys, givens, member_constraints } =

View File

@ -425,7 +425,7 @@ pub enum SubregionOrigin<'tcx> {
static_assert_size!(SubregionOrigin<'_>, 32);
impl<'tcx> SubregionOrigin<'tcx> {
pub fn to_constraint_category(&self) -> ConstraintCategory {
pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
match self {
Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span),

View File

@ -210,7 +210,7 @@ fn push_sub_region_constraint(
origin: SubregionOrigin<'tcx>,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
constraint_category: ConstraintCategory,
constraint_category: ConstraintCategory<'tcx>,
);
fn push_verify(
@ -259,7 +259,7 @@ pub fn type_must_outlive(
origin: infer::SubregionOrigin<'tcx>,
ty: Ty<'tcx>,
region: ty::Region<'tcx>,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
assert!(!ty.has_escaping_bound_vars());
@ -273,7 +273,7 @@ fn components_must_outlive(
origin: infer::SubregionOrigin<'tcx>,
components: &[Component<'tcx>],
region: ty::Region<'tcx>,
category: ConstraintCategory,
category: ConstraintCategory<'tcx>,
) {
for component in components.iter() {
let origin = origin.clone();
@ -529,7 +529,7 @@ fn push_sub_region_constraint(
origin: SubregionOrigin<'tcx>,
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
_constraint_category: ConstraintCategory,
_constraint_category: ConstraintCategory<'tcx>,
) {
self.sub_regions(origin, a, b)
}

View File

@ -302,8 +302,10 @@ pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'tcx, W>
}
}
pub type QueryOutlivesConstraint<'tcx> =
(ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>, ConstraintCategory);
pub type QueryOutlivesConstraint<'tcx> = (
ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>,
ConstraintCategory<'tcx>,
);
TrivialTypeTraversalAndLiftImpls! {
for <'tcx> {

View File

@ -2904,7 +2904,7 @@ fn pretty_print_const_value<'tcx>(
/// `Location` represents the position of the start of the statement; or, if
/// `statement_index` equals the number of statements, then the start of the
/// terminator.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable, TyEncodable, TyDecodable)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
pub struct Location {
/// The block that the location is within.
pub block: BasicBlock,

View File

@ -15,7 +15,7 @@
use std::cell::Cell;
use std::fmt::{self, Debug};
use super::{Field, Location, SourceInfo};
use super::{Field, SourceInfo};
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub enum UnsafetyViolationKind {
@ -314,12 +314,12 @@ pub struct ClosureOutlivesRequirement<'tcx> {
pub blame_span: Span,
// ... due to this reason.
pub category: ConstraintCategory,
pub category: ConstraintCategory<'tcx>,
}
// Make sure this enum doesn't unintentionally grow
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(ConstraintCategory, 16);
rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
/// Outlives-constraints can be categorized to determine whether and why they
/// are interesting (for error reporting). Order of variants indicates sort
@ -327,8 +327,8 @@ pub struct ClosureOutlivesRequirement<'tcx> {
///
/// See also `rustc_const_eval::borrow_check::constraints`.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[derive(TyEncodable, TyDecodable, HashStable)]
pub enum ConstraintCategory {
#[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)]
pub enum ConstraintCategory<'tcx> {
Return(ReturnConstraint),
Yield,
UseAsConst,
@ -342,7 +342,7 @@ pub enum ConstraintCategory {
ClosureBounds,
/// Contains the function type if available.
CallArgument(Location),
CallArgument(Option<Ty<'tcx>>),
CopyBound,
SizedBound,
Assignment,
@ -368,10 +368,6 @@ pub enum ConstraintCategory {
Internal,
}
TrivialTypeTraversalAndLiftImpls! {
ConstraintCategory,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
pub enum ReturnConstraint {

View File

@ -185,7 +185,7 @@ pub fn derived_cause(
self
}
pub fn to_constraint_category(&self) -> ConstraintCategory {
pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
match self.code() {
MatchImpl(cause, _) => cause.to_constraint_category(),
AscribeUserTypeProvePredicate(predicate_span) => {

View File

@ -55,12 +55,39 @@ pub(crate) fn try_inline(
let mut ret = Vec::new();
debug!("attrs={:?}", attrs);
let attrs_clone = attrs;
let attrs_without_docs = attrs.map(|attrs| {
attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>()
});
// We need this ugly code because:
//
// ```
// attrs_without_docs.map(|a| a.as_slice())
// ```
//
// will fail because it returns a temporary slice and:
//
// ```
// attrs_without_docs.map(|s| {
// vec = s.as_slice();
// vec
// })
// ```
//
// will fail because we're moving an uninitialized variable into a closure.
let vec;
let attrs_without_docs = match attrs_without_docs {
Some(s) => {
vec = s;
Some(vec.as_slice())
}
None => None,
};
let kind = match res {
Res::Def(DefKind::Trait, did) => {
record_extern_fqn(cx, did, ItemType::Trait);
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::TraitItem(Box::new(build_external_trait(cx, did)))
}
Res::Def(DefKind::Fn, did) => {
@ -69,27 +96,27 @@ pub(crate) fn try_inline(
}
Res::Def(DefKind::Struct, did) => {
record_extern_fqn(cx, did, ItemType::Struct);
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::StructItem(build_struct(cx, did))
}
Res::Def(DefKind::Union, did) => {
record_extern_fqn(cx, did, ItemType::Union);
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::UnionItem(build_union(cx, did))
}
Res::Def(DefKind::TyAlias, did) => {
record_extern_fqn(cx, did, ItemType::Typedef);
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::TypedefItem(build_type_alias(cx, did))
}
Res::Def(DefKind::Enum, did) => {
record_extern_fqn(cx, did, ItemType::Enum);
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::EnumItem(build_enum(cx, did))
}
Res::Def(DefKind::ForeignTy, did) => {
record_extern_fqn(cx, did, ItemType::ForeignType);
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::ForeignTypeItem
}
// Never inline enum variants but leave them shown as re-exports.
@ -123,7 +150,7 @@ pub(crate) fn try_inline(
_ => return None,
};
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone);
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs);
cx.inlined.insert(did.into());
let mut item = clean::Item::from_def_id_and_attrs_and_parts(
did,

View File

@ -0,0 +1,5 @@
pub struct Foo;
impl Foo {
pub fn foo() {}
}

View File

@ -0,0 +1,8 @@
// aux-build:reexport-doc-aux.rs
extern crate reexport_doc_aux as dep;
// @has 'reexport_doc/struct.Foo.html'
// @count - '//p' 'These are the docs for Foo.' 1
/// These are the docs for Foo.
pub use dep::Foo;

View File

@ -15,19 +15,19 @@ LL | let a = bar(f, x);
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough
--> $DIR/project-fn-ret-invariant.rs:40:13
--> $DIR/project-fn-ret-invariant.rs:42:13
|
LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | let f = foo; // <-- No consistent type can be inferred for `f` here.
LL | let a = bar(f, x);
...
LL | let b = bar(f, y);
| ^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `'a`
= note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant
= note: the struct `Type<'a>` is invariant over the parameter `'a`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: `'a` and `'b` must be the same: replace one with the other

View File

@ -39,8 +39,8 @@ fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
let f = foo; // <-- No consistent type can be inferred for `f` here.
let a = bar(f, x);
//[oneuse]~^ ERROR lifetime may not live long enough
//[oneuse]~| ERROR lifetime may not live long enough
let b = bar(f, y);
//[oneuse]~^ ERROR lifetime may not live long enough
(a, b)
}

View File

@ -0,0 +1,24 @@
// check-fail
// known-bug: #102682
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
use std::fmt::Debug;
trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b {
type MyAssoc;
async fn foo(&'a self, key: &'b T) -> Self::MyAssoc;
}
impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
type MyAssoc = (&'a U, &'b T);
async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
(self, key)
}
}
fn main() {}

View File

@ -0,0 +1,57 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> $DIR/async-associated-types.rs:19:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
| ^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
--> $DIR/async-associated-types.rs:16:6
|
LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
| ^^
note: ...so that the types are compatible
--> $DIR/async-associated-types.rs:19:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
| ^^^^^^^^^^^^^^
= note: expected `(&'a U, &'b T)`
found `(&U, &T)`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
--> $DIR/async-associated-types.rs:19:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
| ^^^^^^^^^^^^^^
= note: expected `MyTrait<'static, 'static, T>`
found `MyTrait<'_, '_, T>`
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
--> $DIR/async-associated-types.rs:19:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
| ^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined here...
--> $DIR/async-associated-types.rs:16:10
|
LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
| ^^
note: ...so that the types are compatible
--> $DIR/async-associated-types.rs:19:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
| ^^^^^^^^^^^^^^
= note: expected `(&'a U, &'b T)`
found `(&U, &T)`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
--> $DIR/async-associated-types.rs:19:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
| ^^^^^^^^^^^^^^
= note: expected `MyTrait<'static, 'static, T>`
found `MyTrait<'_, '_, T>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0495`.

View File

@ -0,0 +1,30 @@
// check-pass
// edition: 2021
#![feature(async_fn_in_trait)]
#![feature(type_alias_impl_trait)]
#![allow(incomplete_features)]
use std::future::Future;
trait MyTrait {
type Fut<'a>: Future<Output = i32>
where
Self: 'a;
fn foo<'a>(&'a self) -> Self::Fut<'a>;
}
impl MyTrait for i32 {
type Fut<'a> = impl Future<Output = i32> + 'a
where
Self: 'a;
fn foo<'a>(&'a self) -> Self::Fut<'a> {
async {
*self
}
}
}
fn main() {}

View File

@ -0,0 +1,21 @@
// edition: 2021
#![feature(async_fn_in_trait)]
#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]
use std::future::Future;
use std::pin::Pin;
trait MyTrait {
fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
}
impl MyTrait for i32 {
async fn foo(&self) -> i32 {
//~^ ERROR method `foo` has an incompatible type for trait
*self
}
}
fn main() {}

View File

@ -0,0 +1,17 @@
error[E0053]: method `foo` has an incompatible type for trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
|
LL | async fn foo(&self) -> i32 {
| ^^^ expected struct `Pin`, found opaque type
|
note: type in trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
|
LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected fn pointer `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
found fn pointer `fn(&i32) -> impl Future<Output = i32>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0053`.

View File

@ -0,0 +1,24 @@
// check-pass
// edition: 2021
#![feature(async_fn_in_trait)]
#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]
use std::future::Future;
use std::pin::Pin;
trait MyTrait {
async fn foo(&self) -> i32;
}
impl MyTrait for i32 {
// This will break once a PR that implements #102745 is merged
fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
Box::pin(async {
*self
})
}
}
fn main() {}

View File

@ -0,0 +1,21 @@
// check-pass
// edition: 2021
#![feature(async_fn_in_trait)]
#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]
use std::future::Future;
trait MyTrait {
fn foo(&self) -> impl Future<Output = i32> + '_;
}
impl MyTrait for i32 {
// This will break once a PR that implements #102745 is merged
async fn foo(&self) -> i32 {
*self
}
}
fn main() {}

View File

@ -0,0 +1,23 @@
// check-pass
// edition: 2021
#![feature(async_fn_in_trait)]
#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]
use std::future::Future;
trait MyTrait {
async fn foo(&self) -> i32;
}
impl MyTrait for i32 {
// This will break once a PR that implements #102745 is merged
fn foo(&self) -> impl Future<Output = i32> + '_ {
async {
*self
}
}
}
fn main() {}

View File

@ -0,0 +1,32 @@
// check-pass
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
trait MyTrait {
async fn foo(&self) -> i32;
async fn bar(&self) -> i32;
}
impl MyTrait for i32 {
async fn foo(&self) -> i32 {
*self
}
async fn bar(&self) -> i32 {
self.foo().await
}
}
fn main() {
let x = 5;
// Calling from non-async context
let _ = x.foo();
let _ = x.bar();
// Calling from async block in non-async context
async {
let _: i32 = x.foo().await;
let _: i32 = x.bar().await;
};
}

View File

@ -0,0 +1,21 @@
// check-fail
// known-bug: #102682
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
use std::fmt::Debug;
use std::hash::Hash;
trait MyTrait<T, U> {
async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
}
impl<T, U> MyTrait<T, U> for (T, U) {
async fn foo(&self) -> &(T, U) {
self
}
}
fn main() {}

View File

@ -0,0 +1,37 @@
error[E0311]: the parameter type `U` may not live long enough
--> $DIR/async-generics-and-bounds.rs:12:28
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^^^^^^^
|
note: the parameter type `U` must be valid for the anonymous lifetime as defined here...
--> $DIR/async-generics-and-bounds.rs:12:18
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^
note: ...so that the reference type `&(T, U)` does not outlive the data it points at
--> $DIR/async-generics-and-bounds.rs:12:28
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^^^^^^^
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/async-generics-and-bounds.rs:12:28
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^^^^^^^
|
note: the parameter type `T` must be valid for the anonymous lifetime as defined here...
--> $DIR/async-generics-and-bounds.rs:12:18
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^
note: ...so that the reference type `&(T, U)` does not outlive the data it points at
--> $DIR/async-generics-and-bounds.rs:12:28
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0311`.

View File

@ -0,0 +1,18 @@
// check-fail
// known-bug: #102682
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
trait MyTrait<T, U> {
async fn foo(&self) -> &(T, U);
}
impl<T, U> MyTrait<T, U> for (T, U) {
async fn foo(&self) -> &(T, U) {
self
}
}
fn main() {}

View File

@ -0,0 +1,37 @@
error[E0311]: the parameter type `U` may not live long enough
--> $DIR/async-generics.rs:9:28
|
LL | async fn foo(&self) -> &(T, U);
| ^^^^^^^
|
note: the parameter type `U` must be valid for the anonymous lifetime as defined here...
--> $DIR/async-generics.rs:9:18
|
LL | async fn foo(&self) -> &(T, U);
| ^
note: ...so that the reference type `&(T, U)` does not outlive the data it points at
--> $DIR/async-generics.rs:9:28
|
LL | async fn foo(&self) -> &(T, U);
| ^^^^^^^
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/async-generics.rs:9:28
|
LL | async fn foo(&self) -> &(T, U);
| ^^^^^^^
|
note: the parameter type `T` must be valid for the anonymous lifetime as defined here...
--> $DIR/async-generics.rs:9:18
|
LL | async fn foo(&self) -> &(T, U);
| ^
note: ...so that the reference type `&(T, U)` does not outlive the data it points at
--> $DIR/async-generics.rs:9:28
|
LL | async fn foo(&self) -> &(T, U);
| ^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0311`.

View File

@ -0,0 +1,20 @@
// check-fail
// known-bug: #102682
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
use std::fmt::Debug;
trait MyTrait<'a, 'b, T> {
async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
}
impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U {
async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
(self, key)
}
}
fn main() {}

View File

@ -0,0 +1,23 @@
error[E0309]: the parameter type `Self` may not live long enough
--> $DIR/async-lifetimes-and-bounds.rs:11:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
| ^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `Self: 'a`...
= note: ...so that the reference type `&'a Self` does not outlive the data it points at
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/async-lifetimes-and-bounds.rs:11:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
| ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'b T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | trait MyTrait<'a, 'b, T: 'b> {
| ++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0309`.

View File

@ -0,0 +1,18 @@
// check-fail
// known-bug: #102682
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
trait MyTrait<'a, 'b, T> {
async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
}
impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U {
async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
(self, key)
}
}
fn main() {}

View File

@ -0,0 +1,23 @@
error[E0309]: the parameter type `Self` may not live long enough
--> $DIR/async-lifetimes.rs:9:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
| ^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `Self: 'a`...
= note: ...so that the reference type `&'a Self` does not outlive the data it points at
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/async-lifetimes.rs:9:43
|
LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
| ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'b T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | trait MyTrait<'a, 'b, T: 'b> {
| ++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0309`.

View File

@ -0,0 +1,21 @@
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
trait MyTrait<T> {
async fn foo_recursive(&self, n: usize) -> T;
}
impl<T> MyTrait<T> for T where T: Copy {
async fn foo_recursive(&self, n: usize) -> T {
//~^ ERROR recursion in an `async fn` requires boxing
if n > 0 {
self.foo_recursive(n - 1).await
} else {
*self
}
}
}
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0733]: recursion in an `async fn` requires boxing
--> $DIR/async-recursive-generic.rs:11:48
|
LL | async fn foo_recursive(&self, n: usize) -> T {
| ^ recursive `async fn`
|
= note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
error: aborting due to previous error
For more information about this error, try `rustc --explain E0733`.

View File

@ -0,0 +1,21 @@
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
trait MyTrait {
async fn foo_recursive(&self, n: usize) -> i32;
}
impl MyTrait for i32 {
async fn foo_recursive(&self, n: usize) -> i32 {
//~^ ERROR recursion in an `async fn` requires boxing
if n > 0 {
self.foo_recursive(n - 1).await
} else {
*self
}
}
}
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0733]: recursion in an `async fn` requires boxing
--> $DIR/async-recursive.rs:11:48
|
LL | async fn foo_recursive(&self, n: usize) -> i32 {
| ^^^ recursive `async fn`
|
= note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
error: aborting due to previous error
For more information about this error, try `rustc --explain E0733`.

View File

@ -0,0 +1,17 @@
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
trait MyTrait {
async fn foo(&self) -> i32;
}
impl MyTrait for i32 {
fn foo(&self) -> i32 {
//~^ ERROR: `i32` is not a future [E0277]
*self
}
}
fn main() {}

View File

@ -0,0 +1,17 @@
error[E0277]: `i32` is not a future
--> $DIR/fn-not-async-err.rs:11:22
|
LL | fn foo(&self) -> i32 {
| ^^^ `i32` is not a future
|
= help: the trait `Future` is not implemented for `i32`
= note: i32 must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `MyTrait::foo::{opaque#0}`
--> $DIR/fn-not-async-err.rs:7:28
|
LL | async fn foo(&self) -> i32;
| ^^^ required by this bound in `MyTrait::foo::{opaque#0}`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// edition: 2021
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
use std::future::Future;
trait MyTrait {
async fn foo(&self) -> i32;
}
impl MyTrait for i32 {
fn foo(&self) -> impl Future<Output = i32> {
//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562]
async {
*self
}
}
}
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
--> $DIR/fn-not-async-err2.rs:13:22
|
LL | fn foo(&self) -> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0562`.

View File

@ -1,5 +1,5 @@
error[E0521]: borrowed data escapes outside of associated function
--> $DIR/issue-72312.rs:12:24
--> $DIR/issue-72312.rs:12:9
|
LL | pub async fn start(&self) {
| -----
@ -7,17 +7,16 @@ LL | pub async fn start(&self) {
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
...
LL | require_static(async move {
| ________________________^
LL | / require_static(async move {
LL | |
LL | |
LL | |
LL | | &self;
LL | | });
| | ^
| | |
| |_________`self` escapes the associated function body here
| argument requires that `'1` must outlive `'static`
| | ^
| | |
| |__________`self` escapes the associated function body here
| argument requires that `'1` must outlive `'static`
error: aborting due to previous error

View File

@ -0,0 +1,31 @@
// edition:2021
struct StructA {
b: StructB,
}
async fn spawn_blocking<T>(f: impl (Fn() -> T) + Send + Sync + 'static) -> T {
todo!()
}
impl StructA {
async fn foo(&self) {
let bar = self.b.bar().await;
spawn_blocking(move || {
//~^ ERROR borrowed data escapes outside of associated function
self.b;
//~^ ERROR cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure
})
.await;
}
}
struct StructB {}
impl StructB {
async fn bar(&self) -> Option<u8> {
None
}
}
fn main() {}

View File

@ -0,0 +1,35 @@
error[E0507]: cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure
--> $DIR/issue-103624.rs:16:13
|
LL | async fn foo(&self) {
| ----- captured outer variable
LL | let bar = self.b.bar().await;
LL | spawn_blocking(move || {
| ------- captured by this `Fn` closure
LL |
LL | self.b;
| ^^^^^^ move occurs because `self.b` has type `StructB`, which does not implement the `Copy` trait
error[E0521]: borrowed data escapes outside of associated function
--> $DIR/issue-103624.rs:14:9
|
LL | async fn foo(&self) {
| -----
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
LL | let bar = self.b.bar().await;
LL | / spawn_blocking(move || {
LL | |
LL | | self.b;
LL | |
LL | | })
| | ^
| | |
| |__________`self` escapes the associated function body here
| argument requires that `'1` must outlive `'static`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0507, E0521.
For more information about an error, try `rustc --explain E0507`.

View File

@ -3,12 +3,24 @@ error[E0199]: implementing the trait `MySafeTrait` is not unsafe
|
LL | unsafe impl MySafeTrait for Foo {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove `unsafe` from this trait implementation
|
LL - unsafe impl MySafeTrait for Foo {}
LL + impl MySafeTrait for Foo {}
|
error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
--> $DIR/coherence-default-trait-impl.rs:13:1
|
LL | impl MyUnsafeTrait for Foo {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `MyUnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
LL | unsafe impl MyUnsafeTrait for Foo {}
| ++++++
error: aborting due to 2 previous errors

View File

@ -8,6 +8,12 @@ LL | | // (unsafe to access self.1 due to #[may_dangle] on A)
LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
LL | | }
| |_^
|
= note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
LL | unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
| ++++++
error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
--> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:27:1
@ -19,6 +25,12 @@ LL | | // (unsafe to access self.1 due to #[may_dangle] on 'a)
LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
LL | | }
| |_^
|
= note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
LL | unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
| ++++++
error: aborting due to 2 previous errors

View File

@ -3,6 +3,12 @@ error[E0199]: implementing the trait `Bar` is not unsafe
|
LL | unsafe impl Bar for Foo { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove `unsafe` from this trait implementation
|
LL - unsafe impl Bar for Foo { }
LL + impl Bar for Foo { }
|
error: aborting due to previous error

View File

@ -3,6 +3,12 @@ error[E0200]: the trait `Bar` requires an `unsafe impl` declaration
|
LL | impl Bar for Foo { }
| ^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `Bar` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
LL | unsafe impl Bar for Foo { }
| ++++++
error: aborting due to previous error

View File

@ -53,14 +53,15 @@ LL | fn case2() {
error[E0597]: `a` does not live long enough
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
|
LL | let cell = Cell::new(&a);
| ----------^^-
| | |
| | borrowed value does not live long enough
| argument requires that `a` is borrowed for `'static`
LL | let cell = Cell::new(&a);
| ^^ borrowed value does not live long enough
...
LL | }
| - `a` dropped here while still borrowed
LL | / foo(cell, |cell_a, cell_x| {
LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
LL | | })
| |______- argument requires that `a` is borrowed for `'static`
LL | }
| - `a` dropped here while still borrowed
error: aborting due to 2 previous errors

View File

@ -1,14 +1,14 @@
error[E0597]: `c` does not live long enough
--> $DIR/adt-nullary-enums.rs:33:41
|
LL | SomeEnum::SomeVariant(Cell::new(&c)),
| ----------^^-
| | |
| | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'static`
...
LL | }
| - `c` dropped here while still borrowed
LL | / combine(
LL | | SomeEnum::SomeVariant(Cell::new(&c)),
| | ^^ borrowed value does not live long enough
LL | | SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
LL | | );
| |_____- argument requires that `c` is borrowed for `'static`
LL | }
| - `c` dropped here while still borrowed
error[E0597]: `c` does not live long enough
--> $DIR/adt-nullary-enums.rs:41:41

View File

@ -0,0 +1,10 @@
trait Trait {
fn func() {}
}
impl Trait for i32 {}
fn main() {
let x: i32 = 123;
x.func(); //~ERROR no method
}

View File

@ -0,0 +1,24 @@
error[E0599]: no method named `func` found for type `i32` in the current scope
--> $DIR/issue-102354.rs:9:7
|
LL | x.func();
| ^^^^ this is an associated function, not a method
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: the candidate is defined in the trait `Trait`
--> $DIR/issue-102354.rs:2:5
|
LL | fn func() {}
| ^^^^^^^^^
help: use associated function syntax instead
|
LL | i32::func();
| ~~~~~~~~~
help: disambiguate the associated function for the candidate
|
LL | <i32 as Trait>::func(x);
| ~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.

View File

@ -7,6 +7,12 @@ LL | | panic!();
LL | | }
LL | | }
| |_^
|
= note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
LL | unsafe impl lib::Foo for Bar {
| ++++++
error: aborting due to previous error

View File

@ -3,12 +3,24 @@ error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration
|
LL | impl UnsafeTrait for u16 { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
LL | unsafe impl UnsafeTrait for u16 { }
| ++++++
error[E0199]: implementing the trait `SafeTrait` is not unsafe
--> $DIR/safety-trait-impl.rs:16:1
|
LL | unsafe impl SafeTrait for u32 { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove `unsafe` from this trait implementation
|
LL - unsafe impl SafeTrait for u32 { }
LL + impl SafeTrait for u32 { }
|
error: aborting due to 2 previous errors