diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e500207d6da19..415630dab38b3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -21,6 +21,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized}; use rustc_middle::{bug, span_bug}; use rustc_session::Session; +use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt}; use rustc_trait_selection::infer::InferCtxtExt; @@ -954,14 +955,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // wrapping in parentheses. We find the statement or expression // following the `match` (`&& true`) and see if it is something that // can reasonably be interpreted as a binop following an expression. - err.multipart_suggestion( - "parentheses are required to parse this as an expression", - vec![ - (expr.span.shrink_to_lo(), "(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); + err.subdiagnostic(ExprParenthesesNeeded::surrounding(expr.span)); } else if expr.can_have_side_effects() { self.suggest_semicolon_at_end(expr.span, err); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index afd5356d5a1e7..7e2f3e62589ff 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -799,14 +799,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::StmtKind::Expr(_) = stmt.kind && self.is_next_stmt_expr_continuation(stmt.hir_id) { - err.multipart_suggestion( - "parentheses are required to parse this as an expression", - vec![ - (stmt.span.shrink_to_lo(), "(".to_string()), - (stmt.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); + err.subdiagnostic(ExprParenthesesNeeded::surrounding(stmt.span)); } else { err.span_suggestion( expression.span.shrink_to_hi(), @@ -843,14 +836,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // wrapping in parentheses. We find the statement or expression following the // `if` (`&& true`) and see if it is something that can reasonably be // interpreted as a binop following an expression. - err.multipart_suggestion( - "parentheses are required to parse this as an expression", - vec![ - (stmt.span.shrink_to_lo(), "(".to_string()), - (stmt.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); + err.subdiagnostic(ExprParenthesesNeeded::surrounding(stmt.span)); } } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index a43a0c687261a..a9e7425fdcbf6 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -22,7 +22,7 @@ use crate::ty::{ impl IntoDiagArg for Ty<'_> { fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { ty::tls::with(|tcx| { - let ty = tcx.short_string(self, path); + let ty = tcx.short_string(tcx.lift(self), path); DiagArgValue::Str(std::borrow::Cow::Owned(ty)) }) } @@ -31,7 +31,7 @@ impl IntoDiagArg for Ty<'_> { impl IntoDiagArg for Instance<'_> { fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { ty::tls::with(|tcx| { - let instance = tcx.short_string_namespace(self, path, Namespace::ValueNS); + let instance = tcx.short_string_namespace(tcx.lift(self), path, Namespace::ValueNS); DiagArgValue::Str(std::borrow::Cow::Owned(instance)) }) } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 082e5de16cf98..52f37ed4a9eac 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -12,7 +12,7 @@ use rustc_macros::extension; pub use rustc_type_ir::error::ExpectedFound; use crate::ty::print::{FmtPrinter, Print, with_forced_trimmed_paths}; -use crate::ty::{self, Lift, Ty, TyCtxt}; +use crate::ty::{self, Ty, TyCtxt}; pub type TypeError<'tcx> = rustc_type_ir::error::TypeError>; @@ -220,10 +220,10 @@ impl<'tcx> Ty<'tcx> { impl<'tcx> TyCtxt<'tcx> { pub fn string_with_limit(self, t: T, length_limit: usize, ns: hir::def::Namespace) -> String where - T: Copy + for<'a, 'b> Lift, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, + T: Copy + for<'a> Print>, { let mut type_limit = 50; - let regular = FmtPrinter::print_string(self, ns, |p| self.lift(t).print(p)) + let regular = FmtPrinter::print_string(self, ns, |p| t.print(p)) .expect("could not write to `String`"); if regular.len() <= length_limit { return regular; @@ -233,7 +233,7 @@ impl<'tcx> TyCtxt<'tcx> { // Look for the longest properly trimmed path that still fits in length_limit. short = with_forced_trimmed_paths!({ let mut p = FmtPrinter::new_with_limit(self, ns, Limit(type_limit)); - self.lift(t).print(&mut p).expect("could not print type"); + t.print(&mut p).expect("could not print type"); p.into_buffer() }); if short.len() <= length_limit || type_limit == 0 { @@ -250,7 +250,7 @@ impl<'tcx> TyCtxt<'tcx> { /// where we wrote the file to is only printed once. The path will use the type namespace. pub fn short_string(self, t: T, path: &mut Option) -> String where - T: Copy + Hash + for<'a, 'b> Lift, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, + T: Copy + Hash + for<'a> Print>, { self.short_string_namespace(t, path, hir::def::Namespace::TypeNS) } @@ -266,9 +266,9 @@ impl<'tcx> TyCtxt<'tcx> { namespace: hir::def::Namespace, ) -> String where - T: Copy + Hash + for<'a, 'b> Lift, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, + T: Copy + Hash + for<'a> Print>, { - let regular = FmtPrinter::print_string(self, namespace, |p| self.lift(t).print(p)) + let regular = FmtPrinter::print_string(self, namespace, |p| t.print(p)) .expect("could not write to `String`"); if !self.sess.opts.unstable_opts.write_long_types_to_disk || self.sess.opts.verbose { diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 94f642bebeb9f..26108f7be6964 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -113,7 +113,7 @@ impl<'tcx> Predicate<'tcx> { impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> { fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { ty::tls::with(|tcx| { - let pred = tcx.short_string(self, path); + let pred = tcx.short_string(tcx.lift(self), path); rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred)) }) } @@ -122,7 +122,7 @@ impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> { impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> { fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { ty::tls::with(|tcx| { - let clause = tcx.short_string(self, path); + let clause = tcx.short_string(tcx.lift(self), path); rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause)) }) } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index d5d1c3634c7d1..29875a3530c15 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -15,7 +15,7 @@ use super::Lift; pub type PrintError = std::fmt::Error; -pub trait Print<'tcx, P> { +pub trait Print

