From 9cee22c1a401ace6dd8633335b131c47a37d7bac Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 23 May 2020 21:40:55 -0400 Subject: [PATCH 01/37] Display information about captured variable in `FnMut` error Fixes #69446 When we encounter a region error involving an `FnMut` closure, we display a specialized error message. However, we currently do not tell the user which upvar was captured. This makes it difficult to determine the cause of the error, especially when the closure is large. This commit records marks constraints involving closure upvars with `ConstraintCategory::ClosureUpvar`. When we decide to 'blame' a `ConstraintCategory::Return`, we additionall store the captured upvar if we found a `ConstraintCategory::ClosureUpvar` in the path. When generating an error message, we point to relevant spans if we have closure upvar information available. We further customize the message if an `async` closure is being returned, to make it clear that the captured variable is being returned indirectly. --- src/libcore/future/mod.rs | 1 + src/librustc_middle/mir/query.rs | 10 +++- .../diagnostics/conflict_errors.rs | 6 +- .../borrow_check/diagnostics/region_errors.rs | 57 +++++++++++++------ src/librustc_mir/borrow_check/mod.rs | 26 +-------- src/librustc_mir/borrow_check/nll.rs | 3 + src/librustc_mir/borrow_check/path_utils.rs | 38 ++++++++++++- .../borrow_check/region_infer/mod.rs | 18 +++++- .../borrow_check/type_check/mod.rs | 27 +++++++-- .../async-await/issue-69446-fnmut-capture.rs | 22 +++++++ .../issue-69446-fnmut-capture.stderr | 19 +++++++ .../borrowck/borrowck-describe-lvalue.stderr | 3 + src/test/ui/issues/issue-40510-1.stderr | 8 ++- src/test/ui/issues/issue-40510-3.stderr | 4 ++ src/test/ui/issues/issue-49824.stderr | 3 + src/test/ui/nll/issue-53040.stderr | 8 ++- ...ons-return-ref-to-upvar-issue-17403.stderr | 8 ++- 17 files changed, 203 insertions(+), 58 deletions(-) create mode 100644 src/test/ui/async-await/issue-69446-fnmut-capture.rs create mode 100644 src/test/ui/async-await/issue-69446-fnmut-capture.stderr diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs index 6f6009b47e672..9dbc23f5c04c5 100644 --- a/src/libcore/future/mod.rs +++ b/src/libcore/future/mod.rs @@ -56,6 +56,7 @@ pub const fn from_generator(gen: T) -> impl Future where T: Generator, { + #[rustc_diagnostic_item = "gen_future"] struct GenFuture>(T); // We rely on the fact that async/await futures are immovable in order to create diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs index 63b8d8c8da782..aed93e86863b9 100644 --- a/src/librustc_middle/mir/query.rs +++ b/src/librustc_middle/mir/query.rs @@ -171,7 +171,7 @@ pub struct ClosureOutlivesRequirement<'tcx> { #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(RustcEncodable, RustcDecodable, HashStable)] pub enum ConstraintCategory { - Return, + Return(ReturnConstraint), Yield, UseAsConst, UseAsStatic, @@ -187,6 +187,7 @@ pub enum ConstraintCategory { SizedBound, Assignment, OpaqueType, + ClosureUpvar(hir::HirId), /// A "boring" constraint (caused by the given location) is one that /// the user probably doesn't want to see described in diagnostics, @@ -204,6 +205,13 @@ pub enum ConstraintCategory { Internal, } +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(RustcEncodable, RustcDecodable, HashStable)] +pub enum ReturnConstraint { + Normal, + ClosureUpvar(hir::HirId), +} + /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing /// that must outlive some region. #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 5f1c0911da2bf..b0b5a819983a8 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -766,7 +766,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { category: category @ - (ConstraintCategory::Return + (ConstraintCategory::Return(_) | ConstraintCategory::CallArgument | ConstraintCategory::OpaqueType), from_closure: false, @@ -1096,7 +1096,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { opt_place_desc: Option<&String>, ) -> Option> { let return_kind = match category { - ConstraintCategory::Return => "return", + ConstraintCategory::Return(_) => "return", ConstraintCategory::Yield => "yield", _ => return None, }; @@ -1210,7 +1210,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let msg = match category { - ConstraintCategory::Return | ConstraintCategory::OpaqueType => { + ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { format!("{} is returned here", kind) } ConstraintCategory::CallArgument => { diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index e19fab89eabfe..681f999e048c1 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -5,9 +5,9 @@ use rustc_infer::infer::{ error_reporting::nice_region_error::NiceRegionError, error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin, }; -use rustc_middle::mir::ConstraintCategory; +use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::{self, RegionVid, Ty}; -use rustc_span::symbol::kw; +use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use crate::util::borrowck_errors; @@ -26,7 +26,7 @@ impl ConstraintDescription for ConstraintCategory { // Must end with a space. Allows for empty names to be provided. match self { ConstraintCategory::Assignment => "assignment ", - ConstraintCategory::Return => "returning this value ", + ConstraintCategory::Return(_) => "returning this value ", ConstraintCategory::Yield => "yielding this value ", ConstraintCategory::UseAsConst => "using this value as a constant ", ConstraintCategory::UseAsStatic => "using this value as a static ", @@ -37,6 +37,7 @@ impl ConstraintDescription for ConstraintCategory { ConstraintCategory::SizedBound => "proving this value is `Sized` ", ConstraintCategory::CopyBound => "copying this value ", ConstraintCategory::OpaqueType => "opaque type ", + ConstraintCategory::ClosureUpvar(_) => "closure capture ", ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => "", @@ -306,8 +307,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let diag = match (category, fr_is_local, outlived_fr_is_local) { - (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(fr) => { - self.report_fnmut_error(&errci) + (ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => { + self.report_fnmut_error(&errci, kind) } (ConstraintCategory::Assignment, true, false) | (ConstraintCategory::CallArgument, true, false) => { @@ -347,7 +348,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// executing... /// = note: ...therefore, returned references to captured variables will escape the closure /// ``` - fn report_fnmut_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> { + fn report_fnmut_error( + &self, + errci: &ErrorConstraintInfo, + kind: ReturnConstraint, + ) -> DiagnosticBuilder<'tcx> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; let mut diag = self @@ -356,19 +361,39 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .sess .struct_span_err(*span, "captured variable cannot escape `FnMut` closure body"); - // We should check if the return type of this closure is in fact a closure - in that - // case, we can special case the error further. - let return_type_is_closure = - self.regioncx.universal_regions().unnormalized_output_ty.is_closure(); - let message = if return_type_is_closure { - "returns a closure that contains a reference to a captured variable, which then \ - escapes the closure body" - } else { - "returns a reference to a captured variable which escapes the closure body" + let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty; + if let ty::Opaque(def_id, _) = output_ty.kind { + output_ty = self.infcx.tcx.type_of(def_id) + }; + + debug!("report_fnmut_error: output_ty={:?}", output_ty); + + let message = match output_ty.kind { + ty::Closure(_, _) => { + "returns a closure that contains a reference to a captured variable, which then \ + escapes the closure body" + } + ty::Adt(def, _) if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did) => { + "returns an `async` block that contains a reference to a captured variable, which then \ + escapes the closure body" + } + _ => "returns a reference to a captured variable which escapes the closure body", }; diag.span_label(*span, message); + if let ReturnConstraint::ClosureUpvar(upvar) = kind { + let def_id = match self.regioncx.universal_regions().defining_ty { + DefiningTy::Closure(def_id, _) => def_id, + ty @ _ => bug!("unexpected DefiningTy {:?}", ty), + }; + + let upvar_def_span = self.infcx.tcx.hir().span(upvar); + let upvar_span = self.infcx.tcx.upvars_mentioned(def_id).unwrap()[&upvar].span; + diag.span_label(upvar_def_span, "variable defined here"); + diag.span_label(upvar_span, "variable captured here"); + } + match self.give_region_a_name(*outlived_fr).unwrap().source { RegionNameSource::NamedEarlyBoundRegion(fr_span) | RegionNameSource::NamedFreeRegion(fr_span) @@ -506,7 +531,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { outlived_fr_name.highlight_region_name(&mut diag); match (category, outlived_fr_is_local, fr_is_local) { - (ConstraintCategory::Return, true, _) => { + (ConstraintCategory::Return(_), true, _) => { diag.span_label( *span, format!( diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a0c1d96bb4743..78d88ac81aaf8 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -218,6 +218,7 @@ fn do_mir_borrowck<'a, 'tcx>( &mut flow_inits, &mdpe.move_data, &borrow_set, + &upvars, ); // Dump MIR results into a file, if that is enabled. This let us @@ -2301,30 +2302,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// be `self` in the current MIR, because that is the only time we directly access the fields /// of a closure type. pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option { - let mut place_projection = place_ref.projection; - let mut by_ref = false; - - if let [proj_base @ .., ProjectionElem::Deref] = place_projection { - place_projection = proj_base; - by_ref = true; - } - - match place_projection { - [base @ .., ProjectionElem::Field(field, _ty)] => { - let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(place_ref.local, base, self.body(), tcx).ty; - - if (base_ty.is_closure() || base_ty.is_generator()) - && (!by_ref || self.upvars[field.index()].by_ref) - { - Some(*field) - } else { - None - } - } - - _ => None, - } + path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body()) } } diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index b820b79c47fe8..5bae31cafb953 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -39,6 +39,7 @@ use crate::borrow_check::{ renumber, type_check::{self, MirTypeckRegionConstraints, MirTypeckResults}, universal_regions::UniversalRegions, + Upvar, }; crate type PoloniusOutput = Output; @@ -166,6 +167,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>, move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, + upvars: &[Upvar], ) -> NllOutput<'tcx> { let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default()); @@ -188,6 +190,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( flow_inits, move_data, elements, + upvars, ); if let Some(all_facts) = &mut all_facts { diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index f5238e7b7bedc..934729553a73b 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -1,10 +1,11 @@ use crate::borrow_check::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; use crate::borrow_check::places_conflict; use crate::borrow_check::AccessDepth; +use crate::borrow_check::Upvar; use crate::dataflow::indexes::BorrowIndex; use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::BorrowKind; -use rustc_middle::mir::{BasicBlock, Body, Location, Place}; +use rustc_middle::mir::{BasicBlock, Body, Field, Location, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::TyCtxt; /// Returns `true` if the borrow represented by `kind` is @@ -135,3 +136,38 @@ pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool { // Any errors will be caught on the initial borrow !place.is_indirect() } + +/// If `place` is a field projection, and the field is being projected from a closure type, +/// then returns the index of the field being projected. Note that this closure will always +/// be `self` in the current MIR, because that is the only time we directly access the fields +/// of a closure type. +pub(crate) fn is_upvar_field_projection( + tcx: TyCtxt<'tcx>, + upvars: &[Upvar], + place_ref: PlaceRef<'tcx>, + body: &Body<'tcx>, +) -> Option { + let mut place_projection = place_ref.projection; + let mut by_ref = false; + + if let [proj_base @ .., ProjectionElem::Deref] = place_projection { + place_projection = proj_base; + by_ref = true; + } + + match place_projection { + [base @ .., ProjectionElem::Field(field, _ty)] => { + let base_ty = Place::ty_from(place_ref.local, base, body, tcx).ty; + + if (base_ty.is_closure() || base_ty.is_generator()) + && (!by_ref || upvars[field.index()].by_ref) + { + Some(*field) + } else { + None + } + } + + _ => None, + } +} diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index fe11384380086..3e459bd52f757 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -12,7 +12,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound} use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin}; use rustc_middle::mir::{ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, - ConstraintCategory, Local, Location, + ConstraintCategory, Local, Location, ReturnConstraint, }; use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; @@ -2017,7 +2017,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => false, ConstraintCategory::TypeAnnotation - | ConstraintCategory::Return + | ConstraintCategory::Return(_) | ConstraintCategory::Yield => true, _ => constraint_sup_scc != target_scc, } @@ -2042,7 +2042,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { if let Some(i) = best_choice { if let Some(next) = categorized_path.get(i + 1) { - if categorized_path[i].0 == ConstraintCategory::Return + if matches!(categorized_path[i].0, ConstraintCategory::Return(_)) && next.0 == ConstraintCategory::OpaqueType { // The return expression is being influenced by the return type being @@ -2050,6 +2050,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { return *next; } } + + if categorized_path[i].0 == ConstraintCategory::Return(ReturnConstraint::Normal) { + let field = categorized_path.iter().find_map(|p| { + if let ConstraintCategory::ClosureUpvar(f) = p.0 { Some(f) } else { None } + }); + + if let Some(field) = field { + categorized_path[i].0 = + ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)); + } + } + return categorized_path[i]; } diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index bdbce1de745ad..d6b06bc1dfa64 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -55,6 +55,7 @@ use crate::borrow_check::{ location::LocationTable, member_constraints::MemberConstraintSet, nll::ToRegionVid, + path_utils, region_infer::values::{ LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, }, @@ -62,6 +63,7 @@ use crate::borrow_check::{ renumber, type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, universal_regions::{DefiningTy, UniversalRegions}, + Upvar, }; macro_rules! span_mirbug { @@ -132,6 +134,7 @@ pub(crate) fn type_check<'mir, 'tcx>( flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, elements: &Rc, + upvars: &[Upvar], ) -> MirTypeckResults<'tcx> { let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body)); let mut constraints = MirTypeckRegionConstraints { @@ -162,6 +165,7 @@ pub(crate) fn type_check<'mir, 'tcx>( borrow_set, all_facts, constraints: &mut constraints, + upvars, }; let opaque_type_values = type_check_internal( @@ -577,7 +581,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { for constraint in constraints.outlives().iter() { let mut constraint = *constraint; constraint.locations = locations; - if let ConstraintCategory::Return + if let ConstraintCategory::Return(_) | ConstraintCategory::UseAsConst | ConstraintCategory::UseAsStatic = constraint.category { @@ -827,6 +831,7 @@ struct BorrowCheckContext<'a, 'tcx> { all_facts: &'a mut Option, borrow_set: &'a BorrowSet<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, + upvars: &'a [Upvar], } crate struct MirTypeckResults<'tcx> { @@ -1420,7 +1425,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::UseAsConst } } else { - ConstraintCategory::Return + ConstraintCategory::Return(ReturnConstraint::Normal) } } Some(l) if !body.local_decls[l].is_user_variable() => { @@ -1703,7 +1708,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::UseAsConst } } else { - ConstraintCategory::Return + ConstraintCategory::Return(ReturnConstraint::Normal) } } Some(l) if !body.local_decls[l].is_user_variable() => { @@ -2487,6 +2492,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); let mut cursor = borrowed_place.projection.as_ref(); + let tcx = self.infcx.tcx; + let field = path_utils::is_upvar_field_projection( + tcx, + &self.borrowck_context.upvars, + borrowed_place.as_ref(), + body, + ); + let category = if let Some(field) = field { + ConstraintCategory::ClosureUpvar(self.borrowck_context.upvars[field.index()].var_hir_id) + } else { + ConstraintCategory::Boring + }; + while let [proj_base @ .., elem] = cursor { cursor = proj_base; @@ -2494,7 +2512,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match elem { ProjectionElem::Deref => { - let tcx = self.infcx.tcx; let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty; debug!("add_reborrow_constraint - base_ty = {:?}", base_ty); @@ -2504,7 +2521,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { sup: ref_region.to_region_vid(), sub: borrow_region.to_region_vid(), locations: location.to_locations(), - category: ConstraintCategory::Boring, + category, }); match mutbl { diff --git a/src/test/ui/async-await/issue-69446-fnmut-capture.rs b/src/test/ui/async-await/issue-69446-fnmut-capture.rs new file mode 100644 index 0000000000000..842115538c9d8 --- /dev/null +++ b/src/test/ui/async-await/issue-69446-fnmut-capture.rs @@ -0,0 +1,22 @@ +// Regression test for issue #69446 - we should display +// which variable is captured +// edition:2018 + +use core::future::Future; + +struct Foo; +impl Foo { + fn foo(&mut self) {} +} + +async fn bar(_: impl FnMut() -> T) +where + T: Future, +{} + +fn main() { + let mut x = Foo; + bar(move || async { //~ ERROR captured + x.foo(); + }); +} diff --git a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr new file mode 100644 index 0000000000000..3d2b0402bc52c --- /dev/null +++ b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr @@ -0,0 +1,19 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-69446-fnmut-capture.rs:19:17 + | +LL | let mut x = Foo; + | ----- variable defined here +LL | bar(move || async { + | _______________-_^ + | | | + | | inferred to be a `FnMut` closure +LL | | x.foo(); + | | - variable captured here +LL | | }); + | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to previous error + diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr index 075e0e2e4515e..4144d70cc1601 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr @@ -21,10 +21,13 @@ LL | *y = 1; error: captured variable cannot escape `FnMut` closure body --> $DIR/borrowck-describe-lvalue.rs:264:16 | +LL | let mut x = 0; + | ----- variable defined here LL | || { | - inferred to be a `FnMut` closure LL | / || { LL | | let y = &mut x; + | | - variable captured here LL | | &mut x; LL | | *y = 1; LL | | drop(y); diff --git a/src/test/ui/issues/issue-40510-1.stderr b/src/test/ui/issues/issue-40510-1.stderr index f4fda0abc2049..54df40b6e3d05 100644 --- a/src/test/ui/issues/issue-40510-1.stderr +++ b/src/test/ui/issues/issue-40510-1.stderr @@ -1,10 +1,16 @@ error: captured variable cannot escape `FnMut` closure body --> $DIR/issue-40510-1.rs:7:9 | +LL | let mut x: Box<()> = Box::new(()); + | ----- variable defined here +LL | LL | || { | - inferred to be a `FnMut` closure LL | &mut x - | ^^^^^^ returns a reference to a captured variable which escapes the closure body + | ^^^^^- + | | | + | | variable captured here + | returns a reference to a captured variable which escapes the closure body | = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape diff --git a/src/test/ui/issues/issue-40510-3.stderr b/src/test/ui/issues/issue-40510-3.stderr index 4bc7d0f5deac5..cb885ec7d952a 100644 --- a/src/test/ui/issues/issue-40510-3.stderr +++ b/src/test/ui/issues/issue-40510-3.stderr @@ -1,10 +1,14 @@ error: captured variable cannot escape `FnMut` closure body --> $DIR/issue-40510-3.rs:7:9 | +LL | let mut x: Vec<()> = Vec::new(); + | ----- variable defined here +LL | LL | || { | - inferred to be a `FnMut` closure LL | / || { LL | | x.push(()) + | | - variable captured here LL | | } | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body | diff --git a/src/test/ui/issues/issue-49824.stderr b/src/test/ui/issues/issue-49824.stderr index 6b486aafcdf40..2fec482543d7b 100644 --- a/src/test/ui/issues/issue-49824.stderr +++ b/src/test/ui/issues/issue-49824.stderr @@ -1,11 +1,14 @@ error: captured variable cannot escape `FnMut` closure body --> $DIR/issue-49824.rs:4:9 | +LL | let mut x = 0; + | ----- variable defined here LL | || { | - inferred to be a `FnMut` closure LL | / || { LL | | LL | | let _y = &mut x; + | | - variable captured here LL | | } | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body | diff --git a/src/test/ui/nll/issue-53040.stderr b/src/test/ui/nll/issue-53040.stderr index 7cba32c67432c..87ffe9b1abf45 100644 --- a/src/test/ui/nll/issue-53040.stderr +++ b/src/test/ui/nll/issue-53040.stderr @@ -1,9 +1,13 @@ error: captured variable cannot escape `FnMut` closure body --> $DIR/issue-53040.rs:3:8 | +LL | let mut v: Vec<()> = Vec::new(); + | ----- variable defined here LL | || &mut v; - | - ^^^^^^ returns a reference to a captured variable which escapes the closure body - | | + | - ^^^^^- + | | | | + | | | variable captured here + | | returns a reference to a captured variable which escapes the closure body | inferred to be a `FnMut` closure | = note: `FnMut` closures only have access to their captured variables while they are executing... diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr index 4c275b19492c6..b087e03b464b3 100644 --- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr +++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr @@ -1,9 +1,13 @@ error: captured variable cannot escape `FnMut` closure body --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24 | +LL | let mut x = 0; + | ----- variable defined here LL | let mut f = || &mut x; - | - ^^^^^^ returns a reference to a captured variable which escapes the closure body - | | + | - ^^^^^- + | | | | + | | | variable captured here + | | returns a reference to a captured variable which escapes the closure body | inferred to be a `FnMut` closure | = note: `FnMut` closures only have access to their captured variables while they are executing... From 4548eb8fcfa0a3d5dfd2766ee12736f67aca0234 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Tue, 2 Jun 2020 23:30:51 +0200 Subject: [PATCH 02/37] Clarify the behaviour of Pattern when used with methods like str::contains --- src/libcore/str/pattern.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 1a2b612b2f95c..263d6b5efdff9 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -60,6 +60,43 @@ use crate::slice::memchr; /// The trait itself acts as a builder for an associated /// `Searcher` type, which does the actual work of finding /// occurrences of the pattern in a string. +/// +/// Depending on the type of the pattern, the behaviour of methods like +/// [`str::find`] and [`str::contains`] can change. The table below describes +/// some of those behaviours. +/// +/// | Pattern type | Match condition | +/// |--------------------------|-------------------------------------------| +/// | `&str` | is substring | +/// | `char` | is contained in string | +/// | `&[char] | any char in slice is contained in string | +/// | `F: FnMut(char) -> bool` | `F` returns `true` for a char in string | +/// | `&&str` | is substring | +/// | `&String` | is substring | +/// +/// # Examples +/// ``` +/// // &str +/// assert_eq!("abaaa".find("ba"), Some(1)); +/// assert_eq!("abaaa".find("bac"), None); +/// +/// // char +/// assert_eq!("abaaa".find('a'), Some(0)); +/// assert_eq!("abaaa".find('b'), Some(1)); +/// assert_eq!("abaaa".find('c'), None); +/// +/// // &[char] +/// assert_eq!("ab".find(&['b', 'a'][..]), Some(0)); +/// assert_eq!("abaaa".find(&['a', 'z'][..]), Some(0)); +/// assert_eq!("abaaa".find(&['c', 'd'][..]), None); +/// +/// // FnMut(char) -> bool +/// assert_eq!("abcdef_z".find(|ch| ch > 'd' && ch < 'y'), Some(4)); +/// assert_eq!("abcddd_z".find(|ch| ch > 'd' && ch < 'y'), None); +/// ``` +/// +/// [`str::find`]: ../../../std/primitive.str.html#method.find +/// [`str::contains`]: ../../../std/primitive.str.html#method.contains pub trait Pattern<'a>: Sized { /// Associated searcher for this pattern type Searcher: Searcher<'a>; From 6f6620b966ce9ea37d034fa9d184d60b84a9ce02 Mon Sep 17 00:00:00 2001 From: Eden Date: Sun, 7 Jun 2020 11:23:15 +0400 Subject: [PATCH 03/37] Rename "cyclone" to "apple-a7" per changes in upstream LLVM See: https://reviews.llvm.org/D70779 https://reviews.llvm.org/D70779#C1703593NL568 LLVM 10 merged into master at: https://github.com/rust-lang/rust/pull/67759 --- src/librustc_target/spec/aarch64_apple_ios.rs | 2 +- src/librustc_target/spec/aarch64_apple_tvos.rs | 2 +- src/librustc_target/spec/apple_sdk_base.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index eac2c3e6aa40c..1447716ca8484 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+neon,+fp-armv8,+cyclone".to_string(), + features: "+neon,+fp-armv8,+apple-a7".to_string(), eliminate_frame_pointer: false, max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs index f1cd14ffd11a6..21f660ac8b839 100644 --- a/src/librustc_target/spec/aarch64_apple_tvos.rs +++ b/src/librustc_target/spec/aarch64_apple_tvos.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+neon,+fp-armv8,+cyclone".to_string(), + features: "+neon,+fp-armv8,+apple-a7".to_string(), eliminate_frame_pointer: false, max_atomic_width: Some(128), abi_blacklist: super::arm_base::abi_blacklist(), diff --git a/src/librustc_target/spec/apple_sdk_base.rs b/src/librustc_target/spec/apple_sdk_base.rs index c7cff17b1544c..b07c2aef1caca 100644 --- a/src/librustc_target/spec/apple_sdk_base.rs +++ b/src/librustc_target/spec/apple_sdk_base.rs @@ -122,7 +122,7 @@ fn target_cpu(arch: Arch) -> String { match arch { Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher Armv7s => "cortex-a9", - Arm64 => "cyclone", + Arm64 => "apple-a7", I386 => "yonah", X86_64 => "core2", X86_64_macabi => "core2", From fb58b7bc5d0f641bbd03550da042841f527496b3 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 13 May 2020 15:18:50 -0400 Subject: [PATCH 04/37] Add compare-mode=chalk and add a little bit more implementations and fixmes --- src/librustc_middle/traits/chalk.rs | 4 +- .../traits/chalk_fulfill.rs | 6 ++- src/librustc_traits/chalk/db.rs | 33 +++++++++--- src/librustc_traits/chalk/lowering.rs | 51 +++++++++++++++++-- .../coherence/coherence-subtyping.re.stderr | 16 ------ src/test/ui/coherence/coherence-subtyping.rs | 7 +-- ....old.stderr => coherence-subtyping.stderr} | 2 +- src/tools/compiletest/src/common.rs | 3 ++ src/tools/compiletest/src/header.rs | 1 + src/tools/compiletest/src/runtest.rs | 3 ++ 10 files changed, 91 insertions(+), 35 deletions(-) delete mode 100644 src/test/ui/coherence/coherence-subtyping.re.stderr rename src/test/ui/coherence/{coherence-subtyping.old.stderr => coherence-subtyping.stderr} (95%) diff --git a/src/librustc_middle/traits/chalk.rs b/src/librustc_middle/traits/chalk.rs index b963af96f5027..e3ecea69da660 100644 --- a/src/librustc_middle/traits/chalk.rs +++ b/src/librustc_middle/traits/chalk.rs @@ -32,12 +32,10 @@ pub enum RustDefId { RawPtr, Trait(DefId), - Impl(DefId), - FnDef(DefId), - AssocTy(DefId), + Opaque(DefId), } #[derive(Copy, Clone)] diff --git a/src/librustc_trait_selection/traits/chalk_fulfill.rs b/src/librustc_trait_selection/traits/chalk_fulfill.rs index 2d4d582c939b6..cbbff82d35f73 100644 --- a/src/librustc_trait_selection/traits/chalk_fulfill.rs +++ b/src/librustc_trait_selection/traits/chalk_fulfill.rs @@ -87,7 +87,9 @@ fn environment<'tcx>( NodeKind::TraitImpl => { let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl"); - inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk())); + // FIXME(chalk): this has problems because of late-bound regions + //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk())); + inputs.extend(trait_ref.substs.iter()); } // In an inherent impl, we assume that the receiver type and all its @@ -136,6 +138,8 @@ fn in_environment( let environment = match obligation.param_env.def_id { Some(def_id) => environment(infcx.tcx, def_id), None if obligation.param_env.caller_bounds.is_empty() => ty::List::empty(), + // FIXME(chalk): this is hit in ui/where-clauses/where-clause-constraints-are-local-for-trait-impl + // and ui/generics/generic-static-methods _ => bug!("non-empty `ParamEnv` with no def-id"), }; diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index a2aee9b6ef74d..18c690a2f5138 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -168,7 +168,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t }); struct_datum } - RustDefId::Ref(_) => Arc::new(chalk_rust_ir::StructDatum { + RustDefId::Ref(_) | RustDefId::RawPtr => Arc::new(chalk_rust_ir::StructDatum { id: struct_id, binders: chalk_ir::Binders::new( chalk_ir::ParameterKinds::from( @@ -204,7 +204,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t }) } - _ => bug!("Used not struct variant when expecting struct variant."), + v => bug!("Used not struct variant ({:?}) when expecting struct variant.", v), } } @@ -283,6 +283,17 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t RustDefId::Trait(def_id) => def_id, _ => bug!("Did not use `Trait` variant when expecting trait."), }; + // FIXME(chalk): this match can be removed when builtin types supported + match struct_id.0 { + RustDefId::Adt(_) => {} + RustDefId::Str => return false, + RustDefId::Never => return false, + RustDefId::Slice => return false, + RustDefId::Array => return false, + RustDefId::Ref(_) => return false, + RustDefId::RawPtr => return false, + _ => bug!("Did not use `Adt` variant when expecting adt."), + } let adt_def_id: DefId = match struct_id.0 { RustDefId::Adt(def_id) => def_id, _ => bug!("Did not use `Adt` variant when expecting adt."), @@ -347,9 +358,19 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn opaque_ty_data( &self, - _id: chalk_ir::OpaqueTyId>, + opaque_ty_id: chalk_ir::OpaqueTyId>, ) -> Arc>> { - unimplemented!() + // FIXME(chalk): actually lower opaque ty + let hidden_ty = + self.tcx.mk_ty(ty::Tuple(self.tcx.intern_substs(&[]))).lower_into(&self.interner); + let value = chalk_rust_ir::OpaqueTyDatumBound { + hidden_ty, + bounds: chalk_ir::Binders::new(chalk_ir::ParameterKinds::new(&self.interner), vec![]), + }; + Arc::new(chalk_rust_ir::OpaqueTyDatum { + opaque_ty_id, + bound: chalk_ir::Binders::new(chalk_ir::ParameterKinds::new(&self.interner), value), + }) } /// Since Chalk can't handle all Rust types currently, we have to handle @@ -386,7 +407,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t Str | Slice => Some(false), - Trait(_) | Impl(_) | AssocTy(_) => panic!(), + Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), } } _ => None, @@ -416,7 +437,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t } } } - Trait(_) | Impl(_) | AssocTy(_) => panic!(), + Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), } } _ => None, diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 9530b07e47cdb..f8dab07a30b97 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -352,7 +352,11 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { }) .intern(interner) } - Dynamic(_, _) => unimplemented!(), + // FIXME(chalk): add region + Dynamic(predicates, _region) => { + TyData::Dyn(chalk_ir::DynTy { bounds: predicates.lower_into(interner) }) + .intern(interner) + } Closure(_def_id, _) => unimplemented!(), Generator(_def_id, _substs, _) => unimplemented!(), GeneratorWitness(_) => unimplemented!(), @@ -361,7 +365,13 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { apply(chalk_ir::TypeName::Tuple(substs.len()), substs.lower_into(interner)) } Projection(proj) => TyData::Alias(proj.lower_into(interner)).intern(interner), - Opaque(_def_id, _substs) => unimplemented!(), + Opaque(def_id, substs) => { + TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { + opaque_ty_id: chalk_ir::OpaqueTyId(RustDefId::Opaque(def_id)), + substitution: substs.lower_into(interner), + })) + .intern(interner) + } // This should have been done eagerly prior to this, and all Params // should have been substituted to placeholders Param(_) => panic!("Lowering Param when not expected."), @@ -376,7 +386,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { }) .intern(interner), Infer(_infer) => unimplemented!(), - Error => unimplemented!(), + Error => apply(chalk_ir::TypeName::Error, empty()), } } } @@ -401,6 +411,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'t ty::BrEnv => unimplemented!(), }, ReFree(_) => unimplemented!(), + // FIXME(chalk): need to handle ReStatic ReStatic => unimplemented!(), ReVar(_) => unimplemented!(), RePlaceholder(placeholder_region) => { @@ -411,6 +422,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'t .intern(interner) } ReEmpty(_) => unimplemented!(), + // FIXME(chalk): need to handle ReErased ReErased => unimplemented!(), } } @@ -472,6 +484,39 @@ impl<'tcx> LowerInto<'tcx, Option LowerInto<'tcx, chalk_ir::Binders>>> + for Binder<&'tcx ty::List>> +{ + fn lower_into( + self, + interner: &RustInterner<'tcx>, + ) -> chalk_ir::Binders>> { + let (predicates, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, &self); + let where_clauses = predicates.into_iter().map(|predicate| match predicate { + ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id, substs }) => { + chalk_ir::Binders::new( + chalk_ir::ParameterKinds::new(interner), + chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { + trait_id: chalk_ir::TraitId(RustDefId::Trait(*def_id)), + substitution: substs.lower_into(interner), + }), + ) + } + ty::ExistentialPredicate::Projection(_predicate) => unimplemented!(), + ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new( + chalk_ir::ParameterKinds::new(interner), + chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { + trait_id: chalk_ir::TraitId(RustDefId::Trait(*def_id)), + substitution: chalk_ir::Substitution::empty(interner), + }), + ), + }); + let value = chalk_ir::QuantifiedWhereClauses::from(interner, where_clauses); + chalk_ir::Binders::new(binders, value) + } +} + /// To collect bound vars, we have to do two passes. In the first pass, we /// collect all `BoundRegion`s and `ty::Bound`s. In the second pass, we then /// replace `BrNamed` into `BrAnon`. The two separate passes are important, diff --git a/src/test/ui/coherence/coherence-subtyping.re.stderr b/src/test/ui/coherence/coherence-subtyping.re.stderr deleted file mode 100644 index b3c2f4516349e..0000000000000 --- a/src/test/ui/coherence/coherence-subtyping.re.stderr +++ /dev/null @@ -1,16 +0,0 @@ -warning: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:16:1 - | -LL | impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} - | ---------------------------------------------------------- first implementation here -LL | -LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - | - = note: `#[warn(coherence_leak_check)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #56105 - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details - -warning: 1 warning emitted - diff --git a/src/test/ui/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs index f5c1d92411baa..b3ed728a81c06 100644 --- a/src/test/ui/coherence/coherence-subtyping.rs +++ b/src/test/ui/coherence/coherence-subtyping.rs @@ -4,7 +4,6 @@ // Note: This scenario is currently accepted, but as part of the // universe transition (#56105) may eventually become an error. -// revisions: old re // check-pass trait TheTrait { @@ -14,10 +13,8 @@ trait TheTrait { impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - //[re]~^ WARNING conflicting implementation - //[re]~^^ WARNING this was previously accepted by the compiler but is being phased out - //[old]~^^^ WARNING conflicting implementation - //[old]~^^^^ WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING conflicting implementation + //~^^ WARNING this was previously accepted by the compiler but is being phased out } fn main() {} diff --git a/src/test/ui/coherence/coherence-subtyping.old.stderr b/src/test/ui/coherence/coherence-subtyping.stderr similarity index 95% rename from src/test/ui/coherence/coherence-subtyping.old.stderr rename to src/test/ui/coherence/coherence-subtyping.stderr index b3c2f4516349e..7f751a24c75c9 100644 --- a/src/test/ui/coherence/coherence-subtyping.old.stderr +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -1,5 +1,5 @@ warning: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:16:1 + --> $DIR/coherence-subtyping.rs:15:1 | LL | impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} | ---------------------------------------------------------- first implementation here diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 64c0298c1fa4e..703b87634cec3 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -123,6 +123,7 @@ pub enum FailMode { pub enum CompareMode { Nll, Polonius, + Chalk, } impl CompareMode { @@ -130,6 +131,7 @@ impl CompareMode { match *self { CompareMode::Nll => "nll", CompareMode::Polonius => "polonius", + CompareMode::Chalk => "chalk", } } @@ -137,6 +139,7 @@ impl CompareMode { match s.as_str() { "nll" => CompareMode::Nll, "polonius" => CompareMode::Polonius, + "chalk" => CompareMode::Chalk, x => panic!("unknown --compare-mode option: {}", x), } } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 9d1940dd4d6c2..984c7a7c90855 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -857,6 +857,7 @@ impl Config { match self.compare_mode { Some(CompareMode::Nll) => name == "compare-mode-nll", Some(CompareMode::Polonius) => name == "compare-mode-polonius", + Some(CompareMode::Chalk) => name == "compare-mode-chalk", None => false, } || (cfg!(debug_assertions) && name == "debug") || diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4f8cf92b86938..8d92823af99d6 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1962,6 +1962,9 @@ impl<'test> TestCx<'test> { Some(CompareMode::Polonius) => { rustc.args(&["-Zpolonius", "-Zborrowck=mir"]); } + Some(CompareMode::Chalk) => { + rustc.args(&["-Zchalk"]); + } None => {} } From 045dfc020fa1c282af22042c2942a9b2016e3832 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 13 May 2020 16:46:26 -0400 Subject: [PATCH 05/37] Update chalk --- Cargo.lock | 30 ++++++++----------- src/librustc_middle/Cargo.toml | 3 +- src/librustc_middle/traits/chalk.rs | 7 +---- src/librustc_traits/Cargo.toml | 9 ++++-- src/librustc_traits/chalk/db.rs | 42 +++++++++------------------ src/librustc_traits/chalk/lowering.rs | 41 ++++++++++++++++---------- src/librustc_traits/chalk/mod.rs | 10 +++++-- 7 files changed, 69 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07c354a332416..ae7dbeb3ab88d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -428,9 +428,8 @@ dependencies = [ [[package]] name = "chalk-derive" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d4620afad4d4d9e63f915cfa10c930b7a3c9c3ca5cd88dd771ff8e5bf04ea10" +version = "0.10.1-dev" +source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -440,9 +439,8 @@ dependencies = [ [[package]] name = "chalk-engine" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ca6e5cef10197789da0b4ec310eda58da4c55530613b2323432642a97372735" +version = "0.10.1-dev" +source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" dependencies = [ "chalk-macros", "rustc-hash", @@ -450,9 +448,8 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45df5fb6328527f976e8a32c9e1c9970084d937ebe93d0d34f5bbf4231cb956" +version = "0.10.1-dev" +source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" dependencies = [ "chalk-derive", "chalk-engine", @@ -461,18 +458,16 @@ dependencies = [ [[package]] name = "chalk-macros" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e4782d108e420a1fcf94d8a919cf248db33c5071678e87d9c2d4f20ed1feb32" +version = "0.10.1-dev" +source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" dependencies = [ "lazy_static", ] [[package]] name = "chalk-rust-ir" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ec96dbe0ab5fdbadfca4179ec2e1d35f0439c3b53a74988b1aec239c63eb08" +version = "0.10.1-dev" +source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" dependencies = [ "chalk-derive", "chalk-engine", @@ -482,9 +477,8 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb99fa9530f0e101475fb60adc931f51bdea05b4642a48928b814d7f0141a6b" +version = "0.10.1-dev" +source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" dependencies = [ "chalk-derive", "chalk-engine", diff --git a/src/librustc_middle/Cargo.toml b/src/librustc_middle/Cargo.toml index 0c22672d5fb7d..6570fe67b3b0e 100644 --- a/src/librustc_middle/Cargo.toml +++ b/src/librustc_middle/Cargo.toml @@ -30,7 +30,8 @@ rustc_serialize = { path = "../librustc_serialize" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } byteorder = { version = "1.3" } -chalk-ir = "0.10.0" +chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" } +#chalk-ir = "0.10.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_middle/traits/chalk.rs b/src/librustc_middle/traits/chalk.rs index e3ecea69da660..2bd22ee800444 100644 --- a/src/librustc_middle/traits/chalk.rs +++ b/src/librustc_middle/traits/chalk.rs @@ -7,7 +7,6 @@ use chalk_ir::{GoalData, Parameter}; -use rustc_middle::mir::Mutability; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -24,16 +23,12 @@ use std::hash::{Hash, Hasher}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum RustDefId { Adt(DefId), - Str, Never, - Slice, Array, - Ref(Mutability), - RawPtr, + FnDef(DefId), Trait(DefId), Impl(DefId), - FnDef(DefId), AssocTy(DefId), Opaque(DefId), } diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index e485bc2929bdb..f429ab7cd0964 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -16,9 +16,12 @@ rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } -chalk-ir = "0.10.0" -chalk-rust-ir = "0.10.0" -chalk-solve = "0.10.0" +#chalk-ir = "0.10.0" +#chalk-rust-ir = "0.10.0" +#chalk-solve = "0.10.0" +chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" } +chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" } +chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 18c690a2f5138..4320436f1e33c 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -168,41 +168,25 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t }); struct_datum } - RustDefId::Ref(_) | RustDefId::RawPtr => Arc::new(chalk_rust_ir::StructDatum { + RustDefId::Array => Arc::new(chalk_rust_ir::StructDatum { id: struct_id, binders: chalk_ir::Binders::new( chalk_ir::ParameterKinds::from( &self.interner, - vec![ - chalk_ir::ParameterKind::Lifetime(()), - chalk_ir::ParameterKind::Ty(()), - ], + Some(chalk_ir::ParameterKind::Ty(())), ), chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, ), flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, }), - RustDefId::Array | RustDefId::Slice => Arc::new(chalk_rust_ir::StructDatum { + RustDefId::Never | RustDefId::FnDef(_) => Arc::new(chalk_rust_ir::StructDatum { id: struct_id, binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::from( - &self.interner, - Some(chalk_ir::ParameterKind::Ty(())), - ), + chalk_ir::ParameterKinds::new(&self.interner), chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, ), flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, }), - RustDefId::Str | RustDefId::Never | RustDefId::FnDef(_) => { - Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::new(&self.interner), - chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, - ), - flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }) - } v => bug!("Used not struct variant ({:?}) when expecting struct variant.", v), } @@ -286,12 +270,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t // FIXME(chalk): this match can be removed when builtin types supported match struct_id.0 { RustDefId::Adt(_) => {} - RustDefId::Str => return false, RustDefId::Never => return false, - RustDefId::Slice => return false, RustDefId::Array => return false, - RustDefId::Ref(_) => return false, - RustDefId::RawPtr => return false, _ => bug!("Did not use `Adt` variant when expecting adt."), } let adt_def_id: DefId = match struct_id.0 { @@ -388,7 +368,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t chalk_ir::TypeName::Struct(chalk_ir::StructId(rust_def_id)) => { use rustc_middle::traits::ChalkRustDefId::*; match rust_def_id { - Never | Array | RawPtr | FnDef(_) | Ref(_) => Some(true), + Never | Array | FnDef(_) => Some(true), Adt(adt_def_id) => { let adt_def = self.tcx.adt_def(adt_def_id); @@ -405,8 +385,6 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t } } - Str | Slice => Some(false), - Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), } } @@ -421,7 +399,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t chalk_ir::TypeName::Struct(chalk_ir::StructId(rust_def_id)) => { use rustc_middle::traits::ChalkRustDefId::*; match rust_def_id { - Never | RawPtr | Ref(_) | Str | Slice => Some(false), + Never => Some(false), FnDef(_) | Array => Some(true), Adt(adt_def_id) => { let adt_def = self.tcx.adt_def(adt_def_id); @@ -489,6 +467,14 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t }; Some(t) } + + fn is_object_safe(&self, trait_id: chalk_ir::TraitId>) -> bool { + let def_id: DefId = match trait_id.0 { + RustDefId::Trait(def_id) => def_id, + _ => bug!("Did not use `Trait` variant when expecting trait."), + }; + self.tcx.is_object_safe(def_id) + } } /// Creates a `InternalSubsts` that maps each generic parameter to a higher-ranked diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index f8dab07a30b97..a293b10fe5b6d 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -309,7 +309,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { apply(struct_ty(RustDefId::Adt(def.did)), substs.lower_into(interner)) } Foreign(_def_id) => unimplemented!(), - Str => apply(struct_ty(RustDefId::Str), empty()), + Str => apply(chalk_ir::TypeName::Str, empty()), Array(ty, _) => apply( struct_ty(RustDefId::Array), chalk_ir::Substitution::from1( @@ -318,25 +318,36 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ), ), Slice(ty) => apply( - struct_ty(RustDefId::Slice), + chalk_ir::TypeName::Slice, chalk_ir::Substitution::from1( interner, chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), ), ), - RawPtr(_) => apply(struct_ty(RustDefId::RawPtr), empty()), - Ref(region, ty, mutability) => apply( - struct_ty(RustDefId::Ref(mutability)), - chalk_ir::Substitution::from( - interner, - [ - chalk_ir::ParameterKind::Lifetime(region.lower_into(interner)) - .intern(interner), - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), - ] - .iter(), - ), - ), + RawPtr(ptr) => { + let name = match ptr.mutbl { + ast::Mutability::Mut => chalk_ir::TypeName::Raw(chalk_ir::Mutability::Mut), + ast::Mutability::Not => chalk_ir::TypeName::Raw(chalk_ir::Mutability::Not), + }; + apply(name, chalk_ir::Substitution::from1(interner, ptr.ty.lower_into(interner))) + } + Ref(region, ty, mutability) => { + let name = match mutability { + ast::Mutability::Mut => chalk_ir::TypeName::Ref(chalk_ir::Mutability::Mut), + ast::Mutability::Not => chalk_ir::TypeName::Ref(chalk_ir::Mutability::Not), + }; + apply( + name, + chalk_ir::Substitution::from( + interner, + &[ + chalk_ir::ParameterKind::Lifetime(region.lower_into(interner)) + .intern(interner), + chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), + ], + ), + ) + } FnDef(def_id, _) => apply(struct_ty(RustDefId::FnDef(def_id)), empty()), FnPtr(sig) => { let (inputs_and_outputs, binders, _named_regions) = diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs index 4e635b9db0901..02c41898eb9cf 100644 --- a/src/librustc_traits/chalk/mod.rs +++ b/src/librustc_traits/chalk/mod.rs @@ -109,9 +109,11 @@ crate fn evaluate_goal<'tcx>( let kind = match _data { TyData::Apply(_application_ty) => match _application_ty.name { chalk_ir::TypeName::Struct(_struct_id) => match _struct_id.0 { + RustDefId::Adt(_) => unimplemented!(), + RustDefId::Never => unimplemented!(), RustDefId::Array => unimplemented!(), - RustDefId::Slice => unimplemented!(), - _ => unimplemented!(), + RustDefId::FnDef(_) => unimplemented!(), + _ => panic!("Unexpected struct id"), }, chalk_ir::TypeName::Scalar(scalar) => match scalar { chalk_ir::Scalar::Bool => ty::Bool, @@ -138,6 +140,10 @@ crate fn evaluate_goal<'tcx>( }, }, chalk_ir::TypeName::Tuple(_size) => unimplemented!(), + chalk_ir::TypeName::Slice => unimplemented!(), + chalk_ir::TypeName::Raw(_) => unimplemented!(), + chalk_ir::TypeName::Ref(_) => unimplemented!(), + chalk_ir::TypeName::Str => unimplemented!(), chalk_ir::TypeName::OpaqueType(_ty) => unimplemented!(), chalk_ir::TypeName::AssociatedType(_assoc_ty) => unimplemented!(), chalk_ir::TypeName::Error => unimplemented!(), From 6ba003ef0488b9768267d962b695626c4ada11dd Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Tue, 26 May 2020 20:19:19 -0400 Subject: [PATCH 06/37] Update chalk --- Cargo.lock | 71 ++++------- src/librustc_data_structures/Cargo.toml | 2 +- src/librustc_middle/Cargo.toml | 2 +- src/librustc_middle/traits/chalk.rs | 67 ++++++---- src/librustc_traits/Cargo.toml | 5 +- src/librustc_traits/chalk/db.rs | 161 ++++++++++++++---------- src/librustc_traits/chalk/lowering.rs | 58 ++++----- src/librustc_traits/chalk/mod.rs | 46 +++---- 8 files changed, 219 insertions(+), 193 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae7dbeb3ab88d..f7407a5c703f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -426,10 +426,18 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "chalk-base" +version = "0.10.1-dev" +source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" +dependencies = [ + "lazy_static 1.4.0", +] + [[package]] name = "chalk-derive" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" +source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -440,52 +448,33 @@ dependencies = [ [[package]] name = "chalk-engine" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" +source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" dependencies = [ - "chalk-macros", + "chalk-base", + "chalk-derive", + "chalk-ir", "rustc-hash", ] [[package]] name = "chalk-ir" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" -dependencies = [ - "chalk-derive", - "chalk-engine", - "chalk-macros", -] - -[[package]] -name = "chalk-macros" -version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "chalk-rust-ir" -version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" +source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" dependencies = [ + "chalk-base", "chalk-derive", - "chalk-engine", - "chalk-ir", - "chalk-macros", ] [[package]] name = "chalk-solve" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3" +source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" dependencies = [ + "chalk-base", "chalk-derive", "chalk-engine", "chalk-ir", - "chalk-macros", - "chalk-rust-ir", - "ena 0.13.1", + "ena 0.14.0", "itertools 0.9.0", "petgraph", "rustc-hash", @@ -1169,9 +1158,9 @@ dependencies = [ [[package]] name = "fixedbitset" -version = "0.1.9" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" @@ -2358,12 +2347,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "ordermap" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" - [[package]] name = "ordslice" version = "0.3.0" @@ -2534,12 +2517,12 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" dependencies = [ "fixedbitset", - "ordermap", + "indexmap", ] [[package]] @@ -3487,12 +3470,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" -dependencies = [ - "byteorder", -] +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-main" @@ -4361,7 +4341,6 @@ name = "rustc_traits" version = "0.0.0" dependencies = [ "chalk-ir", - "chalk-rust-ir", "chalk-solve", "log", "rustc_ast", diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index bf2ab0787cb70..1c2fb90b2d8b4 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -23,7 +23,7 @@ crossbeam-utils = { version = "0.7", features = ["nightly"] } stable_deref_trait = "1.0.0" rayon = { version = "0.3.0", package = "rustc-rayon" } rayon-core = { version = "0.3.0", package = "rustc-rayon-core" } -rustc-hash = "1.0.1" +rustc-hash = "1.1.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_index = { path = "../librustc_index", package = "rustc_index" } bitflags = "1.2.1" diff --git a/src/librustc_middle/Cargo.toml b/src/librustc_middle/Cargo.toml index 6570fe67b3b0e..8e809e338ea1c 100644 --- a/src/librustc_middle/Cargo.toml +++ b/src/librustc_middle/Cargo.toml @@ -30,7 +30,7 @@ rustc_serialize = { path = "../librustc_serialize" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } byteorder = { version = "1.3" } -chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" } +chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" } #chalk-ir = "0.10.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" diff --git a/src/librustc_middle/traits/chalk.rs b/src/librustc_middle/traits/chalk.rs index 2bd22ee800444..a97b6a3ea3625 100644 --- a/src/librustc_middle/traits/chalk.rs +++ b/src/librustc_middle/traits/chalk.rs @@ -5,8 +5,6 @@ //! its name suggest, is to provide an abstraction boundary for creating //! interned Chalk types. -use chalk_ir::{GoalData, Parameter}; - use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -79,16 +77,19 @@ impl fmt::Debug for RustInterner<'_> { impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { type InternedType = Box>; type InternedLifetime = Box>; - type InternedParameter = Box>; + type InternedConst = Box>; + type InternedConcreteConst = u32; + type InternedGenericArg = Box>; type InternedGoal = Box>; type InternedGoals = Vec>; - type InternedSubstitution = Vec>; + type InternedSubstitution = Vec>; type InternedProgramClause = Box>; type InternedProgramClauses = Vec>; type InternedQuantifiedWhereClauses = Vec>; - type InternedParameterKinds = Vec>; - type InternedCanonicalVarKinds = Vec>; + type InternedVariableKinds = Vec>; + type InternedCanonicalVarKinds = Vec>; type DefId = RustDefId; + type InternedAdtId = RustDefId; type Identifier = (); fn debug_program_clause_implication( @@ -202,25 +203,39 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { &lifetime } - fn intern_parameter( + fn intern_const(&self, constant: chalk_ir::ConstData) -> Self::InternedConst { + Box::new(constant) + } + + fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData { + &constant + } + + fn const_eq( &self, - parameter: chalk_ir::ParameterData, - ) -> Self::InternedParameter { - Box::new(parameter) + _ty: &Self::InternedType, + c1: &Self::InternedConcreteConst, + c2: &Self::InternedConcreteConst, + ) -> bool { + c1 == c2 + } + + fn intern_generic_arg(&self, data: chalk_ir::GenericArgData) -> Self::InternedGenericArg { + Box::new(data) } - fn parameter_data<'a>( + fn generic_arg_data<'a>( &self, - parameter: &'a Self::InternedParameter, - ) -> &'a chalk_ir::ParameterData { - ¶meter + data: &'a Self::InternedGenericArg, + ) -> &'a chalk_ir::GenericArgData { + &data } - fn intern_goal(&self, goal: GoalData) -> Self::InternedGoal { + fn intern_goal(&self, goal: chalk_ir::GoalData) -> Self::InternedGoal { Box::new(goal) } - fn goal_data<'a>(&self, goal: &'a Self::InternedGoal) -> &'a GoalData { + fn goal_data<'a>(&self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData { &goal } @@ -237,7 +252,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { fn intern_substitution( &self, - data: impl IntoIterator, E>>, + data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } @@ -245,7 +260,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { fn substitution_data<'a>( &self, substitution: &'a Self::InternedSubstitution, - ) -> &'a [Parameter] { + ) -> &'a [chalk_ir::GenericArg] { substitution } @@ -291,23 +306,23 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { clauses } - fn intern_parameter_kinds( + fn intern_generic_arg_kinds( &self, - data: impl IntoIterator, E>>, - ) -> Result { + data: impl IntoIterator, E>>, + ) -> Result { data.into_iter().collect::, _>>() } - fn parameter_kinds_data<'a>( + fn variable_kinds_data<'a>( &self, - parameter_kinds: &'a Self::InternedParameterKinds, - ) -> &'a [chalk_ir::ParameterKind<()>] { + parameter_kinds: &'a Self::InternedVariableKinds, + ) -> &'a [chalk_ir::VariableKind] { parameter_kinds } fn intern_canonical_var_kinds( &self, - data: impl IntoIterator, E>>, + data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } @@ -315,7 +330,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { fn canonical_var_kinds_data<'a>( &self, canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, - ) -> &'a [chalk_ir::ParameterKind] { + ) -> &'a [chalk_ir::CanonicalVarKind] { canonical_var_kinds } } diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index f429ab7cd0964..c85cd1765ab43 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -19,9 +19,8 @@ rustc_span = { path = "../librustc_span" } #chalk-ir = "0.10.0" #chalk-rust-ir = "0.10.0" #chalk-solve = "0.10.0" -chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" } -chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" } -chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" } +chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" } +chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 4320436f1e33c..15125c33f1f53 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -38,7 +38,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn associated_ty_data( &self, assoc_type_id: chalk_ir::AssocTypeId>, - ) -> Arc>> { + ) -> Arc>> { let def_id = match assoc_type_id.0 { RustDefId::AssocTy(def_id) => def_id, _ => bug!("Did not use `AssocTy` variant when expecting associated type."), @@ -63,13 +63,13 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .map(|(wc, _)| wc.subst(self.tcx, &bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); - Arc::new(chalk_rust_ir::AssociatedTyDatum { + Arc::new(chalk_solve::rust_ir::AssociatedTyDatum { trait_id: chalk_ir::TraitId(RustDefId::Trait(trait_def_id)), id: assoc_type_id, name: (), binders: chalk_ir::Binders::new( binders, - chalk_rust_ir::AssociatedTyDatumBound { bounds: vec![], where_clauses }, + chalk_solve::rust_ir::AssociatedTyDatumBound { bounds: vec![], where_clauses }, ), }) } @@ -77,7 +77,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn trait_datum( &self, trait_id: chalk_ir::TraitId>, - ) -> Arc>> { + ) -> Arc>> { let def_id = match trait_id.0 { RustDefId::Trait(def_id) => def_id, _ => bug!("Did not use `Trait` variant when expecting trait."), @@ -94,21 +94,21 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let well_known = if self.tcx.lang_items().sized_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_rust_ir::WellKnownTrait::SizedTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::SizedTrait) } else if self.tcx.lang_items().copy_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_rust_ir::WellKnownTrait::CopyTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::CopyTrait) } else if self.tcx.lang_items().clone_trait().map(|t| def_id == t).unwrap_or(false) { - Some(chalk_rust_ir::WellKnownTrait::CloneTrait) + Some(chalk_solve::rust_ir::WellKnownTrait::CloneTrait) } else { None }; - Arc::new(chalk_rust_ir::TraitDatum { + Arc::new(chalk_solve::rust_ir::TraitDatum { id: trait_id, binders: chalk_ir::Binders::new( binders, - chalk_rust_ir::TraitDatumBound { where_clauses }, + chalk_solve::rust_ir::TraitDatumBound { where_clauses }, ), - flags: chalk_rust_ir::TraitFlags { + flags: chalk_solve::rust_ir::TraitFlags { auto: trait_def.has_auto_impl, marker: trait_def.is_marker, upstream: !def_id.is_local(), @@ -121,10 +121,10 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t }) } - fn struct_datum( + fn adt_datum( &self, - struct_id: chalk_ir::StructId>, - ) -> Arc>> { + struct_id: chalk_ir::AdtId>, + ) -> Arc>> { match struct_id.0 { RustDefId::Adt(adt_def_id) => { let adt_def = self.tcx.adt_def(adt_def_id); @@ -155,47 +155,64 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t // FIXME(chalk): handle enums; force_impl_for requires this ty::AdtKind::Enum => vec![], }; - let struct_datum = Arc::new(chalk_rust_ir::StructDatum { + let struct_datum = Arc::new(chalk_solve::rust_ir::AdtDatum { id: struct_id, binders: chalk_ir::Binders::new( binders, - chalk_rust_ir::StructDatumBound { fields, where_clauses }, + chalk_solve::rust_ir::AdtDatumBound { fields, where_clauses }, ), - flags: chalk_rust_ir::StructFlags { + flags: chalk_solve::rust_ir::AdtFlags { upstream: !adt_def_id.is_local(), fundamental: adt_def.is_fundamental(), }, }); struct_datum } - RustDefId::Array => Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::from( - &self.interner, - Some(chalk_ir::ParameterKind::Ty(())), + RustDefId::Array => { + return Arc::new(chalk_solve::rust_ir::AdtDatum { + id: struct_id, + binders: chalk_ir::Binders::new( + chalk_ir::VariableKinds::from( + &self.interner, + Some(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)), + ), + chalk_solve::rust_ir::AdtDatumBound { + fields: vec![], + where_clauses: vec![], + }, + ), + flags: chalk_solve::rust_ir::AdtFlags { upstream: false, fundamental: false }, + }); + } + RustDefId::Never | RustDefId::FnDef(_) => { + return Arc::new(chalk_solve::rust_ir::AdtDatum { + id: struct_id, + binders: chalk_ir::Binders::new( + chalk_ir::VariableKinds::new(&self.interner), + chalk_solve::rust_ir::AdtDatumBound { + fields: vec![], + where_clauses: vec![], + }, ), - chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, - ), - flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }), - RustDefId::Never | RustDefId::FnDef(_) => Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::new(&self.interner), - chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, - ), - flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }), + flags: chalk_solve::rust_ir::AdtFlags { upstream: false, fundamental: false }, + }); + } v => bug!("Used not struct variant ({:?}) when expecting struct variant.", v), } } + fn fn_def_datum( + &self, + _fn_def_id: chalk_ir::FnDefId>, + ) -> Arc>> { + unimplemented!() + } + fn impl_datum( &self, impl_id: chalk_ir::ImplId>, - ) -> Arc>> { + ) -> Arc>> { let def_id = match impl_id.0 { RustDefId::Impl(def_id) => def_id, _ => bug!("Did not use `Impl` variant when expecting impl."), @@ -212,15 +229,15 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); - let value = chalk_rust_ir::ImplDatumBound { + let value = chalk_solve::rust_ir::ImplDatumBound { trait_ref: trait_ref.lower_into(&self.interner), where_clauses, }; - Arc::new(chalk_rust_ir::ImplDatum { - polarity: chalk_rust_ir::Polarity::Positive, + Arc::new(chalk_solve::rust_ir::ImplDatum { + polarity: chalk_solve::rust_ir::Polarity::Positive, binders: chalk_ir::Binders::new(binders, value), - impl_type: chalk_rust_ir::ImplType::Local, + impl_type: chalk_solve::rust_ir::ImplType::Local, associated_ty_value_ids: vec![], }) } @@ -228,7 +245,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn impls_for_trait( &self, trait_id: chalk_ir::TraitId>, - parameters: &[chalk_ir::Parameter>], + parameters: &[chalk_ir::GenericArg>], ) -> Vec>> { let def_id: DefId = match trait_id.0 { RustDefId::Trait(def_id) => def_id, @@ -261,7 +278,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn impl_provided_for( &self, auto_trait_id: chalk_ir::TraitId>, - struct_id: chalk_ir::StructId>, + struct_id: chalk_ir::AdtId>, ) -> bool { let trait_def_id: DefId = match auto_trait_id.0 { RustDefId::Trait(def_id) => def_id, @@ -296,8 +313,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn associated_ty_value( &self, - associated_ty_id: chalk_rust_ir::AssociatedTyValueId>, - ) -> Arc>> { + associated_ty_id: chalk_solve::rust_ir::AssociatedTyValueId>, + ) -> Arc>> { let def_id = match associated_ty_id.0 { RustDefId::AssocTy(def_id) => def_id, _ => bug!("Did not use `AssocTy` variant when expecting associated type."), @@ -315,12 +332,12 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let binders = binders_for(&self.interner, bound_vars); let ty = self.tcx.type_of(def_id); - Arc::new(chalk_rust_ir::AssociatedTyValue { + Arc::new(chalk_solve::rust_ir::AssociatedTyValue { impl_id: chalk_ir::ImplId(RustDefId::Impl(impl_id)), associated_ty_id: chalk_ir::AssocTypeId(RustDefId::AssocTy(def_id)), value: chalk_ir::Binders::new( binders, - chalk_rust_ir::AssociatedTyValueBound { ty: ty.lower_into(&self.interner) }, + chalk_solve::rust_ir::AssociatedTyValueBound { ty: ty.lower_into(&self.interner) }, ), }) } @@ -339,17 +356,17 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn opaque_ty_data( &self, opaque_ty_id: chalk_ir::OpaqueTyId>, - ) -> Arc>> { + ) -> Arc>> { // FIXME(chalk): actually lower opaque ty let hidden_ty = self.tcx.mk_ty(ty::Tuple(self.tcx.intern_substs(&[]))).lower_into(&self.interner); - let value = chalk_rust_ir::OpaqueTyDatumBound { + let value = chalk_solve::rust_ir::OpaqueTyDatumBound { hidden_ty, - bounds: chalk_ir::Binders::new(chalk_ir::ParameterKinds::new(&self.interner), vec![]), + bounds: chalk_ir::Binders::new(chalk_ir::VariableKinds::new(&self.interner), vec![]), }; - Arc::new(chalk_rust_ir::OpaqueTyDatum { + Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { opaque_ty_id, - bound: chalk_ir::Binders::new(chalk_ir::ParameterKinds::new(&self.interner), value), + bound: chalk_ir::Binders::new(chalk_ir::VariableKinds::new(&self.interner), value), }) } @@ -358,14 +375,14 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t /// `None` and eventually this function will be removed. fn force_impl_for( &self, - well_known: chalk_rust_ir::WellKnownTrait, + well_known: chalk_solve::rust_ir::WellKnownTrait, ty: &chalk_ir::TyData>, ) -> Option { use chalk_ir::TyData::*; match well_known { - chalk_rust_ir::WellKnownTrait::SizedTrait => match ty { + chalk_solve::rust_ir::WellKnownTrait::SizedTrait => match ty { Apply(apply) => match apply.name { - chalk_ir::TypeName::Struct(chalk_ir::StructId(rust_def_id)) => { + chalk_ir::TypeName::Adt(chalk_ir::AdtId(rust_def_id)) => { use rustc_middle::traits::ChalkRustDefId::*; match rust_def_id { Never | Array | FnDef(_) => Some(true), @@ -390,13 +407,17 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t } _ => None, }, - Dyn(_) | Alias(_) | Placeholder(_) | Function(_) | InferenceVar(_) + Dyn(_) + | Alias(_) + | Placeholder(_) + | Function(_) + | InferenceVar(_, _) | BoundVar(_) => None, }, - chalk_rust_ir::WellKnownTrait::CopyTrait - | chalk_rust_ir::WellKnownTrait::CloneTrait => match ty { + chalk_solve::rust_ir::WellKnownTrait::CopyTrait + | chalk_solve::rust_ir::WellKnownTrait::CloneTrait => match ty { Apply(apply) => match apply.name { - chalk_ir::TypeName::Struct(chalk_ir::StructId(rust_def_id)) => { + chalk_ir::TypeName::Adt(chalk_ir::AdtId(rust_def_id)) => { use rustc_middle::traits::ChalkRustDefId::*; match rust_def_id { Never => Some(false), @@ -420,10 +441,14 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t } _ => None, }, - Dyn(_) | Alias(_) | Placeholder(_) | Function(_) | InferenceVar(_) + Dyn(_) + | Alias(_) + | Placeholder(_) + | Function(_) + | InferenceVar(_, _) | BoundVar(_) => None, }, - chalk_rust_ir::WellKnownTrait::DropTrait => None, + chalk_solve::rust_ir::WellKnownTrait::DropTrait => None, } } @@ -436,9 +461,9 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn well_known_trait_id( &self, - well_known_trait: chalk_rust_ir::WellKnownTrait, + well_known_trait: chalk_solve::rust_ir::WellKnownTrait, ) -> Option>> { - use chalk_rust_ir::WellKnownTrait::*; + use chalk_solve::rust_ir::WellKnownTrait::*; let t = match well_known_trait { SizedTrait => self .tcx @@ -512,13 +537,17 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { fn binders_for<'tcx>( interner: &RustInterner<'tcx>, bound_vars: SubstsRef<'tcx>, -) -> chalk_ir::ParameterKinds> { - chalk_ir::ParameterKinds::from( +) -> chalk_ir::VariableKinds> { + chalk_ir::VariableKinds::from( interner, bound_vars.iter().map(|arg| match arg.unpack() { - ty::subst::GenericArgKind::Lifetime(_re) => chalk_ir::ParameterKind::Lifetime(()), - ty::subst::GenericArgKind::Type(_ty) => chalk_ir::ParameterKind::Ty(()), - ty::subst::GenericArgKind::Const(_const) => chalk_ir::ParameterKind::Ty(()), + ty::subst::GenericArgKind::Lifetime(_re) => chalk_ir::VariableKind::Lifetime, + ty::subst::GenericArgKind::Type(_ty) => { + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General) + } + ty::subst::GenericArgKind::Const(_const) => { + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General) + } }), ) } diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index a293b10fe5b6d..873ce76d4faa6 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -274,7 +274,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { use TyKind::*; let empty = || chalk_ir::Substitution::empty(interner); - let struct_ty = |def_id| chalk_ir::TypeName::Struct(chalk_ir::StructId(def_id)); + let struct_ty = |def_id| chalk_ir::TypeName::Adt(chalk_ir::AdtId(def_id)); let apply = |name, substitution| { TyData::Apply(chalk_ir::ApplicationTy { name, substitution }).intern(interner) }; @@ -314,14 +314,14 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { struct_ty(RustDefId::Array), chalk_ir::Substitution::from1( interner, - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), ), ), Slice(ty) => apply( chalk_ir::TypeName::Slice, chalk_ir::Substitution::from1( interner, - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), ), ), RawPtr(ptr) => { @@ -341,9 +341,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { chalk_ir::Substitution::from( interner, &[ - chalk_ir::ParameterKind::Lifetime(region.lower_into(interner)) + chalk_ir::GenericArgData::Lifetime(region.lower_into(interner)) .intern(interner), - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner), + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), ], ), ) @@ -357,7 +357,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { substitution: chalk_ir::Substitution::from( interner, inputs_and_outputs.iter().map(|ty| { - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)).intern(interner) + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner) }), ), }) @@ -439,16 +439,16 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'t } } -impl<'tcx> LowerInto<'tcx, chalk_ir::Parameter>> for GenericArg<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Parameter> { +impl<'tcx> LowerInto<'tcx, chalk_ir::GenericArg>> for GenericArg<'tcx> { + fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GenericArg> { match self.unpack() { ty::subst::GenericArgKind::Type(ty) => { - chalk_ir::ParameterKind::Ty(ty.lower_into(interner)) + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)) } ty::subst::GenericArgKind::Lifetime(lifetime) => { - chalk_ir::ParameterKind::Lifetime(lifetime.lower_into(interner)) + chalk_ir::GenericArgData::Lifetime(lifetime.lower_into(interner)) } - ty::subst::GenericArgKind::Const(_) => chalk_ir::ParameterKind::Ty( + ty::subst::GenericArgKind::Const(_) => chalk_ir::GenericArgData::Ty( chalk_ir::TyData::Apply(chalk_ir::ApplicationTy { name: chalk_ir::TypeName::Tuple(0), substitution: chalk_ir::Substitution::empty(interner), @@ -507,7 +507,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders { chalk_ir::Binders::new( - chalk_ir::ParameterKinds::new(interner), + chalk_ir::VariableKinds::new(interner), chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { trait_id: chalk_ir::TraitId(RustDefId::Trait(*def_id)), substitution: substs.lower_into(interner), @@ -516,7 +516,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders unimplemented!(), ty::ExistentialPredicate::AutoTrait(def_id) => chalk_ir::Binders::new( - chalk_ir::ParameterKinds::new(interner), + chalk_ir::VariableKinds::new(interner), chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { trait_id: chalk_ir::TraitId(RustDefId::Trait(*def_id)), substitution: chalk_ir::Substitution::empty(interner), @@ -541,7 +541,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( interner: &RustInterner<'tcx>, tcx: TyCtxt<'tcx>, ty: &'a Binder, -) -> (T, chalk_ir::ParameterKinds>, BTreeMap) { +) -> (T, chalk_ir::VariableKinds>, BTreeMap) { let mut bound_vars_collector = BoundVarsCollector::new(); ty.skip_binder().visit_with(&mut bound_vars_collector); let mut parameters = bound_vars_collector.parameters; @@ -556,25 +556,25 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor); for var in named_parameters.values() { - parameters.insert(*var, chalk_ir::ParameterKind::Lifetime(())); + parameters.insert(*var, chalk_ir::VariableKind::Lifetime); } (0..parameters.len()).for_each(|i| { parameters.get(&(i as u32)).expect("Skipped bound var index."); }); - let binders = chalk_ir::ParameterKinds::from(interner, parameters.into_iter().map(|(_, v)| v)); + let binders = chalk_ir::VariableKinds::from(interner, parameters.into_iter().map(|(_, v)| v)); (new_ty, binders, named_parameters) } -crate struct BoundVarsCollector { +crate struct BoundVarsCollector<'tcx> { binder_index: ty::DebruijnIndex, - crate parameters: BTreeMap>, + crate parameters: BTreeMap>>, crate named_parameters: Vec, } -impl BoundVarsCollector { +impl<'tcx> BoundVarsCollector<'tcx> { crate fn new() -> Self { BoundVarsCollector { binder_index: ty::INNERMOST, @@ -584,7 +584,7 @@ impl BoundVarsCollector { } } -impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector { +impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { fn visit_binder>(&mut self, t: &Binder) -> bool { self.binder_index.shift_in(1); let result = t.super_visit_with(self); @@ -597,11 +597,12 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector { ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { match self.parameters.entry(bound_ty.var.as_u32()) { Entry::Vacant(entry) => { - entry.insert(chalk_ir::ParameterKind::Ty(())); - } - Entry::Occupied(entry) => { - entry.get().assert_ty_ref(); + entry.insert(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)); } + Entry::Occupied(entry) => match entry.get() { + chalk_ir::VariableKind::Ty(_) => {} + _ => panic!(), + }, } } @@ -622,11 +623,12 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector { ty::BoundRegion::BrAnon(var) => match self.parameters.entry(*var) { Entry::Vacant(entry) => { - entry.insert(chalk_ir::ParameterKind::Lifetime(())); - } - Entry::Occupied(entry) => { - entry.get().assert_lifetime_ref(); + entry.insert(chalk_ir::VariableKind::Lifetime); } + Entry::Occupied(entry) => match entry.get() { + chalk_ir::VariableKind::Lifetime => {} + _ => panic!(), + }, }, ty::BrEnv => unimplemented!(), diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs index 02c41898eb9cf..bfaa161f7aa76 100644 --- a/src/librustc_traits/chalk/mod.rs +++ b/src/librustc_traits/chalk/mod.rs @@ -55,25 +55,23 @@ crate fn evaluate_goal<'tcx>( CanonicalVarKind::PlaceholderTy(_ty) => unimplemented!(), CanonicalVarKind::PlaceholderRegion(_ui) => unimplemented!(), CanonicalVarKind::Ty(ty) => match ty { - CanonicalTyVarKind::General(ui) => { - chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex { - counter: ui.index(), - }) - } - CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => { - // FIXME(chalk) - this is actually really important - // These variable kinds put some limits on the - // types that can be substituted (floats or ints). - // While it's unclear exactly the design here, we - // probably want some way to "register" these. - chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::root()) - } + CanonicalTyVarKind::General(ui) => chalk_ir::WithKind::new( + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General), + chalk_ir::UniverseIndex { counter: ui.index() }, + ), + CanonicalTyVarKind::Int => chalk_ir::WithKind::new( + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::Integer), + chalk_ir::UniverseIndex::root(), + ), + CanonicalTyVarKind::Float => chalk_ir::WithKind::new( + chalk_ir::VariableKind::Ty(chalk_ir::TyKind::Float), + chalk_ir::UniverseIndex::root(), + ), }, - CanonicalVarKind::Region(ui) => { - chalk_ir::ParameterKind::Lifetime(chalk_ir::UniverseIndex { - counter: ui.index(), - }) - } + CanonicalVarKind::Region(ui) => chalk_ir::WithKind::new( + chalk_ir::VariableKind::Lifetime, + chalk_ir::UniverseIndex { counter: ui.index() }, + ), CanonicalVarKind::Const(_ui) => unimplemented!(), CanonicalVarKind::PlaceholderConst(_pc) => unimplemented!(), }), @@ -101,14 +99,14 @@ crate fn evaluate_goal<'tcx>( // essentially inverse of lowering a `GenericArg`. let _data = p.data(&interner); match _data { - chalk_ir::ParameterKind::Ty(_t) => { + chalk_ir::GenericArgData::Ty(_t) => { use chalk_ir::TyData; use rustc_ast::ast; let _data = _t.data(&interner); let kind = match _data { TyData::Apply(_application_ty) => match _application_ty.name { - chalk_ir::TypeName::Struct(_struct_id) => match _struct_id.0 { + chalk_ir::TypeName::Adt(_struct_id) => match _struct_id.0 { RustDefId::Adt(_) => unimplemented!(), RustDefId::Never => unimplemented!(), RustDefId::Array => unimplemented!(), @@ -139,6 +137,9 @@ crate fn evaluate_goal<'tcx>( chalk_ir::FloatTy::F64 => ty::Float(ast::FloatTy::F64), }, }, + chalk_ir::TypeName::Array => unimplemented!(), + chalk_ir::TypeName::FnDef(_) => unimplemented!(), + chalk_ir::TypeName::Never => unimplemented!(), chalk_ir::TypeName::Tuple(_size) => unimplemented!(), chalk_ir::TypeName::Slice => unimplemented!(), chalk_ir::TypeName::Raw(_) => unimplemented!(), @@ -160,14 +161,14 @@ crate fn evaluate_goal<'tcx>( kind: ty::BoundTyKind::Anon, }, ), - TyData::InferenceVar(_) => unimplemented!(), + TyData::InferenceVar(_, _) => unimplemented!(), TyData::Dyn(_) => unimplemented!(), }; let _ty: Ty<'_> = tcx.mk_ty(kind); let _arg: GenericArg<'_> = _ty.into(); var_values.push(_arg); } - chalk_ir::ParameterKind::Lifetime(_l) => { + chalk_ir::GenericArgData::Lifetime(_l) => { let _data = _l.data(&interner); let _lifetime: Region<'_> = match _data { chalk_ir::LifetimeData::BoundVar(_var) => { @@ -185,6 +186,7 @@ crate fn evaluate_goal<'tcx>( let _arg: GenericArg<'_> = _lifetime.into(); var_values.push(_arg); } + chalk_ir::GenericArgData::Const(_) => unimplemented!(), } }); let sol = Canonical { From 3d730308d3db132fb6ac724c99c6a23a6e90bce8 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Tue, 26 May 2020 20:38:41 -0400 Subject: [PATCH 07/37] Use builtin types for Never, Array, and FnDef --- src/librustc_middle/traits/chalk.rs | 4 +-- src/librustc_traits/chalk/db.rs | 39 ++------------------------- src/librustc_traits/chalk/lowering.rs | 25 +++++++++++++---- src/librustc_traits/chalk/mod.rs | 3 --- 4 files changed, 23 insertions(+), 48 deletions(-) diff --git a/src/librustc_middle/traits/chalk.rs b/src/librustc_middle/traits/chalk.rs index a97b6a3ea3625..ec32bcf8a0b67 100644 --- a/src/librustc_middle/traits/chalk.rs +++ b/src/librustc_middle/traits/chalk.rs @@ -21,10 +21,8 @@ use std::hash::{Hash, Hasher}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum RustDefId { Adt(DefId), - Never, - Array, - FnDef(DefId), + FnDef(DefId), Trait(DefId), Impl(DefId), AssocTy(DefId), diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 15125c33f1f53..367c598027934 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -168,35 +168,6 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t }); struct_datum } - RustDefId::Array => { - return Arc::new(chalk_solve::rust_ir::AdtDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::VariableKinds::from( - &self.interner, - Some(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)), - ), - chalk_solve::rust_ir::AdtDatumBound { - fields: vec![], - where_clauses: vec![], - }, - ), - flags: chalk_solve::rust_ir::AdtFlags { upstream: false, fundamental: false }, - }); - } - RustDefId::Never | RustDefId::FnDef(_) => { - return Arc::new(chalk_solve::rust_ir::AdtDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::VariableKinds::new(&self.interner), - chalk_solve::rust_ir::AdtDatumBound { - fields: vec![], - where_clauses: vec![], - }, - ), - flags: chalk_solve::rust_ir::AdtFlags { upstream: false, fundamental: false }, - }); - } v => bug!("Used not struct variant ({:?}) when expecting struct variant.", v), } @@ -287,8 +258,6 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t // FIXME(chalk): this match can be removed when builtin types supported match struct_id.0 { RustDefId::Adt(_) => {} - RustDefId::Never => return false, - RustDefId::Array => return false, _ => bug!("Did not use `Adt` variant when expecting adt."), } let adt_def_id: DefId = match struct_id.0 { @@ -385,8 +354,6 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t chalk_ir::TypeName::Adt(chalk_ir::AdtId(rust_def_id)) => { use rustc_middle::traits::ChalkRustDefId::*; match rust_def_id { - Never | Array | FnDef(_) => Some(true), - Adt(adt_def_id) => { let adt_def = self.tcx.adt_def(adt_def_id); match adt_def.adt_kind() { @@ -402,7 +369,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t } } - Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), + FnDef(_) | Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), } } _ => None, @@ -420,8 +387,6 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t chalk_ir::TypeName::Adt(chalk_ir::AdtId(rust_def_id)) => { use rustc_middle::traits::ChalkRustDefId::*; match rust_def_id { - Never => Some(false), - FnDef(_) | Array => Some(true), Adt(adt_def_id) => { let adt_def = self.tcx.adt_def(adt_def_id); match adt_def.adt_kind() { @@ -436,7 +401,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t } } } - Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), + FnDef(_) | Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), } } _ => None, diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 873ce76d4faa6..57ef6ec0a25aa 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -311,10 +311,22 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { Foreign(_def_id) => unimplemented!(), Str => apply(chalk_ir::TypeName::Str, empty()), Array(ty, _) => apply( - struct_ty(RustDefId::Array), - chalk_ir::Substitution::from1( + chalk_ir::TypeName::Array, + chalk_ir::Substitution::from( interner, - chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), + &[ + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), + chalk_ir::GenericArgData::Const( + chalk_ir::ConstData { + ty: apply(chalk_ir::TypeName::Tuple(0), empty()), + value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { + interned: 0, + }), + } + .intern(interner), + ) + .intern(interner), + ], ), ), Slice(ty) => apply( @@ -348,7 +360,10 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ), ) } - FnDef(def_id, _) => apply(struct_ty(RustDefId::FnDef(def_id)), empty()), + FnDef(def_id, _) => apply( + chalk_ir::TypeName::FnDef(chalk_ir::FnDefId(RustDefId::FnDef(def_id))), + empty(), + ), FnPtr(sig) => { let (inputs_and_outputs, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, &sig.inputs_and_output()); @@ -371,7 +386,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { Closure(_def_id, _) => unimplemented!(), Generator(_def_id, _substs, _) => unimplemented!(), GeneratorWitness(_) => unimplemented!(), - Never => apply(struct_ty(RustDefId::Never), empty()), + Never => apply(chalk_ir::TypeName::Never, empty()), Tuple(substs) => { apply(chalk_ir::TypeName::Tuple(substs.len()), substs.lower_into(interner)) } diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs index bfaa161f7aa76..f33ec3a9fb915 100644 --- a/src/librustc_traits/chalk/mod.rs +++ b/src/librustc_traits/chalk/mod.rs @@ -108,9 +108,6 @@ crate fn evaluate_goal<'tcx>( TyData::Apply(_application_ty) => match _application_ty.name { chalk_ir::TypeName::Adt(_struct_id) => match _struct_id.0 { RustDefId::Adt(_) => unimplemented!(), - RustDefId::Never => unimplemented!(), - RustDefId::Array => unimplemented!(), - RustDefId::FnDef(_) => unimplemented!(), _ => panic!("Unexpected struct id"), }, chalk_ir::TypeName::Scalar(scalar) => match scalar { From 2544b8c30a76ff0f07d44619d2d8b6e3c2035c8f Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 27 May 2020 01:05:09 -0400 Subject: [PATCH 08/37] Implement fn_def_datum --- Cargo.lock | 27 ++++++----------- src/librustc_middle/Cargo.toml | 2 +- src/librustc_traits/Cargo.toml | 4 +-- src/librustc_traits/chalk/db.rs | 34 ++++++++++++++++++++-- src/librustc_traits/chalk/lowering.rs | 21 ++++--------- src/test/ui/chalkify/impl_wf.rs | 7 ++--- src/test/ui/chalkify/impl_wf.stderr | 16 ++++++++-- src/test/ui/chalkify/type_inference.rs | 4 +-- src/test/ui/chalkify/type_inference.stderr | 13 +++++++-- src/test/ui/chalkify/type_wf.rs | 11 ++----- src/test/ui/chalkify/type_wf.stderr | 12 ++++++++ src/tools/tidy/src/deps.rs | 3 +- 12 files changed, 93 insertions(+), 61 deletions(-) create mode 100644 src/test/ui/chalkify/type_wf.stderr diff --git a/Cargo.lock b/Cargo.lock index f7407a5c703f1..8792434e52b7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,15 +429,15 @@ dependencies = [ [[package]] name = "chalk-base" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" +source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" dependencies = [ - "lazy_static 1.4.0", + "lazy_static", ] [[package]] name = "chalk-derive" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" +source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -448,7 +448,7 @@ dependencies = [ [[package]] name = "chalk-engine" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" +source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" dependencies = [ "chalk-base", "chalk-derive", @@ -459,7 +459,7 @@ dependencies = [ [[package]] name = "chalk-ir" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" +source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" dependencies = [ "chalk-base", "chalk-derive", @@ -468,13 +468,13 @@ dependencies = [ [[package]] name = "chalk-solve" version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=f4977ab4c781e4f3b7fdb9310edbdab6daf56e29#f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" +source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" dependencies = [ "chalk-base", "chalk-derive", "chalk-engine", "chalk-ir", - "ena 0.14.0", + "ena", "itertools 0.9.0", "petgraph", "rustc-hash", @@ -1038,15 +1038,6 @@ dependencies = [ "strum_macros", ] -[[package]] -name = "ena" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" -dependencies = [ - "log", -] - [[package]] name = "ena" version = "0.14.0" @@ -3267,7 +3258,7 @@ dependencies = [ "bitflags", "cfg-if", "crossbeam-utils 0.7.2", - "ena 0.14.0", + "ena", "indexmap", "jobserver", "lazy_static", @@ -3723,7 +3714,7 @@ dependencies = [ "bitflags", "cfg-if", "crossbeam-utils 0.7.2", - "ena 0.14.0", + "ena", "indexmap", "jobserver", "lazy_static", diff --git a/src/librustc_middle/Cargo.toml b/src/librustc_middle/Cargo.toml index 8e809e338ea1c..34dece1a2ad7e 100644 --- a/src/librustc_middle/Cargo.toml +++ b/src/librustc_middle/Cargo.toml @@ -30,7 +30,7 @@ rustc_serialize = { path = "../librustc_serialize" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } byteorder = { version = "1.3" } -chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" } +chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" } #chalk-ir = "0.10.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index c85cd1765ab43..cb056dba9eab8 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -19,8 +19,8 @@ rustc_span = { path = "../librustc_span" } #chalk-ir = "0.10.0" #chalk-rust-ir = "0.10.0" #chalk-solve = "0.10.0" -chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" } -chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "f4977ab4c781e4f3b7fdb9310edbdab6daf56e29" } +chalk-solve = { git = "https://github.com/jackh726/chalk.git", rev = "58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" } +chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 367c598027934..95a6f45f92fa8 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -175,9 +175,39 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn fn_def_datum( &self, - _fn_def_id: chalk_ir::FnDefId>, + fn_def_id: chalk_ir::FnDefId>, ) -> Arc>> { - unimplemented!() + let def_id = match fn_def_id.0 { + RustDefId::FnDef(def_id) => def_id, + _ => bug!("Did not use `FnDef` variant when expecting FnDef."), + }; + let bound_vars = bound_vars_for_item(self.tcx, def_id); + let binders = binders_for(&self.interner, bound_vars); + + let predicates = self.tcx.predicates_defined_on(def_id).predicates; + let where_clauses: Vec<_> = predicates + .into_iter() + .map(|(wc, _)| wc.subst(self.tcx, &bound_vars)) + .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); + + let sig = self.tcx.fn_sig(def_id); + // FIXME(chalk): Why does this have a Binder + let argument_types = sig + .inputs() + .skip_binder() + .iter() + .map(|t| t.subst(self.tcx, &bound_vars).lower_into(&self.interner)) + .collect(); + + let return_type = + sig.output().skip_binder().subst(self.tcx, &bound_vars).lower_into(&self.interner); + + let bound = + chalk_solve::rust_ir::FnDefDatumBound { argument_types, where_clauses, return_type }; + Arc::new(chalk_solve::rust_ir::FnDefDatum { + id: fn_def_id, + binders: chalk_ir::Binders::new(binders, bound), + }) } fn impl_datum( diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 57ef6ec0a25aa..58ea740193860 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -167,20 +167,11 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi ty::PredicateKind::Projection(predicate) => predicate.lower_into(interner), ty::PredicateKind::WellFormed(arg) => match arg.unpack() { GenericArgKind::Type(ty) => match ty.kind { - // These types are always WF. - ty::Str | ty::Placeholder(..) | ty::Error | ty::Never => { - chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)) - } - - // FIXME(chalk): Well-formed only if ref lifetime outlives type - ty::Ref(..) => chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)), - - ty::Param(..) => panic!("No Params expected."), + // FIXME(chalk): In Chalk, a placeholder is WellFormed if it + // `FromEnv`. However, when we "lower" Params, we don't update + // the environment. + ty::Placeholder(..) => chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)), - // FIXME(chalk) -- ultimately I think this is what we - // want to do, and we just have rules for how to prove - // `WellFormed` for everything above, instead of - // inlining a bit the rules of the proof here. _ => chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::WellFormed( chalk_ir::WellFormed::Ty(ty.lower_into(interner)), )), @@ -360,9 +351,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ), ) } - FnDef(def_id, _) => apply( + FnDef(def_id, substs) => apply( chalk_ir::TypeName::FnDef(chalk_ir::FnDefId(RustDefId::FnDef(def_id))), - empty(), + substs.lower_into(interner), ), FnPtr(sig) => { let (inputs_and_outputs, binders, _named_regions) = diff --git a/src/test/ui/chalkify/impl_wf.rs b/src/test/ui/chalkify/impl_wf.rs index 8aa876422924d..fdc94f69bf21a 100644 --- a/src/test/ui/chalkify/impl_wf.rs +++ b/src/test/ui/chalkify/impl_wf.rs @@ -8,12 +8,9 @@ trait Bar { impl Foo for i32 { } -// FIXME(chalk): blocked on better handling of builtin traits for non-struct -// application types (or a workaround) -/* impl Foo for str { } -//^ ERROR the size for values of type `str` cannot be known at compilation time -*/ +//~^ ERROR the size for values of type `str` cannot be known at compilation time + // Implicit `T: Sized` bound. impl Foo for Option { } diff --git a/src/test/ui/chalkify/impl_wf.stderr b/src/test/ui/chalkify/impl_wf.stderr index befd688741c80..5293bbaecd389 100644 --- a/src/test/ui/chalkify/impl_wf.stderr +++ b/src/test/ui/chalkify/impl_wf.stderr @@ -1,5 +1,17 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/impl_wf.rs:11:6 + | +LL | trait Foo: Sized { } + | ----- required by this bound in `Foo` +... +LL | impl Foo for str { } + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `str` + = note: to learn more, visit + error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/impl_wf.rs:43:6 + --> $DIR/impl_wf.rs:40:6 | LL | trait Baz where U: Foo { } | --- required by this bound in `Baz` @@ -7,6 +19,6 @@ LL | trait Baz where U: Foo { } LL | impl Baz for f32 { } | ^^^^^^^^ the trait `Foo` is not implemented for `f32` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs index 5175c5d062a6e..171969afc7f22 100644 --- a/src/test/ui/chalkify/type_inference.rs +++ b/src/test/ui/chalkify/type_inference.rs @@ -18,11 +18,9 @@ fn main() { // is expecting a variable of type `i32`. This behavior differs from the // old-style trait solver. I guess this will change, that's why I'm // adding that test. - // FIXME(chalk): partially blocked on float/int special casing only_foo(x); //~ ERROR the trait bound `f64: Foo` is not satisfied // Here we have two solutions so we get back the behavior of the old-style // trait solver. - // FIXME(chalk): blocked on float/int special casing - //only_bar(x); // ERROR the trait bound `{float}: Bar` is not satisfied + only_bar(x); //~ ERROR the trait bound `f64: Bar` is not satisfied } diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index ee9e67c6c7884..476759292642b 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `f64: Foo` is not satisfied - --> $DIR/type_inference.rs:22:5 + --> $DIR/type_inference.rs:21:5 | LL | fn only_foo(_x: T) { } | --- required by this bound in `only_foo` @@ -7,6 +7,15 @@ LL | fn only_foo(_x: T) { } LL | only_foo(x); | ^^^^^^^^ the trait `Foo` is not implemented for `f64` -error: aborting due to previous error +error[E0277]: the trait bound `f64: Bar` is not satisfied + --> $DIR/type_inference.rs:25:5 + | +LL | fn only_bar(_x: T) { } + | --- required by this bound in `only_bar` +... +LL | only_bar(x); + | ^^^^^^^^ the trait `Bar` is not implemented for `f64` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/chalkify/type_wf.rs b/src/test/ui/chalkify/type_wf.rs index 396baf814a0b0..7c469d99c5799 100644 --- a/src/test/ui/chalkify/type_wf.rs +++ b/src/test/ui/chalkify/type_wf.rs @@ -1,5 +1,4 @@ -// FIXME(chalk): should have an error, see below -// check-pass +// check-fail // compile-flags: -Z chalk trait Foo { } @@ -16,17 +15,11 @@ fn main() { x: 5, }; - // FIXME(chalk): blocked on float/int special handling. Needs to know that {float}: !i32 - /* - let s = S { // ERROR the trait bound `{float}: Foo` is not satisfied + let s = S { //~ ERROR the trait bound `f64: Foo` is not satisfied x: 5.0, }; - */ - // FIXME(chalk): blocked on float/int special handling. Needs to know that {float}: Sized - /* let s = S { x: Some(5.0), }; - */ } diff --git a/src/test/ui/chalkify/type_wf.stderr b/src/test/ui/chalkify/type_wf.stderr new file mode 100644 index 0000000000000..ab585a6ed2140 --- /dev/null +++ b/src/test/ui/chalkify/type_wf.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `f64: Foo` is not satisfied + --> $DIR/type_wf.rs:18:13 + | +LL | struct S { + | ---------------- required by `S` +... +LL | let s = S { + | ^ the trait `Foo` is not implemented for `f64` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index c08f02b972e8f..aec6b5d25235e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -79,10 +79,9 @@ const WHITELIST: &[&str] = &[ "byteorder", "cc", "cfg-if", + "chalk-base", "chalk-derive", - "chalk-engine", "chalk-ir", - "chalk-macros", "cloudabi", "cmake", "compiler_builtins", From 7f2708cf84f9f086cf78d6e930c4b6eb5271e91f Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 27 May 2020 01:26:51 -0400 Subject: [PATCH 09/37] Remove RustDefId --- src/librustc_middle/traits/chalk.rs | 17 +- src/librustc_middle/traits/mod.rs | 3 +- src/librustc_traits/chalk/db.rs | 223 +++++++++----------------- src/librustc_traits/chalk/lowering.rs | 19 +-- src/librustc_traits/chalk/mod.rs | 7 +- 5 files changed, 86 insertions(+), 183 deletions(-) diff --git a/src/librustc_middle/traits/chalk.rs b/src/librustc_middle/traits/chalk.rs index ec32bcf8a0b67..9ce6cc3a51114 100644 --- a/src/librustc_middle/traits/chalk.rs +++ b/src/librustc_middle/traits/chalk.rs @@ -16,19 +16,6 @@ use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; -/// Since Chalk doesn't have full support for all Rust builtin types yet, we -/// need to use an enum here, rather than just `DefId`. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum RustDefId { - Adt(DefId), - - FnDef(DefId), - Trait(DefId), - Impl(DefId), - AssocTy(DefId), - Opaque(DefId), -} - #[derive(Copy, Clone)] pub struct RustInterner<'tcx> { pub tcx: TyCtxt<'tcx>, @@ -86,8 +73,8 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { type InternedQuantifiedWhereClauses = Vec>; type InternedVariableKinds = Vec>; type InternedCanonicalVarKinds = Vec>; - type DefId = RustDefId; - type InternedAdtId = RustDefId; + type DefId = DefId; + type InternedAdtId = DefId; type Identifier = (); fn debug_program_clause_implication( diff --git a/src/librustc_middle/traits/mod.rs b/src/librustc_middle/traits/mod.rs index 9afab5a4d2fe9..cad0187af87bc 100644 --- a/src/librustc_middle/traits/mod.rs +++ b/src/librustc_middle/traits/mod.rs @@ -32,8 +32,7 @@ pub use self::SelectionError::*; pub use self::Vtable::*; pub use self::chalk::{ - ChalkEnvironmentAndGoal, ChalkEnvironmentClause, RustDefId as ChalkRustDefId, - RustInterner as ChalkRustInterner, + ChalkEnvironmentAndGoal, ChalkEnvironmentClause, RustInterner as ChalkRustInterner, }; /// Depending on the stage of compilation, we want projection to be diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 95a6f45f92fa8..818839e2e3b33 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -6,7 +6,7 @@ //! either the `TyCtxt` (for information about types) or //! `crate::chalk::lowering` (to lower rustc types into Chalk types). -use rustc_middle::traits::{ChalkRustDefId as RustDefId, ChalkRustInterner as RustInterner}; +use rustc_middle::traits::ChalkRustInterner as RustInterner; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::{self, AssocItemContainer, AssocKind, TyCtxt}; @@ -39,10 +39,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t &self, assoc_type_id: chalk_ir::AssocTypeId>, ) -> Arc>> { - let def_id = match assoc_type_id.0 { - RustDefId::AssocTy(def_id) => def_id, - _ => bug!("Did not use `AssocTy` variant when expecting associated type."), - }; + let def_id = assoc_type_id.0; let assoc_item = self.tcx.associated_item(def_id); let trait_def_id = match assoc_item.container { AssocItemContainer::TraitContainer(def_id) => def_id, @@ -64,7 +61,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); Arc::new(chalk_solve::rust_ir::AssociatedTyDatum { - trait_id: chalk_ir::TraitId(RustDefId::Trait(trait_def_id)), + trait_id: chalk_ir::TraitId(trait_def_id), id: assoc_type_id, name: (), binders: chalk_ir::Binders::new( @@ -78,10 +75,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t &self, trait_id: chalk_ir::TraitId>, ) -> Arc>> { - let def_id = match trait_id.0 { - RustDefId::Trait(def_id) => def_id, - _ => bug!("Did not use `Trait` variant when expecting trait."), - }; + let def_id = trait_id.0; let trait_def = self.tcx.trait_def(def_id); let bound_vars = bound_vars_for_item(self.tcx, def_id); @@ -125,62 +119,54 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t &self, struct_id: chalk_ir::AdtId>, ) -> Arc>> { - match struct_id.0 { - RustDefId::Adt(adt_def_id) => { - let adt_def = self.tcx.adt_def(adt_def_id); + let adt_def_id = struct_id.0; + let adt_def = self.tcx.adt_def(adt_def_id); - let bound_vars = bound_vars_for_item(self.tcx, adt_def_id); - let binders = binders_for(&self.interner, bound_vars); + let bound_vars = bound_vars_for_item(self.tcx, adt_def_id); + let binders = binders_for(&self.interner, bound_vars); - let predicates = self.tcx.predicates_of(adt_def_id).predicates; - let where_clauses: Vec<_> = predicates + let predicates = self.tcx.predicates_of(adt_def_id).predicates; + let where_clauses: Vec<_> = predicates + .into_iter() + .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) + .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)) + .collect(); + let fields = match adt_def.adt_kind() { + ty::AdtKind::Struct | ty::AdtKind::Union => { + let variant = adt_def.non_enum_variant(); + variant + .fields .iter() - .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) - .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)) - .collect(); - let fields = match adt_def.adt_kind() { - ty::AdtKind::Struct | ty::AdtKind::Union => { - let variant = adt_def.non_enum_variant(); - variant - .fields - .iter() - .map(|field| { - self.tcx - .type_of(field.did) - .subst(self.tcx, bound_vars) - .lower_into(&self.interner) - }) - .collect() - } - // FIXME(chalk): handle enums; force_impl_for requires this - ty::AdtKind::Enum => vec![], - }; - let struct_datum = Arc::new(chalk_solve::rust_ir::AdtDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - binders, - chalk_solve::rust_ir::AdtDatumBound { fields, where_clauses }, - ), - flags: chalk_solve::rust_ir::AdtFlags { - upstream: !adt_def_id.is_local(), - fundamental: adt_def.is_fundamental(), - }, - }); - struct_datum + .map(|field| { + self.tcx + .type_of(field.did) + .subst(self.tcx, bound_vars) + .lower_into(&self.interner) + }) + .collect() } - - v => bug!("Used not struct variant ({:?}) when expecting struct variant.", v), - } + // FIXME(chalk): handle enums; force_impl_for requires this + ty::AdtKind::Enum => vec![], + }; + let struct_datum = Arc::new(chalk_solve::rust_ir::AdtDatum { + id: struct_id, + binders: chalk_ir::Binders::new( + binders, + chalk_solve::rust_ir::AdtDatumBound { fields, where_clauses }, + ), + flags: chalk_solve::rust_ir::AdtFlags { + upstream: !adt_def_id.is_local(), + fundamental: adt_def.is_fundamental(), + }, + }); + return struct_datum; } fn fn_def_datum( &self, fn_def_id: chalk_ir::FnDefId>, ) -> Arc>> { - let def_id = match fn_def_id.0 { - RustDefId::FnDef(def_id) => def_id, - _ => bug!("Did not use `FnDef` variant when expecting FnDef."), - }; + let def_id = fn_def_id.0; let bound_vars = bound_vars_for_item(self.tcx, def_id); let binders = binders_for(&self.interner, bound_vars); @@ -214,10 +200,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t &self, impl_id: chalk_ir::ImplId>, ) -> Arc>> { - let def_id = match impl_id.0 { - RustDefId::Impl(def_id) => def_id, - _ => bug!("Did not use `Impl` variant when expecting impl."), - }; + let def_id = impl_id.0; let bound_vars = bound_vars_for_item(self.tcx, def_id); let binders = binders_for(&self.interner, bound_vars); @@ -248,10 +231,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t trait_id: chalk_ir::TraitId>, parameters: &[chalk_ir::GenericArg>], ) -> Vec>> { - let def_id: DefId = match trait_id.0 { - RustDefId::Trait(def_id) => def_id, - _ => bug!("Did not use `Trait` variant when expecting trait."), - }; + let def_id = trait_id.0; // FIXME(chalk): use TraitDef::for_each_relevant_impl, but that will // require us to be able to interconvert `Ty<'tcx>`, and we're @@ -270,9 +250,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t parameters[0].assert_ty_ref(&self.interner).could_match(&self.interner, &lowered_ty) }); - let impls = matched_impls - .map(|matched_impl| chalk_ir::ImplId(RustDefId::Impl(matched_impl))) - .collect(); + let impls = matched_impls.map(|matched_impl| chalk_ir::ImplId(matched_impl)).collect(); impls } @@ -281,19 +259,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t auto_trait_id: chalk_ir::TraitId>, struct_id: chalk_ir::AdtId>, ) -> bool { - let trait_def_id: DefId = match auto_trait_id.0 { - RustDefId::Trait(def_id) => def_id, - _ => bug!("Did not use `Trait` variant when expecting trait."), - }; - // FIXME(chalk): this match can be removed when builtin types supported - match struct_id.0 { - RustDefId::Adt(_) => {} - _ => bug!("Did not use `Adt` variant when expecting adt."), - } - let adt_def_id: DefId = match struct_id.0 { - RustDefId::Adt(def_id) => def_id, - _ => bug!("Did not use `Adt` variant when expecting adt."), - }; + let trait_def_id = auto_trait_id.0; + let adt_def_id = struct_id.0; let all_impls = self.tcx.all_impls(trait_def_id); for impl_def_id in all_impls { let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); @@ -314,10 +281,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t &self, associated_ty_id: chalk_solve::rust_ir::AssociatedTyValueId>, ) -> Arc>> { - let def_id = match associated_ty_id.0 { - RustDefId::AssocTy(def_id) => def_id, - _ => bug!("Did not use `AssocTy` variant when expecting associated type."), - }; + let def_id = associated_ty_id.0; let assoc_item = self.tcx.associated_item(def_id); let impl_id = match assoc_item.container { AssocItemContainer::TraitContainer(def_id) => def_id, @@ -332,8 +296,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let ty = self.tcx.type_of(def_id); Arc::new(chalk_solve::rust_ir::AssociatedTyValue { - impl_id: chalk_ir::ImplId(RustDefId::Impl(impl_id)), - associated_ty_id: chalk_ir::AssocTypeId(RustDefId::AssocTy(def_id)), + impl_id: chalk_ir::ImplId(impl_id), + associated_ty_id: chalk_ir::AssocTypeId(def_id), value: chalk_ir::Binders::new( binders, chalk_solve::rust_ir::AssociatedTyValueBound { ty: ty.lower_into(&self.interner) }, @@ -381,25 +345,14 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t match well_known { chalk_solve::rust_ir::WellKnownTrait::SizedTrait => match ty { Apply(apply) => match apply.name { - chalk_ir::TypeName::Adt(chalk_ir::AdtId(rust_def_id)) => { - use rustc_middle::traits::ChalkRustDefId::*; - match rust_def_id { - Adt(adt_def_id) => { - let adt_def = self.tcx.adt_def(adt_def_id); - match adt_def.adt_kind() { - ty::AdtKind::Struct | ty::AdtKind::Union => None, - ty::AdtKind::Enum => { - let constraint = self.tcx.adt_sized_constraint(adt_def_id); - if !constraint.0.is_empty() { - unimplemented!() - } else { - Some(true) - } - } - } + chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def_id)) => { + let adt_def = self.tcx.adt_def(adt_def_id); + match adt_def.adt_kind() { + ty::AdtKind::Struct | ty::AdtKind::Union => None, + ty::AdtKind::Enum => { + let constraint = self.tcx.adt_sized_constraint(adt_def_id); + if constraint.0.len() > 0 { unimplemented!() } else { Some(true) } } - - FnDef(_) | Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), } } _ => None, @@ -414,24 +367,14 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t chalk_solve::rust_ir::WellKnownTrait::CopyTrait | chalk_solve::rust_ir::WellKnownTrait::CloneTrait => match ty { Apply(apply) => match apply.name { - chalk_ir::TypeName::Adt(chalk_ir::AdtId(rust_def_id)) => { - use rustc_middle::traits::ChalkRustDefId::*; - match rust_def_id { - Adt(adt_def_id) => { - let adt_def = self.tcx.adt_def(adt_def_id); - match adt_def.adt_kind() { - ty::AdtKind::Struct | ty::AdtKind::Union => None, - ty::AdtKind::Enum => { - let constraint = self.tcx.adt_sized_constraint(adt_def_id); - if !constraint.0.is_empty() { - unimplemented!() - } else { - Some(true) - } - } - } + chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def_id)) => { + let adt_def = self.tcx.adt_def(adt_def_id); + match adt_def.adt_kind() { + ty::AdtKind::Struct | ty::AdtKind::Union => None, + ty::AdtKind::Enum => { + let constraint = self.tcx.adt_sized_constraint(adt_def_id); + if constraint.0.len() > 0 { unimplemented!() } else { Some(true) } } - FnDef(_) | Trait(_) | Impl(_) | AssocTy(_) | Opaque(_) => panic!(), } } _ => None, @@ -460,40 +403,20 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t ) -> Option>> { use chalk_solve::rust_ir::WellKnownTrait::*; let t = match well_known_trait { - SizedTrait => self - .tcx - .lang_items() - .sized_trait() - .map(|t| chalk_ir::TraitId(RustDefId::Trait(t))) - .unwrap(), - CopyTrait => self - .tcx - .lang_items() - .copy_trait() - .map(|t| chalk_ir::TraitId(RustDefId::Trait(t))) - .unwrap(), - CloneTrait => self - .tcx - .lang_items() - .clone_trait() - .map(|t| chalk_ir::TraitId(RustDefId::Trait(t))) - .unwrap(), - DropTrait => self - .tcx - .lang_items() - .drop_trait() - .map(|t| chalk_ir::TraitId(RustDefId::Trait(t))) - .unwrap(), + SizedTrait => { + self.tcx.lang_items().sized_trait().map(|t| chalk_ir::TraitId(t)).unwrap() + } + CopyTrait => self.tcx.lang_items().copy_trait().map(|t| chalk_ir::TraitId(t)).unwrap(), + CloneTrait => { + self.tcx.lang_items().clone_trait().map(|t| chalk_ir::TraitId(t)).unwrap() + } + DropTrait => self.tcx.lang_items().drop_trait().map(|t| chalk_ir::TraitId(t)).unwrap(), }; Some(t) } fn is_object_safe(&self, trait_id: chalk_ir::TraitId>) -> bool { - let def_id: DefId = match trait_id.0 { - RustDefId::Trait(def_id) => def_id, - _ => bug!("Did not use `Trait` variant when expecting trait."), - }; - self.tcx.is_object_safe(def_id) + self.tcx.is_object_safe(trait_id.0) } } diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 58ea740193860..08fbca34177bd 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -32,8 +32,7 @@ //! variables from the current `Binder`. use rustc_middle::traits::{ - ChalkEnvironmentAndGoal, ChalkEnvironmentClause, ChalkRustDefId as RustDefId, - ChalkRustInterner as RustInterner, + ChalkEnvironmentAndGoal, ChalkEnvironmentClause, ChalkRustInterner as RustInterner, }; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; @@ -62,7 +61,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Substitution>> for Subst impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy>> for ty::ProjectionTy<'tcx> { fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::AliasTy> { chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { - associated_ty_id: chalk_ir::AssocTypeId(RustDefId::AssocTy(self.item_def_id)), + associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id), substitution: self.substs.lower_into(interner), }) } @@ -203,7 +202,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::TraitRef>> { fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::TraitRef> { chalk_ir::TraitRef { - trait_id: chalk_ir::TraitId(RustDefId::Trait(self.def_id)), + trait_id: chalk_ir::TraitId(self.def_id), substitution: self.substs.lower_into(interner), } } @@ -296,9 +295,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ast::FloatTy::F32 => float(chalk_ir::FloatTy::F32), ast::FloatTy::F64 => float(chalk_ir::FloatTy::F64), }, - Adt(def, substs) => { - apply(struct_ty(RustDefId::Adt(def.did)), substs.lower_into(interner)) - } + Adt(def, substs) => apply(struct_ty(def.did), substs.lower_into(interner)), Foreign(_def_id) => unimplemented!(), Str => apply(chalk_ir::TypeName::Str, empty()), Array(ty, _) => apply( @@ -352,7 +349,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ) } FnDef(def_id, substs) => apply( - chalk_ir::TypeName::FnDef(chalk_ir::FnDefId(RustDefId::FnDef(def_id))), + chalk_ir::TypeName::FnDef(chalk_ir::FnDefId(def_id)), substs.lower_into(interner), ), FnPtr(sig) => { @@ -384,7 +381,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { Projection(proj) => TyData::Alias(proj.lower_into(interner)).intern(interner), Opaque(def_id, substs) => { TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { - opaque_ty_id: chalk_ir::OpaqueTyId(RustDefId::Opaque(def_id)), + opaque_ty_id: chalk_ir::OpaqueTyId(def_id), substitution: substs.lower_into(interner), })) .intern(interner) @@ -515,7 +512,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders LowerInto<'tcx, chalk_ir::Binders chalk_ir::Binders::new( chalk_ir::VariableKinds::new(interner), chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { - trait_id: chalk_ir::TraitId(RustDefId::Trait(*def_id)), + trait_id: chalk_ir::TraitId(*def_id), substitution: chalk_ir::Substitution::empty(interner), }), ), diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs index f33ec3a9fb915..4d047d2107af5 100644 --- a/src/librustc_traits/chalk/mod.rs +++ b/src/librustc_traits/chalk/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{ use rustc_infer::infer::canonical::{ Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse, }; -use rustc_infer::traits::{self, ChalkCanonicalGoal, ChalkRustDefId as RustDefId}; +use rustc_infer::traits::{self, ChalkCanonicalGoal}; use crate::chalk::db::RustIrDatabase as ChalkRustIrDatabase; use crate::chalk::lowering::{LowerInto, ParamsSubstitutor}; @@ -106,10 +106,7 @@ crate fn evaluate_goal<'tcx>( let _data = _t.data(&interner); let kind = match _data { TyData::Apply(_application_ty) => match _application_ty.name { - chalk_ir::TypeName::Adt(_struct_id) => match _struct_id.0 { - RustDefId::Adt(_) => unimplemented!(), - _ => panic!("Unexpected struct id"), - }, + chalk_ir::TypeName::Adt(_struct_id) => unimplemented!(), chalk_ir::TypeName::Scalar(scalar) => match scalar { chalk_ir::Scalar::Bool => ty::Bool, chalk_ir::Scalar::Char => ty::Char, From ebdc950f0eb73416be5067c143ecaf1d84f0cb02 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 27 May 2020 02:23:30 -0400 Subject: [PATCH 10/37] Test error order is non-deterministic --- src/test/ui/chalkify/type_inference.rs | 4 +++- src/test/ui/chalkify/type_inference.stderr | 13 ++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs index 171969afc7f22..2b62bf18a71ce 100644 --- a/src/test/ui/chalkify/type_inference.rs +++ b/src/test/ui/chalkify/type_inference.rs @@ -18,7 +18,9 @@ fn main() { // is expecting a variable of type `i32`. This behavior differs from the // old-style trait solver. I guess this will change, that's why I'm // adding that test. - only_foo(x); //~ ERROR the trait bound `f64: Foo` is not satisfied + // FIXME(chalk): order of these two errors is non-deterministic, + // so let's just hide one for now + //only_foo(x); // ERROR the trait bound `f64: Foo` is not satisfied // Here we have two solutions so we get back the behavior of the old-style // trait solver. diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index 476759292642b..5cfb968404df6 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -1,14 +1,5 @@ -error[E0277]: the trait bound `f64: Foo` is not satisfied - --> $DIR/type_inference.rs:21:5 - | -LL | fn only_foo(_x: T) { } - | --- required by this bound in `only_foo` -... -LL | only_foo(x); - | ^^^^^^^^ the trait `Foo` is not implemented for `f64` - error[E0277]: the trait bound `f64: Bar` is not satisfied - --> $DIR/type_inference.rs:25:5 + --> $DIR/type_inference.rs:27:5 | LL | fn only_bar(_x: T) { } | --- required by this bound in `only_bar` @@ -16,6 +7,6 @@ LL | fn only_bar(_x: T) { } LL | only_bar(x); | ^^^^^^^^ the trait `Bar` is not implemented for `f64` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. From 1d8264a3f596e90d593cf772fcd30081dbd1a47e Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 27 May 2020 19:27:53 -0400 Subject: [PATCH 11/37] Update Chalk --- Cargo.lock | 10 +++++----- src/librustc_middle/Cargo.toml | 2 +- src/librustc_traits/Cargo.toml | 4 ++-- src/librustc_traits/chalk/db.rs | 11 ++++++++--- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8792434e52b7b..e827ea30b2e50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,7 +429,7 @@ dependencies = [ [[package]] name = "chalk-base" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" +source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" dependencies = [ "lazy_static", ] @@ -437,7 +437,7 @@ dependencies = [ [[package]] name = "chalk-derive" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" +source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -448,7 +448,7 @@ dependencies = [ [[package]] name = "chalk-engine" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" +source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" dependencies = [ "chalk-base", "chalk-derive", @@ -459,7 +459,7 @@ dependencies = [ [[package]] name = "chalk-ir" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" +source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" dependencies = [ "chalk-base", "chalk-derive", @@ -468,7 +468,7 @@ dependencies = [ [[package]] name = "chalk-solve" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b#58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" +source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" dependencies = [ "chalk-base", "chalk-derive", diff --git a/src/librustc_middle/Cargo.toml b/src/librustc_middle/Cargo.toml index 34dece1a2ad7e..121491c8cc4bf 100644 --- a/src/librustc_middle/Cargo.toml +++ b/src/librustc_middle/Cargo.toml @@ -30,7 +30,7 @@ rustc_serialize = { path = "../librustc_serialize" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } byteorder = { version = "1.3" } -chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" } +chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "c8f342bf5e48051333d0b2c7fab81347fc21c474" } #chalk-ir = "0.10.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index cb056dba9eab8..6bfebecf04cbe 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -19,8 +19,8 @@ rustc_span = { path = "../librustc_span" } #chalk-ir = "0.10.0" #chalk-rust-ir = "0.10.0" #chalk-solve = "0.10.0" -chalk-solve = { git = "https://github.com/jackh726/chalk.git", rev = "58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" } -chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "58e5a31f48ddd4b940c682e7079d3e79e6ffaa1b" } +chalk-solve = { git = "https://github.com/jackh726/chalk.git", rev = "c8f342bf5e48051333d0b2c7fab81347fc21c474" } +chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "c8f342bf5e48051333d0b2c7fab81347fc21c474" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 818839e2e3b33..5b00d32276831 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -321,10 +321,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t opaque_ty_id: chalk_ir::OpaqueTyId>, ) -> Arc>> { // FIXME(chalk): actually lower opaque ty - let hidden_ty = - self.tcx.mk_ty(ty::Tuple(self.tcx.intern_substs(&[]))).lower_into(&self.interner); let value = chalk_solve::rust_ir::OpaqueTyDatumBound { - hidden_ty, bounds: chalk_ir::Binders::new(chalk_ir::VariableKinds::new(&self.interner), vec![]), }; Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { @@ -418,6 +415,14 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn is_object_safe(&self, trait_id: chalk_ir::TraitId>) -> bool { self.tcx.is_object_safe(trait_id.0) } + + fn hidden_opaque_type( + &self, + _id: chalk_ir::OpaqueTyId>, + ) -> chalk_ir::Ty> { + // FIXME(chalk): actually get hidden ty + self.tcx.mk_ty(ty::Tuple(self.tcx.intern_substs(&[]))).lower_into(&self.interner) + } } /// Creates a `InternalSubsts` that maps each generic parameter to a higher-ranked From 6172e9a2aeaf254c8aa32f629bd920bd5299538c Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Fri, 29 May 2020 22:09:34 -0400 Subject: [PATCH 12/37] Update chalk and add LifetimeOutlives and ObjectSafe lowering --- Cargo.lock | 20 +++------ src/librustc_middle/Cargo.toml | 2 +- src/librustc_traits/Cargo.toml | 4 +- src/librustc_traits/chalk/lowering.rs | 65 +++++++++++++++++++++++---- src/librustc_traits/chalk/mod.rs | 2 +- 5 files changed, 66 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e827ea30b2e50..5103e6bfd19b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -426,18 +426,10 @@ dependencies = [ "rustc-std-workspace-core", ] -[[package]] -name = "chalk-base" -version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" -dependencies = [ - "lazy_static", -] - [[package]] name = "chalk-derive" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" +source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -448,9 +440,8 @@ dependencies = [ [[package]] name = "chalk-engine" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" +source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" dependencies = [ - "chalk-base", "chalk-derive", "chalk-ir", "rustc-hash", @@ -459,18 +450,17 @@ dependencies = [ [[package]] name = "chalk-ir" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" +source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" dependencies = [ - "chalk-base", "chalk-derive", + "lazy_static 1.4.0", ] [[package]] name = "chalk-solve" version = "0.10.1-dev" -source = "git+https://github.com/jackh726/chalk.git?rev=c8f342bf5e48051333d0b2c7fab81347fc21c474#c8f342bf5e48051333d0b2c7fab81347fc21c474" +source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" dependencies = [ - "chalk-base", "chalk-derive", "chalk-engine", "chalk-ir", diff --git a/src/librustc_middle/Cargo.toml b/src/librustc_middle/Cargo.toml index 121491c8cc4bf..9516d449671d6 100644 --- a/src/librustc_middle/Cargo.toml +++ b/src/librustc_middle/Cargo.toml @@ -30,7 +30,7 @@ rustc_serialize = { path = "../librustc_serialize" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } byteorder = { version = "1.3" } -chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "c8f342bf5e48051333d0b2c7fab81347fc21c474" } +chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ea1ca4ddc43abcfed77420f294a3713fac714e18" } #chalk-ir = "0.10.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index 6bfebecf04cbe..f141daa9f936b 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -19,8 +19,8 @@ rustc_span = { path = "../librustc_span" } #chalk-ir = "0.10.0" #chalk-rust-ir = "0.10.0" #chalk-solve = "0.10.0" -chalk-solve = { git = "https://github.com/jackh726/chalk.git", rev = "c8f342bf5e48051333d0b2c7fab81347fc21c474" } -chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "c8f342bf5e48051333d0b2c7fab81347fc21c474" } +chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "ea1ca4ddc43abcfed77420f294a3713fac714e18" } +chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ea1ca4ddc43abcfed77420f294a3713fac714e18" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 08fbca34177bd..c8a9a42fc13d4 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -97,8 +97,28 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment None, + ty::PredicateKind::RegionOutlives(predicate) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, predicate); + + Some( + chalk_ir::ProgramClauseData::ForAll(chalk_ir::Binders::new( + binders, + chalk_ir::ProgramClauseImplication { + consequence: chalk_ir::DomainGoal::Holds( + chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { + a: predicate.0.lower_into(interner), + b: predicate.1.lower_into(interner), + }) + ), + conditions: chalk_ir::Goals::new(interner), + priority: chalk_ir::ClausePriority::High, + }, + )) + .intern(interner), + ) + }, + // FIXME(chalk): need to add TypeOutlives ty::PredicateKind::TypeOutlives(_) => None, ty::PredicateKind::Projection(predicate) => { let (predicate, binders, _named_regions) = @@ -156,10 +176,24 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GoalData> { match self.kind() { ty::PredicateKind::Trait(predicate, _) => predicate.lower_into(interner), - // FIXME(chalk): we need to register constraints. - ty::PredicateKind::RegionOutlives(_predicate) => { - chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)) + ty::PredicateKind::RegionOutlives(predicate) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, predicate); + + chalk_ir::GoalData::Quantified( + chalk_ir::QuantifierKind::ForAll, + chalk_ir::Binders::new( + binders, + chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds( + chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { + a: predicate.0.lower_into(interner), + b: predicate.1.lower_into(interner), + }) + )).intern(interner) + ) + ) } + // FIXME(chalk): TypeOutlives ty::PredicateKind::TypeOutlives(_predicate) => { chalk_ir::GoalData::All(chalk_ir::Goals::new(interner)) } @@ -182,12 +216,15 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi GenericArgKind::Lifetime(lt) => bug!("unexpect well formed predicate: {:?}", lt), }, + ty::PredicateKind::ObjectSafe(t) => { + chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::ObjectSafe(chalk_ir::TraitId(*t))) + } + // FIXME(chalk): other predicates // // We can defer this, but ultimately we'll want to express // some of these in terms of chalk operations. - ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) + ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) => { @@ -484,7 +521,19 @@ impl<'tcx> LowerInto<'tcx, Option None, + ty::PredicateKind::RegionOutlives(predicate) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, predicate); + + Some(chalk_ir::Binders::new( + binders, + chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { + a: predicate.0.lower_into(interner), + b: predicate.1.lower_into(interner), + }), + )) + + }, ty::PredicateKind::TypeOutlives(_predicate) => None, ty::PredicateKind::Projection(_predicate) => None, ty::PredicateKind::WellFormed(_ty) => None, diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs index 4d047d2107af5..d8f9a40b9432e 100644 --- a/src/librustc_traits/chalk/mod.rs +++ b/src/librustc_traits/chalk/mod.rs @@ -199,7 +199,7 @@ crate fn evaluate_goal<'tcx>( .map(|s| match s { Solution::Unique(_subst) => { // FIXME(chalk): handle constraints - assert!(_subst.value.constraints.is_empty()); + // assert!(_subst.value.constraints.is_empty()); make_solution(_subst.value.subst) } Solution::Ambig(_guidance) => { From 7a5b93977d5d72e88dcbdbec93c0b2860f074e84 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Sat, 30 May 2020 02:21:33 -0400 Subject: [PATCH 13/37] Lower consts --- src/librustc_middle/traits/chalk.rs | 3 +- src/librustc_traits/chalk/db.rs | 4 +- src/librustc_traits/chalk/lowering.rs | 75 +++++++++++++++------------ 3 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/librustc_middle/traits/chalk.rs b/src/librustc_middle/traits/chalk.rs index 9ce6cc3a51114..624fc3b3fb7b7 100644 --- a/src/librustc_middle/traits/chalk.rs +++ b/src/librustc_middle/traits/chalk.rs @@ -5,6 +5,7 @@ //! its name suggest, is to provide an abstraction boundary for creating //! interned Chalk types. +use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -63,7 +64,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { type InternedType = Box>; type InternedLifetime = Box>; type InternedConst = Box>; - type InternedConcreteConst = u32; + type InternedConcreteConst = ConstValue<'tcx>; type InternedGenericArg = Box>; type InternedGoal = Box>; type InternedGoals = Vec>; diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 5b00d32276831..4976ba06815c8 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -468,8 +468,8 @@ fn binders_for<'tcx>( ty::subst::GenericArgKind::Type(_ty) => { chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General) } - ty::subst::GenericArgKind::Const(_const) => { - chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General) + ty::subst::GenericArgKind::Const(c) => { + chalk_ir::VariableKind::Const(c.ty.lower_into(interner)) } }), ) diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index c8a9a42fc13d4..3ea3a63524954 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -100,16 +100,18 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment { let (predicate, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, predicate); - + Some( chalk_ir::ProgramClauseData::ForAll(chalk_ir::Binders::new( binders, chalk_ir::ProgramClauseImplication { consequence: chalk_ir::DomainGoal::Holds( - chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { - a: predicate.0.lower_into(interner), - b: predicate.1.lower_into(interner), - }) + chalk_ir::WhereClause::LifetimeOutlives( + chalk_ir::LifetimeOutlives { + a: predicate.0.lower_into(interner), + b: predicate.1.lower_into(interner), + }, + ), ), conditions: chalk_ir::Goals::new(interner), priority: chalk_ir::ClausePriority::High, @@ -117,7 +119,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment None, ty::PredicateKind::Projection(predicate) => { @@ -188,9 +190,10 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { a: predicate.0.lower_into(interner), b: predicate.1.lower_into(interner), - }) - )).intern(interner) - ) + }), + )) + .intern(interner), + ), ) } // FIXME(chalk): TypeOutlives @@ -216,9 +219,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi GenericArgKind::Lifetime(lt) => bug!("unexpect well formed predicate: {:?}", lt), }, - ty::PredicateKind::ObjectSafe(t) => { - chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::ObjectSafe(chalk_ir::TraitId(*t))) - } + ty::PredicateKind::ObjectSafe(t) => chalk_ir::GoalData::DomainGoal( + chalk_ir::DomainGoal::ObjectSafe(chalk_ir::TraitId(*t)), + ), // FIXME(chalk): other predicates // @@ -335,25 +338,34 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { Adt(def, substs) => apply(struct_ty(def.did), substs.lower_into(interner)), Foreign(_def_id) => unimplemented!(), Str => apply(chalk_ir::TypeName::Str, empty()), - Array(ty, _) => apply( - chalk_ir::TypeName::Array, - chalk_ir::Substitution::from( - interner, - &[ - chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), - chalk_ir::GenericArgData::Const( - chalk_ir::ConstData { - ty: apply(chalk_ir::TypeName::Tuple(0), empty()), - value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { - interned: 0, - }), - } + Array(ty, len) => { + let value = match len.val { + ty::ConstKind::Value(val) => { + chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: val }) + } + ty::ConstKind::Bound(db, bound) => { + chalk_ir::ConstValue::BoundVar(chalk_ir::BoundVar::new( + chalk_ir::DebruijnIndex::new(db.as_u32()), + bound.index(), + )) + } + _ => unimplemented!("Const not implemented. {:?}", len.val), + }; + apply( + chalk_ir::TypeName::Array, + chalk_ir::Substitution::from( + interner, + &[ + chalk_ir::GenericArgData::Ty(ty.lower_into(interner)).intern(interner), + chalk_ir::GenericArgData::Const( + chalk_ir::ConstData { ty: len.ty.lower_into(interner), value } + .intern(interner), + ) .intern(interner), - ) - .intern(interner), - ], - ), - ), + ], + ), + ) + } Slice(ty) => apply( chalk_ir::TypeName::Slice, chalk_ir::Substitution::from1( @@ -532,8 +544,7 @@ impl<'tcx> LowerInto<'tcx, Option None, ty::PredicateKind::Projection(_predicate) => None, ty::PredicateKind::WellFormed(_ty) => None, From 4028c21026f27899b1100ae160fe2da4819f2b51 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Sat, 30 May 2020 02:59:29 -0400 Subject: [PATCH 14/37] Fix building --- Cargo.lock | 2 +- src/librustc_traits/chalk/lowering.rs | 4 ++-- src/tools/tidy/src/deps.rs | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5103e6bfd19b4..ab36c56a57f9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -453,7 +453,7 @@ version = "0.10.1-dev" source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" dependencies = [ "chalk-derive", - "lazy_static 1.4.0", + "lazy_static", ] [[package]] diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 3ea3a63524954..6f0fa6bcef9e6 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -572,7 +572,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders LowerInto<'tcx, chalk_ir::Binders chalk_ir::Binders::new( chalk_ir::VariableKinds::new(interner), chalk_ir::WhereClause::Implemented(chalk_ir::TraitRef { - trait_id: chalk_ir::TraitId(*def_id), + trait_id: chalk_ir::TraitId(def_id), substitution: chalk_ir::Substitution::empty(interner), }), ), diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index aec6b5d25235e..093db2a49d029 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -79,7 +79,6 @@ const WHITELIST: &[&str] = &[ "byteorder", "cc", "cfg-if", - "chalk-base", "chalk-derive", "chalk-ir", "cloudabi", From 8aa289856dc9eb12859ace1ce66420816bc75770 Mon Sep 17 00:00:00 2001 From: Jack Date: Tue, 2 Jun 2020 17:16:39 -0400 Subject: [PATCH 15/37] Update chalk to 0.11.0 --- Cargo.lock | 20 ++++++++++++-------- src/librustc_middle/Cargo.toml | 3 +-- src/librustc_traits/Cargo.toml | 7 ++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab36c56a57f9f..25eb692207266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -428,8 +428,9 @@ dependencies = [ [[package]] name = "chalk-derive" -version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9bd01eab87277d973183a1d2e56bace1c11f8242c52c20636fb7dddf343ac9" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -439,8 +440,9 @@ dependencies = [ [[package]] name = "chalk-engine" -version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c7a637c3d17ed555aef16e16952a5d1e127bd55178cc30be22afeb92da90c7d" dependencies = [ "chalk-derive", "chalk-ir", @@ -449,8 +451,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595e5735ded16c3f3dc348f7b15bbb2521a0080b1863cac38ad5271589944670" dependencies = [ "chalk-derive", "lazy_static", @@ -458,8 +461,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.10.1-dev" -source = "git+https://github.com/rust-lang/chalk.git?rev=ea1ca4ddc43abcfed77420f294a3713fac714e18#ea1ca4ddc43abcfed77420f294a3713fac714e18" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d9d938139db425867a30cc0cfec0269406d8238d0571d829041eaa7a8455d11" dependencies = [ "chalk-derive", "chalk-engine", diff --git a/src/librustc_middle/Cargo.toml b/src/librustc_middle/Cargo.toml index 9516d449671d6..21d0b102a4a66 100644 --- a/src/librustc_middle/Cargo.toml +++ b/src/librustc_middle/Cargo.toml @@ -30,8 +30,7 @@ rustc_serialize = { path = "../librustc_serialize" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } byteorder = { version = "1.3" } -chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ea1ca4ddc43abcfed77420f294a3713fac714e18" } -#chalk-ir = "0.10.0" +chalk-ir = "0.11.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index f141daa9f936b..8def98a9603d8 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -16,11 +16,8 @@ rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } -#chalk-ir = "0.10.0" -#chalk-rust-ir = "0.10.0" -#chalk-solve = "0.10.0" -chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "ea1ca4ddc43abcfed77420f294a3713fac714e18" } -chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ea1ca4ddc43abcfed77420f294a3713fac714e18" } +chalk-ir = "0.11.0" +chalk-solve = "0.11.0" smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } rustc_trait_selection = { path = "../librustc_trait_selection" } From 852313a46e513cbba4e5f4baf094e4a7088b01ff Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 3 Jun 2020 12:21:56 -0400 Subject: [PATCH 16/37] Nits and change skip_binder to no_bound_vars for fndef --- src/librustc_traits/chalk/db.rs | 12 +++++++----- src/librustc_traits/chalk/mod.rs | 1 - src/test/ui/chalkify/inherent_impl.rs | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 4976ba06815c8..78fb787a319ef 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -8,7 +8,7 @@ use rustc_middle::traits::ChalkRustInterner as RustInterner; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::{self, AssocItemContainer, AssocKind, TyCtxt}; +use rustc_middle::ty::{self, AssocItemContainer, AssocKind, Binder, TyCtxt}; use rustc_hir::def_id::DefId; @@ -177,10 +177,12 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); let sig = self.tcx.fn_sig(def_id); - // FIXME(chalk): Why does this have a Binder - let argument_types = sig - .inputs() - .skip_binder() + // FIXME(chalk): collect into an intermediate SmallVec here since + // we need `TypeFoldable` for `no_bound_vars` + let argument_types: Binder> = sig.map_bound(|i| i.inputs().iter().copied().collect()); + let argument_types = argument_types + .no_bound_vars() + .expect("FIXME(chalk): late-bound fn parameters not supported in chalk") .iter() .map(|t| t.subst(self.tcx, &bound_vars).lower_into(&self.interner)) .collect(); diff --git a/src/librustc_traits/chalk/mod.rs b/src/librustc_traits/chalk/mod.rs index d8f9a40b9432e..6f657be0908b4 100644 --- a/src/librustc_traits/chalk/mod.rs +++ b/src/librustc_traits/chalk/mod.rs @@ -199,7 +199,6 @@ crate fn evaluate_goal<'tcx>( .map(|s| match s { Solution::Unique(_subst) => { // FIXME(chalk): handle constraints - // assert!(_subst.value.constraints.is_empty()); make_solution(_subst.value.subst) } Solution::Ambig(_guidance) => { diff --git a/src/test/ui/chalkify/inherent_impl.rs b/src/test/ui/chalkify/inherent_impl.rs index 44e120c1eebba..9dd9eb320ddd3 100644 --- a/src/test/ui/chalkify/inherent_impl.rs +++ b/src/test/ui/chalkify/inherent_impl.rs @@ -1,5 +1,7 @@ // run-pass // compile-flags: -Z chalk +// FIXME(chalk): remove when uncommented +#![allow(dead_code, unused_variables)] trait Foo { } @@ -9,6 +11,8 @@ struct S { x: T, } +// FIXME(chalk): need late-bound regions on FnDefs +/* fn only_foo(_x: &T) { } impl S { @@ -17,6 +21,7 @@ impl S { only_foo(&self.x) } } +*/ trait Bar { } impl Bar for u32 { } @@ -26,10 +31,16 @@ fn only_bar() { } impl S { // Test that the environment of `dummy_bar` adds up with the environment // of the inherent impl. + // FIXME(chalk): need late-bound regions on FnDefs + /* fn dummy_bar(&self) { only_foo(&self.x); only_bar::(); } + */ + fn dummy_bar() { + only_bar::(); + } } fn main() { @@ -37,6 +48,10 @@ fn main() { x: 5, }; + // FIXME(chalk): need late-bound regions on FnDefs + /* s.dummy_foo(); s.dummy_bar::(); + */ + S::::dummy_bar::(); } From 645af624db5b032aedac035862aeaf2286c90ee1 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 3 Jun 2020 13:33:28 -0400 Subject: [PATCH 17/37] Change InternedAdtDef to &'tcx AdtDef --- src/librustc_middle/traits/chalk.rs | 4 +- src/librustc_traits/chalk/db.rs | 54 ++++++++++++--------------- src/librustc_traits/chalk/lowering.rs | 3 +- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/src/librustc_middle/traits/chalk.rs b/src/librustc_middle/traits/chalk.rs index 624fc3b3fb7b7..a49a0045812b0 100644 --- a/src/librustc_middle/traits/chalk.rs +++ b/src/librustc_middle/traits/chalk.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_hir::def_id::DefId; @@ -75,7 +75,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { type InternedVariableKinds = Vec>; type InternedCanonicalVarKinds = Vec>; type DefId = DefId; - type InternedAdtId = DefId; + type InternedAdtId = &'tcx AdtDef; type Identifier = (); fn debug_program_clause_implication( diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 78fb787a319ef..3c83c11b3c438 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -117,15 +117,14 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn adt_datum( &self, - struct_id: chalk_ir::AdtId>, + adt_id: chalk_ir::AdtId>, ) -> Arc>> { - let adt_def_id = struct_id.0; - let adt_def = self.tcx.adt_def(adt_def_id); + let adt_def = adt_id.0; - let bound_vars = bound_vars_for_item(self.tcx, adt_def_id); + let bound_vars = bound_vars_for_item(self.tcx, adt_def.did); let binders = binders_for(&self.interner, bound_vars); - let predicates = self.tcx.predicates_of(adt_def_id).predicates; + let predicates = self.tcx.predicates_of(adt_def.did).predicates; let where_clauses: Vec<_> = predicates .into_iter() .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) @@ -149,13 +148,13 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t ty::AdtKind::Enum => vec![], }; let struct_datum = Arc::new(chalk_solve::rust_ir::AdtDatum { - id: struct_id, + id: adt_id, binders: chalk_ir::Binders::new( binders, chalk_solve::rust_ir::AdtDatumBound { fields, where_clauses }, ), flags: chalk_solve::rust_ir::AdtFlags { - upstream: !adt_def_id.is_local(), + upstream: !adt_def.did.is_local(), fundamental: adt_def.is_fundamental(), }, }); @@ -179,7 +178,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let sig = self.tcx.fn_sig(def_id); // FIXME(chalk): collect into an intermediate SmallVec here since // we need `TypeFoldable` for `no_bound_vars` - let argument_types: Binder> = sig.map_bound(|i| i.inputs().iter().copied().collect()); + let argument_types: Binder> = + sig.map_bound(|i| i.inputs().iter().copied().collect()); let argument_types = argument_types .no_bound_vars() .expect("FIXME(chalk): late-bound fn parameters not supported in chalk") @@ -259,17 +259,17 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fn impl_provided_for( &self, auto_trait_id: chalk_ir::TraitId>, - struct_id: chalk_ir::AdtId>, + adt_id: chalk_ir::AdtId>, ) -> bool { let trait_def_id = auto_trait_id.0; - let adt_def_id = struct_id.0; + let adt_def = adt_id.0; let all_impls = self.tcx.all_impls(trait_def_id); for impl_def_id in all_impls { let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); let self_ty = trait_ref.self_ty(); match self_ty.kind { - ty::Adt(adt_def, _) => { - if adt_def.did == adt_def_id { + ty::Adt(impl_adt_def, _) => { + if impl_adt_def == adt_def { return true; } } @@ -344,16 +344,13 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t match well_known { chalk_solve::rust_ir::WellKnownTrait::SizedTrait => match ty { Apply(apply) => match apply.name { - chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def_id)) => { - let adt_def = self.tcx.adt_def(adt_def_id); - match adt_def.adt_kind() { - ty::AdtKind::Struct | ty::AdtKind::Union => None, - ty::AdtKind::Enum => { - let constraint = self.tcx.adt_sized_constraint(adt_def_id); - if constraint.0.len() > 0 { unimplemented!() } else { Some(true) } - } + chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def)) => match adt_def.adt_kind() { + ty::AdtKind::Struct | ty::AdtKind::Union => None, + ty::AdtKind::Enum => { + let constraint = self.tcx.adt_sized_constraint(adt_def.did); + if constraint.0.len() > 0 { unimplemented!() } else { Some(true) } } - } + }, _ => None, }, Dyn(_) @@ -366,16 +363,13 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t chalk_solve::rust_ir::WellKnownTrait::CopyTrait | chalk_solve::rust_ir::WellKnownTrait::CloneTrait => match ty { Apply(apply) => match apply.name { - chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def_id)) => { - let adt_def = self.tcx.adt_def(adt_def_id); - match adt_def.adt_kind() { - ty::AdtKind::Struct | ty::AdtKind::Union => None, - ty::AdtKind::Enum => { - let constraint = self.tcx.adt_sized_constraint(adt_def_id); - if constraint.0.len() > 0 { unimplemented!() } else { Some(true) } - } + chalk_ir::TypeName::Adt(chalk_ir::AdtId(adt_def)) => match adt_def.adt_kind() { + ty::AdtKind::Struct | ty::AdtKind::Union => None, + ty::AdtKind::Enum => { + let constraint = self.tcx.adt_sized_constraint(adt_def.did); + if constraint.0.len() > 0 { unimplemented!() } else { Some(true) } } - } + }, _ => None, }, Dyn(_) diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 6f0fa6bcef9e6..8f84acee7e424 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -304,7 +304,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { use TyKind::*; let empty = || chalk_ir::Substitution::empty(interner); - let struct_ty = |def_id| chalk_ir::TypeName::Adt(chalk_ir::AdtId(def_id)); + let struct_ty = + |def_id| chalk_ir::TypeName::Adt(chalk_ir::AdtId(interner.tcx.adt_def(def_id))); let apply = |name, substitution| { TyData::Apply(chalk_ir::ApplicationTy { name, substitution }).intern(interner) }; From 4cf2833cf4a7fe7e283e9fc4d96ad124705a678b Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Wed, 3 Jun 2020 16:14:18 -0400 Subject: [PATCH 18/37] Return type is bound too --- src/librustc_traits/chalk/db.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 3c83c11b3c438..235497d374098 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -187,8 +187,12 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .map(|t| t.subst(self.tcx, &bound_vars).lower_into(&self.interner)) .collect(); - let return_type = - sig.output().skip_binder().subst(self.tcx, &bound_vars).lower_into(&self.interner); + let return_type = sig + .output() + .no_bound_vars() + .expect("FIXME(chalk): late-bound fn parameters not supported in chalk") + .subst(self.tcx, &bound_vars) + .lower_into(&self.interner); let bound = chalk_solve::rust_ir::FnDefDatumBound { argument_types, where_clauses, return_type }; From 687767af728ce111a7aa24f74cd9068aedb2ab18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 15:09:43 -0700 Subject: [PATCH 19/37] Suggest substituting `'static` lifetime in impl/dyn `Trait + 'static` return types --- .../nice_region_error/static_impl_trait.rs | 64 ++++++++-- src/librustc_middle/ty/context.rs | 13 +- src/librustc_middle/ty/diagnostics.rs | 8 +- ...t_outlive_least_region_or_bound.nll.stderr | 38 +++++- .../must_outlive_least_region_or_bound.rs | 21 ++++ .../must_outlive_least_region_or_bound.stderr | 117 ++++++++++++++++-- 6 files changed, 232 insertions(+), 29 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index f4c86ddae604e..88d6c23d51441 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -4,6 +4,7 @@ use crate::infer::error_reporting::msg_span_from_free_region; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use rustc_errors::{Applicability, ErrorReported}; +use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind}; use rustc_middle::ty::RegionKind; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -20,8 +21,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = error.clone() { let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; - let (fn_return_span, is_dyn) = - self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; + let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; + let is_dyn = matches!(fn_return.kind, TyKind::TraitObject(..)); + let fn_return_span = fn_return.span; if sub_r == &RegionKind::ReStatic { let sp = var_origin.span(); let return_sp = sub_origin.span(); @@ -67,12 +69,58 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { lifetime, ); // FIXME: account for the need of parens in `&(dyn Trait + '_)` - err.span_suggestion_verbose( - fn_return_span.shrink_to_hi(), - &msg, - format!(" + {}", lifetime_name), - Applicability::MaybeIncorrect, - ); + match fn_return.kind { + TyKind::Def(item_id, _) => { + let item = self.tcx().hir().item(item_id.id); + let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind { + opaque + } else { + err.emit(); + return Some(ErrorReported); + }; + let (span, sugg) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { + name: LifetimeName::Static, + span, + .. + }) => Some((*span, lifetime_name.clone())), + _ => None, + }) + .next() + .unwrap_or_else(|| { + ( + fn_return_span.shrink_to_hi(), + format!(" + {}", lifetime_name), + ) + }); + + err.span_suggestion_verbose( + span, + &msg, + sugg, + Applicability::MaybeIncorrect, + ); + } + TyKind::TraitObject(_, lt) => { + let (span, sugg) = match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => ( + fn_return_span.shrink_to_hi(), + format!(" + {}", lifetime_name), + ), + _ => (lt.span, lifetime_name), + }; + err.span_suggestion_verbose( + span, + &msg, + sugg, + Applicability::MaybeIncorrect, + ); + } + _ => {} + } } err.emit(); return Some(ErrorReported); diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index d5be3508d2d80..4770993d9cb07 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1383,7 +1383,10 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> { + pub fn return_type_impl_or_dyn_trait( + &self, + scope_def_id: DefId, + ) -> Option<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local()); let hir_output = match self.hir().get(hir_id) { Node::Item(hir::Item { @@ -1429,15 +1432,17 @@ impl<'tcx> TyCtxt<'tcx> { let output = self.erase_late_bound_regions(&sig.output()); if output.is_impl_trait() { let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap(); - Some((fn_decl.output.span(), false)) + if let hir::FnRetTy::Return(ty) = fn_decl.output { + return Some(ty); + } } else { let mut v = TraitObjectVisitor(vec![]); rustc_hir::intravisit::walk_ty(&mut v, hir_output); if v.0.len() == 1 { - return Some((v.0[0], true)); + return Some(v.0[0]); } - None } + None } _ => None, } diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index 2e9aa724ac5af..3ca506fe0d590 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -236,21 +236,21 @@ pub fn suggest_constraining_type_param( } } -pub struct TraitObjectVisitor(pub Vec); -impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor { +pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>); +impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { type Map = rustc_hir::intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { hir::intravisit::NestedVisitorMap::None } - fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { if let hir::TyKind::TraitObject( _, hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. }, ) = ty.kind { - self.0.push(ty.span); + self.0.push(ty); } } } diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 1806d2607a3ac..ca9ca8a9debe2 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -26,7 +26,34 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:12:69 + --> $DIR/must_outlive_least_region_or_bound.rs:9:46 + | +LL | fn elided2(x: &i32) -> impl Copy + 'static { x } + | - ^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | + = help: consider replacing `'1` with `'static` + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:12:55 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } + | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + = help: consider replacing `'a` with `'static` + +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/must_outlive_least_region_or_bound.rs:15:41 + | +LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } + | ---- ^ lifetime `'a` required + | | + | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -35,7 +62,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } = help: consider replacing `'a` with `'static` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:17:61 + --> $DIR/must_outlive_least_region_or_bound.rs:38:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` @@ -45,13 +72,14 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 = help: consider adding the following bound: `'b: 'a` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:22:51 + --> $DIR/must_outlive_least_region_or_bound.rs:43:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | ^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0310`. +Some errors have detailed explanations: E0310, E0621. +For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 00f3490991b52..beafe9258209d 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -6,6 +6,27 @@ fn elided(x: &i32) -> impl Copy { x } fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~^ ERROR cannot infer an appropriate lifetime +fn elided2(x: &i32) -> impl Copy + 'static { x } +//~^ ERROR cannot infer an appropriate lifetime + +fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } +//~^ ERROR cannot infer an appropriate lifetime + +fn foo<'a>(x: &i32) -> impl Copy + 'a { x } +//~^ ERROR explicit lifetime required in the type of `x` + +fn elided3(x: &i32) -> Box { Box::new(x) } +//~^ ERROR cannot infer an appropriate lifetime + +fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } +//~^ ERROR cannot infer an appropriate lifetime + +fn elided4(x: &i32) -> Box { Box::new(x) } +//~^ ERROR explicit lifetime required in the type of `x` + +fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } +//~^ ERROR cannot infer an appropriate lifetime + trait LifetimeTrait<'a> {} impl<'a> LifetimeTrait<'a> for &'a i32 {} diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index d7dae6a08a7b9..525e271bea9c3 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -27,7 +27,43 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ error: cannot infer an appropriate lifetime - --> $DIR/must_outlive_least_region_or_bound.rs:12:69 + --> $DIR/must_outlive_least_region_or_bound.rs:9:46 + | +LL | fn elided2(x: &i32) -> impl Copy + 'static { x } + | ---- ------------------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... + | +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 9:1 + | +LL | fn elided2(x: &i32) -> impl Copy + '_ { x } + | ^^ + +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:12:55 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } + | ------- ------------------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... + | +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:14 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } + | ^^ + +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/must_outlive_least_region_or_bound.rs:15:24 + | +LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } + | ---- ^^^^^^^^^^^^^^ lifetime `'a` required + | | + | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` + +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- -------------------------------- ^ ...and is captured here @@ -35,13 +71,13 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:15 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 33:15 | -LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x } - | ^^^^ +LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } + | ^^ error[E0623]: lifetime mismatch - --> $DIR/must_outlive_least_region_or_bound.rs:17:61 + --> $DIR/must_outlive_least_region_or_bound.rs:38:61 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | ------- ^^^^^^^^^^^^^^^^ @@ -50,14 +86,79 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | this parameter and the return type are declared with different lifetimes... error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:22:51 + --> $DIR/must_outlive_least_region_or_bound.rs:43:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static +` -error: aborting due to 5 previous errors +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ---- ---------^- + | | | | + | | | ...and is captured here + | | ...is required to be `'static` by this... + | data with this lifetime... + | +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ^^^^ + +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:21:59 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ------- ---------^- + | | | | + | | | ...and is captured here + | | ...is required to be `'static` by this... + | data with this lifetime... + | +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^ + +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/must_outlive_least_region_or_bound.rs:24:51 + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ---- ^^^^^^^^^^^ lifetime `'static` required + | | + | help: add explicit lifetime `'static` to the type of `x`: `&'static i32` + +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/must_outlive_least_region_or_bound.rs:27:69 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 27:14... + --> $DIR/must_outlive_least_region_or_bound.rs:27:14 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^ +note: ...so that the expression is assignable + --> $DIR/must_outlive_least_region_or_bound.rs:27:69 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^ + = note: expected `&i32` + found `&'a i32` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the expression is assignable + --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ + = note: expected `std::boxed::Box<(dyn std::fmt::Debug + 'static)>` + found `std::boxed::Box` + +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0623. +Some errors have detailed explanations: E0310, E0495, E0621, E0623. For more information about an error, try `rustc --explain E0310`. From c91320f06b0b967b662f62a1c00447b9c87d4542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 18:05:20 -0700 Subject: [PATCH 20/37] When `'static` is explicit, suggest constraining argument with it --- .../infer/error_reporting/mod.rs | 3 +- .../nice_region_error/static_impl_trait.rs | 115 +++++++++++------- src/librustc_middle/ty/diagnostics.rs | 5 +- .../must_outlive_least_region_or_bound.rs | 2 +- .../must_outlive_least_region_or_bound.stderr | 75 +++++++----- src/test/ui/issues/issue-16922.stderr | 2 +- ...ect-lifetime-default-from-box-error.stderr | 2 +- ...ion-object-lifetime-in-coercion.nll.stderr | 19 ++- .../region-object-lifetime-in-coercion.rs | 5 +- .../region-object-lifetime-in-coercion.stderr | 61 +++++++--- .../regions-close-object-into-object-2.stderr | 32 ++--- .../regions-close-object-into-object-4.stderr | 32 ++--- .../regions-proc-bound-capture.nll.stderr | 11 ++ .../ui/regions/regions-proc-bound-capture.rs | 4 +- .../regions/regions-proc-bound-capture.stderr | 25 ++-- .../dyn-trait-underscore.stderr | 2 +- 16 files changed, 237 insertions(+), 158 deletions(-) create mode 100644 src/test/ui/regions/regions-proc-bound-capture.nll.stderr diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index a59a91e3005aa..f7969fe779d33 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -2037,8 +2037,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, var_origin.span(), E0495, - "cannot infer an appropriate lifetime{} \ - due to conflicting requirements", + "cannot infer an appropriate lifetime{} due to conflicting requirements", var_description ) } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 88d6c23d51441..e24535bba5fdc 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::RegionKind; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. pub(super) fn try_report_static_impl_trait(&self) -> Option { + debug!("try_report_static_impl_trait(error={:?})", self.error); if let Some(ref error) = self.error { if let RegionResolutionError::SubSupConflict( _, @@ -18,19 +19,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { sub_r, sup_origin, sup_r, - ) = error.clone() + ) = error { + debug!( + "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})", + var_origin, sub_origin, sub_r, sup_origin, sup_r + ); let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; + debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup); let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; - let is_dyn = matches!(fn_return.kind, TyKind::TraitObject(..)); - let fn_return_span = fn_return.span; - if sub_r == &RegionKind::ReStatic { + debug!("try_report_static_impl_trait: fn_return={:?}", fn_return); + if **sub_r == RegionKind::ReStatic { let sp = var_origin.span(); let return_sp = sub_origin.span(); + let param_info = self.find_param_with_region(sup_r, sub_r)?; let mut err = self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); - let param_info = self.find_param_with_region(sup_r, sub_r)?; err.span_label(param_info.param_ty_span, "data with this lifetime..."); + debug!("try_report_static_impl_trait: param_info={:?}", param_info); // We try to make the output have fewer overlapping spans if possible. if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) @@ -60,14 +66,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; // only apply this suggestion onto functions with // explicit non-desugar'able return. - if fn_return_span.desugaring_kind().is_none() { - let msg = format!( - "to permit non-static references in {} `{} Trait` value, you can add \ - an explicit bound for {}", - if is_dyn { "a" } else { "an" }, - if is_dyn { "dyn" } else { "impl" }, - lifetime, - ); + if fn_return.span.desugaring_kind().is_none() { // FIXME: account for the need of parens in `&(dyn Trait + '_)` match fn_return.kind { TyKind::Def(item_id, _) => { @@ -78,7 +77,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.emit(); return Some(ErrorReported); }; - let (span, sugg) = opaque + + if let Some(span) = opaque .bounds .iter() .filter_map(|arg| match arg { @@ -86,38 +86,71 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { name: LifetimeName::Static, span, .. - }) => Some((*span, lifetime_name.clone())), + }) => Some(*span), _ => None, }) .next() - .unwrap_or_else(|| { - ( - fn_return_span.shrink_to_hi(), - format!(" + {}", lifetime_name), - ) - }); - - err.span_suggestion_verbose( - span, - &msg, - sugg, - Applicability::MaybeIncorrect, - ); - } - TyKind::TraitObject(_, lt) => { - let (span, sugg) = match lt.name { - LifetimeName::ImplicitObjectLifetimeDefault => ( - fn_return_span.shrink_to_hi(), + { + err.span_suggestion_verbose( + span, + "consider changing the `impl Trait`'s explicit \ + `'static` bound", + lifetime_name, + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param_info.param_ty_span, + "alternatively, set an explicit `'static` lifetime to \ + this parameter", + param_info.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "to permit non-static references in an `impl Trait` \ + value, you can add an explicit bound for {}", + lifetime, + ), format!(" + {}", lifetime_name), - ), - _ => (lt.span, lifetime_name), + Applicability::MaybeIncorrect, + ); }; - err.span_suggestion_verbose( - span, - &msg, - sugg, - Applicability::MaybeIncorrect, - ); + } + TyKind::TraitObject(_, lt) => { + match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "to permit non-static references in a trait object \ + value, you can add an explicit bound for {}", + lifetime, + ), + format!(" + {}", lifetime_name), + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_suggestion_verbose( + lt.span, + "consider changing the trait object's explicit \ + `'static` bound", + lifetime_name, + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param_info.param_ty_span, + &format!( + "alternatively, set an explicit `'static` lifetime \ + in this parameter", + ), + param_info.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } + } } _ => {} } diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index 3ca506fe0d590..a2812e117ed39 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -247,7 +247,10 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { if let hir::TyKind::TraitObject( _, - hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. }, + hir::Lifetime { + name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, + .. + }, ) = ty.kind { self.0.push(ty); diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index beafe9258209d..837244b022721 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -22,7 +22,7 @@ fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } //~^ ERROR cannot infer an appropriate lifetime fn elided4(x: &i32) -> Box { Box::new(x) } -//~^ ERROR explicit lifetime required in the type of `x` +//~^ ERROR cannot infer an appropriate lifetime fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } //~^ ERROR cannot infer an appropriate lifetime diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 525e271bea9c3..96d4a121c16af 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -35,10 +35,14 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 9:1 +help: consider changing the `impl Trait`'s explicit `'static` bound | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ +help: alternatively, set an explicit `'static` lifetime to this parameter + | +LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:55 @@ -49,10 +53,14 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:14 +help: consider changing the `impl Trait`'s explicit `'static` bound | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^ +help: alternatively, set an explicit `'static` lifetime to this parameter + | +LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/must_outlive_least_region_or_bound.rs:15:24 @@ -71,10 +79,14 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 33:15 +help: consider changing the `impl Trait`'s explicit `'static` bound | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ^^ +help: alternatively, set an explicit `'static` lifetime to this parameter + | +LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x } + | ^^^^^^^^^^^^ error[E0623]: lifetime mismatch --> $DIR/must_outlive_least_region_or_bound.rs:38:61 @@ -103,7 +115,7 @@ LL | fn elided3(x: &i32) -> Box { Box::new(x) } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ @@ -118,47 +130,48 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | | ...is required to be `'static` by this... | data with this lifetime... | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14 +help: to permit non-static references in a trait object value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/must_outlive_least_region_or_bound.rs:24:51 +error: cannot infer an appropriate lifetime + --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ^^^^^^^^^^^ lifetime `'static` required - | | - | help: add explicit lifetime `'static` to the type of `x`: `&'static i32` - -error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/must_outlive_least_region_or_bound.rs:27:69 + | ---- ---------^- + | | | | + | | | ...and is captured here + | data with this lifetime... ...is required to be `'static` by this... | -LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^ +help: consider changing the trait object's explicit `'static` bound | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 27:14... - --> $DIR/must_outlive_least_region_or_bound.rs:27:14 +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter | -LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^^ -note: ...so that the expression is assignable +LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^ + +error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^ - = note: expected `&i32` - found `&'a i32` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | ------- ---------^- + | | | | + | | | ...and is captured here + | data with this lifetime... ...is required to be `'static` by this... | -LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ - = note: expected `std::boxed::Box<(dyn std::fmt::Debug + 'static)>` - found `std::boxed::Box` +help: consider changing the trait object's explicit `'static` bound + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter + | +LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^^ error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0495, E0621, E0623. +Some errors have detailed explanations: E0310, E0621, E0623. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 02d33aae023ff..038df47e1bd98 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -9,7 +9,7 @@ LL | Box::new(value) as Box | | ...and is captured here | ...is required to be `'static` by this... | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 70a9bf22b8db3..555622c9d13c1 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -7,7 +7,7 @@ LL | fn load(ss: &mut SomeStruct) -> Box { LL | ss.r | ^^^^ ...is captured and required to be `'static` here | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1 | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr index bf02ba8eb9199..7e8f78067e08a 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr @@ -1,21 +1,21 @@ -error[E0621]: explicit lifetime required in the type of `v` +error: lifetime may not live long enough --> $DIR/region-object-lifetime-in-coercion.rs:8:12 | LL | fn a(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | - let's call the lifetime of this reference `'1` LL | let x: Box = Box::new(v); - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:14:5 +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-in-coercion.rs:13:5 | LL | fn b(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | - let's call the lifetime of this reference `'1` LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` error: lifetime may not live long enough - --> $DIR/region-object-lifetime-in-coercion.rs:20:5 + --> $DIR/region-object-lifetime-in-coercion.rs:19:5 | LL | fn c(v: &[u8]) -> Box { | - let's call the lifetime of this reference `'1` @@ -24,7 +24,7 @@ LL | Box::new(v) | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` error: lifetime may not live long enough - --> $DIR/region-object-lifetime-in-coercion.rs:24:5 + --> $DIR/region-object-lifetime-in-coercion.rs:23:5 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | -- -- lifetime `'b` defined here @@ -37,4 +37,3 @@ LL | Box::new(v) error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs index d56eaf77b6646..5d199149c39b8 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs @@ -5,13 +5,12 @@ trait Foo {} impl<'a> Foo for &'a [u8] {} fn a(v: &[u8]) -> Box { - let x: Box = Box::new(v); - //~^ ERROR explicit lifetime required in the type of `v` [E0621] + let x: Box = Box::new(v); //~ ERROR cannot infer an appropriate lifetime x } fn b(v: &[u8]) -> Box { - Box::new(v) //~ ERROR explicit lifetime required in the type of `v` [E0621] + Box::new(v) //~ ERROR cannot infer an appropriate lifetime } fn c(v: &[u8]) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 1462af44cb15a..673300cebc26c 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -1,21 +1,45 @@ -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:8:37 +error: cannot infer an appropriate lifetime + --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | ----- data with this lifetime... LL | let x: Box = Box::new(v); - | ^^^^^^^^^^^ lifetime `'static` required + | ---------^- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... + | +help: consider changing the trait object's explicit `'static` bound + | +LL | fn a(v: &[u8]) -> Box { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter + | +LL | fn a(v: &'static [u8]) -> Box { + | ^^^^^^^^^^^^^ -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:14:5 +error: cannot infer an appropriate lifetime + --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | ----- data with this lifetime... LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ---------^- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... + | +help: consider changing the trait object's explicit `'static` bound + | +LL | fn b(v: &[u8]) -> Box { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter + | +LL | fn b(v: &'static [u8]) -> Box { + | ^^^^^^^^^^^^^ error: cannot infer an appropriate lifetime - --> $DIR/region-object-lifetime-in-coercion.rs:20:14 + --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { | ----- data with this lifetime... @@ -26,36 +50,36 @@ LL | Box::new(v) | | ...and is captured here | ...is required to be `'static` by this... | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 17:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 16:1 | LL | fn c(v: &[u8]) -> Box { | ^^^^ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/region-object-lifetime-in-coercion.rs:24:14 + --> $DIR/region-object-lifetime-in-coercion.rs:23:14 | LL | Box::new(v) | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 23:6... - --> $DIR/region-object-lifetime-in-coercion.rs:23:6 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:6... + --> $DIR/region-object-lifetime-in-coercion.rs:22:6 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ note: ...so that the expression is assignable - --> $DIR/region-object-lifetime-in-coercion.rs:24:14 + --> $DIR/region-object-lifetime-in-coercion.rs:23:14 | LL | Box::new(v) | ^ = note: expected `&[u8]` found `&'a [u8]` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 23:9... - --> $DIR/region-object-lifetime-in-coercion.rs:23:9 +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 22:9... + --> $DIR/region-object-lifetime-in-coercion.rs:22:9 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ note: ...so that the expression is assignable - --> $DIR/region-object-lifetime-in-coercion.rs:24:5 + --> $DIR/region-object-lifetime-in-coercion.rs:23:5 | LL | Box::new(v) | ^^^^^^^^^^^ @@ -64,5 +88,4 @@ LL | Box::new(v) error: aborting due to 4 previous errors -Some errors have detailed explanations: E0495, E0621. -For more information about an error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 147f7f3541816..982ed07232a80 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,28 +1,22 @@ -error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements +error: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-2.rs:10:11 | +LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { + | ------------------ data with this lifetime... LL | box B(&*v) as Box - | ^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6... - --> $DIR/regions-close-object-into-object-2.rs:9:6 + | ------^^^--------------- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... | -LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { - | ^^ -note: ...so that the type `(dyn A + 'a)` is not borrowed for too long - --> $DIR/regions-close-object-into-object-2.rs:10:11 +help: consider changing the trait object's explicit `'static` bound | -LL | box B(&*v) as Box - | ^^^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/regions-close-object-into-object-2.rs:10:5 +LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter | -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `std::boxed::Box<(dyn X + 'static)>` - found `std::boxed::Box` +LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 6e7d6152cd09a..1b82098ee13c2 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -1,28 +1,22 @@ -error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements +error: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-4.rs:10:11 | +LL | fn i<'a, T, U>(v: Box+'a>) -> Box { + | ---------------- data with this lifetime... LL | box B(&*v) as Box - | ^^^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6... - --> $DIR/regions-close-object-into-object-4.rs:9:6 + | ------^^^--------------- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... | -LL | fn i<'a, T, U>(v: Box+'a>) -> Box { - | ^^ -note: ...so that the type `(dyn A + 'a)` is not borrowed for too long - --> $DIR/regions-close-object-into-object-4.rs:10:11 +help: consider changing the trait object's explicit `'static` bound | -LL | box B(&*v) as Box - | ^^^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/regions-close-object-into-object-4.rs:10:5 +LL | fn i<'a, T, U>(v: Box+'a>) -> Box { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter | -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `std::boxed::Box<(dyn X + 'static)>` - found `std::boxed::Box` +LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A + 'static)>) -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-proc-bound-capture.nll.stderr b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr new file mode 100644 index 0000000000000..75890b8581537 --- /dev/null +++ b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/regions-proc-bound-capture.rs:9:5 + | +LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { + | - let's call the lifetime of this reference `'1` +LL | // This is illegal, because the region bound on `proc` is 'static. +LL | Box::new(move || { *x }) + | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs index 0c903b7384992..8617c0e9da8f7 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.rs +++ b/src/test/ui/regions/regions-proc-bound-capture.rs @@ -4,9 +4,9 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> { Box::new(move|| { *x }) } -fn static_proc(x: &isize) -> Box(isize) + 'static> { +fn static_proc(x: &isize) -> Box (isize) + 'static> { // This is illegal, because the region bound on `proc` is 'static. - Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621] + Box::new(move || { *x }) //~ ERROR cannot infer an appropriate lifetime } fn main() { } diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index c53af34456ef3..e7bbfaababe8a 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -1,12 +1,23 @@ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/regions-proc-bound-capture.rs:9:5 +error: cannot infer an appropriate lifetime + --> $DIR/regions-proc-bound-capture.rs:9:14 | -LL | fn static_proc(x: &isize) -> Box(isize) + 'static> { - | ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize` +LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { + | ------ data with this lifetime... LL | // This is illegal, because the region bound on `proc` is 'static. -LL | Box::new(move|| { *x }) - | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required +LL | Box::new(move || { *x }) + | ---------^^^^^^^^^^^^^^- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... + | +help: consider changing the trait object's explicit `'static` bound + | +LL | fn static_proc(x: &isize) -> Box (isize) + '_> { + | ^^ +help: alternatively, set an explicit `'static` lifetime in this parameter + | +LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> { + | ^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 3577dd59289e5..4dc4aac6ceac4 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -7,7 +7,7 @@ LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to LL | Box::new(items.iter()) | ---------------^^^^--- ...is captured and required to be `'static` here | -help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1 | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ From abf74b9e729463a18f5da1d79cecaf9f4fc07d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 18:59:42 -0700 Subject: [PATCH 21/37] Reduce verbosity of suggestion message and mention lifetime in label --- .../nice_region_error/static_impl_trait.rs | 87 ++++++++++--------- .../ui/async-await/issues/issue-62097.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 38 ++++---- .../static-return-lifetime-infered.stderr | 8 +- src/test/ui/issues/issue-16922.stderr | 4 +- ...ect-lifetime-default-from-box-error.stderr | 4 +- .../region-object-lifetime-in-coercion.stderr | 12 +-- .../regions-close-object-into-object-2.stderr | 4 +- .../regions-close-object-into-object-4.stderr | 4 +- .../regions/regions-proc-bound-capture.stderr | 4 +- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 4 +- .../missing-lifetimes-in-signature.stderr | 4 +- .../dyn-trait-underscore.stderr | 4 +- 14 files changed, 95 insertions(+), 86 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index e24535bba5fdc..e9f165d309f8f 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -1,6 +1,5 @@ //! Error Reporting for static impl Traits. -use crate::infer::error_reporting::msg_span_from_free_region; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use rustc_errors::{Applicability, ErrorReported}; @@ -33,9 +32,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let sp = var_origin.span(); let return_sp = sub_origin.span(); let param_info = self.find_param_with_region(sup_r, sub_r)?; + let (lifetime_name, lifetime) = if sup_r.has_name() { + (sup_r.to_string(), format!("lifetime `{}`", sup_r)) + } else { + ("'_".to_owned(), "the anonymous lifetime `'_`".to_string()) + }; let mut err = self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); - err.span_label(param_info.param_ty_span, "data with this lifetime..."); + err.span_label( + param_info.param_ty_span, + &format!("this data with {}...", lifetime), + ); debug!("try_report_static_impl_trait: param_info={:?}", param_info); // We try to make the output have fewer overlapping spans if possible. @@ -60,10 +67,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } - let (lifetime, _) = msg_span_from_free_region(self.tcx(), sup_r); - - let lifetime_name = - if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; // only apply this suggestion onto functions with // explicit non-desugar'able return. if fn_return.span.desugaring_kind().is_none() { @@ -93,8 +96,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { err.span_suggestion_verbose( span, - "consider changing the `impl Trait`'s explicit \ - `'static` bound", + &format!( + "consider changing the `impl Trait`'s explicit \ + `'static` bound to {}", + lifetime, + ), lifetime_name, Applicability::MaybeIncorrect, ); @@ -118,40 +124,41 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); }; } - TyKind::TraitObject(_, lt) => { - match lt.name { - LifetimeName::ImplicitObjectLifetimeDefault => { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!( - "to permit non-static references in a trait object \ - value, you can add an explicit bound for {}", - lifetime, - ), - format!(" + {}", lifetime_name), - Applicability::MaybeIncorrect, - ); - } - _ => { - err.span_suggestion_verbose( - lt.span, + TyKind::TraitObject(_, lt) => match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "to permit non-static references in a trait object \ + value, you can add an explicit bound for {}", + lifetime, + ), + format!(" + {}", lifetime_name), + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_suggestion_verbose( + lt.span, + &format!( "consider changing the trait object's explicit \ - `'static` bound", - lifetime_name, - Applicability::MaybeIncorrect, - ); - err.span_suggestion_verbose( - param_info.param_ty_span, - &format!( - "alternatively, set an explicit `'static` lifetime \ - in this parameter", - ), - param_info.param_ty.to_string(), - Applicability::MaybeIncorrect, - ); - } + `'static` bound to {}", + lifetime, + ), + lifetime_name, + Applicability::MaybeIncorrect, + ); + err.span_suggestion_verbose( + param_info.param_ty_span, + &format!( + "alternatively, set an explicit `'static` lifetime \ + in this parameter", + ), + param_info.param_ty.to_string(), + Applicability::MaybeIncorrect, + ); } - } + }, _ => {} } } diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index af8fc2cd2ab45..fff43ae9f47bc 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime LL | pub async fn run_dummy_fn(&self) { | ^^^^^ | | - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | ...is captured here... LL | foo(|| self.bar()).await; | --- ...and required to be `'static` by this diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 96d4a121c16af..00b6ec38323c3 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -5,9 +5,9 @@ LL | fn elided(x: &i32) -> impl Copy { x } | ---- --------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ @@ -19,9 +19,9 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ------- --------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with lifetime `'a`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 6:13 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ @@ -33,9 +33,9 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ------------------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | -help: consider changing the `impl Trait`'s explicit `'static` bound +help: consider changing the `impl Trait`'s explicit `'static` bound to the anonymous lifetime `'_` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ @@ -51,9 +51,9 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ------------------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with lifetime `'a`... | -help: consider changing the `impl Trait`'s explicit `'static` bound +help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^ @@ -77,9 +77,9 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- -------------------------------- ^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with lifetime `'a`... | -help: consider changing the `impl Trait`'s explicit `'static` bound +help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ^^ @@ -113,9 +113,9 @@ LL | fn elided3(x: &i32) -> Box { Box::new(x) } | | | | | | | ...and is captured here | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ @@ -128,9 +128,9 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | | | | | | | ...and is captured here | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with lifetime `'a`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14 +help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a` | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ @@ -142,9 +142,10 @@ LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ---- ---------^- | | | | | | | ...and is captured here - | data with this lifetime... ...is required to be `'static` by this... + | | ...is required to be `'static` by this... + | this data with the anonymous lifetime `'_`... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ^^ @@ -160,9 +161,10 @@ LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ------- ---------^- | | | | | | | ...and is captured here - | data with this lifetime... ...is required to be `'static` by this... + | | ...is required to be `'static` by this... + | this data with lifetime `'a`... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^ diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 1c3a5979ee55b..67d4f60dff6f1 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -4,13 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn iter_values_anon(&self) -> impl Iterator { | ----- ----------------------- ...is required to be `'static` by this... | | - | data with this lifetime... + | this data with the anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ @@ -21,13 +21,13 @@ error: cannot infer an appropriate lifetime LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -------- ----------------------- ...is required to be `'static` by this... | | - | data with this lifetime... + | this data with lifetime `'a`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the method body at 10:20 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ^^^^ diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 038df47e1bd98..c533a72dfc014 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { - | -- data with this lifetime... + | -- this data with the anonymous lifetime `'_`... LL | Box::new(value) as Box | ---------^^^^^- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 555622c9d13c1..6edef8086b937 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -2,12 +2,12 @@ error: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { - | --------------- data with this lifetime... + | --------------- this data with the anonymous lifetime `'_`... ... LL | ss.r | ^^^^ ...is captured and required to be `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 673300cebc26c..4b08c4bff2ebc 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { - | ----- data with this lifetime... + | ----- this data with the anonymous lifetime `'_`... LL | let x: Box = Box::new(v); | ---------^- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn a(v: &[u8]) -> Box { | ^^ @@ -22,14 +22,14 @@ error: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { - | ----- data with this lifetime... + | ----- this data with the anonymous lifetime `'_`... LL | Box::new(v) | ---------^- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn b(v: &[u8]) -> Box { | ^^ @@ -42,7 +42,7 @@ error: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { - | ----- data with this lifetime... + | ----- this data with the anonymous lifetime `'_`... ... LL | Box::new(v) | ---------^- @@ -50,7 +50,7 @@ LL | Box::new(v) | | ...and is captured here | ...is required to be `'static` by this... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 16:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn c(v: &[u8]) -> Box { | ^^^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 982ed07232a80..894be310fd14b 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-2.rs:10:11 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { - | ------------------ data with this lifetime... + | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box | ------^^^--------------- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 1b82098ee13c2..ce261d78c2909 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-4.rs:10:11 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { - | ---------------- data with this lifetime... + | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box | ------^^^--------------- | | | | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index e7bbfaababe8a..a0df1815247c3 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -2,7 +2,7 @@ error: cannot infer an appropriate lifetime --> $DIR/regions-proc-bound-capture.rs:9:14 | LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { - | ------ data with this lifetime... + | ------ this data with the anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) | ---------^^^^^^^^^^^^^^- @@ -10,7 +10,7 @@ LL | Box::new(move || { *x }) | | ...and is captured here | ...is required to be `'static` by this... | -help: consider changing the trait object's explicit `'static` bound +help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { | ^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 1aeabce5e8aaf..5520341b5b1c3 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | ^^^^ ---------- ---------- ...and required to be `'static` by this | | | - | | data with this lifetime... + | | this data with the anonymous lifetime `'_`... | ...is captured here... error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 04c475be787b8..5374929f3a45f 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -5,9 +5,9 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ---------- ---------- ^^^^ ...and is captured here | | | | | ...is required to be `'static` by this... - | data with this lifetime... + | this data with the anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ^^^^ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 5cf170d566ca9..471f3cd14aa3e 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -12,14 +12,14 @@ error: cannot infer an appropriate lifetime LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() | ------ ------------- ...is required to be `'static` by this... | | - | data with this lifetime... + | this data with the anonymous lifetime `'_`... ... LL | / move || { LL | | *dest = g.get(); LL | | } | |_____^ ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 15:1 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 4dc4aac6ceac4..5fd03f9770e5d 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -2,12 +2,12 @@ error: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | LL | fn a(items: &[T]) -> Box> { - | ---- data with this lifetime... + | ---- this data with the anonymous lifetime `'_`... LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) | ---------------^^^^--- ...is captured and required to be `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1 +help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ From 50c422e028dd7b66302eabb987fe1da482bee8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 May 2020 19:46:22 -0700 Subject: [PATCH 22/37] Move overlapping span to a note --- .../nice_region_error/static_impl_trait.rs | 31 ++++++++++++- .../must_outlive_least_region_or_bound.stderr | 44 ++++++++++++------- src/test/ui/issues/issue-16922.stderr | 10 +++-- .../region-object-lifetime-in-coercion.stderr | 30 ++++++++----- .../regions-close-object-into-object-2.stderr | 10 +++-- .../regions-close-object-into-object-4.stderr | 10 +++-- .../regions/regions-proc-bound-capture.stderr | 10 +++-- 7 files changed, 99 insertions(+), 46 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index e9f165d309f8f..cc95441b68a03 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -53,7 +53,36 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Customize the spans and labels depending on their relative order so // that split sentences flow correctly. - if sup_origin.span().shrink_to_hi() <= return_sp.shrink_to_lo() { + if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { + // Avoid the following: + // + // error: cannot infer an appropriate lifetime + // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + // | + // LL | fn foo(x: &i32) -> Box { Box::new(x) } + // | ---- ---------^- + // | | | | + // | | | ...and is captured here + // | | ...is required to be `'static` by this... + // | this data with the anonymous lifetime `'_`... + // + // and instead show: + // + // error: cannot infer an appropriate lifetime + // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 + // | + // LL | fn foo(x: &i32) -> Box { Box::new(x) } + // | ---- ^ ...is captured here with a `'static` requirement + // | | + // | this data with the anonymous lifetime `'_`... + // | + // note: ...is required to be `'static` by this + // | + // LL | fn elided3(x: &i32) -> Box { Box::new(x) } + // | ^^^^^^^^^^^ + err.span_label(sup_origin.span(), "...is captured here..."); + err.span_note(return_sp, "...and required to be `'static` by this"); + } else if sup_origin.span() <= return_sp { err.span_label(sup_origin.span(), "...is captured here..."); err.span_label(return_sp, "...and required to be `'static` by this"); } else { diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 00b6ec38323c3..2da49379ea8c2 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -109,12 +109,15 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ---- ---------^- - | | | | - | | | ...and is captured here - | | ...is required to be `'static` by this... + | ---- ^ ...is captured here... + | | | this data with the anonymous lifetime `'_`... | +note: ...and required to be `'static` by this + --> $DIR/must_outlive_least_region_or_bound.rs:18:41 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn elided3(x: &i32) -> Box { Box::new(x) } @@ -124,12 +127,15 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ---------^- - | | | | - | | | ...and is captured here - | | ...is required to be `'static` by this... + | ------- ^ ...is captured here... + | | | this data with lifetime `'a`... | +note: ...and required to be `'static` by this + --> $DIR/must_outlive_least_region_or_bound.rs:21:50 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a` | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } @@ -139,12 +145,15 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ---------^- - | | | | - | | | ...and is captured here - | | ...is required to be `'static` by this... + | ---- ^ ...is captured here... + | | | this data with the anonymous lifetime `'_`... | +note: ...and required to be `'static` by this + --> $DIR/must_outlive_least_region_or_bound.rs:24:51 + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } @@ -158,12 +167,13 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ---------^- - | | | | - | | | ...and is captured here - | | ...is required to be `'static` by this... - | this data with lifetime `'a`... + | ------- this data with lifetime `'a`... ^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index c533a72dfc014..6c0b26a86b651 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn foo(value: &T) -> Box { | -- this data with the anonymous lifetime `'_`... LL | Box::new(value) as Box - | ---------^^^^^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^^^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/issue-16922.rs:4:5 + | +LL | Box::new(value) as Box + | ^^^^^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn foo(value: &T) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 4b08c4bff2ebc..b333c314c57c9 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn a(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ---------^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/region-object-lifetime-in-coercion.rs:8:37 + | +LL | let x: Box = Box::new(v); + | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn a(v: &[u8]) -> Box { @@ -24,11 +26,13 @@ error: cannot infer an appropriate lifetime LL | fn b(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... LL | Box::new(v) - | ---------^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/region-object-lifetime-in-coercion.rs:13:5 + | +LL | Box::new(v) + | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn b(v: &[u8]) -> Box { @@ -45,11 +49,13 @@ LL | fn c(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... ... LL | Box::new(v) - | ---------^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^ ...is captured here... + | +note: ...and required to be `'static` by this + --> $DIR/region-object-lifetime-in-coercion.rs:19:5 | +LL | Box::new(v) + | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn c(v: &[u8]) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 894be310fd14b..3127ae65ace7d 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box - | ------^^^--------------- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/regions-close-object-into-object-2.rs:10:5 + | +LL | box B(&*v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index ce261d78c2909..b18c61f137694 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box - | ------^^^--------------- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/regions-close-object-into-object-4.rs:10:5 + | +LL | box B(&*v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index a0df1815247c3..5cb9506afd351 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -5,11 +5,13 @@ LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { | ------ this data with the anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) - | ---------^^^^^^^^^^^^^^- - | | | - | | ...and is captured here - | ...is required to be `'static` by this... + | ^^^^^^^^^^^^^^ ...is captured here... | +note: ...and required to be `'static` by this + --> $DIR/regions-proc-bound-capture.rs:9:5 + | +LL | Box::new(move || { *x }) + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { From 17951e21d4c690ad70e79a40d223a0d0984c0f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 30 May 2020 09:54:05 -0700 Subject: [PATCH 23/37] Tweak output for overlapping required/captured spans --- .../nice_region_error/static_impl_trait.rs | 10 +++---- .../must_outlive_least_region_or_bound.stderr | 28 +++---------------- src/test/ui/issues/issue-16922.stderr | 7 +---- .../region-object-lifetime-in-coercion.stderr | 21 ++------------ .../regions-close-object-into-object-2.stderr | 7 +---- .../regions-close-object-into-object-4.stderr | 7 +---- .../regions/regions-proc-bound-capture.stderr | 7 +---- 7 files changed, 15 insertions(+), 72 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index cc95441b68a03..253057536f133 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -76,12 +76,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // | | // | this data with the anonymous lifetime `'_`... // | - // note: ...is required to be `'static` by this - // | - // LL | fn elided3(x: &i32) -> Box { Box::new(x) } - // | ^^^^^^^^^^^ - err.span_label(sup_origin.span(), "...is captured here..."); - err.span_note(return_sp, "...and required to be `'static` by this"); + err.span_label( + sup_origin.span(), + "...is captured here with a `'static` requirement", + ); } else if sup_origin.span() <= return_sp { err.span_label(sup_origin.span(), "...is captured here..."); err.span_label(return_sp, "...and required to be `'static` by this"); diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 2da49379ea8c2..82e44cff9cc44 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -109,15 +109,10 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here... + | ---- ^ ...is captured here with a `'static` requirement | | | this data with the anonymous lifetime `'_`... | -note: ...and required to be `'static` by this - --> $DIR/must_outlive_least_region_or_bound.rs:18:41 - | -LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn elided3(x: &i32) -> Box { Box::new(x) } @@ -127,15 +122,10 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ^ ...is captured here... + | ------- ^ ...is captured here with a `'static` requirement | | | this data with lifetime `'a`... | -note: ...and required to be `'static` by this - --> $DIR/must_outlive_least_region_or_bound.rs:21:50 - | -LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a` | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } @@ -145,15 +135,10 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here... + | ---- ^ ...is captured here with a `'static` requirement | | | this data with the anonymous lifetime `'_`... | -note: ...and required to be `'static` by this - --> $DIR/must_outlive_least_region_or_bound.rs:24:51 - | -LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } @@ -167,13 +152,8 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- this data with lifetime `'a`... ^ ...is captured here... + | ------- this data with lifetime `'a`... ^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/must_outlive_least_region_or_bound.rs:27:60 - | -LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 6c0b26a86b651..a254343cd1bb7 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime LL | fn foo(value: &T) -> Box { | -- this data with the anonymous lifetime `'_`... LL | Box::new(value) as Box - | ^^^^^ ...is captured here... + | ^^^^^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/issue-16922.rs:4:5 - | -LL | Box::new(value) as Box - | ^^^^^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn foo(value: &T) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index b333c314c57c9..97d1f3579fcd8 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime LL | fn a(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ^ ...is captured here... + | ^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/region-object-lifetime-in-coercion.rs:8:37 - | -LL | let x: Box = Box::new(v); - | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn a(v: &[u8]) -> Box { @@ -26,13 +21,8 @@ error: cannot infer an appropriate lifetime LL | fn b(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... LL | Box::new(v) - | ^ ...is captured here... + | ^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/region-object-lifetime-in-coercion.rs:13:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn b(v: &[u8]) -> Box { @@ -49,13 +39,8 @@ LL | fn c(v: &[u8]) -> Box { | ----- this data with the anonymous lifetime `'_`... ... LL | Box::new(v) - | ^ ...is captured here... - | -note: ...and required to be `'static` by this - --> $DIR/region-object-lifetime-in-coercion.rs:19:5 + | ^ ...is captured here with a `'static` requirement | -LL | Box::new(v) - | ^^^^^^^^^^^ help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` | LL | fn c(v: &[u8]) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 3127ae65ace7d..3d707f2d99941 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here... + | ^^^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/regions-close-object-into-object-2.rs:10:5 - | -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index b18c61f137694..70282c8cbdb30 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here... + | ^^^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/regions-close-object-into-object-4.rs:10:5 - | -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index 5cb9506afd351..8f93fad7fe9d8 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -5,13 +5,8 @@ LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { | ------ this data with the anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) - | ^^^^^^^^^^^^^^ ...is captured here... + | ^^^^^^^^^^^^^^ ...is captured here with a `'static` requirement | -note: ...and required to be `'static` by this - --> $DIR/regions-proc-bound-capture.rs:9:5 - | -LL | Box::new(move || { *x }) - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { From 19bb589410f2ab0ff14178992ef4b44fbe5e297b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 30 May 2020 10:15:58 -0700 Subject: [PATCH 24/37] Tweak wording and add error code --- .../nice_region_error/static_impl_trait.rs | 35 +++++++------ .../ui/async-await/issues/issue-62097.stderr | 6 +-- .../must_outlive_least_region_or_bound.stderr | 52 +++++++++---------- .../static-return-lifetime-infered.stderr | 12 ++--- src/test/ui/issues/issue-16922.stderr | 8 +-- ...ect-lifetime-default-from-box-error.stderr | 8 +-- .../region-object-lifetime-in-coercion.stderr | 24 ++++----- .../regions-close-object-into-object-2.stderr | 4 +- .../regions-close-object-into-object-4.stderr | 4 +- .../regions/regions-proc-bound-capture.stderr | 8 +-- ...types_pin_lifetime_impl_trait-async.stderr | 6 +-- ..._self_types_pin_lifetime_impl_trait.stderr | 8 +-- .../missing-lifetimes-in-signature.stderr | 8 +-- .../dyn-trait-underscore.stderr | 8 +-- 14 files changed, 97 insertions(+), 94 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 253057536f133..4e16e8c2c5717 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -2,7 +2,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use rustc_errors::{Applicability, ErrorReported}; +use rustc_errors::{struct_span_err, Applicability, ErrorReported}; use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind}; use rustc_middle::ty::RegionKind; @@ -35,10 +35,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let (lifetime_name, lifetime) = if sup_r.has_name() { (sup_r.to_string(), format!("lifetime `{}`", sup_r)) } else { - ("'_".to_owned(), "the anonymous lifetime `'_`".to_string()) + ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) }; - let mut err = - self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); + let mut err = struct_span_err!( + self.tcx().sess, + sp, + E0758, + "cannot infer an appropriate lifetime" + ); err.span_label( param_info.param_ty_span, &format!("this data with {}...", lifetime), @@ -61,10 +65,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // | // LL | fn foo(x: &i32) -> Box { Box::new(x) } // | ---- ---------^- - // | | | | - // | | | ...and is captured here - // | | ...is required to be `'static` by this... - // | this data with the anonymous lifetime `'_`... // // and instead show: // @@ -72,25 +72,28 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 // | // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ^ ...is captured here with a `'static` requirement - // | | - // | this data with the anonymous lifetime `'_`... - // | + // | ---- ^ err.span_label( sup_origin.span(), - "...is captured here with a `'static` requirement", + "...is captured here requiring it to live as long as `'static`", ); } else if sup_origin.span() <= return_sp { err.span_label(sup_origin.span(), "...is captured here..."); - err.span_label(return_sp, "...and required to be `'static` by this"); + err.span_label( + return_sp, + "...and required to live as long as `'static` by this", + ); } else { - err.span_label(return_sp, "...is required to be `'static` by this..."); + err.span_label( + return_sp, + "...is required to live as long as `'static` by this...", + ); err.span_label(sup_origin.span(), "...and is captured here"); } } else { err.span_label( return_sp, - "...is captured and required to be `'static` here", + "...is captured and required live as long as `'static` here", ); } diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index fff43ae9f47bc..558d89f928945 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/issue-62097.rs:12:31 | LL | pub async fn run_dummy_fn(&self) { | ^^^^^ | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... | ...is captured here... LL | foo(|| self.bar()).await; - | --- ...and required to be `'static` by this + | --- ...and required to live as long as `'static` by this error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 82e44cff9cc44..eff56ddc440d4 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -1,24 +1,24 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } | ---- --------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... - | this data with the anonymous lifetime `'_`... + | | ...is required to live as long as `'static` by this... + | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ------- --------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... + | | ...is required to live as long as `'static` by this... | this data with lifetime `'a`... | help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` @@ -26,16 +26,16 @@ help: to permit non-static references in an `impl Trait` value, you can add an e LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ------------------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... - | this data with the anonymous lifetime `'_`... + | | ...is required to live as long as `'static` by this... + | this data with an anonymous lifetime `'_`... | -help: consider changing the `impl Trait`'s explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the `impl Trait`'s explicit `'static` bound to an anonymous lifetime `'_` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ @@ -44,13 +44,13 @@ help: alternatively, set an explicit `'static` lifetime to this parameter LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ------------------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... + | | ...is required to live as long as `'static` by this... | this data with lifetime `'a`... | help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` @@ -70,13 +70,13 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | | | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- -------------------------------- ^ ...and is captured here | | | - | | ...is required to be `'static` by this... + | | ...is required to live as long as `'static` by this... | this data with lifetime `'a`... | help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` @@ -105,24 +105,24 @@ LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | | | help: consider adding an explicit lifetime bound...: `T: 'static +` -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here with a `'static` requirement + | ---- ^ ...is captured here requiring it to live as long as `'static` | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ^ ...is captured here with a `'static` requirement + | ------- ^ ...is captured here requiring it to live as long as `'static` | | | this data with lifetime `'a`... | @@ -131,15 +131,15 @@ help: to permit non-static references in a trait object value, you can add an ex LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here with a `'static` requirement + | ---- ^ ...is captured here requiring it to live as long as `'static` | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... | -help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ^^ @@ -148,11 +148,11 @@ help: alternatively, set an explicit `'static` lifetime in this parameter LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- this data with lifetime `'a`... ^ ...is captured here with a `'static` requirement + | ------- this data with lifetime `'a`... ^ ...is captured here requiring it to live as long as `'static` | help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 67d4f60dff6f1..a48580ee2d2fc 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -1,25 +1,25 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- ----------------------- ...is required to be `'static` by this... + | ----- ----------------------- ...is required to live as long as `'static` by this... | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -------- ----------------------- ...is required to be `'static` by this... + | -------- ----------------------- ...is required to live as long as `'static` by this... | | | this data with lifetime `'a`... LL | self.x.iter().map(|a| a.0) diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index a254343cd1bb7..53fd658800a7a 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,12 +1,12 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { - | -- this data with the anonymous lifetime `'_`... + | -- this data with an anonymous lifetime `'_`... LL | Box::new(value) as Box - | ^^^^^ ...is captured here with a `'static` requirement + | ^^^^^ ...is captured here requiring it to live as long as `'static` | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 6edef8086b937..04a06104faf99 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { - | --------------- this data with the anonymous lifetime `'_`... + | --------------- this data with an anonymous lifetime `'_`... ... LL | ss.r - | ^^^^ ...is captured and required to be `'static` here + | ^^^^ ...is captured and required live as long as `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 97d1f3579fcd8..34cf131319a1c 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -1,12 +1,12 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { - | ----- this data with the anonymous lifetime `'_`... + | ----- this data with an anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ^ ...is captured here with a `'static` requirement + | ^ ...is captured here requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` | LL | fn a(v: &[u8]) -> Box { | ^^ @@ -15,15 +15,15 @@ help: alternatively, set an explicit `'static` lifetime in this parameter LL | fn a(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { - | ----- this data with the anonymous lifetime `'_`... + | ----- this data with an anonymous lifetime `'_`... LL | Box::new(v) - | ^ ...is captured here with a `'static` requirement + | ^ ...is captured here requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` | LL | fn b(v: &[u8]) -> Box { | ^^ @@ -32,16 +32,16 @@ help: alternatively, set an explicit `'static` lifetime in this parameter LL | fn b(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { - | ----- this data with the anonymous lifetime `'_`... + | ----- this data with an anonymous lifetime `'_`... ... LL | Box::new(v) - | ^ ...is captured here with a `'static` requirement + | ^ ...is captured here requiring it to live as long as `'static` | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn c(v: &[u8]) -> Box { | ^^^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 3d707f2d99941..be47ef589af8c 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,10 +1,10 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-2.rs:10:11 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here with a `'static` requirement + | ^^^ ...is captured here requiring it to live as long as `'static` | help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 70282c8cbdb30..1b099c7d8bdf0 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -1,10 +1,10 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-4.rs:10:11 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here with a `'static` requirement + | ^^^ ...is captured here requiring it to live as long as `'static` | help: consider changing the trait object's explicit `'static` bound to lifetime `'a` | diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index 8f93fad7fe9d8..e8baf44bd10aa 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/regions-proc-bound-capture.rs:9:14 | LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { - | ------ this data with the anonymous lifetime `'_`... + | ------ this data with an anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) - | ^^^^^^^^^^^^^^ ...is captured here with a `'static` requirement + | ^^^^^^^^^^^^^^ ...is captured here requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { | ^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 5520341b5b1c3..92e1473a5da73 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,10 +1,10 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- ---------- ...and required to be `'static` by this + | ^^^^ ---------- ---------- ...and required to live as long as `'static` by this | | | - | | this data with the anonymous lifetime `'_`... + | | this data with an anonymous lifetime `'_`... | ...is captured here... error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 5374929f3a45f..6721d41bb73c9 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ---------- ---------- ^^^^ ...and is captured here | | | - | | ...is required to be `'static` by this... - | this data with the anonymous lifetime `'_`... + | | ...is required to live as long as `'static` by this... + | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ^^^^ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 471f3cd14aa3e..ba56255af5b0c 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,20 +6,20 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------ ------------- ...is required to be `'static` by this... + | ------ ------------- ...is required to live as long as `'static` by this... | | - | this data with the anonymous lifetime `'_`... + | this data with an anonymous lifetime `'_`... ... LL | / move || { LL | | *dest = g.get(); LL | | } | |_____^ ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 5fd03f9770e5d..20d3640d4118e 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,13 +1,13 @@ -error: cannot infer an appropriate lifetime +error[E0758]: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | LL | fn a(items: &[T]) -> Box> { - | ---- this data with the anonymous lifetime `'_`... + | ---- this data with an anonymous lifetime `'_`... LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ---------------^^^^--- ...is captured and required to be `'static` here + | ---------------^^^^--- ...is captured and required live as long as `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_` +help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ From 3cfecdee0d677e0982cd160991130a997ffc619e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 1 Jun 2020 16:15:10 -0700 Subject: [PATCH 25/37] review comments: wording --- .../nice_region_error/static_impl_trait.rs | 58 ++++++++++--------- .../ui/async-await/issues/issue-62097.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 46 +++++++-------- .../static-return-lifetime-infered.stderr | 8 +-- src/test/ui/issues/issue-16922.stderr | 4 +- ...ect-lifetime-default-from-box-error.stderr | 2 +- .../region-object-lifetime-in-coercion.stderr | 16 ++--- .../regions-close-object-into-object-2.stderr | 6 +- .../regions-close-object-into-object-4.stderr | 6 +- .../regions/regions-proc-bound-capture.stderr | 6 +- ...types_pin_lifetime_impl_trait-async.stderr | 2 +- ..._self_types_pin_lifetime_impl_trait.stderr | 4 +- .../missing-lifetimes-in-signature.stderr | 4 +- .../dyn-trait-underscore.stderr | 2 +- 14 files changed, 85 insertions(+), 81 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 4e16e8c2c5717..86f310eb71d76 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -75,18 +75,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // | ---- ^ err.span_label( sup_origin.span(), - "...is captured here requiring it to live as long as `'static`", + "...is captured here, requiring it to live as long as `'static`", ); } else if sup_origin.span() <= return_sp { err.span_label(sup_origin.span(), "...is captured here..."); err.span_label( return_sp, - "...and required to live as long as `'static` by this", + "...and is required to live as long as `'static` here", ); } else { err.span_label( return_sp, - "...is required to live as long as `'static` by this...", + "...is required to live as long as `'static` here...", ); err.span_label(sup_origin.span(), "...and is captured here"); } @@ -101,6 +101,20 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // explicit non-desugar'able return. if fn_return.span.desugaring_kind().is_none() { // FIXME: account for the need of parens in `&(dyn Trait + '_)` + + let consider = "consider changing the"; + let declare = "to declare that the"; + let arg = match param_info.param.pat.simple_ident() { + Some(simple_ident) => format!("argument `{}`", simple_ident), + None => "the argument".to_string(), + }; + let explicit = + format!("you can add an explicit `{}` lifetime bound", lifetime_name); + let explicit_static = format!("explicit `'static` bound to {}", arg); + let captures = format!("captures data from {}", arg); + let add_static_bound = + "alternatively, add an explicit `'static` bound to this reference"; + let plus_lt = format!(" + {}", lifetime_name); match fn_return.kind { TyKind::Def(item_id, _) => { let item = self.tcx().hir().item(item_id.id); @@ -126,18 +140,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { err.span_suggestion_verbose( span, - &format!( - "consider changing the `impl Trait`'s explicit \ - `'static` bound to {}", - lifetime, - ), + &format!("{} `impl Trait`'s {}", consider, explicit_static), lifetime_name, Applicability::MaybeIncorrect, ); err.span_suggestion_verbose( param_info.param_ty_span, - "alternatively, set an explicit `'static` lifetime to \ - this parameter", + add_static_bound, param_info.param_ty.to_string(), Applicability::MaybeIncorrect, ); @@ -145,11 +154,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), &format!( - "to permit non-static references in an `impl Trait` \ - value, you can add an explicit bound for {}", - lifetime, + "{declare} `impl Trait` {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, ), - format!(" + {}", lifetime_name), + plus_lt, Applicability::MaybeIncorrect, ); }; @@ -159,31 +169,25 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), &format!( - "to permit non-static references in a trait object \ - value, you can add an explicit bound for {}", - lifetime, + "{declare} trait object {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, ), - format!(" + {}", lifetime_name), + plus_lt, Applicability::MaybeIncorrect, ); } _ => { err.span_suggestion_verbose( lt.span, - &format!( - "consider changing the trait object's explicit \ - `'static` bound to {}", - lifetime, - ), + &format!("{} trait object's {}", consider, explicit_static), lifetime_name, Applicability::MaybeIncorrect, ); err.span_suggestion_verbose( param_info.param_ty_span, - &format!( - "alternatively, set an explicit `'static` lifetime \ - in this parameter", - ), + add_static_bound, param_info.param_ty.to_string(), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index 558d89f928945..e9f155c6ced31 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -7,7 +7,7 @@ LL | pub async fn run_dummy_fn(&self) { | this data with an anonymous lifetime `'_`... | ...is captured here... LL | foo(|| self.bar()).await; - | --- ...and required to live as long as `'static` by this + | --- ...and is required to live as long as `'static` here error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index eff56ddc440d4..a9fa0e93fed61 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -4,10 +4,10 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn elided(x: &i32) -> impl Copy { x } | ---- --------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ @@ -18,10 +18,10 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ------- --------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with lifetime `'a`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` +help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'a` lifetime bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ @@ -32,14 +32,14 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ---- ------------------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with an anonymous lifetime `'_`... | -help: consider changing the `impl Trait`'s explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ -help: alternatively, set an explicit `'static` lifetime to this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ @@ -50,14 +50,14 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ------- ------------------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with lifetime `'a`... | -help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` +help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^ -help: alternatively, set an explicit `'static` lifetime to this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ @@ -76,14 +76,14 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ------- -------------------------------- ^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with lifetime `'a`... | -help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a` +help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ^^ -help: alternatively, set an explicit `'static` lifetime to this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^ @@ -109,11 +109,11 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here requiring it to live as long as `'static` + | ---- ^ ...is captured here, requiring it to live as long as `'static` | | | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ @@ -122,11 +122,11 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- ^ ...is captured here requiring it to live as long as `'static` + | ------- ^ ...is captured here, requiring it to live as long as `'static` | | | this data with lifetime `'a`... | -help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a` +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ @@ -135,15 +135,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } - | ---- ^ ...is captured here requiring it to live as long as `'static` + | ---- ^ ...is captured here, requiring it to live as long as `'static` | | | this data with an anonymous lifetime `'_`... | -help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to argument `x` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ @@ -152,13 +152,13 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } - | ------- this data with lifetime `'a`... ^ ...is captured here requiring it to live as long as `'static` + | ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to lifetime `'a` +help: consider changing the trait object's explicit `'static` bound to argument `x` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index a48580ee2d2fc..6681eaa909ee0 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,7 +2,7 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- ----------------------- ...is required to live as long as `'static` by this... + | ----- ----------------------- ...is required to live as long as `'static` here... | | | this data with an anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) @@ -10,7 +10,7 @@ LL | self.x.iter().map(|a| a.0) | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ @@ -19,7 +19,7 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -------- ----------------------- ...is required to live as long as `'static` by this... + | -------- ----------------------- ...is required to live as long as `'static` here... | | | this data with lifetime `'a`... LL | self.x.iter().map(|a| a.0) @@ -27,7 +27,7 @@ LL | self.x.iter().map(|a| a.0) | | | ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a` +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ^^^^ diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 53fd658800a7a..95f46bd7f3eb6 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -4,9 +4,9 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn foo(value: &T) -> Box { | -- this data with an anonymous lifetime `'_`... LL | Box::new(value) as Box - | ^^^^^ ...is captured here requiring it to live as long as `'static` + | ^^^^^ ...is captured here, requiring it to live as long as `'static` | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound | LL | fn foo(value: &T) -> Box { | ^^^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 04a06104faf99..e585db262f2d8 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -7,7 +7,7 @@ LL | fn load(ss: &mut SomeStruct) -> Box { LL | ss.r | ^^^^ ...is captured and required live as long as `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound | LL | fn load(ss: &mut SomeStruct) -> Box { | ^^^^ diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 34cf131319a1c..8d048d90cb345 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -4,13 +4,13 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn a(v: &[u8]) -> Box { | ----- this data with an anonymous lifetime `'_`... LL | let x: Box = Box::new(v); - | ^ ...is captured here requiring it to live as long as `'static` + | ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to argument `v` | LL | fn a(v: &[u8]) -> Box { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn a(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ @@ -21,13 +21,13 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn b(v: &[u8]) -> Box { | ----- this data with an anonymous lifetime `'_`... LL | Box::new(v) - | ^ ...is captured here requiring it to live as long as `'static` + | ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to argument `v` | LL | fn b(v: &[u8]) -> Box { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn b(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ @@ -39,9 +39,9 @@ LL | fn c(v: &[u8]) -> Box { | ----- this data with an anonymous lifetime `'_`... ... LL | Box::new(v) - | ^ ...is captured here requiring it to live as long as `'static` + | ^ ...is captured here, requiring it to live as long as `'static` | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound | LL | fn c(v: &[u8]) -> Box { | ^^^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index be47ef589af8c..5dfe384112b2a 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -4,13 +4,13 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here requiring it to live as long as `'static` + | ^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to lifetime `'a` +help: consider changing the trait object's explicit `'static` bound to argument `v` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 1b099c7d8bdf0..4d23118ba06f0 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -4,13 +4,13 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... LL | box B(&*v) as Box - | ^^^ ...is captured here requiring it to live as long as `'static` + | ^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to lifetime `'a` +help: consider changing the trait object's explicit `'static` bound to argument `v` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A + 'static)>) -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index e8baf44bd10aa..e36f77ec1da96 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -5,13 +5,13 @@ LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { | ------ this data with an anonymous lifetime `'_`... LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) - | ^^^^^^^^^^^^^^ ...is captured here requiring it to live as long as `'static` + | ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to an anonymous lifetime `'_` +help: consider changing the trait object's explicit `'static` bound to argument `x` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { | ^^ -help: alternatively, set an explicit `'static` lifetime in this parameter +help: alternatively, add an explicit `'static` bound to this reference | LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> { | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 92e1473a5da73..365e38515b12c 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,7 +2,7 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- ---------- ...and required to live as long as `'static` by this + | ^^^^ ---------- ---------- ...and is required to live as long as `'static` here | | | | | this data with an anonymous lifetime `'_`... | ...is captured here... diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 6721d41bb73c9..bd3f3efad82f2 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -4,10 +4,10 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn f(self: Pin<&Self>) -> impl Clone { self } | ---------- ---------- ^^^^ ...and is captured here | | | - | | ...is required to live as long as `'static` by this... + | | ...is required to live as long as `'static` here... | this data with an anonymous lifetime `'_`... | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ^^^^ diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index ba56255af5b0c..d96a5f961bdb8 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,7 +10,7 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------ ------------- ...is required to live as long as `'static` by this... + | ------ ------------- ...is required to live as long as `'static` here... | | | this data with an anonymous lifetime `'_`... ... @@ -19,7 +19,7 @@ LL | | *dest = g.get(); LL | | } | |_____^ ...and is captured here | -help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ | ^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 20d3640d4118e..7c649f9c08d64 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -7,7 +7,7 @@ LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to LL | Box::new(items.iter()) | ---------------^^^^--- ...is captured and required live as long as `'static` here | -help: to permit non-static references in a trait object value, you can add an explicit bound for an anonymous lifetime `'_` +help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound | LL | fn a(items: &[T]) -> Box + '_> { | ^^^^ From bdfb9b18ab7ba6c4fc27c79dde62d678c25f3b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 1 Jun 2020 17:51:12 -0700 Subject: [PATCH 26/37] Use note for requirement source span --- .../nice_region_error/static_impl_trait.rs | 10 +--- .../ui/async-await/issues/issue-62097.stderr | 6 ++- .../must_outlive_least_region_or_bound.stderr | 50 +++++++++++++------ .../static-return-lifetime-infered.stderr | 22 +++++--- ...types_pin_lifetime_impl_trait-async.stderr | 11 ++-- ..._self_types_pin_lifetime_impl_trait.stderr | 10 ++-- .../missing-lifetimes-in-signature.stderr | 11 ++-- 7 files changed, 77 insertions(+), 43 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 86f310eb71d76..74267a8dec059 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -77,18 +77,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { sup_origin.span(), "...is captured here, requiring it to live as long as `'static`", ); - } else if sup_origin.span() <= return_sp { + } else { err.span_label(sup_origin.span(), "...is captured here..."); - err.span_label( + err.span_note( return_sp, "...and is required to live as long as `'static` here", ); - } else { - err.span_label( - return_sp, - "...is required to live as long as `'static` here...", - ); - err.span_label(sup_origin.span(), "...and is captured here"); } } else { err.span_label( diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index e9f155c6ced31..ff7007dd30b1b 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -6,8 +6,12 @@ LL | pub async fn run_dummy_fn(&self) { | | | this data with an anonymous lifetime `'_`... | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/issue-62097.rs:13:9 + | LL | foo(|| self.bar()).await; - | --- ...and is required to live as long as `'static` here + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index a9fa0e93fed61..698464b4971a7 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -2,11 +2,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } - | ---- --------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ---- ^ ...is captured here... + | | | this data with an anonymous lifetime `'_`... | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:3:23 + | +LL | fn elided(x: &i32) -> impl Copy { x } + | ^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } @@ -16,11 +20,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | ------- --------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ------- ^ ...is captured here... + | | | this data with lifetime `'a`... | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:6:32 + | +LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } + | ^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'a` lifetime bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } @@ -30,11 +38,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } - | ---- ------------------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ---- ^ ...is captured here... + | | | this data with an anonymous lifetime `'_`... | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:9:24 + | +LL | fn elided2(x: &i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } @@ -48,11 +60,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } - | ------- ------------------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ------- ^ ...is captured here... + | | | this data with lifetime `'a`... | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:12:33 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } + | ^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } @@ -74,11 +90,13 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } - | ------- -------------------------------- ^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... - | this data with lifetime `'a`... + | ------- this data with lifetime `'a`... ^ ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/must_outlive_least_region_or_bound.rs:33:34 | +LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 6681eaa909ee0..bcc46785c5918 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,14 +2,17 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- ----------------------- ...is required to live as long as `'static` here... - | | - | this data with an anonymous lifetime `'_`... + | ----- this data with an anonymous lifetime `'_`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...and is captured here + | ...is captured here... | +note: ...and is required to live as long as `'static` here + --> $DIR/static-return-lifetime-infered.rs:6:35 + | +LL | fn iter_values_anon(&self) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { @@ -19,14 +22,17 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -------- ----------------------- ...is required to live as long as `'static` here... - | | - | this data with lifetime `'a`... + | -------- this data with lifetime `'a`... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...and is captured here + | ...is captured here... | +note: ...and is required to live as long as `'static` here + --> $DIR/static-return-lifetime-infered.rs:10:37 + | +LL | fn iter_values<'a>(&'a self) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 365e38515b12c..2ffbf6e08158e 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,10 +2,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- ---------- ...and is required to live as long as `'static` here - | | | - | | this data with an anonymous lifetime `'_`... + | ^^^^ ---------- this data with an anonymous lifetime `'_`... + | | | ...is captured here... + | +note: ...and is required to live as long as `'static` here + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index bd3f3efad82f2..2da7bcf543d66 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -2,11 +2,15 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ---------- ---------- ^^^^ ...and is captured here - | | | - | | ...is required to live as long as `'static` here... + | ---------- ^^^^ ...is captured here... + | | | this data with an anonymous lifetime `'_`... | +note: ...and is required to live as long as `'static` here + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31 + | +LL | fn f(self: Pin<&Self>) -> impl Clone { self } + | ^^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index d96a5f961bdb8..95d905af05089 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,15 +10,18 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() - | ------ ------------- ...is required to live as long as `'static` here... - | | - | this data with an anonymous lifetime `'_`... + | ------ this data with an anonymous lifetime `'_`... ... LL | / move || { LL | | *dest = g.get(); LL | | } - | |_____^ ...and is captured here + | |_____^ ...is captured here... | +note: ...and is required to live as long as `'static` here + --> $DIR/missing-lifetimes-in-signature.rs:15:37 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + | ^^^^^^^^^^^^^ help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ From 215de3b3c5105982978582861b95b0b449dbff94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 2 Jun 2020 10:47:58 -0700 Subject: [PATCH 27/37] Register new eror code --- src/test/ui/async-await/issues/issue-62097.stderr | 1 + .../ui/impl-trait/must_outlive_least_region_or_bound.stderr | 2 +- src/test/ui/impl-trait/static-return-lifetime-infered.stderr | 1 + src/test/ui/issues/issue-16922.stderr | 1 + .../object-lifetime-default-from-box-error.stderr | 3 ++- src/test/ui/regions/region-object-lifetime-in-coercion.stderr | 3 ++- src/test/ui/regions/regions-close-object-into-object-2.stderr | 1 + src/test/ui/regions/regions-close-object-into-object-4.stderr | 1 + src/test/ui/regions/regions-proc-bound-capture.stderr | 1 + .../arbitrary_self_types_pin_lifetime_impl_trait-async.stderr | 1 + .../self/arbitrary_self_types_pin_lifetime_impl_trait.stderr | 1 + .../lifetimes/missing-lifetimes-in-signature.stderr | 2 +- src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr | 1 + 13 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index ff7007dd30b1b..b3754cce40833 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -15,3 +15,4 @@ LL | foo(|| self.bar()).await; error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 698464b4971a7..5ab450a85d9e1 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -183,5 +183,5 @@ LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0621, E0623. +Some errors have detailed explanations: E0310, E0621, E0623, E0758. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index bcc46785c5918..90aada01d9917 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -40,3 +40,4 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 95f46bd7f3eb6..ec80f6569f5ac 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -13,3 +13,4 @@ LL | fn foo(value: &T) -> Box { error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index e585db262f2d8..ac7502e004c44 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -23,4 +23,5 @@ LL | ss.r = b; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0621`. +Some errors have detailed explanations: E0621, E0758. +For more information about an error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 8d048d90cb345..fe191e9b69565 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -79,4 +79,5 @@ LL | Box::new(v) error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0495`. +Some errors have detailed explanations: E0495, E0758. +For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 5dfe384112b2a..2ea970afcede2 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -17,3 +17,4 @@ LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box(v: std::boxed::Box<(dyn A + 'static)>) -> Box Box (isize) + 'static> error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 2ffbf6e08158e..69022607bd19e 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -14,3 +14,4 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 2da7bcf543d66..c37eb2d136ef1 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -18,3 +18,4 @@ LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 95d905af05089..7e8ab1bfe1633 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -125,5 +125,5 @@ LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a error: aborting due to 7 previous errors -Some errors have detailed explanations: E0261, E0309, E0621. +Some errors have detailed explanations: E0261, E0309, E0621, E0758. For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 7c649f9c08d64..e768d7c8ab99f 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -14,3 +14,4 @@ LL | fn a(items: &[T]) -> Box + '_> { error: aborting due to previous error +For more information about this error, try `rustc --explain E0758`. From 187e1050a2d0ffd822e2ccc0baf8df9679bbde20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 2 Jun 2020 16:05:48 -0700 Subject: [PATCH 28/37] small tweaks --- .../nice_region_error/static_impl_trait.rs | 20 +++++++++++++------ .../ui/async-await/issues/issue-62097.stderr | 6 +----- .../must_outlive_least_region_or_bound.stderr | 10 +++++----- ...ect-lifetime-default-from-box-error.stderr | 2 +- .../region-object-lifetime-in-coercion.stderr | 4 ++-- .../regions-close-object-into-object-2.stderr | 2 +- .../regions-close-object-into-object-4.stderr | 2 +- .../regions/regions-proc-bound-capture.stderr | 2 +- ...types_pin_lifetime_impl_trait-async.stderr | 11 +++------- .../dyn-trait-underscore.stderr | 2 +- 10 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 74267a8dec059..5ad76e3964038 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -79,15 +79,22 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } else { err.span_label(sup_origin.span(), "...is captured here..."); - err.span_note( - return_sp, - "...and is required to live as long as `'static` here", - ); + if return_sp < sup_origin.span() { + err.span_note( + return_sp, + "...and is required to live as long as `'static` here", + ); + } else { + err.span_label( + return_sp, + "...and is required to live as long as `'static` here", + ); + } } } else { err.span_label( return_sp, - "...is captured and required live as long as `'static` here", + "...is captured and required to live as long as `'static` here", ); } @@ -104,7 +111,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }; let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); - let explicit_static = format!("explicit `'static` bound to {}", arg); + let explicit_static = + format!("explicit `'static` bound to the lifetime of {}", arg); let captures = format!("captures data from {}", arg); let add_static_bound = "alternatively, add an explicit `'static` bound to this reference"; diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index b3754cce40833..aa443b9d2fc16 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -6,12 +6,8 @@ LL | pub async fn run_dummy_fn(&self) { | | | this data with an anonymous lifetime `'_`... | ...is captured here... - | -note: ...and is required to live as long as `'static` here - --> $DIR/issue-62097.rs:13:9 - | LL | foo(|| self.bar()).await; - | ^^^ + | --- ...and is required to live as long as `'static` here error: aborting due to previous error diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 5ab450a85d9e1..baed43783a13c 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -47,7 +47,7 @@ note: ...and is required to live as long as `'static` here | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ -help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` +help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn elided2(x: &i32) -> impl Copy + '_ { x } | ^^ @@ -69,7 +69,7 @@ note: ...and is required to live as long as `'static` here | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^^^^^^^^ -help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` +help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^ @@ -97,7 +97,7 @@ note: ...and is required to live as long as `'static` here | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider changing the `impl Trait`'s explicit `'static` bound to argument `x` +help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x` | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } | ^^ @@ -157,7 +157,7 @@ LL | fn elided4(x: &i32) -> Box { Box::new(x) } | | | this data with an anonymous lifetime `'_`... | -help: consider changing the trait object's explicit `'static` bound to argument `x` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn elided4(x: &i32) -> Box { Box::new(x) } | ^^ @@ -172,7 +172,7 @@ error[E0758]: cannot infer an appropriate lifetime LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `x` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^ diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index ac7502e004c44..d461001adead9 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -5,7 +5,7 @@ LL | fn load(ss: &mut SomeStruct) -> Box { | --------------- this data with an anonymous lifetime `'_`... ... LL | ss.r - | ^^^^ ...is captured and required live as long as `'static` here + | ^^^^ ...is captured and required to live as long as `'static` here | help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound | diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index fe191e9b69565..c684373c67e9d 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -6,7 +6,7 @@ LL | fn a(v: &[u8]) -> Box { LL | let x: Box = Box::new(v); | ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `v` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn a(v: &[u8]) -> Box { | ^^ @@ -23,7 +23,7 @@ LL | fn b(v: &[u8]) -> Box { LL | Box::new(v) | ^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `v` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn b(v: &[u8]) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 2ea970afcede2..c4ba395179831 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -6,7 +6,7 @@ LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { LL | box B(&*v) as Box | ^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `v` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 493b7a1df9920..e45930bd95710 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -6,7 +6,7 @@ LL | fn i<'a, T, U>(v: Box+'a>) -> Box { LL | box B(&*v) as Box | ^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `v` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ^^ diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr index c10b9850a4e99..69c7256364d70 100644 --- a/src/test/ui/regions/regions-proc-bound-capture.stderr +++ b/src/test/ui/regions/regions-proc-bound-capture.stderr @@ -7,7 +7,7 @@ LL | // This is illegal, because the region bound on `proc` is 'static. LL | Box::new(move || { *x }) | ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static` | -help: consider changing the trait object's explicit `'static` bound to argument `x` +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` | LL | fn static_proc(x: &isize) -> Box (isize) + '_> { | ^^ diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 69022607bd19e..9b04069136be2 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,15 +2,10 @@ error[E0758]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- this data with an anonymous lifetime `'_`... - | | + | ^^^^ ---------- ---------- ...and is required to live as long as `'static` here + | | | + | | this data with an anonymous lifetime `'_`... | ...is captured here... - | -note: ...and is required to live as long as `'static` here - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 - | -LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index e768d7c8ab99f..fc4c801949512 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -5,7 +5,7 @@ LL | fn a(items: &[T]) -> Box> { | ---- this data with an anonymous lifetime `'_`... LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ---------------^^^^--- ...is captured and required live as long as `'static` here + | ---------------^^^^--- ...is captured and required to live as long as `'static` here | help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound | From 6145918c83d10e9679805b8feff0286ce9e58afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 3 Jun 2020 11:34:04 -0700 Subject: [PATCH 29/37] Change E0758 to E0759 to avoid conflict with #72912 --- src/librustc_error_codes/error_codes.rs | 1 + src/librustc_error_codes/error_codes/E0759.md | 67 +++++++++++++++++++ .../nice_region_error/static_impl_trait.rs | 2 +- .../ui/async-await/issues/issue-62097.stderr | 4 +- .../must_outlive_least_region_or_bound.stderr | 20 +++--- .../static-return-lifetime-infered.stderr | 6 +- src/test/ui/issues/issue-16922.stderr | 4 +- ...ect-lifetime-default-from-box-error.stderr | 4 +- .../region-object-lifetime-in-coercion.stderr | 8 +-- .../regions-close-object-into-object-2.stderr | 4 +- .../regions-close-object-into-object-4.stderr | 4 +- .../regions/regions-proc-bound-capture.stderr | 4 +- ...types_pin_lifetime_impl_trait-async.stderr | 4 +- ..._self_types_pin_lifetime_impl_trait.stderr | 4 +- .../missing-lifetimes-in-signature.stderr | 4 +- .../dyn-trait-underscore.stderr | 4 +- 16 files changed, 106 insertions(+), 38 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0759.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 760b4d7ba00a3..2e3ba13f37911 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -438,6 +438,7 @@ E0752: include_str!("./error_codes/E0752.md"), E0753: include_str!("./error_codes/E0753.md"), E0754: include_str!("./error_codes/E0754.md"), E0758: include_str!("./error_codes/E0758.md"), +E0759: include_str!("./error_codes/E0759.md"), E0760: include_str!("./error_codes/E0760.md"), ; // E0006, // merged with E0005 diff --git a/src/librustc_error_codes/error_codes/E0759.md b/src/librustc_error_codes/error_codes/E0759.md new file mode 100644 index 0000000000000..a74759bdf634b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0759.md @@ -0,0 +1,67 @@ +A `'static` requirement in a return type involving a trait is not fulfilled. + +Erroneous code examples: + +```compile_fail,E0759 +use std::fmt::Debug; + +fn foo(x: &i32) -> impl Debug { + x +} +``` + +```compile_fail,E0759 +# use std::fmt::Debug; +fn bar(x: &i32) -> Box { + Box::new(x) +} +``` + +These examples have the same semantics as the following: + +```compile_fail,E0759 +# use std::fmt::Debug; +fn foo(x: &i32) -> impl Debug + 'static { + x +} +``` + +```compile_fail,E0759 +# use std::fmt::Debug; +fn bar(x: &i32) -> Box { + Box::new(x) +} +``` + +Both [`dyn Trait`] and [`impl Trait`] in return types have a an implicit +`'static` requirement, meaning that the value implementing them that is being +returned has to be either a `'static` borrow or an owned value. + +In order to change the requirement from `'static` to be a lifetime derived from +its arguments, you can add an explicit bound, either to an anonymous lifetime +`'_` or some appropriate named lifetime. + +``` +# use std::fmt::Debug; +fn foo(x: &i32) -> impl Debug + '_ { + x +} +fn bar(x: &i32) -> Box { + Box::new(x) +} +``` + +These are equivalent to the following explicit lifetime annotations: + +``` +# use std::fmt::Debug; +fn foo<'a>(x: &'a i32) -> impl Debug + 'a { + x +} +fn bar<'a>(x: &'a i32) -> Box { + Box::new(x) +} +``` + +[`dyn Trait`]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types +[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 5ad76e3964038..853a414290704 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut err = struct_span_err!( self.tcx().sess, sp, - E0758, + E0759, "cannot infer an appropriate lifetime" ); err.span_label( diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index aa443b9d2fc16..0f58b158904db 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/issue-62097.rs:12:31 | LL | pub async fn run_dummy_fn(&self) { @@ -11,4 +11,4 @@ LL | foo(|| self.bar()).await; error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index baed43783a13c..e1fa4f02b6fcf 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } @@ -16,7 +16,7 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn elided(x: &i32) -> impl Copy + '_ { x } | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } @@ -34,7 +34,7 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:9:46 | LL | fn elided2(x: &i32) -> impl Copy + 'static { x } @@ -56,7 +56,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } | ^^^^^^^^^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:55 | LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } @@ -86,7 +86,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | | | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:33:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } @@ -123,7 +123,7 @@ LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | | | help: consider adding an explicit lifetime bound...: `T: 'static +` -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:18:50 | LL | fn elided3(x: &i32) -> Box { Box::new(x) } @@ -136,7 +136,7 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn elided3(x: &i32) -> Box { Box::new(x) } | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:21:59 | LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } @@ -149,7 +149,7 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:24:60 | LL | fn elided4(x: &i32) -> Box { Box::new(x) } @@ -166,7 +166,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } | ^^^^^^^^^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:27:69 | LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } @@ -183,5 +183,5 @@ LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) error: aborting due to 12 previous errors -Some errors have detailed explanations: E0310, E0621, E0623, E0758. +Some errors have detailed explanations: E0310, E0621, E0623, E0759. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 90aada01d9917..df0db6e4fc6df 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { @@ -18,7 +18,7 @@ help: to declare that the `impl Trait` captures data from argument `self`, you c LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { @@ -40,4 +40,4 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index ec80f6569f5ac..919594fc9af4b 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { @@ -13,4 +13,4 @@ LL | fn foo(value: &T) -> Box { error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index d461001adead9..1b1e0d9610724 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { @@ -23,5 +23,5 @@ LL | ss.r = b; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0621, E0758. +Some errors have detailed explanations: E0621, E0759. For more information about an error, try `rustc --explain E0621`. diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index c684373c67e9d..7f5a3a47976c7 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:8:46 | LL | fn a(v: &[u8]) -> Box { @@ -15,7 +15,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn a(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:13:14 | LL | fn b(v: &[u8]) -> Box { @@ -32,7 +32,7 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn b(v: &'static [u8]) -> Box { | ^^^^^^^^^^^^^ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/region-object-lifetime-in-coercion.rs:19:14 | LL | fn c(v: &[u8]) -> Box { @@ -79,5 +79,5 @@ LL | Box::new(v) error: aborting due to 4 previous errors -Some errors have detailed explanations: E0495, E0758. +Some errors have detailed explanations: E0495, E0759. For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index c4ba395179831..114e4052aae09 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/regions-close-object-into-object-2.rs:10:11 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { @@ -17,4 +17,4 @@ LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box $DIR/regions-close-object-into-object-4.rs:10:11 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { @@ -17,4 +17,4 @@ LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A + 'static)>) -> Box $DIR/regions-proc-bound-capture.rs:9:14 | LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { @@ -18,4 +18,4 @@ LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 9b04069136be2..88bd990b1e81b 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } @@ -9,4 +9,4 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index c37eb2d136ef1..2e10ab3d3f9b8 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } @@ -18,4 +18,4 @@ LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 7e8ab1bfe1633..9ab060328537b 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,7 +6,7 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() @@ -125,5 +125,5 @@ LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a error: aborting due to 7 previous errors -Some errors have detailed explanations: E0261, E0309, E0621, E0758. +Some errors have detailed explanations: E0261, E0309, E0621, E0759. For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index fc4c801949512..dda5de431d309 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,4 +1,4 @@ -error[E0758]: cannot infer an appropriate lifetime +error[E0759]: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | LL | fn a(items: &[T]) -> Box> { @@ -14,4 +14,4 @@ LL | fn a(items: &[T]) -> Box + '_> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0758`. +For more information about this error, try `rustc --explain E0759`. From 975f7dfbb4454f651f87c675547bd89131a461d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Fri, 5 Jun 2020 00:00:00 +0000 Subject: [PATCH 30/37] compiletest: Add directives to detect sanitizer support Add needs-sanitizer-{address,leak,memory,thread} directive indicating that test requires target with support for specific sanitizer. This is an addition to the existing needs-sanitizer-support directive indicating that test requires a sanitizer runtime library. --- .../codegen/sanitizer-memory-track-orgins.rs | 4 +-- .../codegen/sanitizer-no-sanitize-inlining.rs | 6 ++-- src/test/codegen/sanitizer-no-sanitize.rs | 2 +- src/test/codegen/sanitizer-recover.rs | 5 ++-- .../sanitizer-cdylib-link/Makefile | 3 +- .../sanitizer-dylib-link/Makefile | 3 +- .../sanitizer-staticlib-link/Makefile | 3 +- src/test/rustdoc/sanitizer-option.rs | 1 + src/test/ui/sanitize/address.rs | 2 +- src/test/ui/sanitize/badfree.rs | 2 +- src/test/ui/sanitize/cfg.rs | 6 ++-- .../sanitize/issue-72154-lifetime-markers.rs | 2 +- src/test/ui/sanitize/leak.rs | 2 +- src/test/ui/sanitize/memory.rs | 3 +- .../new-llvm-pass-manager-thin-lto.rs | 2 +- src/test/ui/sanitize/thread.rs | 2 +- src/test/ui/sanitize/use-after-scope.rs | 2 +- src/tools/compiletest/src/header.rs | 28 +++++++++++++++---- src/tools/compiletest/src/header/tests.rs | 19 +++++++++++++ src/tools/compiletest/src/util.rs | 11 ++++++++ 20 files changed, 75 insertions(+), 33 deletions(-) diff --git a/src/test/codegen/sanitizer-memory-track-orgins.rs b/src/test/codegen/sanitizer-memory-track-orgins.rs index 8ea41c5d44bb1..4bd50508d1520 100644 --- a/src/test/codegen/sanitizer-memory-track-orgins.rs +++ b/src/test/codegen/sanitizer-memory-track-orgins.rs @@ -1,9 +1,7 @@ // Verifies that MemorySanitizer track-origins level can be controlled // with -Zsanitizer-memory-track-origins option. // -// needs-sanitizer-support -// only-linux -// only-x86_64 +// needs-sanitizer-memory // revisions:MSAN-0 MSAN-1 MSAN-2 MSAN-1-LTO MSAN-2-LTO // //[MSAN-0] compile-flags: -Zsanitizer=memory diff --git a/src/test/codegen/sanitizer-no-sanitize-inlining.rs b/src/test/codegen/sanitizer-no-sanitize-inlining.rs index d96e76618d325..b00441e4fc5ab 100644 --- a/src/test/codegen/sanitizer-no-sanitize-inlining.rs +++ b/src/test/codegen/sanitizer-no-sanitize-inlining.rs @@ -1,11 +1,9 @@ // Verifies that no_sanitize attribute prevents inlining when // given sanitizer is enabled, but has no effect on inlining otherwise. // -// needs-sanitizer-support -// only-x86_64 -// +// needs-sanitizer-address +// needs-sanitizer-leak // revisions: ASAN LSAN -// //[ASAN] compile-flags: -Zsanitizer=address -C opt-level=3 -Z mir-opt-level=3 //[LSAN] compile-flags: -Zsanitizer=leak -C opt-level=3 -Z mir-opt-level=3 diff --git a/src/test/codegen/sanitizer-no-sanitize.rs b/src/test/codegen/sanitizer-no-sanitize.rs index dfceb28c8dd10..1b2b18822e63e 100644 --- a/src/test/codegen/sanitizer-no-sanitize.rs +++ b/src/test/codegen/sanitizer-no-sanitize.rs @@ -1,7 +1,7 @@ // Verifies that no_sanitze attribute can be used to // selectively disable sanitizer instrumentation. // -// needs-sanitizer-support +// needs-sanitizer-address // compile-flags: -Zsanitizer=address #![crate_type="lib"] diff --git a/src/test/codegen/sanitizer-recover.rs b/src/test/codegen/sanitizer-recover.rs index 05b4ab5653cc8..719f219ce4ef1 100644 --- a/src/test/codegen/sanitizer-recover.rs +++ b/src/test/codegen/sanitizer-recover.rs @@ -1,9 +1,8 @@ // Verifies that AddressSanitizer and MemorySanitizer // recovery mode can be enabled with -Zsanitizer-recover. // -// needs-sanitizer-support -// only-linux -// only-x86_64 +// needs-sanitizer-address +// needs-sanitizer-memory // revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER MSAN-RECOVER-LTO // no-prefer-dynamic // diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile index 5d46be87eac6b..e72fe5a50913a 100644 --- a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile @@ -1,6 +1,5 @@ # needs-sanitizer-support -# only-x86_64 -# only-linux +# needs-sanitizer-address -include ../tools.mk diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile index f62c3a6654ed4..b9a3f829555af 100644 --- a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile @@ -1,6 +1,5 @@ # needs-sanitizer-support -# only-x86_64 -# only-linux +# needs-sanitizer-address -include ../tools.mk diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile index f56475b441f1a..4894f65b114cd 100644 --- a/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile @@ -1,6 +1,5 @@ # needs-sanitizer-support -# only-x86_64 -# only-linux +# needs-sanitizer-address -include ../tools.mk diff --git a/src/test/rustdoc/sanitizer-option.rs b/src/test/rustdoc/sanitizer-option.rs index 6af9ed3e33f66..a79b37ee08210 100644 --- a/src/test/rustdoc/sanitizer-option.rs +++ b/src/test/rustdoc/sanitizer-option.rs @@ -1,4 +1,5 @@ // needs-sanitizer-support +// needs-sanitizer-address // compile-flags: --test -Z sanitizer=address // // #43031: Verify that rustdoc passes `-Z` options to rustc. Use an extern diff --git a/src/test/ui/sanitize/address.rs b/src/test/ui/sanitize/address.rs index f8650cd86d51e..cee73b0425ad5 100644 --- a/src/test/ui/sanitize/address.rs +++ b/src/test/ui/sanitize/address.rs @@ -1,5 +1,5 @@ // needs-sanitizer-support -// only-x86_64 +// needs-sanitizer-address // // compile-flags: -Z sanitizer=address -O -g // diff --git a/src/test/ui/sanitize/badfree.rs b/src/test/ui/sanitize/badfree.rs index 1ca082c8b4704..095a6f4697b1c 100644 --- a/src/test/ui/sanitize/badfree.rs +++ b/src/test/ui/sanitize/badfree.rs @@ -1,5 +1,5 @@ // needs-sanitizer-support -// only-x86_64 +// needs-sanitizer-address // // compile-flags: -Z sanitizer=address -O // diff --git a/src/test/ui/sanitize/cfg.rs b/src/test/ui/sanitize/cfg.rs index 9c198543a8664..79dfe58f04d0b 100644 --- a/src/test/ui/sanitize/cfg.rs +++ b/src/test/ui/sanitize/cfg.rs @@ -2,8 +2,10 @@ // the `#[cfg(sanitize = "option")]` attribute is configured. // needs-sanitizer-support -// only-linux -// only-x86_64 +// needs-sanitizer-address +// needs-sanitizer-leak +// needs-sanitizer-memory +// needs-sanitizer-thread // check-pass // revisions: address leak memory thread //[address]compile-flags: -Zsanitizer=address --cfg address diff --git a/src/test/ui/sanitize/issue-72154-lifetime-markers.rs b/src/test/ui/sanitize/issue-72154-lifetime-markers.rs index 458f99143b648..b2e182238ce28 100644 --- a/src/test/ui/sanitize/issue-72154-lifetime-markers.rs +++ b/src/test/ui/sanitize/issue-72154-lifetime-markers.rs @@ -4,7 +4,7 @@ // miscompilation which was subsequently detected by AddressSanitizer as UB. // // needs-sanitizer-support -// only-x86_64 +// needs-sanitizer-address // // compile-flags: -Copt-level=0 -Zsanitizer=address // run-pass diff --git a/src/test/ui/sanitize/leak.rs b/src/test/ui/sanitize/leak.rs index 5c2f2cb4e868b..c9f10fe4f467e 100644 --- a/src/test/ui/sanitize/leak.rs +++ b/src/test/ui/sanitize/leak.rs @@ -1,5 +1,5 @@ // needs-sanitizer-support -// only-x86_64 +// needs-sanitizer-leak // // compile-flags: -Z sanitizer=leak -O // diff --git a/src/test/ui/sanitize/memory.rs b/src/test/ui/sanitize/memory.rs index 3e1cf4509a31f..a26649a580013 100644 --- a/src/test/ui/sanitize/memory.rs +++ b/src/test/ui/sanitize/memory.rs @@ -1,6 +1,5 @@ // needs-sanitizer-support -// only-linux -// only-x86_64 +// needs-sanitizer-memory // // compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O // diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs index d0984bbe65fd5..64d6ccf340916 100644 --- a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs +++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -4,7 +4,7 @@ // // min-llvm-version 9.0 // needs-sanitizer-support -// only-x86_64 +// needs-sanitizer-address // // no-prefer-dynamic // revisions: opt0 opt1 diff --git a/src/test/ui/sanitize/thread.rs b/src/test/ui/sanitize/thread.rs index 26590be8b1870..c70cf5accc077 100644 --- a/src/test/ui/sanitize/thread.rs +++ b/src/test/ui/sanitize/thread.rs @@ -11,7 +11,7 @@ // would occasionally fail, making test flaky. // // needs-sanitizer-support -// only-x86_64 +// needs-sanitizer-thread // // compile-flags: -Z sanitizer=thread -O // diff --git a/src/test/ui/sanitize/use-after-scope.rs b/src/test/ui/sanitize/use-after-scope.rs index 6a2067e157af5..30be2ae6f0906 100644 --- a/src/test/ui/sanitize/use-after-scope.rs +++ b/src/test/ui/sanitize/use-after-scope.rs @@ -1,5 +1,5 @@ // needs-sanitizer-support -// only-x86_64 +// needs-sanitizer-address // // compile-flags: -Zsanitizer=address // run-fail diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 9d1940dd4d6c2..9614707433e13 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -43,6 +43,10 @@ impl EarlyProps { let mut props = EarlyProps::default(); let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some(); let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some(); + let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target); + let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target); + let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target); + let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target); iter_header(testfile, None, rdr, &mut |ln| { // we should check if any only- exists and if it exists @@ -74,7 +78,25 @@ impl EarlyProps { props.ignore = true; } - if !rustc_has_sanitizer_support && config.parse_needs_sanitizer_support(ln) { + if !rustc_has_sanitizer_support + && config.parse_name_directive(ln, "needs-sanitizer-support") + { + props.ignore = true; + } + + if !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address") { + props.ignore = true; + } + + if !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak") { + props.ignore = true; + } + + if !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory") { + props.ignore = true; + } + + if !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread") { props.ignore = true; } @@ -829,10 +851,6 @@ impl Config { self.parse_name_directive(line, "needs-profiler-support") } - fn parse_needs_sanitizer_support(&self, line: &str) -> bool { - self.parse_name_directive(line, "needs-sanitizer-support") - } - /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` /// or `normalize-stderr-32bit`. fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 31d991e0c2f87..036409fbf070f 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -195,3 +195,22 @@ fn debugger() { config.debugger = Some(Debugger::Lldb); assert!(parse_rs(&config, "// ignore-lldb").ignore); } + +#[test] +fn sanitizers() { + let mut config = config(); + + // Target that supports all sanitizers: + config.target = "x86_64-unknown-linux-gnu".to_owned(); + assert!(!parse_rs(&config, "// needs-sanitizer-address").ignore); + assert!(!parse_rs(&config, "// needs-sanitizer-leak").ignore); + assert!(!parse_rs(&config, "// needs-sanitizer-memory").ignore); + assert!(!parse_rs(&config, "// needs-sanitizer-thread").ignore); + + // Target that doesn't support sanitizers: + config.target = "wasm32-unknown-emscripten".to_owned(); + assert!(parse_rs(&config, "// needs-sanitizer-address").ignore); + assert!(parse_rs(&config, "// needs-sanitizer-leak").ignore); + assert!(parse_rs(&config, "// needs-sanitizer-memory").ignore); + assert!(parse_rs(&config, "// needs-sanitizer-thread").ignore); +} diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index c61bee0f8d9ea..b9087dee6174c 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -81,6 +81,17 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("xcore", "xcore"), ]; +pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] = + &["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"]; + +pub const LSAN_SUPPORTED_TARGETS: &'static [&'static str] = + &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + +pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] = &["x86_64-unknown-linux-gnu"]; + +pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] = + &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + pub fn matches_os(triple: &str, name: &str) -> bool { // For the wasm32 bare target we ignore anything also ignored on emscripten // and then we also recognize `wasm32-bare` as the os for the target From 754da8849c18c45ff2fd2e77213f8371de488f80 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 11 Jun 2020 13:42:22 -0400 Subject: [PATCH 31/37] Make `fn_arg_names` return `Ident` instead of symbol Also, implement this query for the local crate, not just foreign crates. --- src/librustc_metadata/rmeta/decoder.rs | 4 ++-- src/librustc_metadata/rmeta/encoder.rs | 16 +++++----------- src/librustc_metadata/rmeta/mod.rs | 4 ++-- src/librustc_middle/hir/map/mod.rs | 9 ++++++++- src/librustc_middle/hir/mod.rs | 20 ++++++++++++++++---- src/librustc_middle/query/mod.rs | 2 +- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index f5a9dceb78295..b2afdd0b4e13f 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1317,13 +1317,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Symbol] { + fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] { let param_names = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names, _ => Lazy::empty(), }; - tcx.arena.alloc_from_iter(param_names.decode(self)) + tcx.arena.alloc_from_iter(param_names.decode((self, tcx))) } fn exported_symbols( diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 64ccd46a744f5..60a5bb4340513 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -30,7 +30,7 @@ use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; use rustc_session::config::CrateType; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{self, ExternalSource, FileName, SourceFile, Span}; use rustc_target::abi::VariantIdx; use std::hash::Hash; @@ -997,18 +997,12 @@ impl EncodeContext<'tcx> { } } - fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Symbol]> { - self.tcx.dep_graph.with_ignore(|| { - let body = self.tcx.hir().body(body_id); - self.lazy(body.params.iter().map(|arg| match arg.pat.kind { - hir::PatKind::Binding(_, _, ident, _) => ident.name, - _ => kw::Invalid, - })) - }) + fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> { + self.tcx.dep_graph.with_ignore(|| self.lazy(self.tcx.hir().body_param_names(body_id))) } - fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Symbol]> { - self.lazy(param_names.iter().map(|ident| ident.name)) + fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Ident]> { + self.lazy(param_names.iter()) } fn encode_optimized_mir(&mut self, def_id: LocalDefId) { diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 89d525eb80b8c..1cf86c7660ee4 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -19,7 +19,7 @@ use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; use rustc_session::CrateDisambiguator; use rustc_span::edition::Edition; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{self, Span}; use rustc_target::spec::{PanicStrategy, TargetTriple}; @@ -327,7 +327,7 @@ struct ModData { struct FnData { asyncness: hir::IsAsync, constness: hir::Constness, - param_names: Lazy<[Symbol]>, + param_names: Lazy<[Ident]>, } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs index b1dafb3c88585..12c7b18d06988 100644 --- a/src/librustc_middle/hir/map/mod.rs +++ b/src/librustc_middle/hir/map/mod.rs @@ -14,7 +14,7 @@ use rustc_hir::*; use rustc_index::vec::IndexVec; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, Symbol}; +use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; @@ -375,6 +375,13 @@ impl<'hir> Map<'hir> { }) } + pub fn body_param_names(&self, id: BodyId) -> impl Iterator + 'hir { + self.body(id).params.iter().map(|arg| match arg.pat.kind { + PatKind::Binding(_, _, ident, _) => ident, + _ => Ident::new(kw::Invalid, rustc_span::DUMMY_SP), + }) + } + /// Returns the `BodyOwnerKind` of this `LocalDefId`. /// /// Panics if `LocalDefId` does not have an associated body. diff --git a/src/librustc_middle/hir/mod.rs b/src/librustc_middle/hir/mod.rs index 1e3676496ce39..e152d11c081a1 100644 --- a/src/librustc_middle/hir/mod.rs +++ b/src/librustc_middle/hir/mod.rs @@ -12,10 +12,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; -use rustc_hir::Body; -use rustc_hir::HirId; -use rustc_hir::ItemLocalId; -use rustc_hir::Node; +use rustc_hir::*; use rustc_index::vec::IndexVec; pub struct Owner<'tcx> { @@ -79,5 +76,20 @@ pub fn provide(providers: &mut Providers<'_>) { }; providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature; providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref(); + providers.fn_arg_names = |tcx, id| { + let hir = tcx.hir(); + let hir_id = hir.as_local_hir_id(id.expect_local()); + if let Some(body_id) = hir.maybe_body_owned_by(hir_id) { + tcx.arena.alloc_from_iter(hir.body_param_names(body_id)) + } else if let Node::TraitItem(&TraitItem { + kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), + .. + }) = hir.get(hir_id) + { + tcx.arena.alloc_slice(idents) + } else { + span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id); + } + }; map::provide(providers); } diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 4d7e7882e426c..d65e01b145ac6 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -700,7 +700,7 @@ rustc_queries! { } Other { - query fn_arg_names(def_id: DefId) -> &'tcx [Symbol] { + query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] { desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) } } /// Gets the rendered value of the specified constant or associated constant. From 2c11c35f8982a9a5fd654f0499cc72b70208d62f Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 11 Jun 2020 13:48:46 -0400 Subject: [PATCH 32/37] Explain move errors that occur due to method calls involving `self` --- src/librustc_ast_lowering/expr.rs | 24 ++- .../infer/error_reporting/need_type_info.rs | 2 +- src/librustc_middle/lint.rs | 4 +- .../diagnostics/conflict_errors.rs | 72 +++++++- .../diagnostics/explain_borrow.rs | 2 +- .../borrow_check/diagnostics/mod.rs | 152 ++++++++++++++--- .../borrow_check/diagnostics/move_errors.rs | 2 +- .../diagnostics/mutability_errors.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 6 + src/librustc_mir/transform/const_prop.rs | 1 + src/librustc_span/hygiene.rs | 13 +- src/librustc_span/lib.rs | 4 +- src/test/ui/binop/binop-consume-args.stderr | 70 ++++++-- src/test/ui/binop/binop-move-semantics.stderr | 21 ++- .../borrowck/borrowck-unboxed-closures.stderr | 7 +- .../ui/closure_context/issue-42065.stderr | 7 +- src/test/ui/codemap_tests/tab_3.stderr | 8 +- .../ui/consts/miri_unleashed/ptr_arith.rs | 5 +- .../ui/consts/miri_unleashed/ptr_arith.stderr | 4 +- src/test/ui/hygiene/unpretty-debug.stdout | 4 + src/test/ui/issues/issue-12127.stderr | 7 +- src/test/ui/issues/issue-33941.rs | 1 + src/test/ui/issues/issue-33941.stderr | 12 +- src/test/ui/issues/issue-34721.stderr | 9 +- src/test/ui/issues/issue-61108.stderr | 8 +- src/test/ui/issues/issue-64559.stderr | 8 +- src/test/ui/moves/move-fn-self-receiver.rs | 74 ++++++++ .../ui/moves/move-fn-self-receiver.stderr | 158 ++++++++++++++++++ ...moves-based-on-type-access-to-field.stderr | 8 +- .../ui/moves/moves-based-on-type-exprs.stderr | 16 +- .../ui/once-cant-call-twice-on-heap.stderr | 7 +- ...ed-closures-infer-fnonce-call-twice.stderr | 7 +- ...osures-infer-fnonce-move-call-twice.stderr | 7 +- src/test/ui/unop-move-semantics.stderr | 7 +- .../unsized-locals/borrow-after-move.stderr | 8 +- src/test/ui/unsized-locals/double-move.stderr | 8 +- .../use-after-move-self-based-on-type.stderr | 8 +- src/test/ui/use/use-after-move-self.stderr | 8 +- src/test/ui/walk-struct-literal-with.stderr | 8 +- 39 files changed, 697 insertions(+), 82 deletions(-) create mode 100644 src/test/ui/moves/move-fn-self-receiver.rs create mode 100644 src/test/ui/moves/move-fn-self-receiver.stderr diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index b7894eb145b0a..e59cacfffc926 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -9,7 +9,7 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; +use rustc_span::source_map::{respan, DesugaringKind, ForLoopLoc, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_target::asm; use std::collections::hash_map::Entry; @@ -25,6 +25,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { + let mut span = e.span; ensure_sufficient_stack(|| { let kind = match e.kind { ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)), @@ -53,6 +54,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span) } ExprKind::Binary(binop, ref lhs, ref rhs) => { + span = self.mark_span_with_reason(DesugaringKind::Operator, e.span, None); let binop = self.lower_binop(binop); let lhs = self.lower_expr(lhs); let rhs = self.lower_expr(rhs); @@ -222,7 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Expr { hir_id: self.lower_node_id(e.id), kind, - span: e.span, + span, attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::>().into(), } }) @@ -237,6 +239,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_binop(&mut self, b: BinOp) -> hir::BinOp { + let span = self.mark_span_with_reason(DesugaringKind::Operator, b.span, None); Spanned { node: match b.node { BinOpKind::Add => hir::BinOpKind::Add, @@ -258,7 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> { BinOpKind::Ge => hir::BinOpKind::Ge, BinOpKind::Gt => hir::BinOpKind::Gt, }, - span: b.span, + span, } } @@ -1360,9 +1363,14 @@ impl<'hir> LoweringContext<'_, 'hir> { body: &Block, opt_label: Option