diff options
| author | bors <bors@rust-lang.org> | 2022-09-14 15:19:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-09-14 15:19:12 +0000 |
| commit | a92669638461836f41f54f95e396f9082bb91391 (patch) | |
| tree | a15b9529a3211770abe582f803a89cbbf7ff191b | |
| parent | c97922dca563cb7f9385b18dbf7ca8c97f8e1597 (diff) | |
| parent | 15a5bc9c52fdf8268544efb239bf9455b795c424 (diff) | |
| download | rust-a92669638461836f41f54f95e396f9082bb91391.tar.gz rust-a92669638461836f41f54f95e396f9082bb91391.zip | |
Auto merge of #101805 - Dylan-DPC:rollup-mpdlbin, r=Dylan-DPC
Rollup of 6 pull requests
Successful merges:
- #101433 (Emit a note that static bounds from HRTBs are a bug)
- #101684 (smol grammar changes to README.md)
- #101769 (rustdoc: remove redundant CSS `.out-of-band > span.since { position }`)
- #101772 (Also replace the placeholder for the stable_features lint)
- #101773 (rustdoc: remove outdated CSS `.content table` etc)
- #101779 (Update test output for drop tracking)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
59 files changed, 947 insertions, 276 deletions
diff --git a/README.md b/README.md index 7c229487d1c..27e7145c5a9 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Read ["Installation"] from [The Book]. ## Installing from Source The Rust build system uses a Python script called `x.py` to build the compiler, -which manages the bootstrapping process. It lives in the root of the project. +which manages the bootstrapping process. It lives at the root of the project. The `x.py` command can be run directly on most systems in the following format: @@ -32,7 +32,7 @@ The `x.py` command can be run directly on most systems in the following format: This is how the documentation and examples assume you are running `x.py`. -Systems such as Ubuntu 20.04 LTS do not create the necessary `python` command by default when Python is installed that allows `x.py` to be run directly. In that case you can either create a symlink for `python` (Ubuntu provides the `python-is-python3` package for this), or run `x.py` using Python itself: +Systems such as Ubuntu 20.04 LTS do not create the necessary `python` command by default when Python is installed that allows `x.py` to be run directly. In that case, you can either create a symlink for `python` (Ubuntu provides the `python-is-python3` package for this), or run `x.py` using Python itself: ```sh # Python 3 @@ -103,11 +103,10 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide ### Building on Windows There are two prominent ABIs in use on Windows: the native (MSVC) ABI used by -Visual Studio, and the GNU ABI used by the GCC toolchain. Which version of Rust -you need depends largely on what C/C++ libraries you want to interoperate with: -for interop with software produced by Visual Studio use the MSVC build of Rust; -for interop with GNU software built using the MinGW/MSYS2 toolchain use the GNU -build. +Visual Studio and the GNU ABI used by the GCC toolchain. Which version of Rust +you need depends largely on what C/C++ libraries you want to interoperate with. +Use the MSVC build of Rust to interop with software produced by Visual Studio and +the GNU build to interop with GNU software built using the MinGW/MSYS2 toolchain. #### MinGW @@ -115,10 +114,10 @@ build. [msys2]: https://www.msys2.org/ -1. Grab the latest [MSYS2 installer][msys2] and go through the installer. +1. Download the latest [MSYS2 installer][msys2] and go through the installer. -2. Run `mingw32_shell.bat` or `mingw64_shell.bat` from wherever you installed - MSYS2 (i.e. `C:\msys64`), depending on whether you want 32-bit or 64-bit +2. Run `mingw32_shell.bat` or `mingw64_shell.bat` from the MSYS2 installation + directory (e.g. `C:\msys64`), depending on whether you want 32-bit or 64-bit Rust. (As of the latest version of MSYS2 you have to run `msys2_shell.cmd -mingw32` or `msys2_shell.cmd -mingw64` from the command line instead) @@ -168,7 +167,7 @@ shell with: python x.py build ``` -Currently, building Rust only works with some known versions of Visual Studio. If +Right now, building Rust only works with some known versions of Visual Studio. If you have a more recent version installed and the build system doesn't understand, you may need to force rustbuild to use an older version. This can be done by manually calling the appropriate vcvars file before running the bootstrap. @@ -225,7 +224,7 @@ the ABI used. I.e., if the ABI was `x86_64-pc-windows-msvc`, the directory will Since the Rust compiler is written in Rust, it must be built by a precompiled "snapshot" version of itself (made in an earlier stage of -development). As such, source builds require a connection to the Internet, to +development). As such, source builds require an Internet connection to fetch snapshots, and an OS that can execute the available snapshot binaries. Snapshot binaries are currently built and tested on several platforms: diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index bb972a18acb..753f62dd589 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -21,6 +21,12 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; /// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591). pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION"; +pub fn rust_version_symbol() -> Symbol { + let version = option_env!("CFG_VERSION").unwrap_or("<current>"); + let version = version.split(' ').next().unwrap(); + Symbol::intern(&version) +} + pub fn is_builtin_attr(attr: &Attribute) -> bool { attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some() } @@ -495,9 +501,7 @@ where } if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER { - let version = option_env!("CFG_VERSION").unwrap_or("<current>"); - let version = version.split(' ').next().unwrap(); - since = Some(Symbol::intern(&version)); + since = Some(rust_version_symbol()); } match (feature, since) { diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index c94dfe39b69..df04128135b 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -21,10 +21,7 @@ pub(crate) struct OutlivesConstraintSet<'tcx> { impl<'tcx> OutlivesConstraintSet<'tcx> { pub(crate) fn push(&mut self, constraint: OutlivesConstraint<'tcx>) { - debug!( - "OutlivesConstraintSet::push({:?}: {:?} @ {:?}", - constraint.sup, constraint.sub, constraint.locations - ); + debug!("OutlivesConstraintSet::push({:?})", constraint); if constraint.sup == constraint.sub { // 'a: 'a is pretty uninteresting return; @@ -73,7 +70,7 @@ impl<'tcx> Index<OutlivesConstraintIndex> for OutlivesConstraintSet<'tcx> { } } -#[derive(Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq)] pub struct OutlivesConstraint<'tcx> { // NB. The ordering here is not significant for correctness, but // it is for convenience. Before we dump the constraints in the diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 2f61849c383..1c01e78abd4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{self, RegionVid, TyCtxt}; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{sym, DesugaringKind, Span}; -use crate::region_infer::BlameConstraint; +use crate::region_infer::{BlameConstraint, ExtraConstraintInfo}; use crate::{ borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt, WriteKind, @@ -38,6 +38,7 @@ pub(crate) enum BorrowExplanation<'tcx> { span: Span, region_name: RegionName, opt_place_desc: Option<String>, + extra_info: Vec<ExtraConstraintInfo>, }, Unexplained, } @@ -243,6 +244,7 @@ impl<'tcx> BorrowExplanation<'tcx> { ref region_name, ref opt_place_desc, from_closure: _, + ref extra_info, } => { region_name.highlight_region_name(err); @@ -268,6 +270,14 @@ impl<'tcx> BorrowExplanation<'tcx> { ); }; + for extra in extra_info { + match extra { + ExtraConstraintInfo::PlaceholderFromPredicate(span) => { + err.span_note(*span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime")); + } + } + } + self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name); } _ => {} @@ -309,18 +319,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self, borrow_region: RegionVid, outlived_region: RegionVid, - ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>) { - let BlameConstraint { category, from_closure, cause, variance_info: _ } = - self.regioncx.best_blame_constraint( - &self.body, - borrow_region, - NllRegionVariableOrigin::FreeRegion, - |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region), - ); + ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) { + let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint( + borrow_region, + NllRegionVariableOrigin::FreeRegion, + |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region), + ); + let BlameConstraint { category, from_closure, cause, .. } = blame_constraint; let outlived_fr_name = self.give_region_a_name(outlived_region); - (category, from_closure, cause.span, outlived_fr_name) + (category, from_closure, cause.span, outlived_fr_name, extra_info) } /// Returns structured explanation for *why* the borrow contains the @@ -392,7 +401,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None => { if let Some(region) = self.to_error_region_vid(borrow_region_vid) { - let (category, from_closure, span, region_name) = + let (category, from_closure, span, region_name, extra_info) = self.free_region_constraint_info(borrow_region_vid, region); if let Some(region_name) = region_name { let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref()); @@ -402,6 +411,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { span, region_name, opt_place_desc, + extra_info, } } else { debug!("Could not generate a region name"); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 9615025fa57..34be2874fcb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -31,7 +31,7 @@ use crate::session_diagnostics::{ }; use super::{OutlivesSuggestionBuilder, RegionName}; -use crate::region_infer::BlameConstraint; +use crate::region_infer::{BlameConstraint, ExtraConstraintInfo}; use crate::{ nll::ConstraintDescription, region_infer::{values::RegionElement, TypeTest}, @@ -234,7 +234,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. let (_, cause) = self.regioncx.find_outlives_blame_span( - &self.body, longer_fr, NllRegionVariableOrigin::Placeholder(placeholder), error_vid, @@ -355,10 +354,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ) { debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let BlameConstraint { category, cause, variance_info, from_closure: _ } = - self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| { + let (blame_constraint, extra_info) = + self.regioncx.best_blame_constraint(fr, fr_origin, |r| { self.regioncx.provides_universal_region(r, fr, outlived_fr) }); + let BlameConstraint { category, cause, variance_info, .. } = blame_constraint; debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info); @@ -467,6 +467,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } + for extra in extra_info { + match extra { + ExtraConstraintInfo::PlaceholderFromPredicate(span) => { + diag.span_note(span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime")); + } + } + } + self.buffer_error(diag); } @@ -558,6 +566,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// LL | ref_obj(x) /// | ^^^^^^^^^^ `x` escapes the function body here /// ``` + #[instrument(level = "debug", skip(self))] fn report_escaping_data_error( &self, errci: &ErrorConstraintInfo<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index de70b17e44c..244e6e3422d 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -245,6 +245,11 @@ enum Trace<'tcx> { NotVisited, } +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum ExtraConstraintInfo { + PlaceholderFromPredicate(Span), +} + impl<'tcx> RegionInferenceContext<'tcx> { /// Creates a new region inference context with a total of /// `num_region_variables` valid inference variables; the first N @@ -590,13 +595,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { // constraints were too strong, and if so, emit or propagate those errors. if infcx.tcx.sess.opts.unstable_opts.polonius { self.check_polonius_subset_errors( - body, outlives_requirements.as_mut(), &mut errors_buffer, polonius_output.expect("Polonius output is unavailable despite `-Z polonius`"), ); } else { - self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer); + self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer); } if errors_buffer.is_empty() { @@ -1409,7 +1413,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// report them as errors. fn check_universal_regions( &self, - body: &Body<'tcx>, mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, errors_buffer: &mut RegionErrors<'tcx>, ) { @@ -1420,7 +1423,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { // they did not grow too large, accumulating any requirements // for our caller into the `outlives_requirements` vector. self.check_universal_region( - body, fr, &mut propagated_outlives_requirements, errors_buffer, @@ -1461,7 +1463,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// report them as errors. fn check_polonius_subset_errors( &self, - body: &Body<'tcx>, mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, errors_buffer: &mut RegionErrors<'tcx>, polonius_output: Rc<PoloniusOutput>, @@ -1508,7 +1509,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { let propagated = self.try_propagate_universal_region_error( *longer_fr, *shorter_fr, - body, &mut propagated_outlives_requirements, ); if propagated == RegionRelationCheckResult::Error { @@ -1548,13 +1548,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// /// Things that are to be propagated are accumulated into the /// `outlives_requirements` vector. - #[instrument( - skip(self, body, propagated_outlives_requirements, errors_buffer), - level = "debug" - )] + #[instrument(skip(self, propagated_outlives_requirements, errors_buffer), level = "debug")] fn check_universal_region( &self, - body: &Body<'tcx>, longer_fr: RegionVid, propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, errors_buffer: &mut RegionErrors<'tcx>, @@ -1577,7 +1573,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { if let RegionRelationCheckResult::Error = self.check_universal_region_relation( longer_fr, representative, - body, propagated_outlives_requirements, ) { errors_buffer.push(RegionErrorKind::RegionError { @@ -1597,7 +1592,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { if let RegionRelationCheckResult::Error = self.check_universal_region_relation( longer_fr, shorter_fr, - body, propagated_outlives_requirements, ) { // We only report the first region error. Subsequent errors are hidden so as @@ -1622,7 +1616,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, longer_fr: RegionVid, shorter_fr: RegionVid, - body: &Body<'tcx>, propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, ) -> RegionRelationCheckResult { // If it is known that `fr: o`, carry on. @@ -1638,7 +1631,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.try_propagate_universal_region_error( longer_fr, shorter_fr, - body, propagated_outlives_requirements, ) } @@ -1650,7 +1642,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, longer_fr: RegionVid, shorter_fr: RegionVid, - body: &Body<'tcx>, propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, ) -> RegionRelationCheckResult { if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { @@ -1662,7 +1653,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus); let blame_span_category = self.find_outlives_blame_span( - body, longer_fr, NllRegionVariableOrigin::FreeRegion, shorter_fr, @@ -1816,50 +1806,26 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn retrieve_closure_constraint_info( &self, - _body: &Body<'tcx>, - constraint: &OutlivesConstraint<'tcx>, - ) -> BlameConstraint<'tcx> { - let loc = match constraint.locations { - Locations::All(span) => { - return BlameConstraint { - category: constraint.category, - from_closure: false, - cause: ObligationCause::dummy_with_span(span), - variance_info: constraint.variance_info, - }; + constraint: OutlivesConstraint<'tcx>, + ) -> Option<(ConstraintCategory<'tcx>, Span)> { + match constraint.locations { + Locations::All(_) => None, + Locations::Single(loc) => { + self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied() } - Locations::Single(loc) => loc, - }; - - let opt_span_category = - self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)); - opt_span_category - .map(|&(category, span)| BlameConstraint { - category, - from_closure: true, - cause: ObligationCause::dummy_with_span(span), - variance_info: constraint.variance_info, - }) - .unwrap_or(BlameConstraint { - category: constraint.category, - from_closure: false, - cause: ObligationCause::dummy_with_span(constraint.span), - variance_info: constraint.variance_info, - }) + } } /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`. pub(crate) fn find_outlives_blame_span( &self, - body: &Body<'tcx>, fr1: RegionVid, fr1_origin: NllRegionVariableOrigin, fr2: RegionVid, ) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) { - let BlameConstraint { category, cause, .. } = - self.best_blame_constraint(body, fr1, fr1_origin, |r| { - self.provides_universal_region(r, fr1, fr2) - }); + let BlameConstraint { category, cause, .. } = self + .best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2)) + .0; (category, cause) } @@ -2045,11 +2011,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { #[instrument(level = "debug", skip(self, target_test))] pub(crate) fn best_blame_constraint( &self, - body: &Body<'tcx>, from_region: RegionVid, from_region_origin: NllRegionVariableOrigin, target_test: impl Fn(RegionVid) -> bool, - ) -> BlameConstraint<'tcx> { + ) -> (BlameConstraint<'tcx>, Vec<ExtraConstraintInfo>) { // Find all paths let (path, target_region) = self.find_constraint_paths_between_regions(from_region, target_test).unwrap(); @@ -2065,6 +2030,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { .collect::<Vec<_>>() ); + let mut extra_info = vec![]; + for constraint in path.iter() { + let outlived = constraint.sub; + let Some(origin) = self.var_infos.get(outlived) else { continue; }; + let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin else { continue; }; + debug!(?constraint, ?p); + let ConstraintCategory::Predicate(span) = constraint.category else { continue; }; + extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span)); + // We only want to point to one + break; + } + // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint. // Instead, we use it to produce an improved `ObligationCauseCode`. // FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate` @@ -2090,19 +2067,29 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut categorized_path: Vec<BlameConstraint<'tcx>> = path .iter() .map(|constraint| { - if constraint.category == ConstraintCategory::ClosureBounds { - self.retrieve_closure_constraint_info(body, &constraint) - } else { - BlameConstraint { - category: constraint.category, - from_closure: false, - cause: ObligationCause::new( - constraint.span, - CRATE_HIR_ID, - cause_code.clone(), - ), - variance_info: constraint.variance_info, - } + let (category, span, from_closure, cause_code) = + if constraint.category == ConstraintCategory::ClosureBounds { + if let Some((category, span)) = + self.retrieve_closure_constraint_info(*constraint) + { + (category, span, true, ObligationCauseCode::MiscObligation) + } else { + ( + constraint.category, + constraint.span, + false, + ObligationCauseCode::MiscObligation, + ) + } + } else { + (constraint.category, constraint.span, false, cause_code.clone()) + }; + BlameConstraint { + category, + from_closure, + cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code), + variance_info: constraint.variance_info, + outlives_constraint: *constraint, } }) .collect(); @@ -2204,7 +2191,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let best_choice = if blame_source { range.rev().find(find_region) } else { range.find(find_region) }; - debug!(?best_choice, ?blame_source); + debug!(?best_choice, ?blame_source, ?extra_info); if let Some(i) = best_choice { if let Some(next) = categorized_path.get(i + 1) { @@ -2213,7 +2200,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { { // The return expression is being influenced by the return type being // impl Trait, point at the return type and not the return expr. - return next.clone(); + return (next.clone(), extra_info); } } @@ -2233,7 +2220,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - return categorized_path[i].clone(); + return (categorized_path[i].clone(), extra_info); } // If that search fails, that is.. unusual. Maybe everything @@ -2243,7 +2230,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category)); debug!("sorted_path={:#?}", categorized_path); - categorized_path.remove(0) + (categorized_path.remove(0), extra_info) } pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { @@ -2325,7 +2312,13 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx outlives_requirement={:?}", region, outlived_region, outlives_requirement, ); - ty::Binder::dummy(ty::OutlivesPredicate(region.into(), outlived_region)) + ( + ty::Binder::dummy(ty::OutlivesPredicate( + region.into(), + outlived_region, + )), + ConstraintCategory::BoringNoLocation, + ) } ClosureOutlivesSubject::Ty(ty) => { @@ -2335,7 +2328,10 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx outlives_requirement={:?}", ty, outlived_region, outlives_requirement, ); - ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)) + ( + ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)), + ConstraintCategory::BoringNoLocation, + ) } } }) @@ -2349,4 +2345,5 @@ pub struct BlameConstraint<'tcx> { pub from_closure: bool, pub cause: ObligationCause<'tcx>, pub variance_info: ty::VarianceDiagInfo<'tcx>, + pub outlives_constraint: OutlivesConstraint<'tcx>, } diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 29195b3922f..9271a2f4dc7 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -25,7 +25,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { /// constraints should occur within this method so that those /// constraints can be properly localized!** #[instrument(skip(self, op), level = "trace")] - pub(super) fn fully_perform_op<R, Op>( + pub(super) fn fully_perform_op<R: fmt::Debug, Op>( &mut self, locations: Locations, category: ConstraintCategory<'tcx>, @@ -39,6 +39,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?; + debug!(?output, ?constraints); + if let Some(data) = constraints { self.push_region_constraints(locations, category, data); } @@ -102,6 +104,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } + #[instrument(level = "debug", skip(self))] pub(super) fn normalize_and_prove_instantiated_predicates( &mut self, // Keep this parameter for now, in case we start using @@ -116,8 +119,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .zip(instantiated_predicates.spans.into_iter()) { debug!(?predicate); - let predicate = self.normalize(predicate, locations); - self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span)); + let category = ConstraintCategory::Predicate(span); + let predicate = self.normalize_with_category(predicate, locations, category); + self.prove_predicate(predicate, locations, category); } } @@ -153,15 +157,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }) } - #[instrument(skip(self), level = "debug")] pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T where T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, { + self.normalize_with_category(value, location, ConstraintCategory::Boring) + } + + #[instrument(skip(self), level = "debug")] + pub(super) fn normalize_with_category<T>( + &mut self, + value: T, + location: impl NormalizeLocation, + category: ConstraintCategory<'tcx>, + ) -> T + where + T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, + { let param_env = self.param_env; self.fully_perform_op( location.to_locations(), - ConstraintCategory::Boring, + category, param_env.and(type_op::normalize::Normalize::new(value)), ) .unwrap_or_else(|NoSolution| { diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 9fab7ad914a..71eae0583cb 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } } - pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) { + fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) { debug!("generate: constraints at: {:#?}", self.locations); // Extract out various useful fields we'll need below. @@ -98,15 +98,18 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // region constraints like `for<'a> 'a: 'b`. At some point // when we move to universes, we will, and this assertion // will start to fail. - let ty::OutlivesPredicate(k1, r2) = query_constraint.no_bound_vars().unwrap_or_else(|| { - bug!("query_constraint {:?} contained bound vars", query_constraint,); - }); + let ty::OutlivesPredicate(k1, r2) = + query_constraint.0.no_bound_vars().unwrap_or_else(|| { + bug!("query_constraint {:?} contained bound vars", query_constraint,); + }); + + let constraint_category = query_constraint.1; match k1.unpack() { GenericArgKind::Lifetime(r1) => { let r1_vid = self.to_region_vid(r1); let r2_vid = self.to_region_vid(r2); - self.add_outlives(r1_vid, r2_vid); + self.add_outlives(r1_vid, r2_vid, constraint_category); } GenericArgKind::Type(t1) => { @@ -121,7 +124,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { Some(implicit_region_bound), param_env, ) - .type_must_outlive(origin, t1, r2); + .type_must_outlive(origin, t1, r2, constraint_category); } GenericArgKind::Const(_) => { @@ -168,10 +171,19 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } } - fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) { + fn add_outlives( + &mut self, + sup: ty::RegionVid, + sub: ty::RegionVid, + category: ConstraintCategory<'tcx>, + ) { + let category = match self.category { + ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category, + _ => self.category, + }; self.constraints.outlives_constraints.push(OutlivesConstraint { locations: self.locations, - category: self.category, + category, span: self.span, sub, sup, @@ -191,10 +203,11 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<' _origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, + constraint_category: ConstraintCategory<'tcx>, ) { let b = self.to_region_vid(b); let a = self.to_region_vid(a); - self.add_outlives(b, a); + self.add_outlives(b, a, constraint_category); } fn push_verify( diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index fc0e95f30c9..3ad89cfe02f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -311,6 +311,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { + debug!(?constant, ?location, "visit_constant"); + self.super_constant(constant, location); let ty = self.sanitize_type(constant, constant.literal.ty()); @@ -1810,6 +1812,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) { + debug!(?op, ?location, "check_operand"); + if let Operand::Constant(constant) = op { let maybe_uneval = match constant.literal { ConstantKind::Ty(ct) => match ct.kind() { @@ -2560,7 +2564,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .enumerate() .filter_map(|(idx, constraint)| { let ty::OutlivesPredicate(k1, r2) = - constraint.no_bound_vars().unwrap_or_else(|| { + constraint.0.no_bound_vars().unwrap_or_else(|| { bug!("query_constraint {:?} contained bound vars", constraint,); }); diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 2899b8304bc..65371a28591 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -110,6 +110,7 @@ infer_relate_param_bound = ...so that the type `{$name}` will meet its required infer_relate_param_bound_2 = ...that is required by this bound infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait +infer_ascribe_user_type_prove_predicate = ...so that the where clause holds infer_nothing = {""} diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 64c759f73d4..56e83489879 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -22,6 +22,7 @@ use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; use rustc_middle::arena::ArenaAllocatable; +use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::TypeRelation; @@ -129,7 +130,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let region_constraints = self.with_region_constraints(|region_constraints| { make_query_region_constraints( tcx, - region_obligations.iter().map(|r_o| (r_o.sup_type, r_o.sub_region)), + region_obligations + .iter() + .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), region_constraints, ) }); @@ -248,6 +251,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // the original values `v_o` that was canonicalized into a // variable... + let constraint_category = cause.to_constraint_category(); + for (index, original_value) in original_values.var_values.iter().enumerate() { // ...with the value `v_r` of that variable from the query. let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| { @@ -263,12 +268,14 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { (GenericArgKind::Lifetime(v_o), GenericArgKind::Lifetime(v_r)) => { // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`. if v_o != v_r { - output_query_region_constraints - .outlives - .push(ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r))); - output_query_region_constraints - .outlives - .push(ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o))); + output_query_region_constraints.outlives.push(( + ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)), + constraint_category, + )); + output_query_region_constraints.outlives.push(( + ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)), + constraint_category, + )); } } @@ -314,7 +321,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Screen out `'a: 'a` cases -- we skip the binder here but // only compare the inner values to one another, so they are still at // consistent binding levels. - let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); + let ty::OutlivesPredicate(k1, r2) = r_c.0.skip_binder(); if k1 != r2.into() { Some(r_c) } else { None } }), ); @@ -559,7 +566,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Obligation<'tcx, ty::Predicate<'tcx>> { - let ty::OutlivesPredicate(k1, r2) = predicate.skip_binder(); + let ty::OutlivesPredicate(k1, r2) = predicate.0.skip_binder(); let atom = match k1.unpack() { GenericArgKind::Lifetime(r1) => { @@ -574,7 +581,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { span_bug!(cause.span, "unexpected const outlives {:?}", predicate); } }; - let predicate = predicate.rebind(atom).to_predicate(self.tcx); + let predicate = predicate.0.rebind(atom).to_predicate(self.tcx); Obligation::new(cause, param_env, predicate) } @@ -625,7 +632,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// creates query region constraints. pub fn make_query_region_constraints<'tcx>( tcx: TyCtxt<'tcx>, - outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>)>, + 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 } = @@ -638,26 +645,31 @@ pub fn make_query_region_constraints<'tcx>( let outlives: Vec<_> = constraints .iter() - .map(|(k, _)| match *k { - // Swap regions because we are going from sub (<=) to outlives - // (>=). - Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( - tcx.mk_region(ty::ReVar(v2)).into(), - tcx.mk_region(ty::ReVar(v1)), - ), - Constraint::VarSubReg(v1, r2) => { - ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1))) - } - Constraint::RegSubVar(r1, v2) => { - ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1) - } - Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), + .map(|(k, origin)| { + // no bound vars in the code above + let constraint = ty::Binder::dummy(match *k { + // Swap regions because we are going from sub (<=) to outlives + // (>=). + Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( + tcx.mk_region(ty::ReVar(v2)).into(), + tcx.mk_region(ty::ReVar(v1)), + ), + Constraint::VarSubReg(v1, r2) => { + ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1))) + } + Constraint::RegSubVar(r1, v2) => { + ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1) + } + Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), + }); + (constraint, origin.to_constraint_category()) }) - .map(ty::Binder::dummy) // no bound vars in the code above .chain( outlives_obligations - .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r)) - .map(ty::Binder::dummy), // no bound vars in the code above + // no bound vars in the code above + .map(|(ty, r, constraint_category)| { + (ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)), constraint_category) + }), ) .collect(); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index cffdf56bb6d..adaa47c0140 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -77,6 +77,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::CheckAssociatedTypeBounds { ref parent, .. } => { self.note_region_origin(err, &parent); } + infer::AscribeUserTypeProvePredicate(span) => { + RegionOriginNote::Plain { + span, + msg: fluent::infer::ascribe_user_type_prove_predicate, + } + .add_to_diagnostic(err); + } } } @@ -356,6 +363,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } + infer::AscribeUserTypeProvePredicate(span) => { + let mut err = + struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); + note_and_explain_region( + self.tcx, + &mut err, + "lifetime instantiated with ", + sup, + "", + None, + ); + note_and_explain_region( + self.tcx, + &mut err, + "but lifetime must outlive ", + sub, + "", + None, + ); + err + } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index bbbc044b85a..efcb6c92998 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -20,6 +20,7 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; +use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::select; use rustc_middle::ty::abstract_const::{AbstractConst, FailureKind}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -408,7 +409,11 @@ pub enum SubregionOrigin<'tcx> { /// Comparing the signature and requirements of an impl method against /// the containing trait. - CompareImplItemObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId }, + CompareImplItemObligation { + span: Span, + impl_item_def_id: LocalDefId, + trait_item_def_id: DefId, + }, /// Checking that the bounds of a trait's associated type hold for a given impl CheckAssociatedTypeBounds { @@ -416,12 +421,24 @@ pub enum SubregionOrigin<'tcx> { impl_item_def_id: LocalDefId, trait_item_def_id: DefId, }, + + AscribeUserTypeProvePredicate(Span), } // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(SubregionOrigin<'_>, 32); +impl<'tcx> SubregionOrigin<'tcx> { + 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), + _ => ConstraintCategory::BoringNoLocation, + } + } +} + /// Times when we replace late-bound regions with variables: #[derive(Clone, Copy, Debug)] pub enum LateBoundRegionConversionTime { @@ -1991,6 +2008,7 @@ impl<'tcx> SubregionOrigin<'tcx> { DataBorrowed(_, a) => a, ReferenceOutlivesReferent(_, a) => a, CompareImplItemObligation { span, .. } => span, + AscribeUserTypeProvePredicate(span) => span, CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), } } @@ -2023,6 +2041,10 @@ impl<'tcx> SubregionOrigin<'tcx> { parent: Box::new(default()), }, + traits::ObligationCauseCode::AscribeUserTypeProvePredicate(span) => { + SubregionOrigin::AscribeUserTypeProvePredicate(span) + } + _ => default(), } } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 74c8bd88d27..b65080e74c4 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -69,6 +69,7 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_hir::def_id::LocalDefId; +use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable}; use smallvec::smallvec; @@ -163,7 +164,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let outlives = &mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env); - outlives.type_must_outlive(origin, sup_type, sub_region); + let category = origin.to_constraint_category(); + outlives.type_must_outlive(origin, sup_type, sub_region, category); } } @@ -207,6 +209,7 @@ pub trait TypeOutlivesDelegate<'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, + constraint_category: ConstraintCategory<'tcx>, ); fn push_verify( @@ -255,12 +258,13 @@ where origin: infer::SubregionOrigin<'tcx>, ty: Ty<'tcx>, region: ty::Region<'tcx>, + category: ConstraintCategory<'tcx>, ) { assert!(!ty.has_escaping_bound_vars()); let mut components = smallvec![]; push_outlives_components(self.tcx, ty, &mut components); - self.components_must_outlive(origin, &components, region); + self.components_must_outlive(origin, &components, region, category); } fn components_must_outlive( @@ -268,12 +272,13 @@ where origin: infer::SubregionOrigin<'tcx>, components: &[Component<'tcx>], region: ty::Region<'tcx>, + category: ConstraintCategory<'tcx>, ) { for component in components.iter() { let origin = origin.clone(); match component { Component::Region(region1) => { - self.delegate.push_sub_region_constraint(origin, region, *region1); + self.delegate.push_sub_region_constraint(origin, region, *region1, category); } Component::Param(param_ty) => { self.param_ty_must_outlive(origin, region, *param_ty); @@ -282,7 +287,7 @@ where self.projection_must_outlive(origin, region, *projection_ty); } Component::EscapingProjection(subcomponents) => { - self.components_must_outlive(origin, &subcomponents, region); + self.components_must_outlive(origin, &subcomponents, region, category); } Component::UnresolvedInferenceVariable(v) => { // ignore this, we presume it will yield an error @@ -392,10 +397,20 @@ where for k in projection_ty.substs { match k.unpack() { GenericArgKind::Lifetime(lt) => { - self.delegate.push_sub_region_constraint(origin.clone(), region, lt); + self.delegate.push_sub_region_constraint( + origin.clone(), + region, + lt, + origin.to_constraint_category(), + ); } GenericArgKind::Type(ty) => { - self.type_must_outlive(origin.clone(), ty, region); + self.type_must_outlive( + origin.clone(), + ty, + region, + origin.to_constraint_category(), + ); } GenericArgKind::Const(_) => { // Const parameters don't impose constraints. @@ -433,7 +448,8 @@ where let unique_bound = trait_bounds[0]; debug!("projection_must_outlive: unique trait bound = {:?}", unique_bound); debug!("projection_must_outlive: unique declared bound appears in trait ref"); - self.delegate.push_sub_region_constraint(origin, region, unique_bound); + let category = origin.to_constraint_category(); + self.delegate.push_sub_region_constraint(origin, region, unique_bound, category); return; } @@ -455,6 +471,7 @@ impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, + _constraint_category: ConstraintCategory<'tcx>, ) { self.sub_regions(origin, a, b) } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 200de9079c2..e467ca13c8e 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -22,6 +22,7 @@ //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html use crate::infer::MemberConstraint; +use crate::mir::ConstraintCategory; use crate::ty::subst::GenericArg; use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt}; use rustc_index::vec::IndexVec; @@ -290,8 +291,10 @@ impl<'tcx, V> Canonical<'tcx, V> { } } -pub type QueryOutlivesConstraint<'tcx> = - ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>; +pub type QueryOutlivesConstraint<'tcx> = ( + ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>, + ConstraintCategory<'tcx>, +); TrivialTypeTraversalAndLiftImpls! { for <'tcx> { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 594c14a642d..d89efe2b3f0 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -327,7 +327,7 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); /// /// See also `rustc_const_eval::borrow_check::constraints`. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable)] +#[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)] pub enum ConstraintCategory<'tcx> { Return(ReturnConstraint), Yield, @@ -369,7 +369,7 @@ pub enum ConstraintCategory<'tcx> { } #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable)] +#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] pub enum ReturnConstraint { Normal, ClosureUpvar(Field), diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a95e6a61854..68a7af0b8c8 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -10,6 +10,7 @@ mod structural_impls; pub mod util; use crate::infer::canonical::Canonical; +use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; @@ -183,6 +184,16 @@ impl<'tcx> ObligationCause<'tcx> { variant(DerivedObligationCause { parent_trait_pred, parent_code: self.code }).into(); self } + + pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { + match self.code() { + MatchImpl(cause, _) => cause.to_constraint_category(), + AscribeUserTypeProvePredicate(predicate_span) => { + ConstraintCategory::Predicate(*predicate_span) + } + _ => ConstraintCategory::BoringNoLocation, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] @@ -418,6 +429,8 @@ pub enum ObligationCauseCode<'tcx> { is_lit: bool, output_ty: Option<Ty<'tcx>>, }, + + AscribeUserTypeProvePredicate(Span), } /// The 'location' at which we try to perform HIR-based wf checking. diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index e6bd2eed565..37f88016f60 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -3,7 +3,7 @@ //! hand, though we've recently added some macros and proc-macros to help with the tedium. use crate::mir::interpret; -use crate::mir::ProjectionKind; +use crate::mir::{Field, ProjectionKind}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; @@ -648,6 +648,20 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { } } +impl<'tcx> Lift<'tcx> for Field { + type Lifted = Field; + fn lift_to_tcx(self, _tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { + Some(self) + } +} + +impl<'tcx> Lift<'tcx> for crate::mir::ReturnConstraint { + type Lifted = crate::mir::ReturnConstraint; + fn lift_to_tcx(self, _tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { + Some(self) + } +} + /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 5aac6943eef..04173c792a9 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -5,7 +5,7 @@ //! collect them instead. use rustc_ast::{Attribute, MetaItemKind}; -use rustc_attr::VERSION_PLACEHOLDER; +use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER}; use rustc_errors::struct_span_err; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; @@ -57,9 +57,7 @@ impl<'tcx> LibFeatureCollector<'tcx> { } if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER { - let version = option_env!("CFG_VERSION").unwrap_or("<current>"); - let version = version.split(' ').next().unwrap(); - since = Some(Symbol::intern(&version)); + since = Some(rust_version_symbol()); } if let Some(feature) = feature { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index a24b191aebf..9ba1276099d 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -2,7 +2,8 @@ //! propagating default levels lexically from parent to children ast nodes. use rustc_attr::{ - self as attr, ConstStability, Stability, StabilityLevel, Unstable, UnstableReason, + self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable, + UnstableReason, VERSION_PLACEHOLDER, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{struct_span_err, Applicability}; @@ -1106,7 +1107,15 @@ fn unnecessary_partially_stable_feature_lint( }); } -fn unnecessary_stable_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol, since: Symbol) { +fn unnecessary_stable_feature_lint( + tcx: TyCtxt<'_>, + span: Span, + feature: Symbol, + mut since: Symbol, +) { + if since.as_str() == VERSION_PLACEHOLDER { + since = rust_version_symbol(); + } tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| { lint.build(&format!( "the feature `{feature}` has been stable since {since} and no longer requires an \ diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index cb605cacc9c..99c5ab6aacd 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2256,7 +2256,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::QuestionMark | ObligationCauseCode::CheckAssociatedTypeBounds { .. } | ObligationCauseCode::LetElse - | ObligationCauseCode::BinOp { .. } => {} + | ObligationCauseCode::BinOp { .. } + | ObligationCauseCode::AscribeUserTypeProvePredicate(..) => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index f65fc5bad0d..a3f8f4e2ed0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -48,10 +48,11 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { T: TypeFoldable<'tcx>, { debug!( - "normalize::<{}>(value={:?}, param_env={:?})", + "normalize::<{}>(value={:?}, param_env={:?}, cause={:?})", std::any::type_name::<T>(), value, self.param_env, + self.cause, ); if !needs_normalization(&value, self.param_env.reveal()) { return Ok(Normalized { value, obligations: vec![] }); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index f6e196e3141..18988861add 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -23,7 +23,7 @@ impl<F, G> CustomTypeOp<F, G> { } } -impl<'tcx, F, R, G> super::TypeOp<'tcx> for CustomTypeOp<F, G> +impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G> where F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>, G: Fn() -> String, @@ -89,8 +89,8 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( infcx.tcx, region_obligations .iter() - .map(|r_o| (r_o.sup_type, r_o.sub_region)) - .map(|(ty, r)| (infcx.resolve_vars_if_possible(ty), r)), + .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())) + .map(|(ty, r, cc)| (infcx.resolve_vars_if_possible(ty), r, cc)), ®ion_constraint_data, ); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index 578e1d00cf9..8a79165702c 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -26,7 +26,7 @@ pub use rustc_middle::traits::query::type_op::*; /// extract out the resulting region constraints (or an error if it /// cannot be completed). pub trait TypeOp<'tcx>: Sized + fmt::Debug { - type Output; + type Output: fmt::Debug; type ErrorInfo; /// Processes the operation and all resulting obligations, diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 60e9b88107d..1a63f853211 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::TraitEngineExt as _; +use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts}; use rustc_middle::ty::{ @@ -22,6 +22,7 @@ use rustc_trait_selection::traits::query::type_op::subtype::Subtype; use rustc_trait_selection::traits::query::{Fallible, NoSolution}; use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine}; use std::fmt; +use std::iter::zip; pub(crate) fn provide(p: &mut Providers) { *p = Providers { @@ -61,14 +62,15 @@ pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>( mir_ty, def_id, user_substs ); - let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx }; - cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs, span)?; + let mut cx = AscribeUserTypeCx { infcx, param_env, span: span.unwrap_or(DUMMY_SP), fulfill_cx }; + cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?; Ok(()) } struct AscribeUserTypeCx<'me, 'tcx> { infcx: &'me InferCtxt<'me, 'tcx>, param_env: ParamEnv<'tcx>, + span: Span, fulfill_cx: &'me mut dyn TraitEngine<'tcx>, } @@ -79,7 +81,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { { self.infcx .partially_normalize_associated_types_in( - ObligationCause::misc(DUMMY_SP, hir::CRATE_HIR_ID), + ObligationCause::misc(self.span, hir::CRATE_HIR_ID), self.param_env, value, ) @@ -91,18 +93,13 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { T: ToTrace<'tcx>, { self.infcx - .at(&ObligationCause::dummy(), self.param_env) + .at(&ObligationCause::dummy_with_span(self.span), self.param_env) .relate(a, variance, b)? .into_value_registering_obligations(self.infcx, self.fulfill_cx); Ok(()) } - fn prove_predicate(&mut self, predicate: Predicate<'tcx>, span: Option<Span>) { - let cause = if let Some(span) = span { - ObligationCause::dummy_with_span(span) - } else { - ObligationCause::dummy() - }; + fn prove_predicate(&mut self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) { self.fulfill_cx.register_predicate_obligation( self.infcx, Obligation::new(cause, self.param_env, predicate), @@ -126,7 +123,6 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>, - span: Option<Span>, ) -> Result<(), NoSolution> { let UserSubsts { user_self_ty, substs } = user_substs; let tcx = self.tcx(); @@ -145,10 +141,20 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { // outlives" error messages. let instantiated_predicates = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); + + let cause = ObligationCause::dummy_with_span(self.span); + debug!(?instantiated_predicates); - for instantiated_predicate in instantiated_predicates.predicates { - let instantiated_predicate = self.normalize(instantiated_predicate); - self.prove_predicate(instantiated_predicate, span); + for (instantiated_predicate, predicate_span) in + zip(instantiated_predicates.predicates, instantiated_predicates.spans) + { + let span = if self.span == DUMMY_SP { predicate_span } else { self.span }; + let cause = ObligationCause::new( + span, + hir::CRATE_HIR_ID, + ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span), + ); + self.prove_predicate(instantiated_predicate, cause); } if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { @@ -161,7 +167,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())) .to_predicate(self.tcx()), - span, + cause.clone(), ); } @@ -178,7 +184,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { // which...could happen with normalization... self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()), - span, + cause, ); Ok(()) } diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index bc644c694a0..27b3da8ab3d 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -10,6 +10,7 @@ use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs}; use rustc_infer::infer::outlives::obligations::TypeOutlives; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; +use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -663,7 +664,7 @@ fn ty_known_to_outlive<'tcx>( resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| { let origin = infer::RelateParamBound(DUMMY_SP, ty, None); let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env); - outlives.type_must_outlive(origin, ty, region); + outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation); }) } @@ -681,7 +682,12 @@ fn region_known_to_outlive<'tcx>( use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; let origin = infer::RelateRegionParamBound(DUMMY_SP); // `region_a: region_b` -> `region_b <= region_a` - infcx.push_sub_region_constraint(origin, region_b, region_a); + infcx.push_sub_region_constraint( + origin, + region_b, + region_a, + ConstraintCategory::BoringNoLocation, + ); }) } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 600e7cf3a0b..9af2b61c037 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -686,15 +686,6 @@ pre, .rustdoc.source .example-wrap { position: relative; } -.content table { - border-spacing: 0 5px; -} -.content td { vertical-align: top; } -.content td:first-child { padding-right: 20px; } -.content td p:first-child { margin-top: 0; } -.content td h1, .content td h2 { margin-left: 0; font-size: 1.125rem; } -.content tr:first-child td { border-top: 0; } - .docblock table { margin: .5em 0; width: calc(100% - 2px); @@ -705,6 +696,7 @@ pre, .rustdoc.source .example-wrap { .docblock table td { padding: .5em; border: 1px dashed var(--border-color); + vertical-align: top; } .docblock table th { @@ -1267,7 +1259,6 @@ a.test-arrow:hover { } .out-of-band > span.since { - position: initial; font-size: 1.25rem; } diff --git a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr new file mode 100644 index 00000000000..3be7f370da3 --- /dev/null +++ b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr @@ -0,0 +1,110 @@ +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:48:13 + | +LL | is_send(foo(Some(true))); + | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` + | + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:11:14 + | +LL | let r = Rc::new(()); + | - has type `Rc<()>` which is not `Send` +LL | bar().await + | ^^^^^^ await occurs here, with `r` maybe used later +LL | }; + | - `r` is later dropped here +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error[E0277]: `Rc<()>` cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:50:13 + | +LL | async fn foo2(x: Option<bool>) { + | - within this `impl Future<Output = ()>` +... +LL | is_send(foo2(Some(true))); + | ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` +note: required because it's used within this `async fn` body + --> $DIR/async-await-let-else.rs:27:29 + | +LL | async fn bar2<T>(_: T) -> ! { + | _____________________________^ +LL | | panic!() +LL | | } + | |_^ + = note: required because it captures the following types: `ResumeTy`, `Option<bool>`, `impl Future<Output = !>`, `()` +note: required because it's used within this `async fn` body + --> $DIR/async-await-let-else.rs:21:32 + | +LL | async fn foo2(x: Option<bool>) { + | ________________________________^ +LL | | let Some(_) = x else { +LL | | bar2(Rc::new(())).await +LL | | }; +LL | | } + | |_^ +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:52:13 + | +LL | is_send(foo3(Some(true))); + | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` + | + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:33:28 + | +LL | (Rc::new(()), bar().await); + | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later + | | + | has type `Rc<()>` which is not `Send` +note: `Rc::new(())` is later dropped here + --> $DIR/async-await-let-else.rs:33:35 + | +LL | (Rc::new(()), bar().await); + | ^ +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:54:13 + | +LL | is_send(foo4(Some(true))); + | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` + | + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:41:14 + | +LL | let r = Rc::new(()); + | - has type `Rc<()>` which is not `Send` +LL | bar().await; + | ^^^^^^ await occurs here, with `r` maybe used later +... +LL | }; + | - `r` is later dropped here +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send<T: Send>(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/async-await-let-else.stderr b/src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr index 4d23e27c426..435cc845870 100644 --- a/src/test/ui/async-await/async-await-let-else.stderr +++ b/src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:45:13 + --> $DIR/async-await-let-else.rs:48:13 | LL | is_send(foo(Some(true))); | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:8:14 + --> $DIR/async-await-let-else.rs:11:14 | LL | let r = Rc::new(()); | - has type `Rc<()>` which is not `Send` @@ -15,20 +15,20 @@ LL | bar().await LL | }; | - `r` is later dropped here note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:16:15 + --> $DIR/async-await-let-else.rs:19:15 | LL | fn is_send<T: Send>(_: T) {} | ^^^^ required by this bound in `is_send` error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:47:13 + --> $DIR/async-await-let-else.rs:50:13 | LL | is_send(foo2(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:20:26 + --> $DIR/async-await-let-else.rs:23:26 | LL | bar2(Rc::new(())).await | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later @@ -37,45 +37,45 @@ LL | bar2(Rc::new(())).await LL | }; | - `Rc::new(())` is later dropped here note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:16:15 + --> $DIR/async-await-let-else.rs:19:15 | LL | fn is_send<T: Send>(_: T) {} | ^^^^ required by this bound in `is_send` error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:49:13 + --> $DIR/async-await-let-else.rs:52:13 | LL | is_send(foo3(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:30:28 + --> $DIR/async-await-let-else.rs:33:28 | LL | (Rc::new(()), bar().await); | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later | | | has type `Rc<()>` which is not `Send` note: `Rc::new(())` is later dropped here - --> $DIR/async-await-let-else.rs:30:35 + --> $DIR/async-await-let-else.rs:33:35 | LL | (Rc::new(()), bar().await); | ^ note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:16:15 + --> $DIR/async-await-let-else.rs:19:15 | LL | fn is_send<T: Send>(_: T) {} | ^^^^ required by this bound in `is_send` error: future cannot be sent between threads safely - --> $DIR/async-await-let-else.rs:51:13 + --> $DIR/async-await-let-else.rs:54:13 | LL | is_send(foo4(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>` note: future is not `Send` as this value is used across an await - --> $DIR/async-await-let-else.rs:38:14 + --> $DIR/async-await-let-else.rs:41:14 | LL | let r = Rc::new(()); | - has type `Rc<()>` which is not `Send` @@ -85,7 +85,7 @@ LL | bar().await; LL | }; | - `r` is later dropped here note: required by a bound in `is_send` - --> $DIR/async-await-let-else.rs:16:15 + --> $DIR/async-await-let-else.rs:19:15 | LL | fn is_send<T: Send>(_: T) {} | ^^^^ required by this bound in `is_send` diff --git a/src/test/ui/async-await/async-await-let-else.rs b/src/test/ui/async-await/async-await-let-else.rs index 7ea07ae9add..4b287159d13 100644 --- a/src/test/ui/async-await/async-await-let-else.rs +++ b/src/test/ui/async-await/async-await-let-else.rs @@ -1,4 +1,7 @@ // edition:2021 +// revisions: drop-tracking no-drop-tracking +// [drop-tracking] compile-flags: -Zdrop-tracking=yes +// [no-drop-tracking] compile-flags: -Zdrop-tracking=no #![feature(let_else)] use std::rc::Rc; @@ -43,11 +46,11 @@ async fn foo4(x: Option<bool>) { fn main() { is_send(foo(Some(true))); - //~^ ERROR future cannot be sent between threads safely + //~^ ERROR cannot be sent between threads safely is_send(foo2(Some(true))); - //~^ ERROR future cannot be sent between threads safely + //~^ ERROR cannot be sent between threads safely is_send(foo3(Some(true))); - //~^ ERROR future cannot be sent between threads safely + //~^ ERROR cannot be sent between threads safely is_send(foo4(Some(true))); - //~^ ERROR future cannot be sent between threads safely + //~^ ERROR cannot be sent between threads safely } diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr index d631e6dc7f7..f609e36362c 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/issue-64130-4-async-move.rs:15:17 + --> $DIR/issue-64130-4-async-move.rs:19:17 | LL | pub fn foo() -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` note: future is not `Send` as this value is used across an await - --> $DIR/issue-64130-4-async-move.rs:21:31 + --> $DIR/issue-64130-4-async-move.rs:25:31 | LL | match client.status() { | ------ has type `&Client` which is not `Send` @@ -17,7 +17,7 @@ LL | let _x = get().await; LL | } | - `client` is later dropped here help: consider moving this into a `let` binding to create a shorter lived borrow - --> $DIR/issue-64130-4-async-move.rs:19:15 + --> $DIR/issue-64130-4-async-move.rs:23:15 | LL | match client.status() { | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr b/src/test/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr new file mode 100644 index 00000000000..f609e36362c --- /dev/null +++ b/src/test/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr @@ -0,0 +1,26 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-64130-4-async-move.rs:19:17 + | +LL | pub fn foo() -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-4-async-move.rs:25:31 + | +LL | match client.status() { + | ------ has type `&Client` which is not `Send` +LL | 200 => { +LL | let _x = get().await; + | ^^^^^^ await occurs here, with `client` maybe used later +... +LL | } + | - `client` is later dropped here +help: consider moving this into a `let` binding to create a shorter lived borrow + --> $DIR/issue-64130-4-async-move.rs:23:15 + | +LL | match client.status() { + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/issue-64130-4-async-move.rs b/src/test/ui/async-await/issue-64130-4-async-move.rs index 2538f34351e..a38428fc00f 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.rs +++ b/src/test/ui/async-await/issue-64130-4-async-move.rs @@ -1,4 +1,8 @@ // edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] check-pass +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no use std::any::Any; use std::future::Future; @@ -10,16 +14,16 @@ impl Client { } } -async fn get() { } +async fn get() {} pub fn foo() -> impl Future + Send { - //~^ ERROR future cannot be sent between threads safely + //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely let client = Client(Box::new(true)); async move { match client.status() { 200 => { let _x = get().await; - }, + } _ => (), } } diff --git a/src/test/ui/async-await/issue-68112.drop_tracking.stderr b/src/test/ui/async-await/issue-68112.drop_tracking.stderr new file mode 100644 index 00000000000..c915164cfce --- /dev/null +++ b/src/test/ui/async-await/issue-68112.drop_tracking.stderr @@ -0,0 +1,79 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:37:18 + | +LL | require_send(send_fut); + | ^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `RefCell<i32>` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:34:17 + | +LL | let _ = non_send_fut.await; + | ^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send` +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:46:18 + | +LL | require_send(send_fut); + | ^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `RefCell<i32>` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:43:17 + | +LL | let _ = make_non_send_future1().await; + | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send` +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `RefCell<i32>` cannot be shared between threads safely + --> $DIR/issue-68112.rs:65:18 + | +LL | require_send(send_fut); + | ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `RefCell<i32>` + = note: required for `Arc<RefCell<i32>>` to implement `Send` +note: required because it's used within this `async fn` body + --> $DIR/issue-68112.rs:50:31 + | +LL | async fn ready2<T>(t: T) -> T { + | _______________________________^ +LL | | t +LL | | } + | |_^ +note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>` + --> $DIR/issue-68112.rs:53:31 + | +LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>` +note: required because it's used within this `async` block + --> $DIR/issue-68112.rs:60:26 + | +LL | let send_fut = async { + | __________________________^ +LL | | let non_send_fut = make_non_send_future2(); +LL | | let _ = non_send_fut.await; +LL | | ready(0).await; +LL | | }; + | |_____^ +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr index c3553e3e0c1..11b7d1aaaa6 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr @@ -1,41 +1,41 @@ error: future cannot be sent between threads safely - --> $DIR/issue-68112.rs:34:18 + --> $DIR/issue-68112.rs:37:18 | LL | require_send(send_fut); | ^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `RefCell<i32>` note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/issue-68112.rs:31:17 + --> $DIR/issue-68112.rs:34:17 | LL | let _ = non_send_fut.await; | ^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send` note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:11:25 + --> $DIR/issue-68112.rs:14:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error: future cannot be sent between threads safely - --> $DIR/issue-68112.rs:43:18 + --> $DIR/issue-68112.rs:46:18 | LL | require_send(send_fut); | ^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `RefCell<i32>` note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/issue-68112.rs:40:17 + --> $DIR/issue-68112.rs:43:17 | LL | let _ = make_non_send_future1().await; | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send` note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:11:25 + --> $DIR/issue-68112.rs:14:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error[E0277]: `RefCell<i32>` cannot be shared between threads safely - --> $DIR/issue-68112.rs:60:18 + --> $DIR/issue-68112.rs:65:18 | LL | require_send(send_fut); | ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely @@ -45,18 +45,21 @@ LL | require_send(send_fut); = help: the trait `Sync` is not implemented for `RefCell<i32>` = note: required for `Arc<RefCell<i32>>` to implement `Send` note: required because it's used within this `async fn` body - --> $DIR/issue-68112.rs:47:31 + --> $DIR/issue-68112.rs:50:31 | -LL | async fn ready2<T>(t: T) -> T { t } - | ^^^^^ +LL | async fn ready2<T>(t: T) -> T { + | _______________________________^ +LL | | t +LL | | } + | |_^ note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>` - --> $DIR/issue-68112.rs:48:31 + --> $DIR/issue-68112.rs:53:31 | LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>` note: required because it's used within this `async` block - --> $DIR/issue-68112.rs:55:26 + --> $DIR/issue-68112.rs:60:26 | LL | let send_fut = async { | __________________________^ @@ -66,7 +69,7 @@ LL | | ready(0).await; LL | | }; | |_____^ note: required by a bound in `require_send` - --> $DIR/issue-68112.rs:11:25 + --> $DIR/issue-68112.rs:14:25 | LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` diff --git a/src/test/ui/async-await/issue-68112.rs b/src/test/ui/async-await/issue-68112.rs index bfabf81d1f5..9c705137a10 100644 --- a/src/test/ui/async-await/issue-68112.rs +++ b/src/test/ui/async-await/issue-68112.rs @@ -1,10 +1,13 @@ // edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no use std::{ - future::Future, cell::RefCell, - sync::Arc, + future::Future, pin::Pin, + sync::Arc, task::{Context, Poll}, }; @@ -44,7 +47,9 @@ fn test1_no_let() { //~^ ERROR future cannot be sent between threads } -async fn ready2<T>(t: T) -> T { t } +async fn ready2<T>(t: T) -> T { + t +} fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> { ready2(Arc::new(RefCell::new(0))) } diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index d2e388c78ca..198de7bf79f 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -1,5 +1,5 @@ error[E0277]: `Sender<i32>` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:12:45 + --> $DIR/issue-70935-complex-spans.rs:13:45 | LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely @@ -7,12 +7,12 @@ LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { = help: the trait `Sync` is not implemented for `Sender<i32>` = note: required for `&Sender<i32>` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:16:13 + --> $DIR/issue-70935-complex-spans.rs:17:13 | LL | baz(|| async{ | ^^ note: required because it's used within this `async fn` body - --> $DIR/issue-70935-complex-spans.rs:9:67 + --> $DIR/issue-70935-complex-spans.rs:10:67 | LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> { | ___________________________________________________________________^ @@ -20,7 +20,7 @@ LL | | } | |_^ = note: required because it captures the following types: `ResumeTy`, `impl for<'r, 's, 't0> Future<Output = ()>`, `()` note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:15:16 + --> $DIR/issue-70935-complex-spans.rs:16:16 | LL | async move { | ________________^ diff --git a/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr b/src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr index 2b81b400099..34b31198e4f 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/issue-70935-complex-spans.rs:12:45 + --> $DIR/issue-70935-complex-spans.rs:13:45 | LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `Sender<i32>` note: future is not `Send` as this value is used across an await - --> $DIR/issue-70935-complex-spans.rs:18:11 + --> $DIR/issue-70935-complex-spans.rs:19:11 | LL | baz(|| async{ | _____________- @@ -14,9 +14,9 @@ LL | | foo(tx.clone()); LL | | }).await; | | - ^^^^^^ await occurs here, with the value maybe used later | |_________| - | has type `[closure@$DIR/issue-70935-complex-spans.rs:16:13: 16:15]` which is not `Send` + | has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send` note: the value is later dropped here - --> $DIR/issue-70935-complex-spans.rs:18:17 + --> $DIR/issue-70935-complex-spans.rs:19:17 | LL | }).await; | ^ diff --git a/src/test/ui/async-await/issue-70935-complex-spans.rs b/src/test/ui/async-await/issue-70935-complex-spans.rs index 48847cdf974..b6d17f93a66 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.rs +++ b/src/test/ui/async-await/issue-70935-complex-spans.rs @@ -1,5 +1,6 @@ // edition:2018 -// revisions: normal drop_tracking +// revisions: no_drop_tracking drop_tracking +// [no_drop_tracking]compile-flags:-Zdrop-tracking=no // [drop_tracking]compile-flags:-Zdrop-tracking // #70935: Check if we do not emit snippet // with newlines which lead complex diagnostics. @@ -10,7 +11,7 @@ async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> { } fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { - //[normal]~^ ERROR future cannot be sent between threads safely + //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely //[drop_tracking]~^^ ERROR `Sender<i32>` cannot be shared between threads async move { baz(|| async{ diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr index 99e960f5d0f..a723503776b 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr @@ -1,5 +1,5 @@ error: future cannot be sent between threads safely - --> $DIR/issue-65436-raw-ptr-not-send.rs:12:17 + --> $DIR/issue-65436-raw-ptr-not-send.rs:16:17 | LL | assert_send(async { | _________________^ @@ -10,24 +10,24 @@ LL | | }) | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await - --> $DIR/issue-65436-raw-ptr-not-send.rs:14:35 + --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35 | LL | bar(Foo(std::ptr::null())).await; | ---------------- ^^^^^^ await occurs here, with `std::ptr::null()` maybe used later | | | has type `*const u8` which is not `Send` note: `std::ptr::null()` is later dropped here - --> $DIR/issue-65436-raw-ptr-not-send.rs:14:41 + --> $DIR/issue-65436-raw-ptr-not-send.rs:18:41 | LL | bar(Foo(std::ptr::null())).await; | ^ help: consider moving this into a `let` binding to create a shorter lived borrow - --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 + --> $DIR/issue-65436-raw-ptr-not-send.rs:18:13 | LL | bar(Foo(std::ptr::null())).await; | ^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `assert_send` - --> $DIR/issue-65436-raw-ptr-not-send.rs:9:19 + --> $DIR/issue-65436-raw-ptr-not-send.rs:13:19 | LL | fn assert_send<T: Send>(_: T) {} | ^^^^ required by this bound in `assert_send` diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs index 3a814b47517..91edbc10dc0 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs @@ -1,4 +1,8 @@ // edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] check-pass +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no struct Foo(*const u8); @@ -10,7 +14,7 @@ fn assert_send<T: Send>(_: T) {} fn main() { assert_send(async { - //~^ ERROR future cannot be sent between threads safely + //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely bar(Foo(std::ptr::null())).await; }) } diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr new file mode 100644 index 00000000000..17b4ef7bdc6 --- /dev/null +++ b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr @@ -0,0 +1,35 @@ +error[E0277]: `NotSend` cannot be sent between threads safely + --> $DIR/partial-drop-partial-reinit.rs:9:16 + | +LL | gimme_send(foo()); + | ---------- ^^^^^ `NotSend` cannot be sent between threads safely + | | + | required by a bound introduced by this call +... +LL | async fn foo() { + | - within this `impl Future<Output = ()>` + | + = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend` + = note: required because it appears within the type `(NotSend,)` + = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future<Output = ()>` +note: required because it's used within this `async fn` body + --> $DIR/partial-drop-partial-reinit.rs:31:16 + | +LL | async fn foo() { + | ________________^ +LL | | +LL | | +LL | | let mut x = (NotSend {},); +... | +LL | | bar().await; +LL | | } + | |_^ +note: required by a bound in `gimme_send` + --> $DIR/partial-drop-partial-reinit.rs:17:18 + | +LL | fn gimme_send<T: Send>(t: T) { + | ^^^^ required by this bound in `gimme_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr index 05f5358340a..34d8a159f10 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.stderr +++ b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr @@ -1,5 +1,5 @@ error[E0277]: `NotSend` cannot be sent between threads safely - --> $DIR/partial-drop-partial-reinit.rs:6:16 + --> $DIR/partial-drop-partial-reinit.rs:9:16 | LL | gimme_send(foo()); | ---------- ^^^^^ `NotSend` cannot be sent between threads safely @@ -13,7 +13,7 @@ LL | async fn foo() { = note: required because it appears within the type `(NotSend,)` = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future<Output = ()>`, `()` note: required because it's used within this `async fn` body - --> $DIR/partial-drop-partial-reinit.rs:28:16 + --> $DIR/partial-drop-partial-reinit.rs:31:16 | LL | async fn foo() { | ________________^ @@ -25,7 +25,7 @@ LL | | bar().await; LL | | } | |_^ note: required by a bound in `gimme_send` - --> $DIR/partial-drop-partial-reinit.rs:14:18 + --> $DIR/partial-drop-partial-reinit.rs:17:18 | LL | fn gimme_send<T: Send>(t: T) { | ^^^^ required by this bound in `gimme_send` diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.rs b/src/test/ui/async-await/partial-drop-partial-reinit.rs index fe0fce7afd9..7d097e72fb4 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.rs +++ b/src/test/ui/async-await/partial-drop-partial-reinit.rs @@ -1,4 +1,7 @@ // edition:2021 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no #![feature(negative_impls)] #![allow(unused)] @@ -12,8 +15,8 @@ fn main() { } fn gimme_send<T: Send>(t: T) { -//~^ NOTE required by this bound -//~| NOTE required by a bound + //~^ NOTE required by this bound + //~| NOTE required by a bound drop(t); } @@ -26,8 +29,8 @@ impl Drop for NotSend { impl !Send for NotSend {} async fn foo() { -//~^ NOTE used within this `async fn` body -//~| NOTE within this `impl Future + //~^ NOTE used within this `async fn` body + //~| NOTE within this `impl Future let mut x = (NotSend {},); drop(x.0); x.0 = NotSend {}; diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs new file mode 100644 index 00000000000..719d1bd5a4c --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.rs @@ -0,0 +1,35 @@ +// check-fail +// known-bug + +// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for +// all 'a where I::Item<'a> is WF", but really means "for all 'a possible" + +use std::fmt::Debug; + +pub trait LendingIterator { + type Item<'this> + where + Self: 'this; +} + +pub struct WindowsMut<'x> { + slice: &'x (), +} + +impl<'y> LendingIterator for WindowsMut<'y> { + type Item<'this> = &'this mut () where 'y: 'this; +} + +fn print_items<I>(_iter: I) +where + I: LendingIterator, + for<'a> I::Item<'a>: Debug, +{ +} + +fn main() { + let slice = &mut (); + //~^ temporary value dropped while borrowed + let windows = WindowsMut { slice }; + print_items::<WindowsMut<'_>>(windows); +} diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr new file mode 100644 index 00000000000..414999881d4 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr @@ -0,0 +1,20 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/hrtb-implied-1.rs:31:22 + | +LL | let slice = &mut (); + | ^^ creates a temporary which is freed while still in use +... +LL | print_items::<WindowsMut<'_>>(windows); + | -------------------------------------- argument requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-implied-1.rs:26:26 + | +LL | for<'a> I::Item<'a>: Debug, + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs new file mode 100644 index 00000000000..8e6c5348e71 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs @@ -0,0 +1,40 @@ +// check-fail +// known-bug + +// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for +// all 'a where I::Item<'a> is WF", but really means "for all 'a possible" + +trait LendingIterator: Sized { + type Item<'a> + where + Self: 'a; + fn next(&mut self) -> Self::Item<'_>; +} +fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool +where + F: FnMut(I::Item<'_>), +{ + let mut iter2 = Eat(iter, f); + let _next = iter2.next(); + //~^ borrowed data escapes + true +} +impl<I: LendingIterator> LendingIterator for &mut I { + type Item<'a> = I::Item<'a> where Self:'a; + fn next(&mut self) -> Self::Item<'_> { + (**self).next() + } +} + +struct Eat<I, F>(I, F); +impl<I: LendingIterator, F> Iterator for Eat<I, F> +where + F: FnMut(I::Item<'_>), +{ + type Item = (); + fn next(&mut self) -> Option<Self::Item> { + None + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr new file mode 100644 index 00000000000..1ee270398de --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/hrtb-implied-2.rs:18:17 + | +LL | fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool + | ---- - let's call the lifetime of this reference `'1` + | | + | `iter` is a reference that is only valid in the function body +... +LL | let _next = iter2.next(); + | ^^^^^^^^^^^^ + | | + | `iter` escapes the function body here + | argument requires that `'1` must outlive `'static` + | + = note: requirement occurs because of a mutable reference to `Eat<&mut I, F>` + = note: mutable references are invariant over their type parameter + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + = note: due to current limitations in the borrow checker, this implies a `'static` lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs new file mode 100644 index 00000000000..bc9e6c8aea8 --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs @@ -0,0 +1,23 @@ +trait LendingIterator { + type Item<'a> + where + Self: 'a; +} + +impl LendingIterator for &str { + type Item<'a> = () where Self:'a; +} + +fn trivial_bound<I>(_: I) +where + I: LendingIterator, + for<'a> I::Item<'a>: Sized, +{ +} + +fn fails(iter: &str) { + trivial_bound(iter); + //~^ borrowed data escapes +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr new file mode 100644 index 00000000000..c67e02437cd --- /dev/null +++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/hrtb-implied-3.rs:19:5 + | +LL | fn fails(iter: &str) { + | ---- - let's call the lifetime of this reference `'1` + | | + | `iter` is a reference that is only valid in the function body +LL | trivial_bound(iter); + | ^^^^^^^^^^^^^^^^^^^ + | | + | `iter` escapes the function body here + | argument requires that `'1` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-implied-3.rs:14:26 + | +LL | for<'a> I::Item<'a>: Sized, + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/generic-associated-types/trait-objects.extended.stderr b/src/test/ui/generic-associated-types/trait-objects.extended.stderr index 086177cc106..45b64d2b024 100644 --- a/src/test/ui/generic-associated-types/trait-objects.extended.stderr +++ b/src/test/ui/generic-associated-types/trait-objects.extended.stderr @@ -11,6 +11,8 @@ LL | x.size_hint().0 | | | `x` escapes the function body here | argument requires that `'1` must outlive `'static` + | + = note: due to current limitations in the borrow checker, this implies a `'static` lifetime error: aborting due to previous error diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr index b4312091edb..31e11e12835 100644 --- a/src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr @@ -14,6 +14,12 @@ LL | fn give_some<'a>() { | -- lifetime `'a` defined here LL | want_hrtb::<&'a u32>() | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-just-for-static.rs:9:15 + | +LL | where T : for<'a> Foo<&'a isize> + | ^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr index 1461e7fd2dd..5e75a4cc8af 100644 --- a/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr @@ -46,6 +46,12 @@ LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) ... LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-perfect-forwarding.rs:37:8 + | +LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, + | ^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `Bar` is not general enough --> $DIR/hrtb-perfect-forwarding.rs:43:5 diff --git a/src/test/ui/issues/issue-26217.stderr b/src/test/ui/issues/issue-26217.stderr index c7601caacdc..73c772205c3 100644 --- a/src/test/ui/issues/issue-26217.stderr +++ b/src/test/ui/issues/issue-26217.stderr @@ -5,6 +5,12 @@ LL | fn bar<'a>() { | -- lifetime `'a` defined here LL | foo::<&'a i32>(); | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/issue-26217.rs:1:30 + | +LL | fn foo<T>() where for<'a> T: 'a {} + | ^^ error: aborting due to previous error diff --git a/src/test/ui/lint/must_not_suspend/ref.drop_tracking.stderr b/src/test/ui/lint/must_not_suspend/ref.drop_tracking.stderr new file mode 100644 index 00000000000..0157c8b7fe1 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/ref.drop_tracking.stderr @@ -0,0 +1,27 @@ +error: reference to `Umm` held across a suspend point, but should not be + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/ref.rs:6:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +note: You gotta use Umm's, ya know? + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/must_not_suspend/ref.stderr b/src/test/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr index 5f000014c7d..438e6489e31 100644 --- a/src/test/ui/lint/must_not_suspend/ref.stderr +++ b/src/test/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr @@ -1,5 +1,5 @@ error: `Umm` held across a suspend point, but should not be - --> $DIR/ref.rs:18:26 + --> $DIR/ref.rs:21:26 | LL | let guard = &mut self.u; | ^^^^^^ @@ -8,17 +8,17 @@ LL | other().await; | ------ the value is held across this suspend point | note: the lint level is defined here - --> $DIR/ref.rs:3:9 + --> $DIR/ref.rs:6:9 | LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ note: You gotta use Umm's, ya know? - --> $DIR/ref.rs:18:26 + --> $DIR/ref.rs:21:26 | LL | let guard = &mut self.u; | ^^^^^^ help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/ref.rs:18:26 + --> $DIR/ref.rs:21:26 | LL | let guard = &mut self.u; | ^^^^^^ diff --git a/src/test/ui/lint/must_not_suspend/ref.rs b/src/test/ui/lint/must_not_suspend/ref.rs index 738dd9e0465..f6b23746fef 100644 --- a/src/test/ui/lint/must_not_suspend/ref.rs +++ b/src/test/ui/lint/must_not_suspend/ref.rs @@ -1,10 +1,13 @@ // edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no #![feature(must_not_suspend)] #![deny(must_not_suspend)] #[must_not_suspend = "You gotta use Umm's, ya know?"] struct Umm { - i: i64 + i: i64, } struct Bar { @@ -19,11 +22,8 @@ impl Bar { other().await; - *guard = Umm { - i: 2 - } + *guard = Umm { i: 2 } } } -fn main() { -} +fn main() {} diff --git a/src/test/ui/nll/local-outlives-static-via-hrtb.stderr b/src/test/ui/nll/local-outlives-static-via-hrtb.stderr index 61009da49ff..f5c10f3ddea 100644 --- a/src/test/ui/nll/local-outlives-static-via-hrtb.stderr +++ b/src/test/ui/nll/local-outlives-static-via-hrtb.stderr @@ -9,6 +9,12 @@ LL | assert_static_via_hrtb(&local); LL | assert_static_via_hrtb_with_assoc_type(&&local); LL | } | - `local` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/local-outlives-static-via-hrtb.rs:15:53 + | +LL | fn assert_static_via_hrtb<G>(_: G) where for<'a> G: Outlives<'a> {} + | ^^^^^^^^^^^^ error[E0597]: `local` does not live long enough --> $DIR/local-outlives-static-via-hrtb.rs:25:45 @@ -20,6 +26,12 @@ LL | assert_static_via_hrtb_with_assoc_type(&&local); | argument requires that `local` is borrowed for `'static` LL | } | - `local` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/local-outlives-static-via-hrtb.rs:19:20 + | +LL | for<'a> &'a T: Reference<AssociatedType = &'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/type-test-universe.stderr b/src/test/ui/nll/type-test-universe.stderr index 242486c360a..31e17d64b8c 100644 --- a/src/test/ui/nll/type-test-universe.stderr +++ b/src/test/ui/nll/type-test-universe.stderr @@ -11,6 +11,12 @@ LL | fn test2<'a>() { | -- lifetime `'a` defined here LL | outlives_forall::<Value<'a>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/type-test-universe.rs:6:16 + | +LL | for<'u> T: 'u, + | ^^ error: aborting due to 2 previous errors |