{ fn print(&self, p: &mut P) -> Result<(), PrintError>; } @@ -350,19 +350,19 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { characteristic_def_id_of_type_cached(ty, &mut SsoHashSet::new()) } -impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> { +impl<'tcx, P: Printer<'tcx>> Print

for ty::Region<'tcx> { fn print(&self, p: &mut P) -> Result<(), PrintError> { p.print_region(*self) } } -impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { +impl<'tcx, P: Printer<'tcx>> Print

for Ty<'tcx> { fn print(&self, p: &mut P) -> Result<(), PrintError> { p.print_type(*self) } } -impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print<'tcx, P> for ty::Instance<'tcx> { +impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print

for ty::Instance<'tcx> { fn print(&self, cx: &mut P) -> Result<(), PrintError> { cx.print_def_path(self.def_id(), self.args)?; match self.def { @@ -399,13 +399,13 @@ impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print<'tcx, P> for ty::Instance<' } } -impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List> { +impl<'tcx, P: Printer<'tcx>> Print

for &'tcx ty::List> { fn print(&self, p: &mut P) -> Result<(), PrintError> { p.print_dyn_existential(self) } } -impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { +impl<'tcx, P: Printer<'tcx>> Print

for ty::Const<'tcx> { fn print(&self, p: &mut P) -> Result<(), PrintError> { p.print_const(*self) } @@ -413,7 +413,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { impl rustc_type_ir::ir_print::IrPrint for TyCtxt<'_> where - T: Copy + for<'a, 'tcx> Lift, Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>>, + T: Copy + for<'a, 'tcx> Lift, Lifted: Print>>, { fn print(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ty::tls::with(|tcx| { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 04d76e4304fe9..daead99b977c1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -265,7 +265,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { fn pretty_print_in_binder(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> where - T: Print<'tcx, Self> + TypeFoldable>, + T: Print + TypeFoldable>, { value.as_ref().skip_binder().print(self) } @@ -285,7 +285,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Prints comma-separated elements. fn comma_sep(&mut self, mut elems: impl Iterator) -> Result<(), PrintError> where - T: Print<'tcx, Self>, + T: Print, { if let Some(first) = elems.next() { first.print(self)?; @@ -2484,7 +2484,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { fn pretty_print_in_binder(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> where - T: Print<'tcx, Self> + TypeFoldable>, + T: Print + TypeFoldable>, { self.wrap_binder(value, WrapBinderMode::ForAll, |new_value, this| new_value.print(this)) } @@ -2940,18 +2940,18 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } } -impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T> +impl<'tcx, T, P: PrettyPrinter<'tcx>> Print

for ty::Binder<'tcx, T> where - T: Print<'tcx, P> + TypeFoldable>, + T: Print

+ TypeFoldable>, { fn print(&self, p: &mut P) -> Result<(), PrintError> { p.pretty_print_in_binder(self) } } -impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate<'tcx, T> +impl<'tcx, T, P: PrettyPrinter<'tcx>> Print

for ty::OutlivesPredicate<'tcx, T> where - T: Print<'tcx, P>, + T: Print

, { fn print(&self, p: &mut P) -> Result<(), PrintError> { self.0.print(p)?; @@ -2970,7 +2970,7 @@ pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintOnlyTraitPath<'tcx> { fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { ty::tls::with(|tcx| { - let trait_ref = tcx.short_string(self, path); + let trait_ref = tcx.short_string(tcx.lift(self), path); rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref)) }) } @@ -2990,7 +2990,7 @@ pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>); impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintSugared<'tcx> { fn into_diag_arg(self, path: &mut Option) -> rustc_errors::DiagArgValue { ty::tls::with(|tcx| { - let trait_ref = tcx.short_string(self, path); + let trait_ref = tcx.short_string(tcx.lift(self), path); rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref)) }) } @@ -3108,7 +3108,7 @@ macro_rules! forward_display_to_print { macro_rules! define_print { (($self:ident, $p:ident): $($ty:ty $print:block)+) => { - $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty { + $(impl<'tcx, P: PrettyPrinter<'tcx>> Print

for $ty { fn print(&$self, $p: &mut P) -> Result<(), PrintError> { let _: () = $print; Ok(()) diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 9386c913a8036..3466eb2f3a5aa 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -480,7 +480,7 @@ impl<'tcx> PrettyPrinter<'tcx> for LegacySymbolMangler<'tcx> { // Identical to `PrettyPrinter::comma_sep` except there is no space after each comma. fn comma_sep(&mut self, mut elems: impl Iterator) -> Result<(), PrintError> where - T: Print<'tcx, Self>, + T: Print, { if let Some(first) = elems.next() { first.print(self)?; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 50dbae0a05d6f..9cf016019bb09 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -28,7 +28,7 @@ pub(crate) struct Highlighted<'tcx, T> { impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T> where - T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, + T: for<'a> Print>, { fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { rustc_errors::DiagArgValue::Str(self.to_string().into()) @@ -43,7 +43,7 @@ impl<'tcx, T> Highlighted<'tcx, T> { impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> where - T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, + T: for<'a> Print>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut p = ty::print::FmtPrinter::new(self.tcx, self.ns); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index a543f549bdae7..0e45df45049b0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> Diag<'a> { fn with_short_path<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> String where - T: fmt::Display + Print<'tcx, FmtPrinter<'tcx, 'tcx>>, + T: fmt::Display + for<'b> Print>, { let s = value.to_string(); if s.len() > 50 { diff --git a/tests/ui/traits/next-solver/alias-relate/transitive-inference.rs b/tests/ui/traits/next-solver/alias-relate/transitive-inference.rs new file mode 100644 index 0000000000000..207cf71c0b3a4 --- /dev/null +++ b/tests/ui/traits/next-solver/alias-relate/transitive-inference.rs @@ -0,0 +1,42 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver=globally +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass +// Regression test for trait-system-refactor-initiative#7. This test +// would error if we were to rely on lazy normalization here. +// +// We eagerly normalize the associated types, here, causing this to +// compile. + +use std::marker::PhantomData; + +#[derive(Default)] +struct Foo(PhantomData<(T, U)>); + +trait Trait { + type Assoc; + + fn to_assoc(self) -> Self::Assoc; +} + +impl Trait for Foo { + type Assoc = Foo; + fn to_assoc(self) -> Self::Assoc { + Foo(PhantomData) + } +} +impl Trait for Foo { + type Assoc = Foo; + fn to_assoc(self) -> Self::Assoc { + Foo(PhantomData) + } +} + +#[allow(unused_assignments)] +fn main() { + let mut x: Foo<_, _> = Default::default(); + let mut assoc = x.to_assoc(); + assoc = Foo::(PhantomData); + assoc = Foo::<_, i32>(PhantomData); + x = assoc; +}