diff options
| author | bors <bors@rust-lang.org> | 2022-10-23 06:20:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-10-23 06:20:24 +0000 |
| commit | faab68eb29121f25b577b50e2e00e33bafc60a36 (patch) | |
| tree | f60ad6322423365c1d9a70a5faf05a261627f2ea /compiler | |
| parent | 6c9c2d862dd10718ba2b2a320c3390995ad414bc (diff) | |
| parent | 25e02d6efcac6bd25131e64b80aaf270f380dd8f (diff) | |
| download | rust-faab68eb29121f25b577b50e2e00e33bafc60a36.tar.gz rust-faab68eb29121f25b577b50e2e00e33bafc60a36.zip | |
Auto merge of #103426 - matthiaskrgr:rollup-n6dqdy8, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #103123 (Introduce `subst_iter` and `subst_iter_copied` on `EarlyBinder` ) - #103328 (Do not suggest trivially false const predicates) - #103354 (Escape string literals when fixing overlong char literal) - #103355 (Handle return-position `impl Trait` in traits properly in `register_hidden_type`) - #103368 (Delay ambiguity span bug in normalize query iff not rustdoc) - #103388 (rustdoc: remove unused CSS class `.result-description`) - #103399 (Change `unknown_lint` applicability to `MaybeIncorrect`) - #103401 (Use functions for headings rustdoc GUI test) - #103412 (Fix typo in docs of `String::leak`.) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/compare_method.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/_match.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/closure.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/mod.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/opaque_types.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/levels.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/print/pretty.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/subst.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lexer/unescape_error_reporting.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/query/normalize.rs | 21 |
12 files changed, 132 insertions, 59 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index 60eaad9b498..3469ec4767b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -664,10 +664,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { }); self.types.insert(proj.item_def_id, (infer_ty, proj.substs)); // Recurse into bounds - for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() { - let pred_span = pred.0.1; - - let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs); + for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) { let pred = pred.fold_with(self); let pred = self.ocx.normalize( ObligationCause::misc(self.span, self.body_id), @@ -1752,15 +1749,10 @@ pub fn check_type_bounds<'tcx>( let obligations = tcx .bound_explicit_item_bounds(trait_ty.def_id) - .transpose_iter() - .map(|e| e.map_bound(|e| *e).transpose_tuple2()) - .map(|(bound, span)| { - debug!(?bound); - // this is where opaque type is found - let concrete_ty_bound = bound.subst(tcx, rebased_substs); + .subst_iter_copied(tcx, rebased_substs) + .map(|(concrete_ty_bound, span)| { debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); - - traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound) + traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound) }) .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations); diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index c22d828625b..2b15d4dcd08 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -514,8 +514,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } for ty in [first_ty, second_ty] { - for pred in self.tcx.bound_explicit_item_bounds(rpit_def_id).transpose_iter() { - let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx, substs); + for (pred, _) in self + .tcx + .bound_explicit_item_bounds(rpit_def_id) + .subst_iter_copied(self.tcx, substs) + { let pred = match pred.kind().skip_binder() { ty::PredicateKind::Trait(mut trait_pred) => { assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index de5b4a50218..a5a45f75e0e 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -176,24 +176,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match *expected_ty.kind() { ty::Opaque(def_id, substs) => { let bounds = self.tcx.bound_explicit_item_bounds(def_id); - let sig = bounds - .transpose_iter() - .map(|e| e.map_bound(|e| *e).transpose_tuple2()) - .find_map(|(pred, span)| match pred.0.kind().skip_binder() { + let sig = + bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred + .kind() + .skip_binder() + { ty::PredicateKind::Projection(proj_predicate) => self .deduce_sig_from_projection( - Some(span.0), - pred.0 - .kind() - .rebind(pred.rebind(proj_predicate).subst(self.tcx, substs)), + Some(span), + pred.kind().rebind(proj_predicate), ), _ => None, }); let kind = bounds - .transpose_iter() - .map(|e| e.map_bound(|e| *e).transpose_tuple2()) - .filter_map(|(pred, _)| match pred.0.kind().skip_binder() { + .0 + .iter() + .filter_map(|(pred, _)| match pred.kind().skip_binder() { ty::PredicateKind::Trait(tp) => { self.tcx.fn_trait_kind_from_lang_item(tp.def_id()) } @@ -697,18 +696,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Opaque(def_id, substs) => self .tcx .bound_explicit_item_bounds(def_id) - .transpose_iter() - .map(|e| e.map_bound(|e| *e).transpose_tuple2()) - .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?, + .subst_iter_copied(self.tcx, substs) + .find_map(|(p, s)| get_future_output(p, s))?, ty::Error(_) => return None, ty::Projection(proj) if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder => { self.tcx .bound_explicit_item_bounds(proj.item_def_id) - .transpose_iter() - .map(|e| e.map_bound(|e| *e).transpose_tuple2()) - .find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))? + .subst_iter_copied(self.tcx, proj.substs) + .find_map(|(p, s)| get_future_output(p, s))? } _ => span_bug!( self.tcx.def_span(expr_def_id), diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index ddeeaa9618e..9ff703e521f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -338,8 +338,7 @@ impl<'tcx> InferCtxt<'tcx> { let bounds = self.tcx.bound_explicit_item_bounds(*def_id); - for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { - let predicate = predicate.subst(self.tcx, substs); + for (predicate, _) in bounds.subst_iter_copied(self.tcx, substs) { let output = predicate .kind() .map_bound(|kind| match kind { @@ -2272,6 +2271,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str) } FailureCode::Error0308(failure_str) => { + fn escape_literal(s: &str) -> String { + let mut escaped = String::with_capacity(s.len()); + let mut chrs = s.chars().peekable(); + while let Some(first) = chrs.next() { + match (first, chrs.peek()) { + ('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => { + escaped.push('\\'); + escaped.push(delim); + chrs.next(); + } + ('"' | '\'', _) => { + escaped.push('\\'); + escaped.push(first) + } + (c, _) => escaped.push(c), + }; + } + escaped + } let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str); if let Some((expected, found)) = trace.values.ty() { match (expected.kind(), found.kind()) { @@ -2293,7 +2311,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.span_suggestion( span, "if you meant to write a `char` literal, use single quotes", - format!("'{}'", code), + format!("'{}'", escape_literal(code)), Applicability::MachineApplicable, ); } @@ -2308,7 +2326,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.span_suggestion( span, "if you meant to write a `str` literal, use double quotes", - format!("\"{}\"", code), + format!("\"{}\"", escape_literal(code)), Applicability::MachineApplicable, ); } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 77e8f72aefa..0a4ecc4c033 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,6 +1,7 @@ use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{DefiningAnchor, InferCtxt, InferOk}; use crate::traits; +use hir::def::DefKind; use hir::def_id::{DefId, LocalDefId}; use hir::{HirId, OpaqueTyOrigin}; use rustc_data_structures::sync::Lrc; @@ -543,16 +544,18 @@ impl<'tcx> InferCtxt<'tcx> { let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id()); - for predicate in item_bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { - debug!(?predicate); - let predicate = predicate.subst(tcx, substs); - + for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) { let predicate = predicate.fold_with(&mut BottomUpFolder { tcx, ty_op: |ty| match *ty.kind() { // We can't normalize associated types from `rustc_infer`, // but we can eagerly register inference variables for them. - ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => { + // FIXME(RPITIT): Don't replace RPITITs with inference vars. + ty::Projection(projection_ty) + if !projection_ty.has_escaping_bound_vars() + && tcx.def_kind(projection_ty.item_def_id) + != DefKind::ImplTraitPlaceholder => + { self.infer_projection( param_env, projection_ty, @@ -568,6 +571,12 @@ impl<'tcx> InferCtxt<'tcx> { { hidden_ty } + // FIXME(RPITIT): This can go away when we move to associated types + ty::Projection(proj) + if def_id.to_def_id() == proj.item_def_id && substs == proj.substs => + { + hidden_ty + } _ => ty, }, lt_op: |lt| lt, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index d3879ff487d..db0a3419e6a 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -960,7 +960,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { sp, "did you mean", suggestion, - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } lint diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 81b9f55e703..e0958b039dc 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -91,14 +91,12 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`, // e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait` // with `impl Send: OtherTrait`. - for assoc_pred_and_span in - cx.tcx.bound_explicit_item_bounds(proj.projection_ty.item_def_id).transpose_iter() + for (assoc_pred, assoc_pred_span) in cx + .tcx + .bound_explicit_item_bounds(proj.projection_ty.item_def_id) + .subst_iter_copied(cx.tcx, &proj.projection_ty.substs) { - let assoc_pred_span = assoc_pred_and_span.0.1; - let assoc_pred = assoc_pred_and_span - .map_bound(|(pred, _)| *pred) - .subst(cx.tcx, &proj.projection_ty.substs) - .fold_with(proj_replacer); + let assoc_pred = assoc_pred.fold_with(proj_replacer); let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else { continue; }; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 0b06ccc19ec..f18c95a61d4 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -795,8 +795,7 @@ pub trait PrettyPrinter<'tcx>: let mut fn_traits = FxIndexMap::default(); let mut is_sized = false; - for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { - let predicate = predicate.subst(tcx, substs); + for (predicate, _) in bounds.subst_iter_copied(tcx, substs) { let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index c9930e8ad0a..0660e9b79a7 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -6,6 +6,7 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; +use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; @@ -558,6 +559,28 @@ impl<T, U> EarlyBinder<(T, U)> { } } +impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> { + pub fn subst_iter( + self, + tcx: TyCtxt<'tcx>, + substs: &'s [GenericArg<'tcx>], + ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> { + self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs)) + } +} + +impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a> + EarlyBinder<T> +{ + pub fn subst_iter_copied( + self, + tcx: TyCtxt<'tcx>, + substs: &'s [GenericArg<'tcx>], + ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> { + self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs)) + } +} + pub struct EarlyBinderIter<T> { t: T, } diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 77c4fadab45..f075de71426 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -113,11 +113,26 @@ pub(crate) fn emit_unescape_error( } else { ("", "if you meant to write a `str` literal, use double quotes") }; - + let mut escaped = String::with_capacity(lit.len()); + let mut chrs = lit.chars().peekable(); + while let Some(first) = chrs.next() { + match (first, chrs.peek()) { + ('\\', Some('"')) => { + escaped.push('\\'); + escaped.push('"'); + chrs.next(); + } + ('"', _) => { + escaped.push('\\'); + escaped.push('"') + } + (c, _) => escaped.push(c), + }; + } handler.span_suggestion( span_with_quotes, msg, - format!("{}\"{}\"", prefix, lit), + format!("{prefix}\"{escaped}\""), Applicability::MachineApplicable, ); } 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 fc0040de6b3..1217d264a9c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -764,6 +764,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty); } + let mut unsatisfied_const = false; if trait_predicate.is_const_if_const() && obligation.param_env.is_const() { let non_const_predicate = trait_ref.without_const(); let non_const_obligation = Obligation { @@ -773,6 +774,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { recursion_depth: obligation.recursion_depth, }; if self.predicate_may_hold(&non_const_obligation) { + unsatisfied_const = true; err.span_note( span, &format!( @@ -924,7 +926,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } } else if !trait_ref.has_non_region_infer() - && self.predicate_can_apply(obligation.param_env, trait_ref) + && self.predicate_can_apply(obligation.param_env, trait_predicate) { // If a where-clause may be useful, remind the // user that they can add it. @@ -939,7 +941,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { None, obligation.cause.body_id, ); - } else if !suggested { + } else if !suggested && !unsatisfied_const { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(trait_predicate); if !self.report_similar_impl_candidates( @@ -1436,7 +1438,7 @@ trait InferCtxtPrivExt<'tcx> { fn predicate_can_apply( &self, param_env: ty::ParamEnv<'tcx>, - pred: ty::PolyTraitRef<'tcx>, + pred: ty::PolyTraitPredicate<'tcx>, ) -> bool; fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>); @@ -2511,7 +2513,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn predicate_can_apply( &self, param_env: ty::ParamEnv<'tcx>, - pred: ty::PolyTraitRef<'tcx>, + pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { struct ParamToVarFolder<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, @@ -2555,7 +2557,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let obligation = Obligation::new( ObligationCause::dummy(), param_env, - cleaned_pred.without_const().to_predicate(selcx.tcx()), + cleaned_pred.to_predicate(selcx.tcx()), ); self.predicate_may_hold(&obligation) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index aa8094a60dd..715f5be8e2f 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -14,6 +14,7 @@ use rustc_infer::traits::Normalized; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; +use rustc_span::DUMMY_SP; use std::ops::ControlFlow; @@ -253,7 +254,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { let result = tcx.normalize_projection_ty(c_data)?; // We don't expect ambiguity. if result.is_ambiguous() { - bug!("unexpected ambiguity: {:?} {:?}", c_data, result); + // Rustdoc normalizes possibly not well-formed types, so only + // treat this as a bug if we're not in rustdoc. + if !tcx.sess.opts.actually_rustdoc { + tcx.sess.delay_span_bug( + DUMMY_SP, + format!("unexpected ambiguity: {:?} {:?}", c_data, result), + ); + } + return Err(NoSolution); } let InferOk { value: result, obligations } = self.infcx.instantiate_query_response_and_region_obligations( @@ -296,7 +305,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { let result = tcx.normalize_projection_ty(c_data)?; // We don't expect ambiguity. if result.is_ambiguous() { - bug!("unexpected ambiguity: {:?} {:?}", c_data, result); + // Rustdoc normalizes possibly not well-formed types, so only + // treat this as a bug if we're not in rustdoc. + if !tcx.sess.opts.actually_rustdoc { + tcx.sess.delay_span_bug( + DUMMY_SP, + format!("unexpected ambiguity: {:?} {:?}", c_data, result), + ); + } + return Err(NoSolution); } let InferOk { value: result, obligations } = self.infcx.instantiate_query_response_and_region_obligations( |
