diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src')
6 files changed, 67 insertions, 19 deletions
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 381da6f7e2a..50c618bb3bd 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -10,12 +10,12 @@ //! //! This API is completely unstable and subject to change. -#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![doc(rust_logo)] -#![feature(rustdoc_internals)] +// tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![doc(rust_logo)] #![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] @@ -24,8 +24,10 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(never_type)] +#![feature(rustdoc_internals)] #![feature(type_alias_impl_trait)] #![recursion_limit = "512"] // For rustdoc +// tidy-alphabetical-end #[macro_use] extern crate tracing; diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index b522022c206..43013a01069 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -961,15 +961,15 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, ) -> Result<(), NoSolution> { - let mut obligations = Vec::new(); + let mut goals = Vec::new(); self.infcx.insert_hidden_type( opaque_type_key, - &ObligationCause::dummy(), + DUMMY_SP, param_env, hidden_ty, - &mut obligations, + &mut goals, )?; - self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into())); + self.add_goals(GoalSource::Misc, goals); Ok(()) } @@ -980,16 +980,15 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, ) { - let mut obligations = Vec::new(); + let mut goals = Vec::new(); self.infcx.add_item_bounds_for_hidden_type( opaque_def_id, opaque_args, - ObligationCause::dummy(), param_env, hidden_ty, - &mut obligations, + &mut goals, ); - self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into())); + self.add_goals(GoalSource::Misc, goals); } // Do something for each opaque/hidden pair defined with `def_id` in the diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 1ef2f26cd09..fc5c71252e1 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -12,9 +12,7 @@ use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::NormalizeExt; use crate::traits::SkipLeakCheck; use crate::traits::{util, FulfillmentErrorCode}; -use crate::traits::{ - Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, -}; +use crate::traits::{Obligation, ObligationCause, PredicateObligation, SelectionContext}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def::DefKind; @@ -305,7 +303,7 @@ fn equate_impl_headers<'tcx>( param_env: ty::ParamEnv<'tcx>, impl1: &ty::ImplHeader<'tcx>, impl2: &ty::ImplHeader<'tcx>, -) -> Option<PredicateObligations<'tcx>> { +) -> Option<Vec<PredicateObligation<'tcx>>> { let result = match (impl1.trait_ref, impl2.trait_ref) { (Some(impl1_ref), Some(impl2_ref)) => infcx 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 c7da85bd1cc..087f7fbea00 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -4587,6 +4587,47 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { _ => "/* value */".to_string(), }) } + + fn suggest_add_result_as_return_type( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diag<'_>, + trait_ref: ty::PolyTraitRef<'tcx>, + ) { + if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() { + return; + } + + let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id); + if let hir::Node::Item(item) = node + && let hir::ItemKind::Fn(sig, _, body_id) = item.kind + && let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output + && self.tcx.is_diagnostic_item(sym::FromResidual, trait_ref.def_id()) + && let ty::Tuple(l) = trait_ref.skip_binder().args.type_at(0).kind() + && l.len() == 0 + && let ty::Adt(def, _) = trait_ref.skip_binder().args.type_at(1).kind() + && self.tcx.is_diagnostic_item(sym::Result, def.did()) + { + let body = self.tcx.hir().body(body_id); + let mut sugg_spans = + vec![(ret_span, " -> Result<(), Box<dyn std::error::Error>>".to_string())]; + + if let hir::ExprKind::Block(b, _) = body.value.kind + && b.expr.is_none() + { + sugg_spans.push(( + // The span will point to the closing curly brace `}` of the block. + b.span.shrink_to_hi().with_lo(b.span.hi() - BytePos(1)), + "\n Ok(())\n}".to_string(), + )); + } + err.multipart_suggestion_verbose( + format!("consider adding return type"), + sugg_spans, + Applicability::MaybeIncorrect, + ); + } + } } /// Add a hint to add a missing borrow or remove an unnecessary one. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 46b13788186..6b6438a7887 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -611,6 +611,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &mut err, trait_predicate, ); + self.suggest_add_result_as_return_type(&obligation, + &mut err, + trait_ref); + if self.suggest_add_reference_to_arg( &obligation, &mut err, @@ -2069,12 +2073,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }) .collect(); - let end = if candidates.len() <= 9 { candidates.len() } else { 8 }; + let end = if candidates.len() <= 9 || self.tcx.sess.opts.verbose { + candidates.len() + } else { + 8 + }; err.help(format!( "the following {other}types implement trait `{}`:{}{}", trait_ref.print_trait_sugared(), candidates[..end].join(""), - if candidates.len() > 9 { + if candidates.len() > 9 && !self.tcx.sess.opts.verbose { format!("\nand {} others", candidates.len() - 8) } else { String::new() diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index ae4cdb9258e..c1b1bfd300b 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -5,7 +5,7 @@ use crate::infer::{InferCtxt, InferOk}; use crate::traits::{ObligationCause, ObligationCtxt}; use rustc_errors::ErrorGuaranteed; use rustc_infer::infer::canonical::Certainty; -use rustc_infer::traits::PredicateObligations; +use rustc_infer::traits::PredicateObligation; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; @@ -103,7 +103,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't ( Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>, - PredicateObligations<'tcx>, + Vec<PredicateObligation<'tcx>>, Certainty, ), NoSolution, |
