From 40a053361a2871e286cf5cbc83cc2ed3926e1b4b Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 25 Nov 2022 15:51:46 +0100 Subject: [PATCH 01/16] small method code cleanup --- compiler/rustc_hir_typeck/src/callee.rs | 16 ++++++++++------ compiler/rustc_hir_typeck/src/coercion.rs | 7 +++---- compiler/rustc_hir_typeck/src/method/probe.rs | 9 ++++----- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 25b6cf4ef2e3e..cd1322d1a3bcc 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -179,12 +179,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Hack: we know that there are traits implementing Fn for &F // where F:Fn and so forth. In the particular case of types - // like `x: &mut FnMut()`, if there is a call `x()`, we would - // normally translate to `FnMut::call_mut(&mut x, ())`, but - // that winds up requiring `mut x: &mut FnMut()`. A little - // over the top. The simplest fix by far is to just ignore - // this case and deref again, so we wind up with - // `FnMut::call_mut(&mut *x, ())`. + // like `f: &mut FnMut()`, if there is a call `f()`, we would + // normally translate to `FnMut::call_mut(&mut f, ())`, but + // that winds up requiring the user to potentially mark their + // variable as `mut` which feels unnecessary and unexpected. + // + // fn foo(f: &mut impl FnMut()) { f() } + // ^ without this hack `f` would have to be declared as mutable + // + // The simplest fix by far is to just ignore this case and deref again, + // so we wind up with `FnMut::call_mut(&mut *f, ())`. ty::Ref(..) if autoderef.step_count() == 0 => { return None; } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 82784bb8a661a..f6377f9f49403 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1112,15 +1112,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Special-case that coercion alone cannot handle: // Function items or non-capturing closures of differing IDs or InternalSubsts. let (a_sig, b_sig) = { - #[allow(rustc::usage_of_ty_tykind)] - let is_capturing_closure = |ty: &ty::TyKind<'tcx>| { - if let &ty::Closure(closure_def_id, _substs) = ty { + let is_capturing_closure = |ty: Ty<'tcx>| { + if let &ty::Closure(closure_def_id, _substs) = ty.kind() { self.tcx.upvars_mentioned(closure_def_id.expect_local()).is_some() } else { false } }; - if is_capturing_closure(prev_ty.kind()) || is_capturing_closure(new_ty.kind()) { + if is_capturing_closure(prev_ty) || is_capturing_closure(new_ty) { (None, None) } else { match (prev_ty.kind(), new_ty.kind()) { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 44c3edf06a883..37f9cdfeebc60 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -342,10 +342,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut orig_values, ); - let steps = if mode == Mode::MethodCall { - self.tcx.method_autoderef_steps(param_env_and_self_ty) - } else { - self.probe(|_| { + let steps = match mode { + Mode::MethodCall => self.tcx.method_autoderef_steps(param_env_and_self_ty), + Mode::Path => self.probe(|_| { // Mode::Path - the deref steps is "trivial". This turns // our CanonicalQuery into a "trivial" QueryResponse. This // is a bit inefficient, but I don't think that writing @@ -374,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_bad_ty: None, reached_recursion_limit: false, } - }) + }), }; // If our autoderef loop had reached the recursion limit, From a215b7b4dfef1d8f4161416838a0cd6abb348216 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 25 Nov 2022 16:21:42 +0100 Subject: [PATCH 02/16] remove `TypeError::ObjectUnsafeCoercion` --- compiler/rustc_hir_typeck/src/cast.rs | 12 ---- compiler/rustc_hir_typeck/src/coercion.rs | 4 -- .../src/infer/error_reporting/mod.rs | 62 ++++++++----------- compiler/rustc_middle/src/ty/error.rs | 5 +- 4 files changed, 27 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 5e1e44dcb6d15..6f8743ed32ab6 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -46,7 +46,6 @@ use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; -use rustc_trait_selection::traits::error_reporting::report_object_safety_error; /// Reifies a cast check to be checked once we have full type information for /// a function context. @@ -727,9 +726,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { debug!(" -> CoercionCast"); fcx.typeck_results.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id); } - Err(ty::error::TypeError::ObjectUnsafeCoercion(did)) => { - self.report_object_unsafe_cast(&fcx, did); - } Err(_) => { match self.do_check(fcx) { Ok(k) => { @@ -741,14 +737,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { }; } } - - fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) { - let violations = fcx.tcx.object_safety_violations(did); - let mut err = report_object_safety_error(fcx.tcx, self.cast_span, did, violations); - err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty))); - err.emit(); - } - /// Checks a cast, and report an error if one exists. In some cases, this /// can return Ok and create type errors in the fcx rather than returning /// directly. coercion-cast is handled in check instead of here. diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index f6377f9f49403..121dd4a1be1ca 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -199,10 +199,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { debug!("coerce: unsize successful"); return unsize; } - Err(TypeError::ObjectUnsafeCoercion(did)) => { - debug!("coerce: unsize not object safe"); - return Err(TypeError::ObjectUnsafeCoercion(did)); - } Err(error) => { debug!(?error, "coerce: unsize failed"); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 0dee3be705474..5c0a460e5d637 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1677,40 +1677,34 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } }; - match terr { - // Ignore msg for object safe coercion - // since E0038 message will be printed - TypeError::ObjectUnsafeCoercion(_) => {} - _ => { - let mut label_or_note = |span: Span, msg: &str| { - if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() { - diag.span_label(span, msg); - } else { - diag.span_note(span, msg); - } - }; - if let Some((sp, msg)) = secondary_span { - if swap_secondary_and_primary { - let terr = if let Some(infer::ValuePairs::Terms(infer::ExpectedFound { - expected, - .. - })) = values - { - format!("expected this to be `{}`", expected) - } else { - terr.to_string() - }; - label_or_note(sp, &terr); - label_or_note(span, &msg); - } else { - label_or_note(span, &terr.to_string()); - label_or_note(sp, &msg); - } - } else { - label_or_note(span, &terr.to_string()); - } + let mut label_or_note = |span: Span, msg: &str| { + if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() { + diag.span_label(span, msg); + } else { + diag.span_note(span, msg); } }; + if let Some((sp, msg)) = secondary_span { + if swap_secondary_and_primary { + let terr = if let Some(infer::ValuePairs::Terms(infer::ExpectedFound { + expected, + .. + })) = values + { + format!("expected this to be `{}`", expected) + } else { + terr.to_string() + }; + label_or_note(sp, &terr); + label_or_note(span, &msg); + } else { + label_or_note(span, &terr.to_string()); + label_or_note(sp, &msg); + } + } else { + label_or_note(span, &terr.to_string()); + } + if let Some((expected, found)) = expected_found { let (expected_label, found_label, exp_found) = match exp_found { Mismatch::Variable(ef) => ( @@ -1880,9 +1874,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); } } - TypeError::ObjectUnsafeCoercion(_) => { - diag.note_unsuccessful_coercion(found, expected); - } _ => { debug!( "note_type_err: exp_found={:?}, expected={:?} found={:?}", @@ -3127,7 +3118,6 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { TypeError::IntrinsicCast => { Error0308("cannot coerce intrinsics to function pointers") } - TypeError::ObjectUnsafeCoercion(did) => Error0038(did), _ => Error0308("mismatched types"), }, } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index a61f41b9c580f..d83e17574a094 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -70,7 +70,6 @@ pub enum TypeError<'tcx> { CyclicConst(ty::Const<'tcx>), ProjectionMismatched(ExpectedFound), ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), - ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound>), IntrinsicCast, @@ -222,7 +221,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { f, "cannot coerce functions with `#[target_feature]` to safe function pointers" ), - ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"), } } } @@ -249,8 +247,7 @@ impl<'tcx> TypeError<'tcx> { | ProjectionMismatched(_) | ExistentialMismatch(_) | ConstMismatch(_) - | IntrinsicCast - | ObjectUnsafeCoercion(_) => true, + | IntrinsicCast => true, } } } From 4f07008419667eb7d9feea5ec391eda19d6d9338 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 25 Nov 2022 16:35:10 +0100 Subject: [PATCH 03/16] remove confusing comment `?0: CoerceUnsized` can definitely apply because `?0` matches any type, same for `SomeTy: CoerceUnsized` --- compiler/rustc_hir_typeck/src/coercion.rs | 24 +++-------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 121dd4a1be1ca..e949f7ec34f8a 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -503,27 +503,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { target = self.shallow_resolve(target); debug!(?source, ?target); - // These 'if' statements require some explanation. - // The `CoerceUnsized` trait is special - it is only - // possible to write `impl CoerceUnsized for A` where - // A and B have 'matching' fields. This rules out the following - // two types of blanket impls: - // - // `impl CoerceUnsized for SomeType` - // `impl CoerceUnsized for T` - // - // Both of these trigger a special `CoerceUnsized`-related error (E0376) - // - // We can take advantage of this fact to avoid performing unnecessary work. - // If either `source` or `target` is a type variable, then any applicable impl - // would need to be generic over the self-type (`impl CoerceUnsized for T`) - // or generic over the `CoerceUnsized` type parameter (`impl CoerceUnsized for - // SomeType`). - // - // However, these are exactly the kinds of impls which are forbidden by - // the compiler! Therefore, we can be sure that coercion will always fail - // when either the source or target type is a type variable. This allows us - // to skip performing any trait selection, and immediately bail out. + // We don't apply any coercions incase either the source or target + // aren't sufficiently well known but tend to instead just equate + // them both. if source.is_ty_var() { debug!("coerce_unsized: source is a TyVar, bailing out"); return Err(TypeError::Mismatch); From 6436c348dbaa0eb8f2853dfb64cbf8b30f5119f2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 25 Nov 2022 23:31:28 +0000 Subject: [PATCH 04/16] Remove SelectionContext::infcx() in favor of field access --- .../src/traits/auto_trait.rs | 31 +++++------ .../src/traits/coherence.rs | 14 ++--- .../src/traits/fulfill.rs | 31 ++++++----- .../src/traits/project.rs | 54 +++++++++---------- .../src/traits/select/candidate_assembly.rs | 10 ++-- .../src/traits/select/confirmation.rs | 4 +- .../src/traits/select/mod.rs | 19 +++---- .../rustc_trait_selection/src/traits/util.rs | 4 +- 8 files changed, 75 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 52552ff3f8674..3bc248bb0b274 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -599,17 +599,17 @@ impl<'tcx> AutoTraitFinder<'tcx> { computed_preds: &mut FxIndexSet>, fresh_preds: &mut FxHashSet>, predicates: &mut VecDeque>, - select: &mut SelectionContext<'_, 'tcx>, + selcx: &mut SelectionContext<'_, 'tcx>, only_projections: bool, ) -> bool { let dummy_cause = ObligationCause::dummy(); for obligation in nested { let is_new_pred = - fresh_preds.insert(self.clean_pred(select.infcx(), obligation.predicate)); + fresh_preds.insert(self.clean_pred(selcx.infcx, obligation.predicate)); // Resolve any inference variables that we can, to help selection succeed - let predicate = select.infcx().resolve_vars_if_possible(obligation.predicate); + let predicate = selcx.infcx.resolve_vars_if_possible(obligation.predicate); // We only add a predicate as a user-displayable bound if // it involves a generic parameter, and doesn't contain @@ -717,10 +717,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { // and turn them into an explicit negative impl for our type. debug!("Projecting and unifying projection predicate {:?}", predicate); - match project::poly_project_and_unify_type( - select, - &obligation.with(self.tcx, p), - ) { + match project::poly_project_and_unify_type(selcx, &obligation.with(self.tcx, p)) + { ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { debug!( "evaluate_nested_obligations: Unable to unify predicate \ @@ -745,7 +743,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { computed_preds, fresh_preds, predicates, - select, + selcx, only_projections, ) { return false; @@ -768,7 +766,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } ty::PredicateKind::Clause(ty::Clause::RegionOutlives(binder)) => { let binder = bound_predicate.rebind(binder); - select.infcx().region_outlives_predicate(&dummy_cause, binder) + selcx.infcx.region_outlives_predicate(&dummy_cause, binder) } ty::PredicateKind::Clause(ty::Clause::TypeOutlives(binder)) => { let binder = bound_predicate.rebind(binder); @@ -777,14 +775,14 @@ impl<'tcx> AutoTraitFinder<'tcx> { binder.map_bound_ref(|pred| pred.0).no_bound_vars(), ) { (None, Some(t_a)) => { - select.infcx().register_region_obligation_with_cause( + selcx.infcx.register_region_obligation_with_cause( t_a, - select.infcx().tcx.lifetimes.re_static, + selcx.infcx.tcx.lifetimes.re_static, &dummy_cause, ); } (Some(ty::OutlivesPredicate(t_a, r_b)), _) => { - select.infcx().register_region_obligation_with_cause( + selcx.infcx.register_region_obligation_with_cause( t_a, r_b, &dummy_cause, @@ -796,13 +794,13 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::PredicateKind::ConstEquate(c1, c2) => { let evaluate = |c: ty::Const<'tcx>| { if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() { - match select.infcx().const_eval_resolve( + match selcx.infcx.const_eval_resolve( obligation.param_env, unevaluated, Some(obligation.cause.span), ) { Ok(Some(valtree)) => { - Ok(ty::Const::from_value(select.tcx(), valtree, c.ty())) + Ok(ty::Const::from_value(selcx.tcx(), valtree, c.ty())) } Ok(None) => { let tcx = self.tcx; @@ -823,10 +821,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match select - .infcx() - .at(&obligation.cause, obligation.param_env) - .eq(c1, c2) + match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) { Ok(_) => (), Err(_) => return false, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 741bf206d037e..99724fb28db11 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -119,7 +119,7 @@ fn with_fresh_ty_vars<'cx, 'tcx>( impl_def_id: DefId, ) -> ty::ImplHeader<'tcx> { let tcx = selcx.tcx(); - let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id); + let impl_substs = selcx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); let header = ty::ImplHeader { impl_def_id, @@ -149,7 +149,7 @@ fn overlap<'cx, 'tcx>( impl1_def_id, impl2_def_id, overlap_mode ); - selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { + selcx.infcx.probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { overlap_within_probe(selcx, impl1_def_id, impl2_def_id, overlap_mode, snapshot) }) } @@ -161,7 +161,7 @@ fn overlap_within_probe<'cx, 'tcx>( overlap_mode: OverlapMode, snapshot: &CombinedSnapshot<'tcx>, ) -> Option> { - let infcx = selcx.infcx(); + let infcx = selcx.infcx; if overlap_mode.use_negative_impl() { if negative_impl(infcx.tcx, impl1_def_id, impl2_def_id) @@ -200,9 +200,9 @@ fn overlap_within_probe<'cx, 'tcx>( debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); let involves_placeholder = - matches!(selcx.infcx().region_constraints_added_in_snapshot(snapshot), Some(true)); + matches!(selcx.infcx.region_constraints_added_in_snapshot(snapshot), Some(true)); - let impl_header = selcx.infcx().resolve_vars_if_possible(impl1_header); + let impl_header = selcx.infcx.resolve_vars_if_possible(impl1_header); Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder }) } @@ -214,7 +214,7 @@ fn equate_impl_headers<'cx, 'tcx>( // Do `a` and `b` unify? If not, no overlap. debug!("equate_impl_headers(impl1_header={:?}, impl2_header={:?}", impl1_header, impl2_header); selcx - .infcx() + .infcx .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) .eq_impl_headers(impl1_header, impl2_header) .map(|infer_ok| infer_ok.obligations) @@ -255,7 +255,7 @@ fn implicit_negative<'cx, 'tcx>( "implicit_negative(impl1_header={:?}, impl2_header={:?}, obligations={:?})", impl1_header, impl2_header, obligations ); - let infcx = selcx.infcx(); + let infcx = selcx.infcx; let opt_failing_obligation = impl1_header .predicates .iter() diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index b0d0d1a7cba44..19c384671b3b9 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -199,7 +199,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // code is so hot. 1 and 0 dominate; 2+ is fairly rare. 1 => { let infer_var = pending_obligation.stalled_on[0]; - self.selcx.infcx().ty_or_const_infer_var_changed(infer_var) + self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) } 0 => { // In this case we haven't changed, but wish to make a change. @@ -210,7 +210,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // form was a perf win. See #64545 for details. (|| { for &infer_var in &pending_obligation.stalled_on { - if self.selcx.infcx().ty_or_const_infer_var_changed(infer_var) { + if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) { return true; } } @@ -240,13 +240,12 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { debug!(?obligation, "pre-resolve"); if obligation.predicate.has_non_region_infer() { - obligation.predicate = - self.selcx.infcx().resolve_vars_if_possible(obligation.predicate); + obligation.predicate = self.selcx.infcx.resolve_vars_if_possible(obligation.predicate); } let obligation = &pending_obligation.obligation; - let infcx = self.selcx.infcx(); + let infcx = self.selcx.infcx; if obligation.predicate.has_projections() { let mut obligations = Vec::new(); @@ -353,7 +352,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::PredicateKind::ClosureKind(_, closure_substs, kind) => { - match self.selcx.infcx().closure_kind(closure_substs) { + match self.selcx.infcx.closure_kind(closure_substs) { Some(closure_kind) => { if closure_kind.extends(kind) { ProcessResult::Changed(vec![]) @@ -367,7 +366,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::WellFormed(arg) => { match wf::obligations( - self.selcx.infcx(), + self.selcx.infcx, obligation.param_env, obligation.cause.body_id, obligation.recursion_depth + 1, @@ -384,7 +383,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::PredicateKind::Subtype(subtype) => { - match self.selcx.infcx().subtype_predicate( + match self.selcx.infcx.subtype_predicate( &obligation.cause, obligation.param_env, Binder::dummy(subtype), @@ -408,7 +407,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::PredicateKind::Coerce(coerce) => { - match self.selcx.infcx().coerce_predicate( + match self.selcx.infcx.coerce_predicate( &obligation.cause, obligation.param_env, Binder::dummy(coerce), @@ -432,7 +431,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::ConstEvaluatable(uv) => { match const_evaluatable::is_const_evaluatable( - self.selcx.infcx(), + self.selcx.infcx, uv, obligation.param_env, obligation.cause.span, @@ -476,7 +475,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let mut evaluate = |c: Const<'tcx>| { if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() { - match self.selcx.infcx().try_const_eval_resolve( + match self.selcx.infcx.try_const_eval_resolve( obligation.param_env, unevaluated, c.ty(), @@ -504,7 +503,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { (Ok(c1), Ok(c2)) => { match self .selcx - .infcx() + .infcx .at(&obligation.cause, obligation.param_env) .eq(c1, c2) { @@ -572,7 +571,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { trait_obligation: TraitObligation<'tcx>, stalled_on: &mut Vec>, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { - let infcx = self.selcx.infcx(); + let infcx = self.selcx.infcx; if obligation.predicate.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. @@ -630,7 +629,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { if obligation.predicate.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) { + if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) { if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate( &mut self.selcx, project_obligation.predicate, @@ -639,7 +638,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { // evaluated all sub-obligations. We can therefore mark the 'root' // obligation as complete, and skip evaluating sub-obligations. self.selcx - .infcx() + .infcx .inner .borrow_mut() .projection_cache() @@ -678,7 +677,7 @@ fn substs_infer_vars<'a, 'tcx>( substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> impl Iterator> { selcx - .infcx() + .infcx .resolve_vars_if_possible(substs) .skip_binder() // ok because this check doesn't care about regions .iter() diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ae6fa841856cb..f358687402f47 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -194,7 +194,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &PolyProjectionObligation<'tcx>, ) -> ProjectAndUnifyResult<'tcx> { - let infcx = selcx.infcx(); + let infcx = selcx.infcx; let r = infcx.commit_if_ok(|_snapshot| { let old_universe = infcx.universe(); let placeholder_predicate = @@ -250,7 +250,7 @@ fn project_and_unify_type<'cx, 'tcx>( ) -> ProjectAndUnifyResult<'tcx> { let mut obligations = vec![]; - let infcx = selcx.infcx(); + let infcx = selcx.infcx; let normalized = match opt_normalize_projection_type( selcx, obligation.param_env, @@ -269,7 +269,7 @@ fn project_and_unify_type<'cx, 'tcx>( // This allows users to omit re-mentioning all bounds on an associated type and just use an // `impl Trait` for the assoc type to add more bounds. let InferOk { value: actual, obligations: new } = - selcx.infcx().replace_opaque_types_with_inference_vars( + selcx.infcx.replace_opaque_types_with_inference_vars( actual, obligation.cause.body_id, obligation.cause.span, @@ -445,7 +445,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { } fn fold>(&mut self, value: T) -> T { - let value = self.selcx.infcx().resolve_vars_if_possible(value); + let value = self.selcx.infcx.resolve_vars_if_possible(value); debug!(?value); assert!( @@ -524,7 +524,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { self.param_env, ty, ); - self.selcx.infcx().err_ctxt().report_overflow_error(&obligation, true); + self.selcx.infcx.err_ctxt().report_overflow_error(&obligation, true); } let substs = substs.fold_with(self); @@ -590,7 +590,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // want to figure out how to register obligations with escaping vars // or handle this some other way. - let infcx = self.selcx.infcx(); + let infcx = self.selcx.infcx; let (data, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); let data = data.fold_with(self); @@ -640,7 +640,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { let constant = constant.super_fold_with(self); debug!(?constant, ?self.param_env); with_replaced_escaping_bound_vars( - self.selcx.infcx(), + self.selcx.infcx, &mut self.universes, constant, |constant| constant.eval(tcx, self.param_env), @@ -992,10 +992,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( // and a deferred predicate to resolve this when more type // information is available. - selcx - .infcx() - .infer_projection(param_env, projection_ty, cause, depth + 1, obligations) - .into() + selcx.infcx.infer_projection(param_env, projection_ty, cause, depth + 1, obligations).into() }) } @@ -1018,7 +1015,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( depth: usize, obligations: &mut Vec>, ) -> Result>, InProgress> { - let infcx = selcx.infcx(); + let infcx = selcx.infcx; // Don't use the projection cache in intercrate mode - // the `infcx` may be re-used between intercrate in non-intercrate // mode, which could lead to using incorrect cache results. @@ -1110,7 +1107,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // an impl, where-clause etc) and hence we must // re-normalize it - let projected_term = selcx.infcx().resolve_vars_if_possible(projected_term); + let projected_term = selcx.infcx.resolve_vars_if_possible(projected_term); let mut result = if projected_term.has_projections() { let mut normalizer = AssocTypeNormalizer::new( @@ -1206,9 +1203,9 @@ fn normalize_to_error<'a, 'tcx>( param_env, predicate: trait_ref.without_const().to_predicate(selcx.tcx()), }; - let tcx = selcx.infcx().tcx; + let tcx = selcx.infcx.tcx; let def_id = projection_ty.item_def_id; - let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin { + let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::NormalizeProjectionType, span: tcx.def_span(def_id), }); @@ -1330,7 +1327,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( let trait_predicate = ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs }); - let _ = selcx.infcx().commit_if_ok(|_| { + let _ = selcx.infcx.commit_if_ok(|_| { match selcx.select(&obligation.with(tcx, trait_predicate)) { Ok(Some(super::ImplSource::UserDefined(data))) => { candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait( @@ -1435,7 +1432,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); - let object_ty = selcx.infcx().shallow_resolve(self_ty); + let object_ty = selcx.infcx.shallow_resolve(self_ty); let data = match object_ty.kind() { ty::Dynamic(data, ..) => data, ty::Infer(ty::TyVar(_)) => { @@ -1473,7 +1470,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( env_predicates: impl Iterator>, potentially_unnormalized_candidates: bool, ) { - let infcx = selcx.infcx(); + let infcx = selcx.infcx; for predicate in env_predicates { let bound_predicate = predicate.kind(); if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = @@ -1529,7 +1526,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // start out by selecting the predicate `T as TraitRef<...>`: let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx())); let trait_obligation = obligation.with(selcx.tcx(), poly_trait_ref); - let _ = selcx.infcx().commit_if_ok(|_| { + let _ = selcx.infcx.commit_if_ok(|_| { let impl_source = match selcx.select(&trait_obligation) { Ok(Some(impl_source)) => impl_source, Ok(None) => { @@ -1587,7 +1584,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( if obligation.param_env.reveal() == Reveal::All { // NOTE(eddyb) inference variables can resolve to parameters, so // assume `poly_trait_ref` isn't monomorphic, if it contains any. - let poly_trait_ref = selcx.infcx().resolve_vars_if_possible(poly_trait_ref); + let poly_trait_ref = selcx.infcx.resolve_vars_if_possible(poly_trait_ref); !poly_trait_ref.still_further_specializable() } else { debug!( @@ -1603,7 +1600,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // While a builtin impl may be known to exist, the associated type may not yet // be known. Any type with multiple potential associated types is therefore // not eligible. - let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); + let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let lang_items = selcx.tcx().lang_items(); if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) { @@ -1690,7 +1687,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // type parameters, opaques, and unnormalized projections have pointer // metadata if they're known (e.g. by the param_env) to be sized ty::Param(_) | ty::Projection(..) | ty::Opaque(..) - if selcx.infcx().predicate_must_hold_modulo_regions( + if selcx.infcx.predicate_must_hold_modulo_regions( &obligation.with( selcx.tcx(), ty::Binder::dummy( @@ -1818,8 +1815,7 @@ fn confirm_candidate<'cx, 'tcx>( // when possible for this to work. See `auto-trait-projection-recursion.rs` // for a case where this matters. if progress.term.has_infer_regions() { - progress.term = - progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx())); + progress.term = progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx)); } progress } @@ -2000,7 +1996,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, fn_pointer_impl_source: ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx> { - let fn_type = selcx.infcx().shallow_resolve(fn_pointer_impl_source.fn_ty); + let fn_type = selcx.infcx.shallow_resolve(fn_pointer_impl_source.fn_ty); let sig = fn_type.fn_sig(selcx.tcx()); let Normalized { value: sig, obligations } = normalize_with_depth( selcx, @@ -2073,7 +2069,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, potentially_unnormalized_candidate: bool, ) -> Progress<'tcx> { - let infcx = selcx.infcx(); + let infcx = selcx.infcx; let cause = &obligation.cause; let param_env = obligation.param_env; @@ -2168,7 +2164,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( // * `substs` ends up as `[u32, S]` let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs); let substs = - translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node); + translate_substs(selcx.infcx, param_env, impl_def_id, substs, assoc_ty.defining_node); let ty = tcx.bound_type_of(assoc_ty.item.def_id); let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst); let term: ty::EarlyBinder> = if is_const { @@ -2264,7 +2260,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); let impl_fn_substs = translate_substs( - selcx.infcx(), + selcx.infcx, obligation.param_env, data.impl_def_id, impl_fn_substs, @@ -2424,7 +2420,7 @@ impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> { selcx: &mut SelectionContext<'cx, 'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>, ) -> Option { - let infcx = selcx.infcx(); + let infcx = selcx.infcx; // We don't do cross-snapshot caching of obligations with escaping regions, // so there's no cache key to use predicate.no_bound_vars().map(|predicate| { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index f8c7a896b530b..fa076765ad991 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -238,7 +238,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env: obligation.param_env, cause: obligation.cause.clone(), recursion_depth: obligation.recursion_depth, - predicate: self.infcx().resolve_vars_if_possible(obligation.predicate), + predicate: self.infcx.resolve_vars_if_possible(obligation.predicate), }; if obligation.predicate.skip_binder().self_ty().is_ty_var() { @@ -689,9 +689,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?poly_trait_ref, "assemble_candidates_from_object_ty"); - let poly_trait_predicate = self.infcx().resolve_vars_if_possible(obligation.predicate); + let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = - self.infcx().replace_bound_vars_with_placeholders(poly_trait_predicate); + self.infcx.replace_bound_vars_with_placeholders(poly_trait_predicate); // Count only those upcast versions that match the trait-ref // we are looking for. Specifically, do not only check for the @@ -940,7 +940,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - let self_ty = self.infcx().shallow_resolve(obligation.self_ty()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); match self_ty.skip_binder().kind() { ty::Opaque(..) | ty::Dynamic(..) @@ -1007,7 +1007,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - let self_ty = self.infcx().shallow_resolve(obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); match self_ty.kind() { ty::Tuple(_) => { candidates.vec.push(BuiltinCandidate { has_nested: false }); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 8c589aa8cd1de..86fd69c159e57 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -147,7 +147,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); let placeholder_trait_predicate = - self.infcx().replace_bound_vars_with_placeholders(trait_predicate).trait_ref; + self.infcx.replace_bound_vars_with_placeholders(trait_predicate).trait_ref; let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let (def_id, substs) = match *placeholder_self_ty.kind() { @@ -639,7 +639,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligation, "confirm_trait_alias_candidate"); let alias_def_id = obligation.predicate.def_id(); - let predicate = self.infcx().replace_bound_vars_with_placeholders(obligation.predicate); + let predicate = self.infcx.replace_bound_vars_with_placeholders(obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let substs = trait_ref.substs; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3c8f8b5642c9e..7088016e6e6a5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -101,7 +101,7 @@ impl IntercrateAmbiguityCause { } pub struct SelectionContext<'cx, 'tcx> { - infcx: &'cx InferCtxt<'tcx>, + pub infcx: &'cx InferCtxt<'tcx>, /// Freshener used specifically for entries on the obligation /// stack. This ensures that all entries on the stack at one time @@ -237,10 +237,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.intercrate_ambiguity_causes.take().unwrap_or_default() } - pub fn infcx(&self) -> &'cx InferCtxt<'tcx> { - self.infcx - } - pub fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -693,10 +689,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match (evaluate(c1), evaluate(c2)) { (Ok(c1), Ok(c2)) => { - match self - .infcx() - .at(&obligation.cause, obligation.param_env) - .eq(c1, c2) + match self.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2) { Ok(_) => Ok(EvaluatedToOk), Err(_) => Ok(EvaluatedToErr), @@ -1212,7 +1205,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let obligation = &stack.obligation; - let predicate = self.infcx().resolve_vars_if_possible(obligation.predicate); + let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); // Okay to skip binder because of the nature of the // trait-ref-is-knowable check, which does not care about @@ -1349,9 +1342,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> { - let poly_trait_predicate = self.infcx().resolve_vars_if_possible(obligation.predicate); + let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = - self.infcx().replace_bound_vars_with_placeholders(poly_trait_predicate); + self.infcx.replace_bound_vars_with_placeholders(poly_trait_predicate); debug!(?placeholder_trait_predicate); let tcx = self.infcx.tcx; @@ -2131,7 +2124,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, ) -> Result>, ()> { let placeholder_obligation = - self.infcx().replace_bound_vars_with_placeholders(obligation.predicate); + self.infcx.replace_bound_vars_with_placeholders(obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index dae7d589d5cca..a06db4c274831 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -203,13 +203,13 @@ pub fn impl_subject_and_oblig<'a, 'tcx>( let subject = selcx.tcx().bound_impl_subject(impl_def_id); let subject = subject.subst(selcx.tcx(), impl_substs); let InferOk { value: subject, obligations: normalization_obligations1 } = selcx - .infcx() + .infcx .partially_normalize_associated_types_in(ObligationCause::dummy(), param_env, subject); let predicates = selcx.tcx().predicates_of(impl_def_id); let predicates = predicates.instantiate(selcx.tcx(), impl_substs); let InferOk { value: predicates, obligations: normalization_obligations2 } = selcx - .infcx() + .infcx .partially_normalize_associated_types_in(ObligationCause::dummy(), param_env, predicates); let impl_obligations = super::predicates_for_generics(|_, _| ObligationCause::dummy(), param_env, predicates); From 61e185b5d08d0db64e0fa331b64ac7283968f8a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 26 Nov 2022 05:11:06 +0000 Subject: [PATCH 05/16] simplify some binder shifting logic --- compiler/rustc_middle/src/ty/fold.rs | 47 ++++++++++++++-------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 2842b3c3102d2..d431d008ddf06 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -407,6 +407,7 @@ where match *t.kind() { ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => { let ty = self.delegate.replace_ty(bound_ty); + debug_assert!(!ty.has_vars_bound_above(ty::INNERMOST)); ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32()) } _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self), @@ -437,6 +438,7 @@ where match ct.kind() { ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => { let ct = self.delegate.replace_const(bound_const, ct.ty()); + debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST)); ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32()) } _ => ct.super_fold_with(self), @@ -697,14 +699,10 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) => { - if self.amount == 0 || debruijn < self.current_index { - r - } else { - let debruijn = debruijn.shifted_in(self.amount); - let shifted = ty::ReLateBound(debruijn, br); - self.tcx.mk_region(shifted) - } + ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + let shifted = ty::ReLateBound(debruijn, br); + self.tcx.mk_region(shifted) } _ => r, } @@ -712,31 +710,30 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match *ty.kind() { - ty::Bound(debruijn, bound_ty) => { - if self.amount == 0 || debruijn < self.current_index { - ty - } else { - let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_ty(ty::Bound(debruijn, bound_ty)) - } + ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + self.tcx.mk_ty(ty::Bound(debruijn, bound_ty)) } - _ => ty.super_fold_with(self), + _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self), + _ => ty, } } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind() { - if self.amount == 0 || debruijn < self.current_index { - ct - } else { - let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty()) - } + if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind() + && debruijn >= self.current_index + { + let debruijn = debruijn.shifted_in(self.amount); + self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty()) } else { ct.super_fold_with(self) } } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } + } } pub fn shift_region<'tcx>( @@ -758,5 +755,9 @@ where { debug!("shift_vars(value={:?}, amount={})", value, amount); + if amount == 0 || !value.has_escaping_bound_vars() { + return value; + } + value.fold_with(&mut Shifter::new(tcx, amount)) } From 881862ecb79a447c9631becb7f35c1c47b406346 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 22 Nov 2022 18:12:12 +0000 Subject: [PATCH 06/16] Rename `fn_trait_kind_from_{from_lang=>def_id}` to better convey meaning --- compiler/rustc_hir_typeck/src/closure.rs | 6 +++--- .../error_reporting/nice_region_error/placeholder_error.rs | 2 +- compiler/rustc_middle/src/middle/lang_items.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 2 +- .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 4 ++-- .../rustc_trait_selection/src/traits/select/confirmation.rs | 2 +- compiler/rustc_ty_utils/src/instance.rs | 2 +- src/librustdoc/clean/utils.rs | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index e2fefd2724f7e..11a5f2b0d90e7 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); let kind = object_type .principal_def_id() - .and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did)); + .and_then(|did| self.tcx.fn_trait_kind_from_def_id(did)); (sig, kind) } ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates( @@ -235,7 +235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }; if let Some(closure_kind) = - trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_lang_item(def_id)) + trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_def_id(def_id)) { expected_kind = Some( expected_kind @@ -263,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_def_id = projection.trait_def_id(tcx); - let is_fn = tcx.fn_trait_kind_from_lang_item(trait_def_id).is_some(); + let is_fn = tcx.fn_trait_kind_from_def_id(trait_def_id).is_some(); let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span); let is_gen = gen_trait == trait_def_id; if !is_fn && !is_gen { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index a585168294a29..3a74ac51b2c27 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -401,7 +401,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { if self_ty.value.is_closure() && self .tcx() - .fn_trait_kind_from_lang_item(expected_trait_ref.value.def_id) + .fn_trait_kind_from_def_id(expected_trait_ref.value.def_id) .is_some() { let closure_sig = self_ty.map(|closure| { diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index dd4332d0db6d2..e1bcb74b281c4 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -27,7 +27,7 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn fn_trait_kind_from_lang_item(self, id: DefId) -> Option { + pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option { let items = self.lang_items(); match Some(id) { x if x == items.fn_trait() => Some(ty::ClosureKind::Fn), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index d5e196b2e9faa..6afb8bdc45743 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1085,7 +1085,7 @@ pub trait PrettyPrinter<'tcx>: let mut resugared = false; // Special-case `Fn(...) -> ...` and re-sugar it. - let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id); + let fn_trait_kind = cx.tcx().fn_trait_kind_from_def_id(principal.def_id); if !cx.should_print_verbose() && fn_trait_kind.is_some() { if let ty::Tuple(tys) = principal.substs.type_at(0).kind() { let mut projections = predicates.projection_bounds(); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 68703eb0a232e..a115bb2831a4b 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -37,7 +37,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' } ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); - let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) { + let adjustment = match tcx.fn_trait_kind_from_def_id(trait_) { Some(ty::ClosureKind::FnOnce) => Adjustment::Identity, Some(ty::ClosureKind::FnMut | ty::ClosureKind::Fn) => Adjustment::Deref, None => bug!("fn pointer {:?} is not an fn", ty), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 4ac53f6302fbf..c466e1e29ad80 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2155,7 +2155,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if generics.params.iter().any(|p| p.name != kw::SelfUpper) && !snippet.ends_with('>') && !generics.has_impl_trait() - && !self.tcx.fn_trait_kind_from_lang_item(def_id).is_some() + && !self.tcx.fn_trait_kind_from_def_id(def_id).is_some() { // FIXME: To avoid spurious suggestions in functions where type arguments // where already supplied, we check the snippet to make sure it doesn't diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index da6ca30cc9a32..07ba4d0c3b856 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1680,7 +1680,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let inputs = trait_ref.skip_binder().substs.type_at(1); let sig = match inputs.kind() { ty::Tuple(inputs) - if infcx.tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() => + if infcx.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()).is_some() => { infcx.tcx.mk_fn_sig( inputs.iter(), diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index f8c7a896b530b..460ca923c6e29 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -451,7 +451,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - let Some(kind) = self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()) else { + let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else { return; }; @@ -489,7 +489,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) { // We provide impl of all fn traits for fn pointers. - if self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()).is_none() { + if self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()).is_none() { return; } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 8c589aa8cd1de..28e742688a914 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -735,7 +735,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result>, SelectionError<'tcx>> { let kind = self .tcx() - .fn_trait_kind_from_lang_item(obligation.predicate.def_id()) + .fn_trait_kind_from_def_id(obligation.predicate.def_id()) .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation)); // Okay to skip binder because the substs on closure types never diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 4a887bc591827..c6f2b16ca2102 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -209,7 +209,7 @@ fn resolve_associated_item<'tcx>( substs: future_data.substs, }), traits::ImplSource::Closure(closure_data) => { - let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap(); + let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap(); Instance::resolve_closure( tcx, closure_data.closure_def_id, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 35e2720fdff89..d540d828d3b10 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -106,7 +106,7 @@ fn external_generic_args<'tcx>( ) -> GenericArgs { let args = substs_to_args(cx, substs, has_self); - if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() { + if cx.tcx.fn_trait_kind_from_def_id(did).is_some() { let inputs = // The trait's first substitution is the one after self, if there is one. match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() { From d0c7ed3beaaef613d2b0676c7808ee818cb8c8bc Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 22 Nov 2022 18:24:50 +0000 Subject: [PATCH 07/16] Remove `ty::ClosureKind::from_def_id` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …in favour of `TyCtxt::fn_trait_kind_from_def_id` --- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 4 ++-- compiler/rustc_middle/src/ty/closure.rs | 15 +++------------ .../src/traits/error_reporting/mod.rs | 9 +++++---- .../src/traits/error_reporting/suggestions.rs | 4 ++-- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index ecf6f458ca3f7..5c7d21fc2e418 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2089,7 +2089,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id) && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id) // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce" - && let Some(call_kind) = ty::ClosureKind::from_def_id(self.tcx, maybe_trait_def_id) + && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id) && let Some(callee_ty) = callee_ty { let callee_ty = callee_ty.peel_refs(); @@ -2115,7 +2115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = predicate.kind().skip_binder() && pred.self_ty().peel_refs() == callee_ty - && ty::ClosureKind::from_def_id(self.tcx, pred.def_id()).is_some() + && self.tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some() { err.span_note(span, "callable defined here"); return; diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 273a61c966c72..2653c8576de6c 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -118,18 +118,9 @@ impl<'tcx> ClosureKind { } } - pub fn from_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if Some(def_id) == tcx.lang_items().fn_once_trait() { - Some(ClosureKind::FnOnce) - } else if Some(def_id) == tcx.lang_items().fn_mut_trait() { - Some(ClosureKind::FnMut) - } else if Some(def_id) == tcx.lang_items().fn_trait() { - Some(ClosureKind::Fn) - } else { - None - } - } - + /// Converts `self` to a [`DefId`] of the corresponding trait. + /// + /// Note: the inverse of this function is [`TyCtxt::fn_trait_kind_from_def_id`] pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId { tcx.require_lang_item( match self { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index c466e1e29ad80..de35fbfe6d0db 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -357,7 +357,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { ocx.register_obligation(obligation); if ocx.select_all_or_error().is_empty() { return Ok(( - ty::ClosureKind::from_def_id(self.tcx, trait_def_id) + self.tcx + .fn_trait_kind_from_def_id(trait_def_id) .expect("expected to map DefId to ClosureKind"), ty.rebind(self.resolve_vars_if_possible(var)), )); @@ -686,7 +687,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ItemObligation(def_id) - if ty::ClosureKind::from_def_id(tcx, *def_id).is_some() => + if tcx.fn_trait_kind_from_def_id(*def_id).is_some() => { err.code(rustc_errors::error_code!(E0059)); err.set_primary_message(format!( @@ -847,7 +848,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } let is_fn_trait = - ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some(); + tcx.fn_trait_kind_from_def_id(trait_ref.def_id()).is_some(); let is_target_feature_fn = if let ty::FnDef(def_id, _) = *trait_ref.skip_binder().self_ty().kind() { @@ -877,7 +878,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Note if the `FnMut` or `FnOnce` is less general than the trait we're trying // to implement. let selected_kind = - ty::ClosureKind::from_def_id(self.tcx, trait_ref.def_id()) + self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) .expect("expected to map DefId to ClosureKind"); if !implemented_kind.extends(selected_kind) { err.note( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 07ba4d0c3b856..4ae9b22f22171 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1752,7 +1752,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) && let Some(pred) = predicates.predicates.get(*idx) && let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() - && ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id()).is_some() + && self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()).is_some() { let expected_self = self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty())); @@ -1766,7 +1766,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .enumerate() .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) - if ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id()) + if self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) .is_some() && other_idx != idx // Make sure that the self type matches From 4b6e1d1c5fc9eaedc119759d99b6105b4f7f5d1e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 22 Nov 2022 18:31:23 +0000 Subject: [PATCH 08/16] Add `TyCtxt::is_fn_trait` --- compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_middle/src/middle/lang_items.rs | 8 ++++++++ .../src/traits/error_reporting/mod.rs | 7 +++---- .../src/traits/error_reporting/suggestions.rs | 6 ++---- .../src/traits/select/candidate_assembly.rs | 2 +- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 11a5f2b0d90e7..e584d413c4190 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -263,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_def_id = projection.trait_def_id(tcx); - let is_fn = tcx.fn_trait_kind_from_def_id(trait_def_id).is_some(); + let is_fn = tcx.is_fn_trait(trait_def_id); let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span); let is_gen = gen_trait == trait_def_id; if !is_fn && !is_gen { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 5c7d21fc2e418..86384c7b93e71 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2115,7 +2115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = predicate.kind().skip_binder() && pred.self_ty().peel_refs() == callee_ty - && self.tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some() + && self.tcx.is_fn_trait(pred.def_id()) { err.span_note(span, "callable defined here"); return; diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index e1bcb74b281c4..343ea1f00f58b 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -27,6 +27,9 @@ impl<'tcx> TyCtxt<'tcx> { }) } + /// Given a [`DefId`] of a [`Fn`], [`FnMut`] or [`FnOnce`] traits, + /// returns a corresponding [`ty::ClosureKind`]. + /// For any other [`DefId`] return `None`. pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option { let items = self.lang_items(); match Some(id) { @@ -36,6 +39,11 @@ impl<'tcx> TyCtxt<'tcx> { _ => None, } } + + /// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits. + pub fn is_fn_trait(self, id: DefId) -> bool { + self.fn_trait_kind_from_def_id(id).is_some() + } } /// Returns `true` if the specified `lang_item` must be present for this diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index de35fbfe6d0db..e96b9b64e7874 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -687,7 +687,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ItemObligation(def_id) - if tcx.fn_trait_kind_from_def_id(*def_id).is_some() => + if tcx.is_fn_trait(*def_id) => { err.code(rustc_errors::error_code!(E0059)); err.set_primary_message(format!( @@ -847,8 +847,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } - let is_fn_trait = - tcx.fn_trait_kind_from_def_id(trait_ref.def_id()).is_some(); + let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id()); let is_target_feature_fn = if let ty::FnDef(def_id, _) = *trait_ref.skip_binder().self_ty().kind() { @@ -2156,7 +2155,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if generics.params.iter().any(|p| p.name != kw::SelfUpper) && !snippet.ends_with('>') && !generics.has_impl_trait() - && !self.tcx.fn_trait_kind_from_def_id(def_id).is_some() + && !self.tcx.is_fn_trait(def_id) { // FIXME: To avoid spurious suggestions in functions where type arguments // where already supplied, we check the snippet to make sure it doesn't diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 4ae9b22f22171..ddffe25bc263c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1679,9 +1679,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> Ty<'tcx> { let inputs = trait_ref.skip_binder().substs.type_at(1); let sig = match inputs.kind() { - ty::Tuple(inputs) - if infcx.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()).is_some() => - { + ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => { infcx.tcx.mk_fn_sig( inputs.iter(), infcx.next_ty_var(TypeVariableOrigin { @@ -1752,7 +1750,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) && let Some(pred) = predicates.predicates.get(*idx) && let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() - && self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()).is_some() + && self.tcx.is_fn_trait(trait_pred.def_id()) { let expected_self = self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty())); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 460ca923c6e29..adce549a858cb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -489,7 +489,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) { // We provide impl of all fn traits for fn pointers. - if self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()).is_none() { + if !self.tcx().is_fn_trait(obligation.predicate.def_id()) { return; } From fa89f533524ba41589b211845f19a75811330efc Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 22 Nov 2022 18:35:58 +0000 Subject: [PATCH 09/16] Simplify `ty::ClosureKind::extends` This is valid per the comment of the `ClosureKind` defition --- compiler/rustc_middle/src/ty/closure.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 2653c8576de6c..e0bd490981074 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -97,15 +97,7 @@ impl<'tcx> ClosureKind { /// Returns `true` if a type that impls this closure kind /// must also implement `other`. pub fn extends(self, other: ty::ClosureKind) -> bool { - matches!( - (self, other), - (ClosureKind::Fn, ClosureKind::Fn) - | (ClosureKind::Fn, ClosureKind::FnMut) - | (ClosureKind::Fn, ClosureKind::FnOnce) - | (ClosureKind::FnMut, ClosureKind::FnMut) - | (ClosureKind::FnMut, ClosureKind::FnOnce) - | (ClosureKind::FnOnce, ClosureKind::FnOnce) - ) + self <= other } /// Returns the representative scalar type for this closure kind. From ea447924cef96746d27c396d395cc5cfea738928 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 22 Nov 2022 18:52:07 +0000 Subject: [PATCH 10/16] micro doc fixes --- compiler/rustc_middle/src/ty/closure.rs | 22 +++++++++++----------- compiler/rustc_middle/src/ty/sty.rs | 3 +-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index e0bd490981074..286946d1d1f27 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -100,19 +100,9 @@ impl<'tcx> ClosureKind { self <= other } - /// Returns the representative scalar type for this closure kind. - /// See `Ty::to_opt_closure_kind` for more details. - pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match self { - ClosureKind::Fn => tcx.types.i8, - ClosureKind::FnMut => tcx.types.i16, - ClosureKind::FnOnce => tcx.types.i32, - } - } - /// Converts `self` to a [`DefId`] of the corresponding trait. /// - /// Note: the inverse of this function is [`TyCtxt::fn_trait_kind_from_def_id`] + /// Note: the inverse of this function is [`TyCtxt::fn_trait_kind_from_def_id`]. pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId { tcx.require_lang_item( match self { @@ -123,6 +113,16 @@ impl<'tcx> ClosureKind { None, ) } + + /// Returns the representative scalar type for this closure kind. + /// See `Ty::to_opt_closure_kind` for more details. + pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match self { + ClosureKind::Fn => tcx.types.i8, + ClosureKind::FnMut => tcx.types.i16, + ClosureKind::FnOnce => tcx.types.i32, + } + } } /// A composite describing a `Place` that is captured by a closure. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index a53b275fb02cd..4fc97c0baaf53 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2114,8 +2114,7 @@ impl<'tcx> Ty<'tcx> { /// parameter. This is kind of a phantom type, except that the /// most convenient thing for us to are the integral types. This /// function converts such a special type into the closure - /// kind. To go the other way, use - /// `tcx.closure_kind_ty(closure_kind)`. + /// kind. To go the other way, use `closure_kind.to_ty(tcx)`. /// /// Note that during type checking, we use an inference variable /// to represent the closure kind, because it has not yet been From 5ba0056346a745e61cb2cb90d69a3304a255ff42 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 22 Nov 2022 19:03:26 +0000 Subject: [PATCH 11/16] Use `TyCtxt::is_fn_trait` is a couple more places --- .../error_reporting/nice_region_error/placeholder_error.rs | 5 +---- .../src/traits/error_reporting/suggestions.rs | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 3a74ac51b2c27..1f554c81eff8e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -399,10 +399,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); if self_ty.value.is_closure() - && self - .tcx() - .fn_trait_kind_from_def_id(expected_trait_ref.value.def_id) - .is_some() + && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) { let closure_sig = self_ty.map(|closure| { if let ty::Closure(_, substs) = closure.kind() { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index ddffe25bc263c..2cb04b949546c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1764,8 +1764,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .enumerate() .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) - if self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) - .is_some() + if self.tcx.is_fn_trait(trait_pred.def_id()) && other_idx != idx // Make sure that the self type matches // (i.e. constraining this closure) From 5b0e80ecf32e2c4f01d6f45fbcfd9b1709381289 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 Nov 2022 13:03:01 +0300 Subject: [PATCH 12/16] Stabilize native library modifier `verbatim` --- compiler/rustc_codegen_ssa/src/back/link.rs | 16 +++---- compiler/rustc_codegen_ssa/src/back/linker.rs | 2 +- compiler/rustc_codegen_ssa/src/lib.rs | 4 +- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/active.rs | 2 - compiler/rustc_metadata/src/native_libs.rs | 13 ++--- compiler/rustc_session/src/config.rs | 5 +- src/doc/rustc/src/command-line-arguments.md | 27 +++++++++++ .../native-link-modifiers-verbatim.md | 20 -------- .../Makefile | 4 +- .../Makefile | 4 +- src/test/run-make/raw-dylib-c/lib.rs | 2 +- .../rust_dep.rs | 1 - ...ure-gate-native_link_modifiers_verbatim.rs | 5 -- ...gate-native_link_modifiers_verbatim.stderr | 12 ----- .../linkage-attr/link-attr-validation-late.rs | 1 - .../link-attr-validation-late.stderr | 48 +++++++++---------- 17 files changed, 73 insertions(+), 95 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/native-link-modifiers-verbatim.md delete mode 100644 src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 762430c618721..b103c7de74c14 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -377,12 +377,8 @@ fn link_rlib<'a>( find_native_static_library(name.as_str(), lib.verbatim, &lib_search_paths, sess); if sess.opts.unstable_opts.packed_bundled_libs && flavor == RlibFlavor::Normal { let filename = lib.filename.unwrap(); - let lib_path = find_native_static_library( - filename.as_str(), - Some(true), - &lib_search_paths, - sess, - ); + let lib_path = + find_native_static_library(filename.as_str(), true, &lib_search_paths, sess); let src = read(lib_path) .map_err(|e| sess.emit_fatal(errors::ReadFileError { message: e }))?; let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src); @@ -465,7 +461,7 @@ fn collate_raw_dylibs<'a, 'b>( for lib in used_libraries { if lib.kind == NativeLibKind::RawDylib { - let ext = if matches!(lib.verbatim, Some(true)) { "" } else { ".dll" }; + let ext = if lib.verbatim { "" } else { ".dll" }; let name = format!("{}{}", lib.name.expect("unnamed raw-dylib library"), ext); let imports = dylib_table.entry(name.clone()).or_default(); for import in &lib.dll_imports { @@ -1335,7 +1331,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { NativeLibKind::Static { bundle: Some(false), .. } | NativeLibKind::Dylib { .. } | NativeLibKind::Unspecified => { - let verbatim = lib.verbatim.unwrap_or(false); + let verbatim = lib.verbatim; if sess.target.is_like_msvc { Some(format!("{}{}", name, if verbatim { "" } else { ".lib" })) } else if sess.target.linker_flavor.is_gnu() { @@ -2306,7 +2302,7 @@ fn add_native_libs_from_crate( _ => &codegen_results.crate_info.native_libraries[&cnum], }; - let mut last = (None, NativeLibKind::Unspecified, None); + let mut last = (None, NativeLibKind::Unspecified, false); for lib in native_libs { let Some(name) = lib.name else { continue; @@ -2323,7 +2319,7 @@ fn add_native_libs_from_crate( }; let name = name.as_str(); - let verbatim = lib.verbatim.unwrap_or(false); + let verbatim = lib.verbatim; match lib.kind { NativeLibKind::Static { bundle, whole_archive } => { if link_static { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 7f0c2861f7e29..5fb11e6b914b8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -515,7 +515,7 @@ impl<'a> Linker for GccLinker<'a> { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = find_native_static_library(lib, Some(verbatim), search_path, &self.sess); + let lib = find_native_static_library(lib, verbatim, search_path, &self.sess); self.linker_arg(&lib); } } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index ade33b6c77728..def6390f6a36b 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -116,7 +116,7 @@ pub struct NativeLib { pub name: Option, pub filename: Option, pub cfg: Option, - pub verbatim: Option, + pub verbatim: bool, pub dll_imports: Vec, } @@ -127,7 +127,7 @@ impl From<&cstore::NativeLib> for NativeLib { filename: lib.filename, name: lib.name, cfg: lib.cfg.clone(), - verbatim: lib.verbatim, + verbatim: lib.verbatim.unwrap_or(false), dll_imports: lib.dll_imports.clone(), } } diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 1646727a1c85f..7678ce323dfbc 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -237,6 +237,8 @@ declare_features! ( (accepted, native_link_modifiers, "1.61.0", Some(81490), None), /// Allows specifying the bundle link modifier (accepted, native_link_modifiers_bundle, "1.63.0", Some(81490), None), + /// Allows specifying the verbatim link modifier + (accepted, native_link_modifiers_verbatim, "CURRENT_RUSTC_VERSION", Some(81490), None), /// Allows specifying the whole-archive link modifier (accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490), None), /// Allows using non lexical lifetimes (RFC 2094). diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 9ca63c393c623..69c5297bf6b82 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -455,8 +455,6 @@ declare_features! ( (active, naked_functions, "1.9.0", Some(32408), None), /// Allows specifying the as-needed link modifier (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), - /// Allows specifying the verbatim link modifier - (active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None), /// Allow negative trait implementations. (active, negative_impls, "1.44.0", Some(68318), None), /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 20a2e78299aed..1fd35adf1bd2c 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -29,11 +29,11 @@ use std::path::PathBuf; pub fn find_native_static_library( name: &str, - verbatim: Option, + verbatim: bool, search_paths: &[PathBuf], sess: &Session, ) -> PathBuf { - let formats = if verbatim.unwrap_or(false) { + let formats = if verbatim { vec![("".into(), "".into())] } else { let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone()); @@ -52,7 +52,7 @@ pub fn find_native_static_library( } } - sess.emit_fatal(MissingNativeLibrary::new(name, verbatim.unwrap_or(false))); + sess.emit_fatal(MissingNativeLibrary::new(name, verbatim)); } fn find_bundled_library( @@ -66,7 +66,7 @@ fn find_bundled_library( let NativeLibKind::Static { bundle: Some(true) | None, .. } = kind { find_native_static_library( name.unwrap().as_str(), - verbatim, + verbatim.unwrap_or(false), &sess.target_filesearch(PathKind::Native).search_path_dirs(), sess, ).file_name().and_then(|s| s.to_str()).map(Symbol::intern) @@ -311,10 +311,7 @@ impl<'tcx> Collector<'tcx> { sess.emit_err(BundleNeedsStatic { span }); } - ("verbatim", _) => { - report_unstable_modifier!(native_link_modifiers_verbatim); - assign_modifier(&mut verbatim) - } + ("verbatim", _) => assign_modifier(&mut verbatim), ("whole-archive", Some(NativeLibKind::Static { whole_archive, .. })) => { assign_modifier(whole_archive) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3b1b33aa095a1..927810351e958 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2029,10 +2029,7 @@ fn parse_native_lib_modifiers( "linking modifier `bundle` is only compatible with `static` linking kind", ), - ("verbatim", _) => { - report_unstable_modifier(); - assign_modifier(&mut verbatim) - } + ("verbatim", _) => assign_modifier(&mut verbatim), ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { assign_modifier(whole_archive) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 2dc182b3d83ed..ef6eee75f1ce6 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -104,6 +104,33 @@ This modifier has no effect when building other targets like executables or dyna The default for this modifier is `+bundle`. +### Linking modifiers: `verbatim` + +This modifier is compatible with all linking kinds. + +`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes +(like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the +linker. + +For `ld`-like linkers supporting GNU extensions rustc will use the `-l:filename` syntax (note the +colon) when passing the library, so the linker won't add any prefixes or suffixes to it. +See [`-l namespec`](https://sourceware.org/binutils/docs/ld/Options.html) in ld documentation for +more details. \ +For linkers not supporting any verbatim modifiers (e.g. `link.exe` or `ld64`) the library name will +be passed as is. So the most reliable cross-platform use scenarios for this option are when no +linker is involved, for example bundling native libraries into rlibs. + +`-verbatim` means that rustc will either add a target-specific prefix and suffix to the library +name before passing it to linker, or won't prevent linker from implicitly adding it. \ +In case of `raw-dylib` kind in particular `.dll` will be added to the library name on Windows. + +The default for this modifier is `-verbatim`. + +NOTE: Even with `+verbatim` and `-l:filename` syntax `ld`-like linkers do not typically support +passing absolute paths to libraries. Usually such paths need to be passed as input files without +using any options like `-l`, e.g. `ld /my/absolute/path`. \ +`-Clink-arg=/my/absolute/path` can be used for doing this from stable `rustc`. + ## `--crate-type`: a list of types of crates for the compiler to emit diff --git a/src/doc/unstable-book/src/language-features/native-link-modifiers-verbatim.md b/src/doc/unstable-book/src/language-features/native-link-modifiers-verbatim.md deleted file mode 100644 index 02bd87e50956d..0000000000000 --- a/src/doc/unstable-book/src/language-features/native-link-modifiers-verbatim.md +++ /dev/null @@ -1,20 +0,0 @@ -# `native_link_modifiers_verbatim` - -The tracking issue for this feature is: [#81490] - -[#81490]: https://github.com/rust-lang/rust/issues/81490 - ------------------------- - -The `native_link_modifiers_verbatim` feature allows you to use the `verbatim` modifier. - -`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker. - -For `ld`-like linkers rustc will use the `-l:filename` syntax (note the colon) when passing the library, so the linker won't add any prefixes or suffixes as well. -See [`-l namespec`](https://sourceware.org/binutils/docs/ld/Options.html) in ld documentation for more details. -For linkers not supporting any verbatim modifiers (e.g. `link.exe` or `ld64`) the library name will be passed as is. - -The default for this modifier is `-verbatim`. - -This RFC changes the behavior of `raw-dylib` linking kind specified by [RFC 2627](https://github.com/rust-lang/rfcs/pull/2627). The `.dll` suffix (or other target-specified suffixes for other targets) is now added automatically. -If your DLL doesn't have the `.dll` suffix, it can be specified with `+verbatim`. diff --git a/src/test/run-make/native-link-modifier-verbatim-linker/Makefile b/src/test/run-make/native-link-modifier-verbatim-linker/Makefile index e56e1e94ec5b1..666e4084ce295 100644 --- a/src/test/run-make/native-link-modifier-verbatim-linker/Makefile +++ b/src/test/run-make/native-link-modifier-verbatim-linker/Makefile @@ -6,10 +6,10 @@ include ../../run-make-fulldeps/tools.mk all: # Verbatim allows specify precise name. $(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_some_strange_name.ext - $(RUSTC) main.rs -Zunstable-options -l static:+verbatim=local_some_strange_name.ext + $(RUSTC) main.rs -l static:+verbatim=local_some_strange_name.ext # With verbatim any other name cannot be used (local). $(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/liblocal_native_dep.a $(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_native_dep.a $(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_native_dep.lib - $(RUSTC) main.rs -Zunstable-options -l static:+verbatim=local_native_dep 2>&1 | $(CGREP) "local_native_dep" + $(RUSTC) main.rs -l static:+verbatim=local_native_dep 2>&1 | $(CGREP) "local_native_dep" diff --git a/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile b/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile index 1093b1cd3694d..6f01f37804a2a 100644 --- a/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile +++ b/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile @@ -3,10 +3,10 @@ include ../../run-make-fulldeps/tools.mk all: # Verbatim allows specify precise name. $(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_some_strange_name.ext - $(RUSTC) rust_dep.rs -Zunstable-options -l static:+verbatim=upstream_some_strange_name.ext --crate-type rlib + $(RUSTC) rust_dep.rs -l static:+verbatim=upstream_some_strange_name.ext --crate-type rlib # With verbatim any other name cannot be used (upstream). $(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/libupstream_native_dep.a $(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_native_dep.a $(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_native_dep.lib - $(RUSTC) rust_dep.rs -Zunstable-options -l static:+verbatim=upstream_native_dep --crate-type rlib 2>&1 | $(CGREP) "upstream_native_dep" + $(RUSTC) rust_dep.rs -l static:+verbatim=upstream_native_dep --crate-type rlib 2>&1 | $(CGREP) "upstream_native_dep" diff --git a/src/test/run-make/raw-dylib-c/lib.rs b/src/test/run-make/raw-dylib-c/lib.rs index 005ffcdda5c2e..5fb1204037c93 100644 --- a/src/test/run-make/raw-dylib-c/lib.rs +++ b/src/test/run-make/raw-dylib-c/lib.rs @@ -1,4 +1,4 @@ -#![feature(raw_dylib, native_link_modifiers_verbatim)] +#![feature(raw_dylib)] #[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")] extern { diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs b/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs index d99dda05cf215..77e41e237d42a 100644 --- a/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs +++ b/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs @@ -1,4 +1,3 @@ -#![feature(native_link_modifiers_verbatim)] #[link(name = "native_dep.ext", kind = "static", modifiers = "+verbatim")] extern "C" { fn native_f1() -> i32; diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs deleted file mode 100644 index 7b09195dc3fb0..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[link(name = "foo", modifiers = "+verbatim")] -//~^ ERROR: linking modifier `verbatim` is unstable -extern "C" {} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr deleted file mode 100644 index 3bfbeb8db35fe..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: linking modifier `verbatim` is unstable - --> $DIR/feature-gate-native_link_modifiers_verbatim.rs:1:34 - | -LL | #[link(name = "foo", modifiers = "+verbatim")] - | ^^^^^^^^^^^ - | - = note: see issue #81490 for more information - = help: add `#![feature(native_link_modifiers_verbatim)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/linkage-attr/link-attr-validation-late.rs b/src/test/ui/linkage-attr/link-attr-validation-late.rs index b454fbd0ed117..34f720dd2d3c5 100644 --- a/src/test/ui/linkage-attr/link-attr-validation-late.rs +++ b/src/test/ui/linkage-attr/link-attr-validation-late.rs @@ -1,4 +1,3 @@ -#![feature(native_link_modifiers_verbatim)] #![feature(link_cfg)] // Top-level ill-formed diff --git a/src/test/ui/linkage-attr/link-attr-validation-late.stderr b/src/test/ui/linkage-attr/link-attr-validation-late.stderr index dd0f1dba2ecf7..1ad5fbaf7de80 100644 --- a/src/test/ui/linkage-attr/link-attr-validation-late.stderr +++ b/src/test/ui/linkage-attr/link-attr-validation-late.stderr @@ -1,143 +1,143 @@ error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type - --> $DIR/link-attr-validation-late.rs:5:22 + --> $DIR/link-attr-validation-late.rs:4:22 | LL | #[link(name = "...", "literal")] | ^^^^^^^^^ error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type - --> $DIR/link-attr-validation-late.rs:6:22 + --> $DIR/link-attr-validation-late.rs:5:22 | LL | #[link(name = "...", unknown)] | ^^^^^^^ error: multiple `name` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:10:22 + --> $DIR/link-attr-validation-late.rs:9:22 | LL | #[link(name = "foo", name = "bar")] | ^^^^^^^^^^^^ error: multiple `kind` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:11:38 + --> $DIR/link-attr-validation-late.rs:10:38 | LL | #[link(name = "...", kind = "dylib", kind = "bar")] | ^^^^^^^^^^^^ error: multiple `modifiers` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:12:47 + --> $DIR/link-attr-validation-late.rs:11:47 | LL | #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] | ^^^^^^^^^^^^^^^^^ error: multiple `cfg` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:13:34 + --> $DIR/link-attr-validation-late.rs:12:34 | LL | #[link(name = "...", cfg(FALSE), cfg(FALSE))] | ^^^^^^^^^^ error: multiple `wasm_import_module` arguments in a single `#[link]` attribute - --> $DIR/link-attr-validation-late.rs:14:36 + --> $DIR/link-attr-validation-late.rs:13:36 | LL | #[link(wasm_import_module = "foo", wasm_import_module = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: link name must be of the form `name = "string"` - --> $DIR/link-attr-validation-late.rs:18:8 + --> $DIR/link-attr-validation-late.rs:17:8 | LL | #[link(name)] | ^^^^ error[E0459]: `#[link]` attribute requires a `name = "string"` argument - --> $DIR/link-attr-validation-late.rs:18:1 + --> $DIR/link-attr-validation-late.rs:17:1 | LL | #[link(name)] | ^^^^^^^^^^^^^ missing `name` argument error: link name must be of the form `name = "string"` - --> $DIR/link-attr-validation-late.rs:20:8 + --> $DIR/link-attr-validation-late.rs:19:8 | LL | #[link(name())] | ^^^^^^ error[E0459]: `#[link]` attribute requires a `name = "string"` argument - --> $DIR/link-attr-validation-late.rs:20:1 + --> $DIR/link-attr-validation-late.rs:19:1 | LL | #[link(name())] | ^^^^^^^^^^^^^^^ missing `name` argument error: link kind must be of the form `kind = "string"` - --> $DIR/link-attr-validation-late.rs:22:22 + --> $DIR/link-attr-validation-late.rs:21:22 | LL | #[link(name = "...", kind)] | ^^^^ error: link kind must be of the form `kind = "string"` - --> $DIR/link-attr-validation-late.rs:23:22 + --> $DIR/link-attr-validation-late.rs:22:22 | LL | #[link(name = "...", kind())] | ^^^^^^ error: link modifiers must be of the form `modifiers = "string"` - --> $DIR/link-attr-validation-late.rs:24:22 + --> $DIR/link-attr-validation-late.rs:23:22 | LL | #[link(name = "...", modifiers)] | ^^^^^^^^^ error: link modifiers must be of the form `modifiers = "string"` - --> $DIR/link-attr-validation-late.rs:25:22 + --> $DIR/link-attr-validation-late.rs:24:22 | LL | #[link(name = "...", modifiers())] | ^^^^^^^^^^^ error: link cfg must be of the form `cfg(/* predicate */)` - --> $DIR/link-attr-validation-late.rs:26:22 + --> $DIR/link-attr-validation-late.rs:25:22 | LL | #[link(name = "...", cfg)] | ^^^ error: link cfg must be of the form `cfg(/* predicate */)` - --> $DIR/link-attr-validation-late.rs:27:22 + --> $DIR/link-attr-validation-late.rs:26:22 | LL | #[link(name = "...", cfg = "literal")] | ^^^^^^^^^^^^^^^ error: link cfg must have a single predicate argument - --> $DIR/link-attr-validation-late.rs:28:22 + --> $DIR/link-attr-validation-late.rs:27:22 | LL | #[link(name = "...", cfg("literal"))] | ^^^^^^^^^^^^^^ error: wasm import module must be of the form `wasm_import_module = "string"` - --> $DIR/link-attr-validation-late.rs:29:22 + --> $DIR/link-attr-validation-late.rs:28:22 | LL | #[link(name = "...", wasm_import_module)] | ^^^^^^^^^^^^^^^^^^ error: wasm import module must be of the form `wasm_import_module = "string"` - --> $DIR/link-attr-validation-late.rs:30:22 + --> $DIR/link-attr-validation-late.rs:29:22 | LL | #[link(name = "...", wasm_import_module())] | ^^^^^^^^^^^^^^^^^^^^ error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed - --> $DIR/link-attr-validation-late.rs:34:34 + --> $DIR/link-attr-validation-late.rs:33:34 | LL | #[link(name = "...", modifiers = "")] | ^^ error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed - --> $DIR/link-attr-validation-late.rs:35:34 + --> $DIR/link-attr-validation-late.rs:34:34 | LL | #[link(name = "...", modifiers = "no-plus-minus")] | ^^^^^^^^^^^^^^^ error: unknown linking modifier `unknown`, expected one of: bundle, verbatim, whole-archive, as-needed - --> $DIR/link-attr-validation-late.rs:36:34 + --> $DIR/link-attr-validation-late.rs:35:34 | LL | #[link(name = "...", modifiers = "+unknown")] | ^^^^^^^^^^ error: multiple `verbatim` modifiers in a single `modifiers` argument - --> $DIR/link-attr-validation-late.rs:37:34 + --> $DIR/link-attr-validation-late.rs:36:34 | LL | #[link(name = "...", modifiers = "+verbatim,+verbatim")] | ^^^^^^^^^^^^^^^^^^^^^ From 99c3dda06649ae9878138366bf2423ce45ce198b Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 27 Nov 2022 20:48:31 +0100 Subject: [PATCH 13/16] fix type Co-authored-by: fee1-dead --- compiler/rustc_hir_typeck/src/callee.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index cd1322d1a3bcc..b390d34b37bda 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -181,7 +181,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // where F:Fn and so forth. In the particular case of types // like `f: &mut FnMut()`, if there is a call `f()`, we would // normally translate to `FnMut::call_mut(&mut f, ())`, but - // that winds up requiring the user to potentially mark their + // that winds up potentially requiring the user to mark their // variable as `mut` which feels unnecessary and unexpected. // // fn foo(f: &mut impl FnMut()) { f() } From ab04080b56448c4bcd7e5b79215a1097e1a9b217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 23 Nov 2022 14:28:45 -0800 Subject: [PATCH 14/16] Change multiline span ASCII art visual order --- compiler/rustc_errors/src/emitter.rs | 8 +- compiler/rustc_expand/src/tests.rs | 108 +++++++++--------- ...alloc-error-handler-bad-signature-1.stderr | 24 ++-- ...alloc-error-handler-bad-signature-2.stderr | 24 ++-- src/test/ui/inference/deref-suggestion.stderr | 12 +- src/test/ui/issues/issue-13497-2.stderr | 6 +- src/test/ui/lint/suggestions.stderr | 6 +- .../issue-86188-return-not-in-fn-body.stderr | 12 +- src/test/ui/suggestions/issue-99240-2.stderr | 6 +- .../suggestions/suggest-remove-refs-3.stderr | 10 +- 10 files changed, 111 insertions(+), 105 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index bf20c7431e4eb..d22f3ca42144a 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2300,8 +2300,14 @@ impl FileWithAnnotatedLines { } let mut max_depth = 0; // max overlapping multiline spans - for (file, ann) in multiline_annotations { + for (_, ann) in &multiline_annotations { max_depth = max(max_depth, ann.depth); + } + // Change order of multispan depth to minimize the number of overlaps in the ASCII art. + for (_, a) in multiline_annotations.iter_mut() { + a.depth = max_depth - a.depth + 1; + } + for (file, ann) in multiline_annotations { let mut end_ann = ann.as_end(); if !ann.overlaps_exactly { // avoid output like diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index d82a7a54030c6..539b04535a0d0 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -272,13 +272,13 @@ error: foo --> test.rs:3:3 | 3 | X0 Y0 - | ____^__- - | | ___| + | ___^__- + | |___| | || 4 | || X1 Y1 5 | || X2 Y2 | ||____^__- `Y` is a good letter too - | |____| + | |_____| | `X` is a good letter "#, @@ -311,12 +311,12 @@ error: foo --> test.rs:3:3 | 3 | X0 Y0 - | ____^__- - | | ___| + | ___^__- + | |___| | || 4 | || Y1 X1 | ||____-__^ `X` is a good letter - | |_____| + | |____| | `Y` is a good letter too "#, @@ -351,13 +351,13 @@ error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 - | ______^ -4 | | X1 Y1 Z1 - | |_________- + | _______^ +4 | | X1 Y1 Z1 + | | _________- 5 | || X2 Y2 Z2 | ||____^ `X` is a good letter -6 | | X3 Y3 Z3 - | |_____- `Y` is a good letter too +6 | | X3 Y3 Z3 + | |____- `Y` is a good letter too "#, ); @@ -395,15 +395,15 @@ error: foo --> test.rs:3:3 | 3 | X0 Y0 Z0 - | _____^__-__- - | | ____|__| - | || ___| + | ___^__-__- + | |___|__| + | ||___| | ||| 4 | ||| X1 Y1 Z1 5 | ||| X2 Y2 Z2 | |||____^__-__- `Z` label - | ||____|__| - | |____| `Y` is a good letter too + | ||_____|__| + | |______| `Y` is a good letter too | `X` is a good letter "#, @@ -487,17 +487,17 @@ error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 - | ______^ -4 | | X1 Y1 Z1 - | |____^_- + | _______^ +4 | | X1 Y1 Z1 + | | ____^_- | ||____| - | | `X` is a good letter -5 | | X2 Y2 Z2 - | |____-______- `Y` is a good letter too - | ____| - | | -6 | | X3 Y3 Z3 - | |________- `Z` + | | `X` is a good letter +5 | | X2 Y2 Z2 + | |___-______- `Y` is a good letter too + | ___| + | | +6 | | X3 Y3 Z3 + | |_______- `Z` "#, ); @@ -570,14 +570,14 @@ error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 - | ______^ -4 | | X1 Y1 Z1 - | |____^____- + | _______^ +4 | | X1 Y1 Z1 + | | ____^____- | ||____| - | | `X` is a good letter -5 | | X2 Y2 Z2 -6 | | X3 Y3 Z3 - | |___________- `Y` is a good letter too + | | `X` is a good letter +5 | | X2 Y2 Z2 +6 | | X3 Y3 Z3 + | |__________- `Y` is a good letter too "#, ); @@ -941,18 +941,18 @@ error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 - | ______^ -4 | | X1 Y1 Z1 - | |____^____- + | _______^ +4 | | X1 Y1 Z1 + | | ____^____- | ||____| - | | `X` is a good letter -5 | | 1 -6 | | 2 -7 | | 3 -... | -15 | | X2 Y2 Z2 -16 | | X3 Y3 Z3 - | |___________- `Y` is a good letter too + | | `X` is a good letter +5 | | 1 +6 | | 2 +7 | | 3 +... | +15 | | X2 Y2 Z2 +16 | | X3 Y3 Z3 + | |__________- `Y` is a good letter too "#, ); @@ -996,21 +996,21 @@ error: foo --> test.rs:3:6 | 3 | X0 Y0 Z0 - | ______^ -4 | | 1 -5 | | 2 -6 | | 3 -7 | | X1 Y1 Z1 - | |_________- + | _______^ +4 | | 1 +5 | | 2 +6 | | 3 +7 | | X1 Y1 Z1 + | | _________- 8 | || 4 9 | || 5 10 | || 6 11 | || X2 Y2 Z2 | ||__________- `Z` is a good letter too -... | -15 | | 10 -16 | | X3 Y3 Z3 - | |_______^ `Y` is a good letter +... | +15 | | 10 +16 | | X3 Y3 Z3 + | |________^ `Y` is a good letter "#, ); diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr index d0911fa3985d0..3e840a28a92ad 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr @@ -4,16 +4,16 @@ error[E0308]: mismatched types LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion LL | fn oom( - | _^ - | |_| + | __^ + | | _| | || LL | || info: &Layout, LL | || ) -> () | ||_______- arguments to this function are incorrect -LL | | { -LL | | loop {} -LL | | } - | |__^ expected `&Layout`, found struct `Layout` +LL | | { +LL | | loop {} +LL | | } + | |_^ expected `&Layout`, found struct `Layout` | note: function defined here --> $DIR/alloc-error-handler-bad-signature-1.rs:10:4 @@ -30,16 +30,16 @@ error[E0308]: mismatched types LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion LL | fn oom( - | _^ - | |_| + | __^ + | | _| | || LL | || info: &Layout, LL | || ) -> () | ||_______^ expected `!`, found `()` -LL | | { -LL | | loop {} -LL | | } - | |__- expected `!` because of return type +LL | | { +LL | | loop {} +LL | | } + | |_- expected `!` because of return type | = note: expected type `!` found unit type `()` diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr index 5777279855d97..7cbfd55770515 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr @@ -4,17 +4,17 @@ error[E0308]: mismatched types LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion LL | fn oom( - | _^ - | |_| + | __^ + | | _| | || LL | || info: Layout, LL | || ) { | || - | ||_| - | | arguments to this function are incorrect -LL | | loop {} -LL | | } - | |__^ expected struct `Layout`, found struct `core::alloc::Layout` + | | arguments to this function are incorrect +LL | | loop {} +LL | | } + | |_^ expected struct `Layout`, found struct `core::alloc::Layout` | = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types note: struct `core::alloc::Layout` is defined in crate `core` @@ -42,17 +42,17 @@ error[E0308]: mismatched types LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion LL | fn oom( - | _^ - | |_| + | __^ + | | _| | || LL | || info: Layout, LL | || ) { | || ^ | ||_| - | | expected `!`, found `()` -LL | | loop {} -LL | | } - | |__- expected `!` because of return type + | | expected `!`, found `()` +LL | | loop {} +LL | | } + | |_- expected `!` because of return type | = note: expected type `!` found unit type `()` diff --git a/src/test/ui/inference/deref-suggestion.stderr b/src/test/ui/inference/deref-suggestion.stderr index d729f2d682a61..034005697b434 100644 --- a/src/test/ui/inference/deref-suggestion.stderr +++ b/src/test/ui/inference/deref-suggestion.stderr @@ -157,11 +157,11 @@ error[E0308]: `if` and `else` have incompatible types --> $DIR/deref-suggestion.rs:69:12 | LL | let val = if true { - | _______________- -LL | | *a - | | -- expected because of this -LL | | } else if true { - | |____________^ + | ________________- +LL | | *a + | | -- expected because of this +LL | | } else if true { + | | ____________^ LL | || LL | || b LL | || } else { @@ -169,7 +169,7 @@ LL | || &0 LL | || }; | || ^ | ||_____| - | |______`if` and `else` have incompatible types + | |_____`if` and `else` have incompatible types | expected `i32`, found `&{integer}` error: aborting due to 13 previous errors diff --git a/src/test/ui/issues/issue-13497-2.stderr b/src/test/ui/issues/issue-13497-2.stderr index 6f72b79f2a5e0..3abeadf9e4bbe 100644 --- a/src/test/ui/issues/issue-13497-2.stderr +++ b/src/test/ui/issues/issue-13497-2.stderr @@ -2,12 +2,12 @@ error[E0515]: cannot return value referencing local variable `rawLines` --> $DIR/issue-13497-2.rs:3:5 | LL | rawLines - | _____^ - | |_____| + | ______^ + | | _____| | || LL | || .iter().map(|l| l.trim()).collect() | ||_______________-___________________________^ returns a value referencing data owned by the current function - | |________________| + | |_______________| | `rawLines` is borrowed here error: aborting due to previous error diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index f4c0e2141b232..4caee777a131b 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -41,12 +41,12 @@ warning: variable does not need to be mutable --> $DIR/suggestions.rs:54:13 | LL | let mut - | _____________^ - | |_____________| + | ______________^ + | | _____________| | || LL | || b = 1; | ||____________-^ - | |____________| + | |_____________| | help: remove this `mut` error: const items should never be `#[no_mangle]` diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr index d7eeb3a729099..4f938670e5e2c 100644 --- a/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr +++ b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr @@ -35,17 +35,17 @@ LL | | } error[E0572]: return statement outside of function body --> $DIR/issue-86188-return-not-in-fn-body.rs:36:10 | -LL | / fn main() { -LL | | -LL | | [(); return || { - | |__________^ +LL | / fn main() { +LL | | +LL | | [(); return || { + | | __________^ LL | || LL | || LL | || let tx; LL | || }]; | ||_____^ the return is part of this body... -LL | | } - | |_- ...not the enclosing function body +LL | | } + | |__- ...not the enclosing function body error: aborting due to 4 previous errors diff --git a/src/test/ui/suggestions/issue-99240-2.stderr b/src/test/ui/suggestions/issue-99240-2.stderr index 2af60f5975992..260df85653b15 100644 --- a/src/test/ui/suggestions/issue-99240-2.stderr +++ b/src/test/ui/suggestions/issue-99240-2.stderr @@ -5,12 +5,12 @@ LL | Unit, | ---- enum variant `Alias::Unit` defined here ... LL | Alias:: - | _____^ - | |_____| + | ______^ + | | _____| | || LL | || Unit(); | ||________^_- call expression requires function - | |_________| + | |________| | | help: `Alias::Unit` is a unit enum variant, and does not take parentheses to be constructed diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr index 4d07324273c30..b1afa2b0a6b11 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-3.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr @@ -2,14 +2,14 @@ error[E0277]: `&&&&&Enumerate>` is not an iterat --> $DIR/suggest-remove-refs-3.rs:6:19 | LL | for (i, _) in & & & - | ___________________^ - | |___________________| + | ____________________^ + | | ___________________| | || LL | || & &v | ||___________- help: consider removing 5 leading `&`-references -LL | | .iter() -LL | | .enumerate() { - | |_____________________^ `&&&&&Enumerate>` is not an iterator +LL | | .iter() +LL | | .enumerate() { + | |____________________^ `&&&&&Enumerate>` is not an iterator | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` = note: required for `&&&&&Enumerate>` to implement `IntoIterator` From 6f64432a3933475321d0083b1876d07b2f06cd7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 23 Nov 2022 14:51:24 -0800 Subject: [PATCH 15/16] Tweak output --- compiler/rustc_errors/src/emitter.rs | 2 +- ...alloc-error-handler-bad-signature-1.stderr | 16 +++++++-------- ...alloc-error-handler-bad-signature-2.stderr | 20 ++++++++----------- .../suggestions/suggest-remove-refs-3.stderr | 6 +++--- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index d22f3ca42144a..1fabe15ff83ba 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2282,7 +2282,7 @@ impl FileWithAnnotatedLines { } // Find overlapping multiline annotations, put them at different depths - multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end)); + multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, usize::MAX - ml.line_end)); for (_, ann) in multiline_annotations.clone() { for (_, a) in multiline_annotations.iter_mut() { // Move all other multiline annotations overlapping with this one diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr index 3e840a28a92ad..dd3665f22ac78 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr @@ -10,10 +10,10 @@ LL | fn oom( LL | || info: &Layout, LL | || ) -> () | ||_______- arguments to this function are incorrect -LL | | { -LL | | loop {} -LL | | } - | |_^ expected `&Layout`, found struct `Layout` +LL | | { +LL | | loop {} +LL | | } + | |__^ expected `&Layout`, found struct `Layout` | note: function defined here --> $DIR/alloc-error-handler-bad-signature-1.rs:10:4 @@ -36,10 +36,10 @@ LL | fn oom( LL | || info: &Layout, LL | || ) -> () | ||_______^ expected `!`, found `()` -LL | | { -LL | | loop {} -LL | | } - | |_- expected `!` because of return type +LL | | { +LL | | loop {} +LL | | } + | |__- expected `!` because of return type | = note: expected type `!` found unit type `()` diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr index 7cbfd55770515..adb652fe61659 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr @@ -9,12 +9,10 @@ LL | fn oom( | || LL | || info: Layout, LL | || ) { - | || - - | ||_| - | | arguments to this function are incorrect -LL | | loop {} -LL | | } - | |_^ expected struct `Layout`, found struct `core::alloc::Layout` + | ||_- arguments to this function are incorrect +LL | | loop {} +LL | | } + | |__^ expected struct `Layout`, found struct `core::alloc::Layout` | = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types note: struct `core::alloc::Layout` is defined in crate `core` @@ -47,12 +45,10 @@ LL | fn oom( | || LL | || info: Layout, LL | || ) { - | || ^ - | ||_| - | | expected `!`, found `()` -LL | | loop {} -LL | | } - | |_- expected `!` because of return type + | ||_^ expected `!`, found `()` +LL | | loop {} +LL | | } + | |__- expected `!` because of return type | = note: expected type `!` found unit type `()` diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr index b1afa2b0a6b11..31cca323d0e42 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-3.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr @@ -7,9 +7,9 @@ LL | for (i, _) in & & & | || LL | || & &v | ||___________- help: consider removing 5 leading `&`-references -LL | | .iter() -LL | | .enumerate() { - | |____________________^ `&&&&&Enumerate>` is not an iterator +LL | | .iter() +LL | | .enumerate() { + | |_____________________^ `&&&&&Enumerate>` is not an iterator | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` = note: required for `&&&&&Enumerate>` to implement `IntoIterator` From 136ffa2ab1e4c1b8c1f30a775040b63f65b871da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 28 Nov 2022 00:41:31 -0800 Subject: [PATCH 16/16] fix clippy tests --- .../clippy/tests/ui/async_yields_async.stderr | 20 +++++++++---------- .../ui/result_map_unit_fn_unfixable.stderr | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index b0c4215e7ddf1..92ba359296780 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -2,14 +2,14 @@ error: an async construct yields a type which is itself awaitable --> $DIR/async_yields_async.rs:39:9 | LL | let _h = async { - | ____________________- -LL | | async { - | |_________^ + | _____________________- +LL | | async { + | | _________^ LL | || 3 LL | || } | ||_________^ awaitable value not awaited -LL | | }; - | |_____- outer async construct +LL | | }; + | |______- outer async construct | = note: `-D clippy::async-yields-async` implied by `-D warnings` help: consider awaiting this value @@ -36,14 +36,14 @@ error: an async construct yields a type which is itself awaitable --> $DIR/async_yields_async.rs:50:9 | LL | let _j = async || { - | _______________________- -LL | | async { - | |_________^ + | ________________________- +LL | | async { + | | _________^ LL | || 3 LL | || } | ||_________^ awaitable value not awaited -LL | | }; - | |_____- outer async construct +LL | | }; + | |______- outer async construct | help: consider awaiting this value | diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr index 88e4efdb0f054..2e1eb8eb18066 100644 --- a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr @@ -20,14 +20,14 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns --> $DIR/result_map_unit_fn_unfixable.rs:29:5 | LL | x.field.map(|value| { - | _____^ - | |_____| + | ______^ + | | _____| | || LL | || do_nothing(value); LL | || do_nothing(value) LL | || }); | ||______^- help: try this: `if let Ok(value) = x.field { ... }` - | |_______| + | |______| | error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()`