diff options
| author | The Miri Conjob Bot <miri@cron.bot> | 2024-02-22 05:02:05 +0000 |
|---|---|---|
| committer | The Miri Conjob Bot <miri@cron.bot> | 2024-02-22 05:02:05 +0000 |
| commit | 76a596c48d1b8ed3805e623e003c73edaf00c5fc (patch) | |
| tree | d455bd062e68808928fdbdd46ff10e38d5c4575e /compiler/rustc_borrowck/src | |
| parent | f5ec4cb37561743efd869d61e457ae39938c1680 (diff) | |
| parent | c5f69bdd5173a948e0131f934fa7c4cbf5e0b55f (diff) | |
Merge from rustc
Diffstat (limited to 'compiler/rustc_borrowck/src')
17 files changed, 557 insertions, 116 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2b0c0e939f5..e1509da913a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -6,9 +6,7 @@ use either::Either; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{ - codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan, -}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; @@ -635,7 +633,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn suggest_assign_value( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, moved_place: PlaceRef<'tcx>, sugg_span: Span, ) { @@ -674,7 +672,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn suggest_borrow_fn_like( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, ty: Ty<'tcx>, move_sites: &[MoveSite], value_name: &str, @@ -742,7 +740,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn suggest_cloning( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'_>, span: Span, @@ -778,7 +776,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { + fn suggest_adding_copy_bounds( + &self, + err: &mut DiagnosticBuilder<'_>, + ty: Ty<'tcx>, + span: Span, + ) { let tcx = self.infcx.tcx; let generics = tcx.generics_of(self.mir_def_id()); @@ -1225,7 +1228,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { #[instrument(level = "debug", skip(self, err))] fn suggest_using_local_if_applicable( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, location: Location, issued_borrow: &BorrowData<'tcx>, explanation: BorrowExplanation<'tcx>, @@ -1321,7 +1324,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn suggest_slice_method_if_applicable( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, place: Place<'tcx>, borrowed_place: Place<'tcx>, ) { @@ -1430,7 +1433,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// ``` pub(crate) fn explain_iterator_advancement_in_for_loop_if_applicable( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, span: Span, issued_spans: &UseSpans<'tcx>, ) { @@ -1617,7 +1620,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// ``` fn suggest_using_closure_argument_instead_of_capture( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, borrowed_place: Place<'tcx>, issued_spans: &UseSpans<'tcx>, ) { @@ -1751,7 +1754,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn suggest_binding_for_closure_capture_self( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, issued_spans: &UseSpans<'tcx>, ) { let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return }; @@ -2997,7 +3000,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.buffer_error(err); } - fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diagnostic) { + fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut DiagnosticBuilder<'_>) { let tcx = self.infcx.tcx; if let ( Some(Terminator { @@ -3532,7 +3535,11 @@ enum AnnotatedBorrowFnSignature<'tcx> { impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { /// Annotate the provided diagnostic with information about borrow from the fn signature that /// helps explain. - pub(crate) fn emit(&self, cx: &mut MirBorrowckCtxt<'_, 'tcx>, diag: &mut Diagnostic) -> String { + pub(crate) fn emit( + &self, + cx: &mut MirBorrowckCtxt<'_, 'tcx>, + diag: &mut DiagnosticBuilder<'_>, + ) -> String { match self { &AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => { diag.span_label( diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 483ecee850b..f7b59ec5fe0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -3,7 +3,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -use rustc_errors::{Applicability, Diagnostic}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_index::IndexSlice; @@ -65,7 +65,7 @@ impl<'tcx> BorrowExplanation<'tcx> { tcx: TyCtxt<'tcx>, body: &Body<'tcx>, local_names: &IndexSlice<Local, Option<Symbol>>, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, borrow_desc: &str, borrow_span: Option<Span>, multiple_borrow_span: Option<(Span, Span)>, @@ -306,7 +306,7 @@ impl<'tcx> BorrowExplanation<'tcx> { fn add_object_lifetime_default_note( &self, tcx: TyCtxt<'tcx>, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, unsize_ty: Ty<'tcx>, ) { if let ty::Adt(def, args) = unsize_ty.kind() { @@ -359,7 +359,7 @@ impl<'tcx> BorrowExplanation<'tcx> { fn add_lifetime_bound_suggestion_to_diagnostic( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, category: &ConstraintCategory<'tcx>, span: Span, region_name: &RegionName, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 4ca854c857d..db0d69b6eaa 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -5,7 +5,7 @@ use crate::session_diagnostics::{ CaptureVarKind, CaptureVarPathUseCause, OnClosureNote, }; use itertools::Itertools; -use rustc_errors::{Applicability, Diagnostic}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::CoroutineKind; @@ -80,7 +80,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self, location: Location, place: PlaceRef<'tcx>, - diag: &mut Diagnostic, + diag: &mut DiagnosticBuilder<'_>, ) -> bool { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); let mut target = place.local_or_deref_local(); @@ -588,7 +588,7 @@ impl UseSpans<'_> { pub(super) fn args_subdiag( self, dcx: &rustc_errors::DiagCtxt, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, f: impl FnOnce(Span) -> CaptureArgLabel, ) { if let UseSpans::ClosureUse { args_span, .. } = self { @@ -601,7 +601,7 @@ impl UseSpans<'_> { pub(super) fn var_path_only_subdiag( self, dcx: &rustc_errors::DiagCtxt, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, action: crate::InitializationRequiringAction, ) { use crate::InitializationRequiringAction::*; @@ -638,7 +638,7 @@ impl UseSpans<'_> { pub(super) fn var_subdiag( self, dcx: &rustc_errors::DiagCtxt, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, kind: Option<rustc_middle::mir::BorrowKind>, f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause, ) { @@ -1010,7 +1010,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn explain_captures( &mut self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, span: Span, move_span: Span, move_spans: UseSpans<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index dad20690d02..3478a73254a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,7 +1,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; @@ -437,7 +437,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err } - fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, span: Span) { + fn add_move_hints( + &self, + error: GroupedMoveError<'tcx>, + err: &mut DiagnosticBuilder<'_>, + span: Span, + ) { match error { GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => { self.add_borrow_suggestions(err, span); @@ -500,7 +505,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - fn add_borrow_suggestions(&self, err: &mut Diagnostic, span: Span) { + fn add_borrow_suggestions(&self, err: &mut DiagnosticBuilder<'_>, span: Span) { match self.infcx.tcx.sess.source_map().span_to_snippet(span) { Ok(snippet) if snippet.starts_with('*') => { err.span_suggestion_verbose( @@ -521,7 +526,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - fn add_move_error_suggestions(&self, err: &mut Diagnostic, binds_to: &[Local]) { + fn add_move_error_suggestions(&self, err: &mut DiagnosticBuilder<'_>, binds_to: &[Local]) { let mut suggestions: Vec<(Span, String, String)> = Vec::new(); for local in binds_to { let bind_to = &self.body.local_decls[*local]; @@ -573,7 +578,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - fn add_move_error_details(&self, err: &mut Diagnostic, binds_to: &[Local]) { + fn add_move_error_details(&self, err: &mut DiagnosticBuilder<'_>, binds_to: &[Local]) { for (j, local) in binds_to.iter().enumerate() { let bind_to = &self.body.local_decls[*local]; let binding_span = bind_to.source_info.span; @@ -610,7 +615,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// expansion of a packed struct. /// Such errors happen because derive macro expansions shy away from taking /// references to the struct's fields since doing so would be undefined behaviour - fn add_note_for_packed_struct_derive(&self, err: &mut Diagnostic, local: Local) { + fn add_note_for_packed_struct_derive(&self, err: &mut DiagnosticBuilder<'_>, local: Local) { let local_place: PlaceRef<'tcx> = local.into(); let local_ty = local_place.ty(self.body.local_decls(), self.infcx.tcx).ty.peel_refs(); diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 514e9c39eb4..b8257ba0adc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -2,7 +2,7 @@ #![allow(rustc::untranslatable_diagnostic)] use hir::ExprKind; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; @@ -540,7 +540,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) { + fn suggest_map_index_mut_alternatives( + &self, + ty: Ty<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + span: Span, + ) { let Some(adt) = ty.ty_adt_def() else { return }; let did = adt.did(); if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did) @@ -548,7 +553,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { struct V<'a, 'tcx> { assign_span: Span, - err: &'a mut Diagnostic, + err: &'a mut DiagnosticBuilder<'tcx>, ty: Ty<'tcx>, suggested: bool, } @@ -790,7 +795,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { tcx: TyCtxt<'_>, closure_local_def_id: hir::def_id::LocalDefId, the_place_err: PlaceRef<'tcx>, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, ) { let tables = tcx.typeck(closure_local_def_id); if let Some((span, closure_kind_origin)) = tcx.closure_kind_origin(closure_local_def_id) { @@ -852,7 +857,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Attempt to search similar mutable associated items for suggestion. // In the future, attempt in all path but initially for RHS of for_loop - fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diagnostic, span: Span) { + fn suggest_similar_mut_method_for_for_loop(&self, err: &mut DiagnosticBuilder<'_>, span: Span) { use hir::{ BorrowKind, Expr, ExprKind::{AddrOf, Block, Call, MethodCall}, @@ -936,7 +941,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. - fn expected_fn_found_fn_mut_call(&self, err: &mut Diagnostic, sp: Span, act: &str) { + fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) { err.span_label(sp, format!("cannot {act}")); let hir = self.infcx.tcx.hir(); diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 93e28a5f3f3..b2c7a98142e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -5,7 +5,7 @@ #![allow(rustc::untranslatable_diagnostic)] use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::Diagnostic; +use rustc_errors::DiagnosticBuilder; use rustc_middle::ty::RegionVid; use smallvec::SmallVec; use std::collections::BTreeMap; @@ -158,13 +158,13 @@ impl OutlivesSuggestionBuilder { self.constraints_to_add.entry(fr).or_default().push(outlived_fr); } - /// Emit an intermediate note on the given `Diagnostic` if the involved regions are + /// Emit an intermediate note on the given `DiagnosticBuilder` if the involved regions are /// suggestable. pub(crate) fn intermediate_suggestion( &mut self, mbcx: &MirBorrowckCtxt<'_, '_>, errci: &ErrorConstraintInfo<'_>, - diag: &mut Diagnostic, + diag: &mut DiagnosticBuilder<'_>, ) { // Emit an intermediate note. let fr_name = self.region_vid_to_name(mbcx, errci.fr); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e8effd5c163..50d22881c3e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,7 +1,7 @@ //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; +use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res::Def; use rustc_hir::def_id::DefId; @@ -251,6 +251,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { hrtb_bounds.iter().for_each(|bound| { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; }; + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.span_note( *trait_span, "due to current limitations in the borrow checker, this implies a `'static` lifetime" @@ -421,6 +424,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` /// /// Here we would be invoked with `fr = 'a` and `outlived_fr = 'b`. + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] pub(crate) fn report_region_error( &mut self, fr: RegionVid, @@ -685,12 +691,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { borrowck_errors::borrowed_data_escapes_closure(self.infcx.tcx, *span, escapes_from); if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span { + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.span_label( outlived_fr_span, format!("`{outlived_fr_name}` declared here, outside of the {escapes_from} body",), ); } + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] if let Some((Some(fr_name), fr_span)) = fr_name_and_span { diag.span_label( fr_span, @@ -714,6 +726,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap(); outlived_fr_region_name.highlight_region_name(&mut diag); + // FIXME: make this translatable + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.span_label( *span, format!( @@ -808,7 +823,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn add_static_impl_trait_suggestion( &self, - diag: &mut Diagnostic, + diag: &mut DiagnosticBuilder<'_>, fr: RegionVid, // We need to pass `fr_name` - computing it again will label it twice. fr_name: RegionName, @@ -897,7 +912,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn maybe_suggest_constrain_dyn_trait_impl( &self, - diag: &mut Diagnostic, + diag: &mut DiagnosticBuilder<'_>, f: Region<'tcx>, o: Region<'tcx>, category: &ConstraintCategory<'tcx>, @@ -959,7 +974,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { #[instrument(skip(self, err), level = "debug")] fn suggest_constrain_dyn_trait_in_impl( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'_>, found_dids: &FxIndexSet<DefId>, ident: Ident, self_ty: &hir::Ty<'_>, @@ -994,7 +1009,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn suggest_adding_lifetime_params( &self, - diag: &mut Diagnostic, + diag: &mut DiagnosticBuilder<'_>, sub: RegionVid, sup: RegionVid, ) { @@ -1023,7 +1038,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag); } - fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) { + fn suggest_move_on_borrowing_closure(&self, diag: &mut DiagnosticBuilder<'_>) { let map = self.infcx.tcx.hir(); let body_id = map.body_owned_by(self.mir_def_id()); let expr = &map.body(body_id).value.peel_blocks(); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index e008d230656..e228bef1139 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -5,7 +5,7 @@ use std::fmt::{self, Display}; use std::iter; use rustc_data_structures::fx::IndexEntry; -use rustc_errors::Diagnostic; +use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_middle::ty::print::RegionHighlightMode; @@ -106,7 +106,7 @@ impl RegionName { } } - pub(crate) fn highlight_region_name(&self, diag: &mut Diagnostic) { + pub(crate) fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) { match &self.source { RegionNameSource::NamedLateParamRegion(span) | RegionNameSource::NamedEarlyParamRegion(span) => { @@ -626,9 +626,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { | GenericArgKind::Const(_), _, ) => { - // HIR lowering sometimes doesn't catch this in erroneous - // programs, so we need to use span_delayed_bug here. See #82126. - self.dcx().span_delayed_bug( + // This was previously a `span_delayed_bug` and could be + // reached by the test for #82126, but no longer. + self.dcx().span_bug( hir_arg.span(), format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"), ); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 6c2a511538d..dbaa9e5bcfa 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2497,6 +2497,8 @@ mod diags { } for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) { if count > 10 { + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } self.diags.buffered_diags.push(BufferedDiag::Error(diag)); diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 34d60fc8f6e..ce2c0dbaff7 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -5,7 +5,7 @@ use rustc_data_structures::binary_search_util; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::scc::Sccs; -use rustc_errors::Diagnostic; +use rustc_errors::DiagnosticBuilder; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::outlives::test_type_match; @@ -592,7 +592,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`. - pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) { + pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_, ()>) { self.universal_regions.annotate(tcx, err) } diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index fc600af1b76..e5ebf97cfc4 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, ) { for (predicate, span) in instantiated_predicates { - debug!(?predicate); + debug!(?span, ?predicate); let category = ConstraintCategory::Predicate(span); let predicate = self.normalize_with_category(predicate, locations, category); self.prove_predicate(predicate, locations, category); diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index c97e3170166..de75a9857f8 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Const use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use rustc_trait_selection::solve::deeply_normalize; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; @@ -183,7 +183,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // we don't actually use this for anything, but // the `TypeOutlives` code needs an origin. - let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + let origin = infer::RelateParamBound(self.span, t1, None); TypeOutlives::new( &mut *self, diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 2e0caf44819..897918fb0a4 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::OutlivesBound; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; -use rustc_span::{ErrorGuaranteed, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::solve::deeply_normalize; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; @@ -269,7 +269,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { debug!("build: input_or_output={:?}", ty); // We add implied bounds from both the unnormalized and normalized ty. // See issue #87748 - let constraints_unnorm = self.add_implied_bounds(ty); + let constraints_unnorm = self.add_implied_bounds(ty, span); if let Some(c) = constraints_unnorm { constraints.push(c) } @@ -299,7 +299,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // ``` // Both &Self::Bar and &() are WF if ty != norm_ty { - let constraints_norm = self.add_implied_bounds(norm_ty); + let constraints_norm = self.add_implied_bounds(norm_ty, span); if let Some(c) = constraints_norm { constraints.push(c) } @@ -316,6 +316,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { .and(type_op::normalize::Normalize::new(ty)) .fully_perform(self.infcx, span) else { + // Note: this path is currently not reached in any test, so + // any example that triggers this would be worth minimizing + // and converting into a test. tcx.dcx().span_delayed_bug(span, format!("failed to normalize {ty:?}")); continue; }; @@ -323,7 +326,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // We currently add implied bounds from the normalized ty only. // This is more conservative and matches wfcheck behavior. - let c = self.add_implied_bounds(norm_ty); + let c = self.add_implied_bounds(norm_ty, span); constraints.extend(c); } } @@ -361,11 +364,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { /// the same time, compute and add any implied bounds that come /// from this local. #[instrument(level = "debug", skip(self))] - fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<&'tcx QueryRegionConstraints<'tcx>> { + fn add_implied_bounds( + &mut self, + ty: Ty<'tcx>, + span: Span, + ) -> Option<&'tcx QueryRegionConstraints<'tcx>> { let TypeOpOutput { output: bounds, constraints, .. } = self .param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) - .fully_perform(self.infcx, DUMMY_SP) + .fully_perform(self.infcx, span) .map_err(|_: ErrorGuaranteed| debug!("failed to compute implied bounds {:?}", ty)) .ok()?; debug!(?bounds, ?constraints); diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index af5b635ae66..8af78b08f69 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -154,8 +154,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if argument_index + 1 >= body.local_decls.len() { self.tcx() .dcx() - .span_delayed_bug(body.span, "found more normalized_input_ty than local_decls"); - break; + .span_bug(body.span, "found more normalized_input_ty than local_decls"); } // In MIR, argument N is stored in local N+1. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 64469727d0d..81193902f9b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -37,7 +37,7 @@ use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; @@ -220,14 +220,13 @@ pub(crate) fn type_check<'mir, 'tcx>( "opaque_type_map", ), ); - let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); + let hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind()); if hidden_type.has_non_region_infer() { - let reported = infcx.dcx().span_delayed_bug( + infcx.dcx().span_bug( decl.hidden_type.span, format!("could not resolve {:#?}", hidden_type.ty.kind()), ); - hidden_type.ty = Ty::new_error(infcx.tcx, reported); } (opaque_type_key, hidden_type) @@ -1014,7 +1013,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) -> Self { let mut checker = Self { infcx, - last_span: DUMMY_SP, + last_span: body.span, body, user_type_annotations: &body.user_type_annotations, param_env, @@ -1089,10 +1088,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); if result.is_err() { - self.infcx.dcx().span_delayed_bug( - self.body.span, - "failed re-defining predefined opaques in mir typeck", - ); + self.infcx + .dcx() + .span_bug(self.body.span, "failed re-defining predefined opaques in mir typeck"); } } @@ -2766,7 +2764,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.param_env, self.known_type_outlives_obligations, locations, - DUMMY_SP, // irrelevant; will be overridden. + self.body.span, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. self.borrowck_context.constraints, ) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index ee0bd13109b..dd355c3525c 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,11 +1,14 @@ +use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; -use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; -use rustc_infer::infer::NllRegionVariableOrigin; -use rustc_infer::traits::PredicateObligations; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{NllRegionVariableOrigin, ObligationEmittingRelation}; +use rustc_infer::traits::{Obligation, PredicateObligations}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::NoSolution; -use rustc_middle::ty::relate::TypeRelation; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::fold::FnMutDelegate; +use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -32,12 +35,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory<'tcx>, ) -> Result<(), NoSolution> { - TypeRelating::new( - self.infcx, - NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)), - v, - ) - .relate(a, b)?; + NllTypeRelating::new(self, locations, category, UniverseInfo::relate(a, b), v) + .relate(a, b)?; Ok(()) } @@ -49,9 +48,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory<'tcx>, ) -> Result<(), NoSolution> { - TypeRelating::new( - self.infcx, - NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()), + NllTypeRelating::new( + self, + locations, + category, + UniverseInfo::other(), ty::Variance::Invariant, ) .relate(a, b)?; @@ -59,7 +60,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } -struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { +pub struct NllTypeRelating<'me, 'bccx, 'tcx> { type_checker: &'me mut TypeChecker<'bccx, 'tcx>, /// Where (and why) is this relation taking place? @@ -71,26 +72,177 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { /// Information so that error reporting knows what types we are relating /// when reporting a bound region error. universe_info: UniverseInfo<'tcx>, + + /// How are we relating `a` and `b`? + /// + /// - Covariant means `a <: b`. + /// - Contravariant means `b <: a`. + /// - Invariant means `a == b`. + /// - Bivariant means that it doesn't matter. + ambient_variance: ty::Variance, + + ambient_variance_info: ty::VarianceDiagInfo<'tcx>, } -impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { - fn new( +impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { + pub fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, universe_info: UniverseInfo<'tcx>, + ambient_variance: ty::Variance, ) -> Self { - Self { type_checker, locations, category, universe_info } + Self { + type_checker, + locations, + category, + universe_info, + ambient_variance, + ambient_variance_info: ty::VarianceDiagInfo::default(), + } } -} -impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { - fn span(&self) -> Span { - self.locations.span(self.type_checker.body) + fn ambient_covariance(&self) -> bool { + match self.ambient_variance { + ty::Variance::Covariant | ty::Variance::Invariant => true, + ty::Variance::Contravariant | ty::Variance::Bivariant => false, + } } - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.type_checker.param_env + fn ambient_contravariance(&self) -> bool { + match self.ambient_variance { + ty::Variance::Contravariant | ty::Variance::Invariant => true, + ty::Variance::Covariant | ty::Variance::Bivariant => false, + } + } + + fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { + let infcx = self.type_checker.infcx; + debug_assert!(!infcx.next_trait_solver()); + let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; + // `handle_opaque_type` cannot handle subtyping, so to support subtyping + // we instead eagerly generalize here. This is a bit of a mess but will go + // away once we're using the new solver. + let mut enable_subtyping = |ty, ty_is_expected| { + let ty_vid = infcx.next_ty_var_id_in_universe( + TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: self.span(), + }, + ty::UniverseIndex::ROOT, + ); + + let variance = if ty_is_expected { + self.ambient_variance + } else { + self.ambient_variance.xform(ty::Contravariant) + }; + + self.type_checker.infcx.instantiate_ty_var( + self, + ty_is_expected, + ty_vid, + variance, + ty, + )?; + Ok(infcx.resolve_vars_if_possible(Ty::new_infer(infcx.tcx, ty::TyVar(ty_vid)))) + }; + + let (a, b) = match (a.kind(), b.kind()) { + (&ty::Alias(ty::Opaque, ..), _) => (a, enable_subtyping(b, false)?), + (_, &ty::Alias(ty::Opaque, ..)) => (enable_subtyping(a, true)?, b), + _ => unreachable!( + "expected at least one opaque type in `relate_opaques`, got {a} and {b}." + ), + }; + let cause = ObligationCause::dummy_with_span(self.span()); + let obligations = + infcx.handle_opaque_type(a, b, true, &cause, self.param_env())?.obligations; + self.register_obligations(obligations); + Ok(()) + } + + fn enter_forall<T, U>( + &mut self, + binder: ty::Binder<'tcx, T>, + f: impl FnOnce(&mut Self, T) -> U, + ) -> U + where + T: ty::TypeFoldable<TyCtxt<'tcx>> + Copy, + { + let value = if let Some(inner) = binder.no_bound_vars() { + inner + } else { + let infcx = self.type_checker.infcx; + let mut lazy_universe = None; + let delegate = FnMutDelegate { + regions: &mut |br: ty::BoundRegion| { + // The first time this closure is called, create a + // new universe for the placeholders we will make + // from here out. + let universe = lazy_universe.unwrap_or_else(|| { + let universe = self.create_next_universe(); + lazy_universe = Some(universe); + universe + }); + + let placeholder = ty::PlaceholderRegion { universe, bound: br }; + debug!(?placeholder); + let placeholder_reg = self.next_placeholder_region(placeholder); + debug!(?placeholder_reg); + + placeholder_reg + }, + types: &mut |_bound_ty: ty::BoundTy| { + unreachable!("we only replace regions in nll_relate, not types") + }, + consts: &mut |_bound_var: ty::BoundVar, _ty| { + unreachable!("we only replace regions in nll_relate, not consts") + }, + }; + + infcx.tcx.replace_bound_vars_uncached(binder, delegate) + }; + + debug!(?value); + f(self, value) + } + + #[instrument(skip(self), level = "debug")] + fn instantiate_binder_with_existentials<T>(&mut self, binder: ty::Binder<'tcx, T>) -> T + where + T: ty::TypeFoldable<TyCtxt<'tcx>> + Copy, + { + if let Some(inner) = binder.no_bound_vars() { + return inner; + } + + let infcx = self.type_checker.infcx; + let mut reg_map = FxHashMap::default(); + let delegate = FnMutDelegate { + regions: &mut |br: ty::BoundRegion| { + if let Some(ex_reg_var) = reg_map.get(&br) { + return *ex_reg_var; + } else { + let ex_reg_var = self.next_existential_region_var(true, br.kind.get_name()); + debug!(?ex_reg_var); + reg_map.insert(br, ex_reg_var); + + ex_reg_var + } + }, + types: &mut |_bound_ty: ty::BoundTy| { + unreachable!("we only replace regions in nll_relate, not types") + }, + consts: &mut |_bound_var: ty::BoundVar, _ty| { + unreachable!("we only replace regions in nll_relate, not consts") + }, + }; + + let replaced = infcx.tcx.replace_bound_vars_uncached(binder, delegate); + debug!(?replaced); + + replaced } fn create_next_universe(&mut self) -> ty::UniverseIndex { @@ -143,22 +295,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> reg } - #[instrument(skip(self), level = "debug")] - fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { - let reg = self.type_checker.infcx.next_nll_region_var_in_universe( - NllRegionVariableOrigin::Existential { from_forall: false }, - universe, - ); - - if cfg!(debug_assertions) { - let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut(); - let prev = var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None)); - assert_eq!(prev, None); - } - - reg - } - fn push_outlives( &mut self, sup: ty::Region<'tcx>, @@ -179,11 +315,250 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> }, ); } +} + +impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.type_checker.infcx.tcx + } + + fn tag(&self) -> &'static str { + "nll::subtype" + } - fn forbid_inference_vars() -> bool { + fn a_is_expected(&self) -> bool { true } + #[instrument(skip(self, info), level = "trace", ret)] + fn relate_with_variance<T: Relate<'tcx>>( + &mut self, + variance: ty::Variance, + info: ty::VarianceDiagInfo<'tcx>, + a: T, + b: T, + ) -> RelateResult<'tcx, T> { + let old_ambient_variance = self.ambient_variance; + self.ambient_variance = self.ambient_variance.xform(variance); + self.ambient_variance_info = self.ambient_variance_info.xform(info); + + debug!(?self.ambient_variance); + // In a bivariant context this always succeeds. + let r = + if self.ambient_variance == ty::Variance::Bivariant { a } else { self.relate(a, b)? }; + + self.ambient_variance = old_ambient_variance; + + Ok(r) + } + + #[instrument(skip(self), level = "debug")] + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + let infcx = self.type_checker.infcx; + + let a = self.type_checker.infcx.shallow_resolve(a); + assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b); + + if a == b { + return Ok(a); + } + + match (a.kind(), b.kind()) { + (_, &ty::Infer(ty::TyVar(_))) => { + span_bug!( + self.span(), + "should not be relating type variables on the right in MIR typeck" + ); + } + + (&ty::Infer(ty::TyVar(a_vid)), _) => { + infcx.instantiate_ty_var(self, true, a_vid, self.ambient_variance, b)? + } + + ( + &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), + &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), + ) if a_def_id == b_def_id || infcx.next_trait_solver() => { + infcx.super_combine_tys(self, a, b).map(|_| ()).or_else(|err| { + // This behavior is only there for the old solver, the new solver + // shouldn't ever fail. Instead, it unconditionally emits an + // alias-relate goal. + assert!(!self.type_checker.infcx.next_trait_solver()); + self.tcx().dcx().span_delayed_bug( + self.span(), + "failure to relate an opaque to itself should result in an error later on", + ); + if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) } + })?; + } + (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) + | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) + if def_id.is_local() && !self.type_checker.infcx.next_trait_solver() => + { + self.relate_opaques(a, b)?; + } + + _ => { + debug!(?a, ?b, ?self.ambient_variance); + + // Will also handle unification of `IntVar` and `FloatVar`. + self.type_checker.infcx.super_combine_tys(self, a, b)?; + } + } + + Ok(a) + } + + #[instrument(skip(self), level = "trace")] + fn regions( + &mut self, + a: ty::Region<'tcx>, + b: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { + debug!(?self.ambient_variance); + + if self.ambient_covariance() { + // Covariant: &'a u8 <: &'b u8. Hence, `'a: 'b`. + self.push_outlives(a, b, self.ambient_variance_info); + } + + if self.ambient_contravariance() { + // Contravariant: &'b u8 <: &'a u8. Hence, `'b: 'a`. + self.push_outlives(b, a, self.ambient_variance_info); + } + + Ok(a) + } + + fn consts( + &mut self, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { + let a = self.type_checker.infcx.shallow_resolve(a); + assert!(!a.has_non_region_infer(), "unexpected inference var {:?}", a); + assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b); + + self.type_checker.infcx.super_combine_consts(self, a, b) + } + + #[instrument(skip(self), level = "trace")] + fn binders<T>( + &mut self, + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> + where + T: Relate<'tcx>, + { + // We want that + // + // ``` + // for<'a> fn(&'a u32) -> &'a u32 <: + // fn(&'b u32) -> &'b u32 + // ``` + // + // but not + // + // ``` + // fn(&'a u32) -> &'a u32 <: + // for<'b> fn(&'b u32) -> &'b u32 + // ``` + // + // We therefore proceed as follows: + // + // - Instantiate binders on `b` universally, yielding a universe U1. + // - Instantiate binders on `a` existentially in U1. + + debug!(?self.ambient_variance); + + if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) { + // Fast path for the common case. + self.relate(a, b)?; + return Ok(ty::Binder::dummy(a)); + } + + if self.ambient_covariance() { + // Covariance, so we want `for<..> A <: for<..> B` -- + // therefore we compare any instantiation of A (i.e., A + // instantiated with existentials) against every + // instantiation of B (i.e., B instantiated with + // universals). + + // Reset the ambient variance to covariant. This is needed + // to correctly handle cases like + // + // for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32) + // + // Somewhat surprisingly, these two types are actually + // **equal**, even though the one on the right looks more + // polymorphic. The reason is due to subtyping. To see it, + // consider that each function can call the other: + // + // - The left function can call the right with `'b` and + // `'c` both equal to `'a` + // + // - The right function can call the left with `'a` set to + // `{P}`, where P is the point in the CFG where the call + // itself occurs. Note that `'b` and `'c` must both + // include P. At the point, the call works because of + // subtyping (i.e., `&'b u32 <: &{P} u32`). + let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant); + + // Note: the order here is important. Create the placeholders first, otherwise + // we assign the wrong universe to the existential! + self.enter_forall(b, |this, b| { + let a = this.instantiate_binder_with_existentials(a); + this.relate(a, b) + })?; + + self.ambient_variance = variance; + } + + if self.ambient_contravariance() { + // Contravariance, so we want `for<..> A :> for<..> B` + // -- therefore we compare every instantiation of A (i.e., + // A instantiated with universals) against any + // instantiation of B (i.e., B instantiated with + // existentials). Opposite of above. + + // Reset ambient variance to contravariance. See the + // covariant case above for an explanation. + let variance = + std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant); + + self.enter_forall(a, |this, a| { + let b = this.instantiate_binder_with_existentials(b); + this.relate(a, b) + })?; + + self.ambient_variance = variance; + } + + Ok(a) + } +} + +impl<'bccx, 'tcx> ObligationEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> { + fn span(&self) -> Span { + self.locations.span(self.type_checker.body) + } + + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.type_checker.param_env + } + + fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) { + self.register_obligations( + obligations + .into_iter() + .map(|to_pred| { + Obligation::new(self.tcx(), ObligationCause::dummy(), self.param_env(), to_pred) + }) + .collect(), + ); + } + fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op( self.locations, @@ -196,4 +571,32 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> }, ); } + + fn alias_relate_direction(&self) -> ty::AliasRelationDirection { + unreachable!("manually overridden to handle ty::Variance::Contravariant ambient variance") + } + + fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + self.register_predicates([ty::Binder::dummy(match self.ambient_variance { + ty::Variance::Covariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Subtype, + ), + // a :> b is b <: a + ty::Variance::Contravariant => ty::PredicateKind::AliasRelate( + b.into(), + a.into(), + ty::AliasRelationDirection::Subtype, + ), + ty::Variance::Invariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ), + ty::Variance::Bivariant => { + unreachable!("cannot defer an alias-relate goal with Bivariant variance (yet?)") + } + })]); + } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index a69f5335f71..e7439481034 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -16,7 +16,7 @@ #![allow(rustc::untranslatable_diagnostic)] use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::Diagnostic; +use rustc_errors::DiagnosticBuilder; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::BodyOwnerKind; @@ -343,7 +343,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// that this region imposes on others. The methods in this file /// handle the part about dumping the inference context internal /// state. - pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) { + pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_, ()>) { match self.defining_ty { DefiningTy::Closure(def_id, args) => { let v = with_no_trimmed_paths!( |
