1// ignore-tidy-file-filelength2use core::ops::ControlFlow;3use std::borrow::Cow;4use std::collections::hash_set;5use std::path::PathBuf;67use rustc_ast::ast::LitKind;8use rustc_ast::{LitIntType, TraitObjectSyntax};9use rustc_attr_ir::diagnostic::CustomDiagnostic;10use rustc_attr_ir::find_attr;11use rustc_attr_ir::lang_items::LangItem;12use rustc_data_structures::fx::{FxHashMap, FxHashSet};13use rustc_data_structures::unord::UnordSet;14use rustc_errors::codes::*;15use rustc_errors::{16 Applicability, Diag, ErrorGuaranteed, MultiSpan, StringPart, Sublevel, msg, pluralize,17 struct_span_code_err,18};19use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};20use rustc_hir::intravisit::Visitor;21use rustc_hir::{self as hir, Node, expr_needs_parens};22use rustc_infer::infer::{InferOk, TypeTrace};23use rustc_infer::traits::solve::Goal;24use rustc_infer::traits::{ImplSource, TraitErrors, WellFormedLoc};25use rustc_middle::traits::SignatureMismatchData;26use rustc_middle::traits::select::OverflowError;27use rustc_middle::ty::abstract_const::NotConstEvaluatable;28use rustc_middle::ty::error::{ExpectedFound, TypeError};29use rustc_middle::ty::print::{30 PrintPolyTraitClauseExt, PrintPolyTraitRefExt as _, PrintTraitClauseExt as _,31 PrintTraitRefExt as _, with_forced_trimmed_paths,32};33use rustc_middle::ty::transmute::{Answer, Reason};34use rustc_middle::ty::{35 self, GenericArgKind, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder,36 TypeSuperFoldable, TypeVisitableExt, Unnormalized, Upcast,37};38use rustc_span::def_id::CrateNum;39use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, bug, span_bug, sym};40use tracing::{debug, instrument};4142use super::suggestions::get_explanation_based_on_obligation;43use super::{ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate};44use crate::diagnostics::{45 AssocTypeWithSameName, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,46 CoroClosureNotFn,47};48use crate::error_reporting::TypeErrCtxt;49use crate::error_reporting::infer::TyCategory;50use crate::error_reporting::traits::report_dyn_incompatibility;51use crate::infer::{self, InferCtxt, InferCtxtExt as _};52use crate::traits::query::evaluate_obligation::InferCtxtExt as _;53use crate::traits::{54 MismatchedProjectionTypes, NormalizeExt, Obligation, ObligationCause, ObligationCauseCode,55 ObligationCtxt, PredicateObligation, SelectionContext, SelectionError, elaborate,56 specialization_graph,57};5859impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {60 /// Checks for an explicit `Self: Trait` bound on an associated type impl.61 fn is_explicit_self_trait_bound_on_impl_assoc_type(62 &self,63 body_def_id: LocalDefId,64 cause_code: &ObligationCauseCode<'tcx>,65 trait_def_id: DefId,66 ) -> bool {67 let ObligationCauseCode::WhereClause(item_def_id, span) = *cause_code.peel_derives() else {68 return false;69 };70 // Continue only if there is an impl associated type corresponding to the expected trait item.71 if !self.tcx.opt_associated_item(body_def_id.to_def_id()).is_some_and(|assoc_item| {72 assoc_item.trait_item_def_id().is_some_and(|trait_item_def_id| {73 trait_item_def_id == item_def_id74 && matches!(assoc_item.kind, ty::AssocKind::Type { .. })75 })76 }) {77 return false;78 }7980 self.tcx.clauses_of(item_def_id).instantiate_own_identity().any(|(clause, clause_span)| {81 clause_span == span82 && clause.skip_norm_wip().as_trait_clause().is_some_and(|trait_pred| {83 trait_pred.def_id() == trait_def_id84 && trait_pred.skip_binder().self_ty().is_self_param()85 })86 })87 }8889 /// The `root_obligation` parameter should be the `root_obligation` field90 /// from a `FulfillmentError`. If no `FulfillmentError` is available,91 /// then it should be the same as `obligation`.92 pub fn report_selection_error(93 &self,94 mut obligation: PredicateObligation<'tcx>,95 root_obligation: &PredicateObligation<'tcx>,96 error: &SelectionError<'tcx>,97 ) -> ErrorGuaranteed {98 let tcx = self.tcx;99 let mut span = obligation.cause.span;100 let mut long_ty_file = None;101102 let mut err = match *error {103 SelectionError::Unimplemented => {104 // If this obligation was generated as a result of well-formedness checking, see if we105 // can get a better error message by performing HIR-based well-formedness checking.106 if let ObligationCauseCode::WellFormed(wf_loc) =107 root_obligation.cause.code().peel_derives()108 && !obligation.predicate.has_non_region_infer()109 && !matches!(wf_loc, WellFormedLoc::None)110 {111 if let Some(cause) = self.tcx.diagnostic_hir_wf_check((112 tcx.erase_and_anonymize_regions(obligation.predicate),113 *wf_loc,114 )) {115 obligation.cause = cause.clone();116 span = obligation.cause.span;117 }118 }119120 if let ObligationCauseCode::CompareImplItem {121 impl_item_def_id,122 trait_item_def_id,123 kind: _,124 } = *obligation.cause.code()125 {126 debug!("ObligationCauseCode::CompareImplItemObligation");127 return self128 .report_extra_impl_obligation(129 span,130 impl_item_def_id,131 trait_item_def_id,132 &format!("`{}`", obligation.predicate),133 )134 .emit_err();135 }136137 // Report a const-param specific error138 if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives()139 {140 return self.report_const_param_not_wf(ty, &obligation).emit_err();141 }142143 let bound_predicate = obligation.predicate.kind();144 match bound_predicate.skip_binder() {145 ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {146 let leaf_trait_predicate = self.deeply_resolve_ignoring_regions(147 bound_predicate.rebind(trait_predicate),148 );149150 // Let's use the root obligation as the main message, when we care about the151 // most general case ("X doesn't implement Pattern<'_>") over the case that152 // happened to fail ("char doesn't implement Fn(&mut char)").153 //154 // We rely on a few heuristics to identify cases where this root155 // obligation is more important than the leaf obligation:156 let (main_trait_predicate, main_obligation) =157 if let ty::PredicateKind::Clause(158 ty::ClauseKind::Trait(root_pred)159 ) = root_obligation.predicate.kind().skip_binder()160 && !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()161 && !root_pred.self_ty().has_escaping_bound_vars()162 // The type of the leaf predicate is (roughly) the same as the type163 // from the root predicate, as a proxy for "we care about the root"164 // FIXME: this doesn't account for trivial derefs, but works as a first165 // approximation.166 && (167 // `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait`168 self.can_eq(169 obligation.param_env,170 leaf_trait_predicate.self_ty().skip_binder(),171 root_pred.self_ty().peel_refs(),172 )173 // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator`174 || self.can_eq(175 obligation.param_env,176 leaf_trait_predicate.self_ty().skip_binder(),177 root_pred.self_ty(),178 )179 )180 // The leaf trait and the root trait are different, so as to avoid181 // talking about `&mut T: Trait` and instead remain talking about182 // `T: Trait` instead183 && leaf_trait_predicate.def_id() != root_pred.def_id()184 // The root trait is not `Unsize`, as to avoid talking about it in185 // `tests/ui/coercion/coerce-issue-49593-box-never.rs`.186 && !self.tcx.is_lang_item(root_pred.def_id(), LangItem::Unsize)187 {188 (189 self.deeply_resolve_ignoring_regions(190 root_obligation.predicate.kind().rebind(root_pred),191 ),192 root_obligation,193 )194 } else {195 (leaf_trait_predicate, &obligation)196 };197198 if let Some(guar) = self199 .emit_specialized_closure_kind_error(&obligation, leaf_trait_predicate)200 {201 return guar;202 }203204 if let Err(guar) = leaf_trait_predicate.error_reported() {205 return guar;206 }207 if self.is_explicit_self_trait_bound_on_impl_assoc_type(208 obligation.cause.body_def_id,209 obligation.cause.code(),210 leaf_trait_predicate.def_id(),211 ) && let ty::Param(param_ty) =212 *leaf_trait_predicate.skip_binder().self_ty().kind()213 {214 span = param_ty.span_from_generics(215 self.tcx,216 obligation.cause.body_def_id.to_def_id(),217 );218 }219 // Silence redundant errors on binding access that are already220 // reported on the binding definition (#56607).221 if let Err(guar) = self.fn_arg_obligation(&obligation) {222 return guar;223 }224 let (post_message, pre_message, type_def) = self225 .get_parent_trait_ref(obligation.cause.code())226 .map(|(t, s)| {227 let t = self.tcx.short_string(t, &mut long_ty_file);228 (229 format!(" in `{t}`"),230 format!("within `{t}`, "),231 s.map(|s| (format!("within this `{t}`"), s)),232 )233 })234 .unwrap_or_default();235236 let CustomDiagnostic { message, label, notes, parent_label } = self237 .on_unimplemented_note(238 main_trait_predicate,239 main_obligation,240 &mut long_ty_file,241 );242243 let have_alt_message = message.is_some() || label.is_some();244245 let message = message.unwrap_or_else(|| {246 self.get_standard_error_message(247 main_trait_predicate,248 None,249 post_message,250 &mut long_ty_file,251 )252 });253 let is_try_conversion =254 self.is_try_conversion(span, main_trait_predicate.def_id());255 let is_question_mark = matches!(256 root_obligation.cause.code().peel_derives(),257 ObligationCauseCode::QuestionMark,258 ) && !(self259 .tcx260 .is_diagnostic_item(sym::FromResidual, main_trait_predicate.def_id())261 || self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::Try));262 let is_unsize =263 self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Unsize);264 let question_mark_message = "the question mark operation (`?`) implicitly \265 performs a conversion on the error value \266 using the `From` trait";267 let (message, notes) = if is_try_conversion {268 let ty = self.tcx.short_string(269 main_trait_predicate.skip_binder().self_ty(),270 &mut long_ty_file,271 );272 // We have a `-> Result<_, E1>` and `gives_E2()?`.273 (274 format!("`?` couldn't convert the error to `{ty}`"),275 vec![question_mark_message.to_owned()],276 )277 } else if is_question_mark {278 let main_trait_predicate =279 self.tcx.short_string(main_trait_predicate, &mut long_ty_file);280 // Similar to the case above, but in this case the conversion is for a281 // trait object: `-> Result<_, Box<dyn Error>` and `gives_E()?` when282 // `E: Error` isn't met.283 (284 format!(285 "`?` couldn't convert the error: `{main_trait_predicate}` is \286 not satisfied",287 ),288 vec![question_mark_message.to_owned()],289 )290 } else {291 (message, notes)292 };293294 let (err_msg, safe_transmute_explanation) = if self295 .tcx296 .is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait)297 {298 // Recompute the safe transmute reason and use that for the error reporting299 let (report_obligation, report_pred) = self300 .select_transmute_obligation_for_reporting(301 &obligation,302 main_trait_predicate,303 root_obligation,304 );305306 match self.get_safe_transmute_error_and_reason(307 report_obligation,308 report_pred,309 span,310 ) {311 GetSafeTransmuteErrorAndReason::Silent => {312 return self313 .dcx()314 .span_delayed_bug(span, "silent safe transmute error");315 }316 GetSafeTransmuteErrorAndReason::Default => (message, None),317 GetSafeTransmuteErrorAndReason::Error {318 err_msg,319 safe_transmute_explanation,320 } => (err_msg, safe_transmute_explanation),321 }322 } else {323 (message, None)324 };325326 let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);327328 let trait_def_id = main_trait_predicate.def_id();329 let leaf_trait_def_id = leaf_trait_predicate.def_id();330 if (self.tcx.is_diagnostic_item(sym::From, trait_def_id)331 || self.tcx.is_diagnostic_item(sym::TryFrom, trait_def_id))332 && (self.tcx.is_diagnostic_item(sym::From, leaf_trait_def_id)333 || self.tcx.is_diagnostic_item(sym::TryFrom, leaf_trait_def_id))334 && let Some(trait_ref) =335 leaf_trait_predicate.no_bound_vars().map(|pred| pred.trait_ref)336 && let Some(found_ty) =337 trait_ref.args.get(1).and_then(|arg| arg.as_type())338 && let Some(ty) =339 main_trait_predicate.no_bound_vars().map(|pred| pred.self_ty())340 && let Some(cast_ty) =341 self.find_explicit_cast_type(obligation.param_env, found_ty, ty)342 {343 let found_ty_str = self.tcx.short_string(found_ty, &mut long_ty_file);344 let cast_ty_str = self.tcx.short_string(cast_ty, &mut long_ty_file);345346 err.help(format!(347 "consider casting the `{found_ty_str}` value to `{cast_ty_str}`",348 ));349 }350351 *err.long_ty_path() = long_ty_file;352353 let mut suggested = false;354 let mut noted_missing_impl = false;355 if is_try_conversion || is_question_mark {356 (suggested, noted_missing_impl) = self.try_conversion_context(357 &obligation,358 main_trait_predicate,359 &mut err,360 );361 }362363 suggested |= self.detect_negative_literal(364 &obligation,365 main_trait_predicate,366 &mut err,367 );368369 if let Some(ret_span) = self.return_type_span(&obligation) {370 if is_try_conversion {371 let ty = self.tcx.short_string(372 main_trait_predicate.skip_binder().self_ty(),373 err.long_ty_path(),374 );375 err.span_label(376 ret_span,377 format!("expected `{ty}` because of this"),378 );379 } else if is_question_mark {380 let main_trait_predicate =381 self.tcx.short_string(main_trait_predicate, err.long_ty_path());382 err.span_label(383 ret_span,384 format!("required `{main_trait_predicate}` because of this"),385 );386 }387 }388389 if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Tuple) {390 self.add_tuple_trait_message(391 obligation.cause.code().peel_derives(),392 &mut err,393 );394 }395396 let explanation = get_explanation_based_on_obligation(397 self.tcx,398 &obligation,399 leaf_trait_predicate,400 pre_message,401 err.long_ty_path(),402 );403404 self.check_for_binding_assigned_block_without_tail_expression(405 &obligation,406 &mut err,407 leaf_trait_predicate,408 );409 self.suggest_add_result_as_return_type(410 &obligation,411 &mut err,412 leaf_trait_predicate,413 );414415 if self.suggest_add_reference_to_arg(416 &obligation,417 &mut err,418 leaf_trait_predicate,419 have_alt_message,420 ) {421 self.note_obligation_cause(&mut err, &obligation);422 return err.emit_err();423 }424425 let ty_span = match leaf_trait_predicate.self_ty().skip_binder().kind() {426 ty::Adt(def, _)427 if def.did().is_local()428 && !self429 .can_suggest_derive(&obligation, leaf_trait_predicate) =>430 {431 self.tcx.def_span(def.did())432 }433 ty::Closure(def_id, _) => self.tcx.def_span(*def_id),434 _ => DUMMY_SP,435 };436 if let Some(s) = label {437 // If it has a custom `#[rustc_on_unimplemented]`438 // error message, let's display it as the label!439 err.span_label(span, s);440 if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_))441 // When the self type is a type param We don't need to "the trait442 // `std::marker::Sized` is not implemented for `T`" as we will point443 // at the type param with a label to suggest constraining it.444 && !self.tcx.is_diagnostic_item(sym::FromResidual, leaf_trait_predicate.def_id())445 // Don't say "the trait `FromResidual<Option<!>>` is446 // not implemented for `Result<T, E>`".447 {448 // We do this just so that the JSON output's `help` position is the449 // right one and not `file.rs:1:1`. The render is the same.450 if ty_span == DUMMY_SP {451 err.help(explanation);452 } else {453 err.span_help(ty_span, explanation);454 }455 }456 } else if let Some(custom_explanation) = safe_transmute_explanation {457 err.span_label(span, custom_explanation);458 } else if (explanation.len() > self.tcx.sess.diagnostic_width()459 || ty_span != DUMMY_SP)460 && !noted_missing_impl461 {462 // Really long types don't look good as span labels, instead move it463 // to a `help`.464 err.span_label(span, "unsatisfied trait bound");465466 // We do this just so that the JSON output's `help` position is the467 // right one and not `file.rs:1:1`. The render is the same.468 if ty_span == DUMMY_SP {469 err.help(explanation);470 } else {471 err.span_help(ty_span, explanation);472 }473 } else {474 err.span_label(span, explanation);475 }476477 if let ObligationCauseCode::Coercion { source, target } =478 *obligation.cause.code().peel_derives()479 {480 if self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Sized)481 {482 self.suggest_borrowing_for_object_cast(483 &mut err,484 root_obligation,485 source,486 target,487 );488 }489 }490491 if let Some((msg, span)) = type_def {492 err.span_label(span, msg);493 }494 // `#[rustc_on_unimplemented]` notes for derivable traits (e.g. `Debug`'s495 // "add `#[derive(Debug)]` to `X` or manually `impl Debug for X`") duplicate496 // the `consider annotating X with #[derive(..)]` suggestion that497 // `suggest_derive` emits below, so skip them when that suggestion will be498 // shown. We keep the note otherwise (e.g. when a field isn't `Debug`, so499 // the derive can't be suggested) to avoid leaving the diagnostic without500 // actionable guidance.501 let derive_suggestion_will_be_shown = main_trait_predicate502 == leaf_trait_predicate503 && self.can_suggest_derive(&obligation, leaf_trait_predicate);504 if !derive_suggestion_will_be_shown {505 for note in notes {506 // If it has a custom `#[rustc_on_unimplemented]` note, let's display507 // it.508 err.note(note);509 }510 }511 if let Some(s) = parent_label {512 let body = obligation.cause.body_def_id;513 err.span_label(tcx.def_span(body), s);514 }515516 self.suggest_floating_point_literal(517 &obligation,518 &mut err,519 leaf_trait_predicate,520 );521 self.suggest_dereferencing_index(522 &obligation,523 &mut err,524 leaf_trait_predicate,525 );526 suggested |=527 self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate)528 || self.suggest_remove_reference(529 &obligation,530 &mut err,531 leaf_trait_predicate,532 );533534 suggested |=535 self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate);536 suggested |= self.suggest_cast_to_fn_pointer(537 &obligation,538 &mut err,539 leaf_trait_predicate,540 main_trait_predicate,541 span,542 );543544 suggested |= self.suggest_semicolon_removal(545 &obligation,546 &mut err,547 span,548 leaf_trait_predicate,549 );550 self.note_different_trait_with_same_name(551 &mut err,552 &obligation,553 leaf_trait_predicate,554 );555 self.note_adt_version_mismatch(&mut err, leaf_trait_predicate);556 self.suggest_remove_await(&obligation, &mut err);557 self.suggest_derive(&obligation, &mut err, leaf_trait_predicate);558559 if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Try) {560 self.suggest_await_before_try(561 &mut err,562 &obligation,563 leaf_trait_predicate,564 span,565 );566 }567568 if self.suggest_add_clone_to_arg(569 &obligation,570 &mut err,571 leaf_trait_predicate,572 ) {573 return err.emit_err();574 }575576 if self.suggest_impl_trait(&mut err, &obligation, leaf_trait_predicate) {577 return err.emit_err();578 }579580 if is_unsize {581 // If the obligation failed due to a missing implementation of the582 // `Unsize` trait, give a pointer to why that might be the case583 err.note(584 "all implementations of `Unsize` are provided \585 automatically by the compiler, see \586 <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> \587 for more information",588 );589 }590591 let is_fn_trait = tcx.is_fn_trait(leaf_trait_predicate.def_id());592 let is_target_feature_fn = if let ty::FnDef(def_id, _) =593 *leaf_trait_predicate.skip_binder().self_ty().kind()594 {595 !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()596 } else {597 false598 };599 if is_fn_trait && is_target_feature_fn {600 err.note(601 "`#[target_feature(..)]` functions do not implement the `Fn` traits",602 );603 err.note(604 "try casting the function to a `fn` pointer or wrapping it in a closure",605 );606 }607608 self.note_field_shadowed_by_private_candidate_in_cause(609 &mut err,610 &obligation.cause,611 obligation.param_env,612 );613 self.try_to_add_help_message(614 &root_obligation,615 &obligation,616 leaf_trait_predicate,617 &mut err,618 span,619 is_fn_trait,620 suggested,621 );622623 // Changing mutability doesn't make a difference to whether we have624 // an `Unsize` impl (Fixes ICE in #71036)625 if !is_unsize {626 self.suggest_change_mut(&obligation, &mut err, leaf_trait_predicate);627 }628629 // If this error is due to `!: Trait` not implemented but `(): Trait` is630 // implemented, and fallback has occurred, then it could be due to a631 // variable that used to fallback to `()` now falling back to `!`. Issue a632 // note informing about the change in behaviour.633 if leaf_trait_predicate.skip_binder().self_ty().is_never()634 && self.diverging_fallback_has_occurred635 {636 let predicate = leaf_trait_predicate.map_bound(|trait_pred| {637 trait_pred.with_replaced_self_ty(self.tcx, tcx.types.unit)638 });639 let unit_obligation = obligation.with(tcx, predicate);640 if self.predicate_may_hold(&unit_obligation) {641 err.note(642 "this error might have been caused by changes to \643 Rust's type-inference algorithm (see issue #148922 \644 <https://github.com/rust-lang/rust/issues/148922> \645 for more information)",646 );647 err.help(648 "you might have intended to use the type `()` here instead",649 );650 }651 }652653 self.explain_hrtb_projection(654 &mut err,655 leaf_trait_predicate,656 obligation.param_env,657 &obligation.cause,658 );659 self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_predicate);660661 // Return early if the trait is Debug or Display and the invocation662 // originates within a standard library macro, because the output663 // is otherwise overwhelming and unhelpful (see #85844 for an664 // example).665666 let in_std_macro =667 match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {668 Some(macro_def_id) => {669 let crate_name = tcx.crate_name(macro_def_id.krate);670 STDLIB_STABLE_CRATES.contains(&crate_name)671 }672 None => false,673 };674675 if in_std_macro676 && matches!(677 self.tcx.get_diagnostic_name(leaf_trait_predicate.def_id()),678 Some(sym::Debug | sym::Display)679 )680 {681 return err.emit_err();682 }683684 err685 }686687 ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(clause)) => self688 .report_host_effect_error(689 bound_predicate.rebind(clause),690 &obligation,691 span,692 ),693694 ty::PredicateKind::Subtype(predicate) => {695 // Errors for Subtype predicates show up as696 // `FulfillmentErrorCode::SubtypeError`,697 // not selection error.698 span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)699 }700701 ty::PredicateKind::Coerce(predicate) => {702 // Errors for Coerce predicates show up as703 // `FulfillmentErrorCode::SubtypeError`,704 // not selection error.705 span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate)706 }707708 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))709 if self.next_trait_solver() =>710 {711 // We normalize `TypeOutlives` in the next solver, which is fallible712 return self.dcx().span_delayed_bug(713 span,714 "type outlives claues errored outside borrowck without any other error",715 );716 }717 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))718 | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => {719 span_bug!(720 span,721 "outlives clauses should not error outside borrowck. obligation: `{:?}`",722 obligation723 )724 }725726 ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {727 span_bug!(728 span,729 "projection clauses should be implied from elsewhere. obligation: `{:?}`",730 obligation731 )732 }733734 ty::PredicateKind::DynCompatible(trait_def_id) => {735 let violations = self.tcx.dyn_compatibility_violations(trait_def_id);736 let mut err = report_dyn_incompatibility(737 self.tcx,738 span,739 None,740 trait_def_id,741 violations,742 );743 if let hir::Node::Item(item) =744 self.tcx.hir_node_by_def_id(obligation.cause.body_def_id)745 && let hir::ItemKind::Impl(impl_) = item.kind746 && let None = impl_.of_trait747 && let hir::TyKind::TraitObject(_, tagged_ptr) = impl_.self_ty.kind748 && let TraitObjectSyntax::None = tagged_ptr.tag()749 && impl_.self_ty.span.edition().at_least_rust_2021()750 {751 // Silence the dyn-compatibility error in favor of the missing dyn on752 // self type error. #131051.753 err.downgrade_to_delayed_bug();754 }755 err756 }757758 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {759 let ty = self.deeply_resolve_ignoring_regions(ty);760 if self.next_trait_solver() {761 if let Err(guar) = ty.error_reported() {762 return guar;763 }764765 // FIXME: we'll need a better message which takes into account766 // which bounds actually failed to hold.767 self.dcx().struct_span_err(768 span,769 format!("the type `{ty}` is not well-formed"),770 )771 } else {772 // WF predicates cannot themselves make773 // errors. They can only block due to774 // ambiguity; otherwise, they always775 // degenerate into other obligations776 // (which may fail).777 span_bug!(span, "WF predicate not satisfied for {:?}", ty);778 }779 }780781 // Errors for `ConstEvaluatable`, `ConstEquate` predicates show up as782 // `SelectionError::ConstEvalFailure`, not `Unimplemented`.783 // Ambiguous predicates should never error.784 // We never return `Err` when proving `UnstableFeature` goal.785 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))786 | ty::PredicateKind::ConstEquate { .. }787 | ty::PredicateKind::Ambiguous788 | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature { .. })789 | ty::PredicateKind::NormalizesTo { .. }790 | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => {791 span_bug!(792 span,793 "Unexpected `Predicate` for `SelectionError`: `{:?}`",794 obligation795 )796 }797 }798 }799800 SelectionError::SignatureMismatch(SignatureMismatchData {801 found_trait_ref,802 expected_trait_ref,803 terr: terr @ TypeError::CyclicTy(_),804 }) => self.report_cyclic_signature_error(805 &obligation,806 found_trait_ref,807 expected_trait_ref,808 terr,809 ),810 SelectionError::SignatureMismatch(SignatureMismatchData {811 found_trait_ref,812 expected_trait_ref,813 terr: _,814 }) => {815 match self.report_signature_mismatch_error(816 &obligation,817 span,818 found_trait_ref,819 expected_trait_ref,820 ) {821 Ok(err) => err,822 Err(guar) => return guar,823 }824 }825826 SelectionError::TraitDynIncompatible(did) => {827 let violations = self.tcx.dyn_compatibility_violations(did);828 report_dyn_incompatibility(self.tcx, span, None, did, violations)829 }830831 SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {832 bug!(833 "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`"834 )835 }836 SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {837 match self.report_not_const_evaluatable_error(&obligation, span) {838 Ok(err) => err,839 Err(guar) => return guar,840 }841 }842843 // Already reported in the query.844 SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar))845 | SelectionError::Overflow(OverflowError::Error(guar)) => {846 self.set_tainted_by_errors(guar);847 return guar;848 }849850 SelectionError::Overflow(_) => {851 bug!("overflow should be handled before the `report_selection_error` path");852 }853854 SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => {855 let expected_ty_str = self.tcx.short_string(expected_ty, &mut long_ty_file);856 let ct_str = self.tcx.short_string(ct, &mut long_ty_file);857 let mut diag = self.dcx().struct_span_err(858 span,859 format!("the constant `{ct_str}` is not of type `{expected_ty_str}`"),860 );861 diag.long_ty_path = long_ty_file;862863 self.note_type_err(864 &mut diag,865 &obligation.cause,866 None,867 None,868 TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)),869 false,870 None,871 );872 diag873 }874 };875876 self.note_obligation_cause(&mut err, &obligation);877 self.silence_redundant_cause(&mut err, &obligation, &root_obligation);878 err.emit_err()879 }880}881882impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {883 pub(super) fn apply_do_not_recommend(884 &self,885 obligation: &mut PredicateObligation<'tcx>,886 root_obligation: &PredicateObligation<'tcx>,887 ) -> bool {888 let mut base_cause = obligation.cause.code().clone();889 let mut applied_do_not_recommend = false;890 loop {891 if let ObligationCauseCode::ImplDerived(ref c) = base_cause {892 if self.tcx.do_not_recommend_impl(c.impl_or_alias_def_id) {893 let code = (*c.derived.parent_code).clone();894 // Keep more precise spans that still point within the parent obligation,895 // but do not let hidden impl details move the span outside of it.896 if code == *root_obligation.cause.code()897 && root_obligation.cause.span.eq_ctxt(obligation.cause.span)898 && !root_obligation.cause.span.contains(obligation.cause.span)899 {900 obligation.cause.span = root_obligation.cause.span;901 }902 obligation.cause.map_code(|_| code);903 obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);904 applied_do_not_recommend = true;905 }906 }907 if let Some(parent_cause) = base_cause.parent() {908 base_cause = parent_cause.clone();909 } else {910 break;911 }912 }913914 applied_do_not_recommend915 }916917 fn report_host_effect_error(918 &self,919 clause: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>,920 main_obligation: &PredicateObligation<'tcx>,921 span: Span,922 ) -> Diag<'a> {923 // FIXME(const_trait_impl): We should recompute the clause with `[const]`924 // if it's `const`, and if it holds, explain that this bound only925 // *conditionally* holds.926 let trait_ref = clause.map_bound(|clause| ty::TraitClause {927 trait_ref: clause.trait_ref,928 polarity: ty::ClausePolarity::Positive,929 });930 let mut file = None;931932 let err_msg = self.get_standard_error_message(933 trait_ref,934 Some(clause.constness()),935 String::new(),936 &mut file,937 );938 let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);939 *diag.long_ty_path() = file;940 let obligation = Obligation::new(941 self.tcx,942 ObligationCause::dummy(),943 main_obligation.param_env,944 trait_ref,945 );946 if !self.predicate_may_hold(&obligation) {947 diag.downgrade_to_delayed_bug();948 }949950 if let Ok(Some(ImplSource::UserDefined(impl_data))) =951 SelectionContext::new(self).poly_select(&obligation.with(self.tcx, trait_ref))952 {953 let impl_did = impl_data.impl_def_id;954 let trait_did = trait_ref.def_id();955 let impl_span = self.tcx.def_span(impl_did);956 let trait_name = self.tcx.item_name(trait_did);957958 if self.tcx.is_const_trait(trait_did) && !self.tcx.is_const_trait_impl(impl_did) {959 if !impl_did.is_local() {960 diag.span_note(961 impl_span,962 format!("trait `{trait_name}` is implemented but not `const`"),963 );964 }965966 if let Some(command) =967 find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref())968 .flatten()969 {970 let (_, mut format_args) = self.on_unimplemented_components(971 trait_ref,972 main_obligation,973 diag.long_ty_path(),974 false,975 );976 if let ty::Adt(def, args) = trait_ref.self_ty().skip_binder().kind() {977 for param in self.tcx.generics_of(def.did()).own_params.iter() {978 match param.kind {979 GenericParamDefKind::Type { .. }980 | GenericParamDefKind::Const { .. } => {981 format_args982 .generic_args983 .push((param.name, args[param.index as usize].to_string()));984 }985 _ => continue,986 }987 }988 }989 let CustomDiagnostic { message, label, notes, parent_label: _ } =990 command.eval(None, &format_args);991992 if let Some(message) = message {993 diag.primary_message(message);994 }995 if let Some(label) = label {996 diag.span_label(span, label);997 }998 for note in notes {999 diag.note(note);1000 }1001 } else if let Some(impl_did) = impl_did.as_local()1002 && let item = self.tcx.hir_expect_item(impl_did)1003 && let hir::ItemKind::Impl(impl_) = item.kind1004 && impl_.of_trait.is_some()1005 {1006 // trait is const, impl is local and not const1007 diag.span_suggestion_verbose(1008 item.span.shrink_to_lo(),1009 format!("make the `impl` of trait `{trait_name}` `const`"),1010 "const ".to_string(),1011 Applicability::MaybeIncorrect,1012 );1013 }1014 }1015 } else if let ty::Param(param) = trait_ref.self_ty().skip_binder().kind()1016 && let Some(generics) =1017 self.tcx.hir_node_by_def_id(main_obligation.cause.body_def_id).generics()1018 {1019 let constraint = ty::print::with_no_trimmed_paths!(format!(1020 "[const] {}",1021 trait_ref.map_bound(|tr| tr.trait_ref).print_trait_sugared(),1022 ));1023 ty::suggest_constraining_type_param(1024 self.tcx,1025 generics,1026 &mut diag,1027 param.name.as_str(),1028 &constraint,1029 Some(trait_ref.def_id()),1030 None,1031 );1032 }1033 diag1034 }10351036 fn emit_specialized_closure_kind_error(1037 &self,1038 obligation: &PredicateObligation<'tcx>,1039 mut trait_pred: ty::PolyTraitClause<'tcx>,1040 ) -> Option<ErrorGuaranteed> {1041 // If we end up on an `AsyncFnKindHelper` goal, try to unwrap the parent1042 // `AsyncFn*` goal.1043 if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::AsyncFnKindHelper) {1044 let mut code = obligation.cause.code();1045 // Unwrap a `FunctionArg` cause, which has been refined from a derived obligation.1046 if let ObligationCauseCode::FunctionArg { parent_code, .. } = code {1047 code = &**parent_code;1048 }1049 // If we have a derived obligation, then the parent will be a `AsyncFn*` goal.1050 if let Some((_, Some(parent))) = code.parent_with_predicate() {1051 trait_pred = parent;1052 }1053 }10541055 let original_self_ty = trait_pred.self_ty().skip_binder();1056 let peeled_self_ty = original_self_ty.peel_refs();10571058 let is_ref_to_closure = matches!(original_self_ty.kind(), ty::Ref(..))1059 && matches!(peeled_self_ty.kind(), ty::Closure(..));10601061 let self_ty = if is_ref_to_closure { peeled_self_ty } else { original_self_ty };10621063 let (expected_kind, is_async) =1064 if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_pred.def_id()) {1065 (expected_kind, false)1066 } else if let Some(expected_kind) =1067 self.tcx.async_fn_trait_kind_from_def_id(trait_pred.def_id())1068 {1069 (expected_kind, true)1070 } else {1071 return None;1072 };1073 let trait_prefix = if is_async { "Async" } else { "" };10741075 let (closure_def_id, found_args, has_self_borrows) = match *self_ty.kind() {1076 ty::Closure(def_id, args) => {1077 (def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), false)1078 }1079 ty::CoroutineClosure(def_id, args) => (1080 def_id,1081 args.as_coroutine_closure()1082 .coroutine_closure_sig()1083 .map_bound(|sig| sig.tupled_inputs_ty),1084 !args.as_coroutine_closure().tupled_upvars_ty().is_ty_var()1085 && args.as_coroutine_closure().has_self_borrows(),1086 ),1087 _ => return None,1088 };10891090 let expected_args = trait_pred.map_bound(|trait_pred| trait_pred.trait_ref.args.type_at(1));10911092 // Verify that the arguments are compatible. If the signature is1093 // mismatched, then we have a totally different error to report.1094 if self.enter_forall(found_args, |found_args| {1095 self.enter_forall(expected_args, |expected_args| {1096 !self.can_eq(obligation.param_env, expected_args, found_args)1097 })1098 }) {1099 return None;1100 }11011102 let mut found_kind = self.closure_kind(self_ty);1103 let mut kind_origin = None;11041105 if found_kind.is_none()1106 && is_ref_to_closure1107 && !is_async1108 && let Some(local_def_id) = closure_def_id.as_local()1109 && let Some((inferred_kind, origin)) = (self.infer_closure_kind)(local_def_id)1110 {1111 found_kind = Some(inferred_kind);1112 kind_origin = origin;1113 }11141115 if let Some(found_kind) = found_kind1116 && !found_kind.extends(expected_kind)1117 {1118 let mut err = self.report_closure_error(1119 &obligation,1120 closure_def_id,1121 found_kind,1122 expected_kind,1123 trait_prefix,1124 kind_origin,1125 );1126 self.suggest_change_mut_ref_for_closure(&mut err, &obligation);1127 self.note_obligation_cause(&mut err, &obligation);1128 return Some(err.emit_err());1129 }11301131 // If the closure has captures, then perhaps the reason that the trait1132 // is unimplemented is because async closures don't implement `Fn`/`FnMut`1133 // if they have captures.1134 if has_self_borrows && expected_kind != ty::ClosureKind::FnOnce {1135 let coro_kind = match self1136 .tcx1137 .coroutine_kind(self.tcx.coroutine_for_closure(closure_def_id))1138 .unwrap()1139 {1140 rustc_hir::CoroutineKind::Desugared(desugaring, _) => desugaring.to_string(),1141 coro => coro.to_string(),1142 };1143 let mut err = self.dcx().create_err(CoroClosureNotFn {1144 span: self.tcx.def_span(closure_def_id),1145 kind: expected_kind.as_str(),1146 coro_kind,1147 });1148 self.note_obligation_cause(&mut err, &obligation);1149 return Some(err.emit_err());1150 }11511152 None1153 }11541155 fn fn_arg_obligation(1156 &self,1157 obligation: &PredicateObligation<'tcx>,1158 ) -> Result<(), ErrorGuaranteed> {1159 if let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()1160 && let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id)1161 && let arg = arg.peel_borrows()1162 && let hir::ExprKind::Path(hir::QPath::Resolved(1163 None,1164 hir::Path { res: hir::def::Res::Local(hir_id), .. },1165 )) = arg.kind1166 && let Node::Pat(pat) = self.tcx.hir_node(*hir_id)1167 && let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span)1168 && preds.contains(&obligation.as_goal())1169 {1170 return Err(*guar);1171 }1172 Ok(())1173 }11741175 fn detect_negative_literal(1176 &self,1177 obligation: &PredicateObligation<'tcx>,1178 trait_pred: ty::PolyTraitClause<'tcx>,1179 err: &mut Diag<'_>,1180 ) -> bool {1181 if let ObligationCauseCode::UnOp { hir_id, .. } = obligation.cause.code()1182 && let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id)1183 && let hir::ExprKind::Unary(hir::UnOp::Neg, inner) = expr.kind1184 && let hir::ExprKind::Lit(lit) = inner.kind1185 && let LitKind::Int(_, LitIntType::Unsuffixed) = lit.node1186 {1187 err.span_suggestion_verbose(1188 lit.span.shrink_to_hi(),1189 "consider specifying an integer type that can be negative",1190 match trait_pred.skip_binder().self_ty().kind() {1191 ty::Uint(ty::UintTy::Usize) => "isize",1192 ty::Uint(ty::UintTy::U8) => "i8",1193 ty::Uint(ty::UintTy::U16) => "i16",1194 ty::Uint(ty::UintTy::U32) => "i32",1195 ty::Uint(ty::UintTy::U64) => "i64",1196 ty::Uint(ty::UintTy::U128) => "i128",1197 _ => "i64",1198 }1199 .to_string(),1200 Applicability::MaybeIncorrect,1201 );1202 return true;1203 }1204 false1205 }12061207 /// When the `E` of the resulting `Result<T, E>` in an expression `foo().bar().baz()?`,1208 /// identify those method chain sub-expressions that could or could not have been annotated1209 /// with `?`.1210 fn try_conversion_context(1211 &self,1212 obligation: &PredicateObligation<'tcx>,1213 trait_pred: ty::PolyTraitClause<'tcx>,1214 err: &mut Diag<'_>,1215 ) -> (bool, bool) {1216 let span = obligation.cause.span;1217 /// Look for the (direct) sub-expr of `?`, and return it if it's a `.` method call.1218 struct FindMethodSubexprOfTry {1219 search_span: Span,1220 }1221 impl<'v> Visitor<'v> for FindMethodSubexprOfTry {1222 type Result = ControlFlow<&'v hir::Expr<'v>>;1223 fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {1224 if let hir::ExprKind::Match(expr, _arms, hir::MatchSource::TryDesugar(_)) = ex.kind1225 && ex.span.with_lo(ex.span.hi() - BytePos(1)).lo_hi()1226 == self.search_span.lo_hi()1227 && let hir::ExprKind::Call(_, [expr, ..]) = expr.kind1228 {1229 ControlFlow::Break(expr)1230 } else {1231 hir::intravisit::walk_expr(self, ex)1232 }1233 }1234 }1235 let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_def_id);1236 let Some(body_id) = self.tcx.hir_node(hir_id).body_id() else { return (false, false) };1237 let ControlFlow::Break(expr) =1238 (FindMethodSubexprOfTry { search_span: span }).visit_body(self.tcx.hir_body(body_id))1239 else {1240 return (false, false);1241 };1242 let Some(typeck) = &self.typeck_results else {1243 return (false, false);1244 };1245 let ObligationCauseCode::QuestionMark = obligation.cause.code().peel_derives() else {1246 return (false, false);1247 };1248 let self_ty = trait_pred.skip_binder().self_ty();1249 let found_ty = trait_pred.skip_binder().trait_ref.args.get(1).and_then(|a| a.as_type());1250 let noted_missing_impl =1251 self.note_missing_impl_for_question_mark(err, self_ty, found_ty, trait_pred);12521253 let mut prev_ty = self.deeply_resolve_ignoring_regions(1254 typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),1255 );12561257 // We always look at the `E` type, because that's the only one affected by `?`. If the1258 // incorrect `Result<T, E>` is because of the `T`, we'll get an E0308 on the whole1259 // expression, after the `?` has "unwrapped" the `T`.1260 let get_e_type = |prev_ty: Ty<'tcx>| -> Option<Ty<'tcx>> {1261 let ty::Adt(def, args) = prev_ty.kind() else {1262 return None;1263 };1264 let Some(arg) = args.get(1) else {1265 return None;1266 };1267 if !self.tcx.is_diagnostic_item(sym::Result, def.did()) {1268 return None;1269 }1270 arg.as_type()1271 };12721273 let mut suggested = false;1274 let mut chain = vec![];12751276 // The following logic is similar to `point_at_chain`, but that's focused on associated types1277 let mut expr = expr;1278 while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind {1279 // Point at every method call in the chain with the `Result` type.1280 // let foo = bar.iter().map(mapper)?;1281 // ------ -----------1282 expr = rcvr_expr;1283 chain.push((span, prev_ty));12841285 let next_ty = self.deeply_resolve_ignoring_regions(1286 typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),1287 );12881289 let is_diagnostic_item = |symbol: Symbol, ty: Ty<'tcx>| {1290 let ty::Adt(def, _) = ty.kind() else {1291 return false;1292 };1293 self.tcx.is_diagnostic_item(symbol, def.did())1294 };1295 // For each method in the chain, see if this is `Result::map_err` or1296 // `Option::ok_or_else` and if it is, see if the closure passed to it has an incorrect1297 // trailing `;`.1298 if let Some(ty) = get_e_type(prev_ty)1299 && let Some(found_ty) = found_ty1300 // Ideally we would instead use `FnCtxt::lookup_method_for_diagnostic` for 100%1301 // accurate check, but we are in the wrong stage to do that and looking for1302 // `Result::map_err` by checking the Self type and the path segment is enough.1303 // sym::ok_or_else1304 && (1305 ( // Result::map_err1306 path_segment.ident.name == sym::map_err1307 && is_diagnostic_item(sym::Result, next_ty)1308 ) || ( // Option::ok_or_else1309 path_segment.ident.name == sym::ok_or_else1310 && is_diagnostic_item(sym::Option, next_ty)1311 )1312 )1313 // Found `Result<_, ()>?`1314 && let ty::Tuple(tys) = found_ty.kind()1315 && tys.is_empty()1316 // The current method call returns `Result<_, ()>`1317 && self.can_eq(obligation.param_env, ty, found_ty)1318 // There's a single argument in the method call and it is a closure1319 && let [arg] = args1320 && let hir::ExprKind::Closure(closure) = arg.kind1321 // The closure has a block for its body with no tail expression1322 && let body = self.tcx.hir_body(closure.body)1323 && let hir::ExprKind::Block(block, _) = body.value.kind1324 && let None = block.expr1325 // The last statement is of a type that can be converted to the return error type1326 && let [.., stmt] = block.stmts1327 && let hir::StmtKind::Semi(expr) = stmt.kind1328 && let expr_ty = self.deeply_resolve_ignoring_regions(1329 typeck.expr_ty_adjusted_opt(expr)1330 .unwrap_or(Ty::new_misc_error(self.tcx)),1331 )1332 && self1333 .infcx1334 .type_implements_trait(1335 self.tcx.get_diagnostic_item(sym::From).unwrap(),1336 [self_ty, expr_ty],1337 obligation.param_env,1338 )1339 .must_apply_modulo_regions()1340 {1341 suggested = true;1342 err.span_suggestion_short(1343 stmt.span.with_lo(expr.span.hi()),1344 "remove this semicolon",1345 String::new(),1346 Applicability::MachineApplicable,1347 );1348 }13491350 prev_ty = next_ty;13511352 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind1353 && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path1354 && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)1355 {1356 let parent = self.tcx.parent_hir_node(binding.hir_id);1357 // We've reached the root of the method call chain...1358 if let hir::Node::LetStmt(local) = parent1359 && let Some(binding_expr) = local.init1360 {1361 // ...and it is a binding. Get the binding creation and continue the chain.1362 expr = binding_expr;1363 }1364 if let hir::Node::Param(_param) = parent {1365 // ...and it is an fn argument.1366 break;1367 }1368 }1369 }1370 // `expr` is now the "root" expression of the method call chain, which can be any1371 // expression kind, like a method call or a path. If this expression is `Result<T, E>` as1372 // well, then we also point at it.1373 prev_ty = self.deeply_resolve_ignoring_regions(1374 typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),1375 );1376 chain.push((expr.span, prev_ty));13771378 let mut prev = None;1379 let mut iter = chain.into_iter().rev().peekable();1380 while let Some((span, err_ty)) = iter.next() {1381 let is_last = iter.peek().is_none();1382 let err_ty = get_e_type(err_ty);1383 let err_ty = match (err_ty, prev) {1384 (Some(err_ty), Some(prev)) if !self.can_eq(obligation.param_env, err_ty, prev) => {1385 err_ty1386 }1387 (Some(err_ty), None) => err_ty,1388 _ => {1389 prev = err_ty;1390 continue;1391 }1392 };13931394 let implements_from = self1395 .infcx1396 .type_implements_trait(1397 self.tcx.get_diagnostic_item(sym::From).unwrap(),1398 [self_ty, err_ty],1399 obligation.param_env,1400 )1401 .must_apply_modulo_regions();14021403 let err_ty_str = self.tcx.short_string(err_ty, err.long_ty_path());1404 let label = if !implements_from && is_last {1405 format!(1406 "this can't be annotated with `?` because it has type `Result<_, {err_ty_str}>`"1407 )1408 } else {1409 format!("this has type `Result<_, {err_ty_str}>`")1410 };14111412 if !suggested || !implements_from {1413 err.span_label(span, label);1414 }1415 prev = Some(err_ty);1416 }1417 (suggested, noted_missing_impl)1418 }14191420 fn note_missing_impl_for_question_mark(1421 &self,1422 err: &mut Diag<'_>,1423 self_ty: Ty<'_>,1424 found_ty: Option<Ty<'_>>,1425 trait_pred: ty::PolyTraitClause<'tcx>,1426 ) -> bool {1427 match (self_ty.kind(), found_ty) {1428 (ty::Adt(def, _), Some(ty))1429 if let ty::Adt(found, _) = ty.kind()1430 && def.did().is_local()1431 && found.did().is_local() =>1432 {1433 err.span_note(1434 self.tcx.def_span(def.did()),1435 format!("`{self_ty}` needs to implement `From<{ty}>`"),1436 );1437 }1438 (ty::Adt(def, _), None) if def.did().is_local() => {1439 let trait_path = self.tcx.short_string(1440 trait_pred.skip_binder().trait_ref.print_only_trait_path(),1441 err.long_ty_path(),1442 );1443 err.span_note(1444 self.tcx.def_span(def.did()),1445 format!("`{self_ty}` needs to implement `{trait_path}`"),1446 );1447 }1448 (ty::Adt(def, _), Some(ty)) if def.did().is_local() => {1449 err.span_note(1450 self.tcx.def_span(def.did()),1451 format!("`{self_ty}` needs to implement `From<{ty}>`"),1452 );1453 }1454 (_, Some(ty))1455 if let ty::Adt(def, _) = ty.kind()1456 && def.did().is_local() =>1457 {1458 err.span_note(1459 self.tcx.def_span(def.did()),1460 format!("`{ty}` needs to implement `Into<{self_ty}>`"),1461 );1462 }1463 _ => return false,1464 }1465 true1466 }14671468 fn report_const_param_not_wf(1469 &self,1470 ty: Ty<'tcx>,1471 obligation: &PredicateObligation<'tcx>,1472 ) -> Diag<'a> {1473 let def_id = obligation.cause.body_def_id;1474 let span = self.tcx.ty_span(def_id);14751476 let mut file = None;1477 let ty_str = self.tcx.short_string(ty, &mut file);1478 let mut diag = match ty.kind() {1479 ty::Float(_) => {1480 struct_span_code_err!(1481 self.dcx(),1482 span,1483 E0741,1484 "`{ty_str}` is forbidden as the type of a const generic parameter",1485 )1486 }1487 ty::FnPtr(..) => {1488 struct_span_code_err!(1489 self.dcx(),1490 span,1491 E0741,1492 "using function pointers as const generic parameters is forbidden",1493 )1494 }1495 ty::RawPtr(_, _) => {1496 struct_span_code_err!(1497 self.dcx(),1498 span,1499 E0741,1500 "using raw pointers as const generic parameters is forbidden",1501 )1502 }1503 ty::Adt(def, _) => {1504 // We should probably see if we're *allowed* to derive `ConstParamTy` on the type...1505 let mut diag = struct_span_code_err!(1506 self.dcx(),1507 span,1508 E0741,1509 "`{ty_str}` must implement `ConstParamTy` to be used as the type of a const \1510 generic parameter",1511 );1512 // Only suggest derive if this isn't a derived obligation,1513 // and the struct is local.1514 if let Some(span) = self.tcx.hir_span_if_local(def.did())1515 && obligation.cause.code().parent().is_none()1516 {1517 if ty.is_structural_eq_shallow(self.tcx) {1518 diag.span_suggestion_verbose(1519 span.shrink_to_lo(),1520 format!("add `#[derive(ConstParamTy)]` to the {}", def.descr()),1521 "#[derive(ConstParamTy)]\n",1522 Applicability::MachineApplicable,1523 );1524 } else {1525 // FIXME(adt_const_params): We should check there's not already an1526 // overlapping `Eq`/`PartialEq` impl.1527 diag.span_suggestion_verbose(1528 span.shrink_to_lo(),1529 format!(1530 "add `#[derive(ConstParamTy, PartialEq, Eq)]` to the {}",1531 def.descr()1532 ),1533 "#[derive(ConstParamTy, PartialEq, Eq)]\n",1534 Applicability::MachineApplicable,1535 );1536 }1537 }1538 diag1539 }1540 _ => {1541 struct_span_code_err!(1542 self.dcx(),1543 span,1544 E0741,1545 "`{ty_str}` can't be used as a const parameter type",1546 )1547 }1548 };1549 diag.long_ty_path = file;15501551 let mut code = obligation.cause.code();1552 let mut pred = obligation.predicate.as_trait_clause();1553 while let Some((next_code, next_pred)) = code.parent_with_predicate() {1554 if let Some(pred) = pred {1555 self.enter_forall(pred, |pred| {1556 let ty = self.tcx.short_string(pred.self_ty(), diag.long_ty_path());1557 let trait_path = self1558 .tcx1559 .short_string(pred.print_modifiers_and_trait_path(), diag.long_ty_path());1560 diag.note(format!("`{ty}` must implement `{trait_path}`, but it does not"));1561 })1562 }1563 code = next_code;1564 pred = next_pred;1565 }15661567 diag1568 }1569}15701571impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {1572 fn can_match_trait(1573 &self,1574 param_env: ty::ParamEnv<'tcx>,1575 goal: ty::TraitClause<'tcx>,1576 assumption: ty::PolyTraitClause<'tcx>,1577 ) -> bool {1578 // Fast path1579 if goal.polarity != assumption.polarity() {1580 return false;1581 }15821583 let trait_assumption = self.instantiate_binder_with_fresh_vars(1584 DUMMY_SP,1585 infer::BoundRegionConversionTime::HigherRankedType,1586 assumption,1587 );15881589 self.can_eq(param_env, goal.trait_ref, trait_assumption.trait_ref)1590 }15911592 fn can_match_host_effect(1593 &self,1594 param_env: ty::ParamEnv<'tcx>,1595 goal: ty::HostEffectClause<'tcx>,1596 assumption: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>,1597 ) -> bool {1598 let assumption = self.instantiate_binder_with_fresh_vars(1599 DUMMY_SP,1600 infer::BoundRegionConversionTime::HigherRankedType,1601 assumption,1602 );16031604 assumption.constness.satisfies(goal.constness)1605 && self.can_eq(param_env, goal.trait_ref, assumption.trait_ref)1606 }16071608 fn as_host_effect_clause(1609 predicate: ty::Predicate<'tcx>,1610 ) -> Option<ty::Binder<'tcx, ty::HostEffectClause<'tcx>>> {1611 predicate.as_clause().and_then(|clause| match clause.kind().skip_binder() {1612 ty::ClauseKind::HostEffect(host_clause) => Some(clause.kind().rebind(host_clause)),1613 _ => None,1614 })1615 }16161617 fn can_match_projection(1618 &self,1619 param_env: ty::ParamEnv<'tcx>,1620 goal: ty::ProjectionClause<'tcx>,1621 assumption: ty::PolyProjectionClause<'tcx>,1622 ) -> bool {1623 let assumption = self.instantiate_binder_with_fresh_vars(1624 DUMMY_SP,1625 infer::BoundRegionConversionTime::HigherRankedType,1626 assumption,1627 );16281629 self.can_eq(param_env, goal.projection_term, assumption.projection_term)1630 && self.can_eq(param_env, goal.term, assumption.term)1631 }16321633 // returns if `cond` not occurring implies that `error` does not occur - i.e., that1634 // `error` occurring implies that `cond` occurs.1635 #[instrument(level = "debug", skip(self), ret)]1636 pub(super) fn error_implies(1637 &self,1638 cond: Goal<'tcx, ty::Predicate<'tcx>>,1639 error: Goal<'tcx, ty::Predicate<'tcx>>,1640 ) -> bool {1641 if cond == error {1642 return true;1643 }16441645 // FIXME: We could be smarter about this, i.e. if cond's param-env is a1646 // subset of error's param-env. This only matters when binders will carry1647 // predicates though, and obviously only matters for error reporting.1648 if cond.param_env != error.param_env {1649 return false;1650 }1651 let param_env = error.param_env;16521653 if let Some(error) = error.predicate.as_trait_clause() {1654 self.enter_forall(error, |error| {1655 elaborate(self.tcx, std::iter::once(cond.predicate))1656 .filter_map(|implied| implied.as_trait_clause())1657 .any(|implied| self.can_match_trait(param_env, error, implied))1658 })1659 } else if let Some(error) = Self::as_host_effect_clause(error.predicate) {1660 self.enter_forall(error, |error| {1661 elaborate(self.tcx, std::iter::once(cond.predicate))1662 .filter_map(Self::as_host_effect_clause)1663 .any(|implied| self.can_match_host_effect(param_env, error, implied))1664 })1665 } else if let Some(error) = error.predicate.as_projection_clause() {1666 self.enter_forall(error, |error| {1667 elaborate(self.tcx, std::iter::once(cond.predicate))1668 .filter_map(|implied| implied.as_projection_clause())1669 .any(|implied| self.can_match_projection(param_env, error, implied))1670 })1671 } else {1672 false1673 }1674 }16751676 /// Whether `error`, a projection goal, only failed because the trait goal it rests on1677 /// did: `<T as Trait>::Assoc == U` cannot hold when `T: Trait` doesn't, so an error on1678 /// the latter says everything the former would.1679 pub(super) fn trait_error_implies_projection_error(1680 &self,1681 cond: Goal<'tcx, ty::Predicate<'tcx>>,1682 error: Goal<'tcx, ty::Predicate<'tcx>>,1683 ) -> bool {1684 if cond.param_env != error.param_env {1685 return false;1686 }1687 let Some(error) = error.predicate.as_projection_clause() else {1688 return false;1689 };16901691 self.enter_forall(error, |error| {1692 if !error.projection_term.kind.is_trait_projection() {1693 return false;1694 }1695 let trait_pred = ty::TraitClause {1696 trait_ref: error.projection_term.trait_ref(self.tcx),1697 polarity: ty::ClausePolarity::Positive,1698 };1699 // Elaborating is what pairs a failing `C: FnMut(..)` with the1700 // `<C as FnOnce<..>>::Output` projection resting on it. A supertrait can hold1701 // while `cond` fails though, so the projection is only covered if its own trait1702 // goal is unproven too, otherwise it failed for its own reasons.1703 elaborate(self.tcx, std::iter::once(cond.predicate))1704 .filter_map(|implied| implied.as_trait_clause())1705 .any(|implied| self.can_match_trait(cond.param_env, trait_pred, implied))1706 && !self.predicate_must_hold_modulo_regions(&Obligation::new(1707 self.tcx,1708 ObligationCause::dummy(),1709 cond.param_env,1710 trait_pred,1711 ))1712 })1713 }17141715 #[instrument(level = "debug", skip_all)]1716 pub(super) fn report_projection_error(1717 &self,1718 obligation: &PredicateObligation<'tcx>,1719 error: &MismatchedProjectionTypes<'tcx>,1720 ) -> ErrorGuaranteed {1721 let predicate = self.deeply_resolve_ignoring_regions(obligation.predicate);17221723 if let Err(e) = predicate.error_reported() {1724 return e;1725 }17261727 self.probe(|_| {1728 // try to find the mismatched types to report the error with.1729 //1730 // this can fail if the problem was higher-ranked, in which1731 // cause I have no idea for a good error message.1732 let bound_predicate = predicate.kind();1733 let (values, err) = match bound_predicate.skip_binder() {1734 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {1735 let ocx = ObligationCtxt::new(self);17361737 let data = self.instantiate_binder_with_fresh_vars(1738 obligation.cause.span,1739 infer::BoundRegionConversionTime::HigherRankedType,1740 bound_predicate.rebind(data),1741 );1742 let unnormalized_term = data.projection_term.to_term(self.tcx, ty::IsRigid::No);1743 let normalized_term = ocx.normalize(1744 &obligation.cause,1745 obligation.param_env,1746 Unnormalized::new_wip(unnormalized_term),1747 );17481749 // constrain inference variables a bit more to nested obligations from normalize so1750 // we can have more helpful errors.1751 //1752 // we intentionally drop errors from normalization here,1753 // since the normalization is just done to improve the error message.1754 let _ = ocx.try_evaluate_obligations();17551756 if let Err(new_err) =1757 ocx.eq(&obligation.cause, obligation.param_env, data.term, normalized_term)1758 {1759 (1760 Some((1761 data.projection_term,1762 self.deeply_resolve_ignoring_regions(normalized_term),1763 data.term,1764 )),1765 new_err,1766 )1767 } else {1768 (None, error.err)1769 }1770 }1771 _ => (None, error.err),1772 };17731774 let mut file = None;1775 let (msg, mut span, mut closure_span) = values1776 .and_then(|(predicate, normalized_term, expected_term)| {1777 self.maybe_detailed_projection_msg(1778 obligation.cause.span,1779 predicate,1780 normalized_term,1781 expected_term,1782 &mut file,1783 )1784 })1785 .unwrap_or_else(|| {1786 (1787 with_forced_trimmed_paths!(format!(1788 "type mismatch resolving `{}`",1789 self.tcx.short_string(1790 self.deeply_resolve_ignoring_regions(predicate),1791 &mut file1792 ),1793 )),1794 obligation.cause.span,1795 None,1796 )1797 });17981799 // When the obligation comes from a closure arg and the projection isn't FnOnceOutput1800 // (which maybe_detailed_projection_msg handles via self_ty), point at the closure's1801 // return expression and label the closure declaration.1802 if closure_span.is_none()1803 && let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code()1804 && let Node::Expr(arg_expr) = self.tcx.hir_node(*arg_hir_id)1805 && let hir::ExprKind::Closure(closure) = arg_expr.kind1806 && closure.kind == hir::ClosureKind::Closure1807 {1808 let body = self.tcx.hir_body(closure.body);1809 let ret_span = match body.value.kind {1810 hir::ExprKind::Block(hir::Block { expr: Some(expr), .. }, _) => expr.span,1811 hir::ExprKind::Block(hir::Block { expr: None, stmts: [.., last], .. }, _) => {1812 last.span1813 }1814 _ => body.value.span,1815 };1816 if !closure.fn_decl_span.overlaps(ret_span) {1817 closure_span = Some(closure.fn_decl_span);1818 span = ret_span;1819 }1820 }18211822 let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}");1823 *diag.long_ty_path() = file;1824 let mut mention_bounds = true;1825 if let Some(span) = closure_span {1826 if let Some((_, _, expected_ty)) = values1827 && let Some(expected_ty) = expected_ty.as_type()1828 && let ty::Closure(def_id, _) = expected_ty.kind()1829 && self.tcx.def_span(*def_id).overlaps(span)1830 && let ObligationCauseCode::FunctionArg { parent_code, arg_hir_id, .. } =1831 obligation.cause.code()1832 && let ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _)1833 | ObligationCauseCode::WhereClause(def_id, span) = &**parent_code1834 {1835 // We have a trait bound for a closure to return itself, like1836 // `T: FnOnce() -> T`. This is nonsensical, but as far as the type system is1837 // concerned, valid. This is quite an edge case, but lets produce a reasonable1838 // diagnostic even in the face of an unreasonable user :)1839 let mut multispan: MultiSpan = (*span).into();1840 multispan.push_span_label(*span, "this requires the closure to return itself");1841 if let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) {1842 multispan1843 .push_span_label(arg.span, "this closure would have to return itself");1844 }1845 let in_the_item = match self.tcx.opt_item_name(*def_id) {1846 Some(name) => format!("in `{name}`"),1847 None => String::new(),1848 };1849 diag.span_note(1850 multispan,1851 format!(1852 "a bound {in_the_item} requires that a closure return itself, which is \1853 not possible",1854 ),1855 );1856 mention_bounds = false;1857 } else {1858 // Mark the closure decl so that it is seen even if we are pointing at the1859 // return type or expression.1860 //1861 // error[E0271]: expected `{closure@foo.rs:41:16}` to be a closure that returns1862 // `Unit3`, but it returns `Unit4`1863 // --> $DIR/foo.rs:43:171864 // |1865 // LL | let v = Unit2.m(1866 // | - required by a bound introduced by this call1867 // ...1868 // LL | f: |x| {1869 // | --- /* this span */1870 // LL | drop(x);1871 // LL | Unit41872 // | ^^^^^ expected `Unit3`, found `Unit4`1873 // |1874 diag.span_label(span, "this closure");1875 if !span.overlaps(obligation.cause.span) {1876 // Point at the binding corresponding to the closure where it is used.1877 diag.span_label(obligation.cause.span, "closure used here");1878 }1879 }1880 }18811882 let secondary_span = self.probe(|_| {1883 let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =1884 predicate.kind().skip_binder()1885 else {1886 return None;1887 };1888 if !proj.projection_term.kind.is_trait_projection() {1889 return None;1890 }18911892 let trait_ref = self.enter_forall_and_leak_universe(1893 predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)),1894 );1895 let Ok(Some(ImplSource::UserDefined(impl_data))) =1896 SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref))1897 else {1898 return None;1899 };19001901 let Ok(node) =1902 specialization_graph::assoc_def(self.tcx, impl_data.impl_def_id, proj.def_id())1903 else {1904 return None;1905 };19061907 if !node.is_final() {1908 return None;1909 }19101911 match self.tcx.hir_get_if_local(node.item.def_id) {1912 Some(1913 hir::Node::TraitItem(hir::TraitItem {1914 kind: hir::TraitItemKind::Type(_, Some(ty)),1915 ..1916 })1917 | hir::Node::ImplItem(hir::ImplItem {1918 kind: hir::ImplItemKind::Type(ty),1919 ..1920 }),1921 ) => Some((1922 ty.span,1923 with_forced_trimmed_paths!(Cow::from(format!(1924 "type mismatch resolving `{}`",1925 self.tcx.short_string(1926 self.deeply_resolve_ignoring_regions(predicate),1927 diag.long_ty_path()1928 ),1929 ))),1930 true,1931 )),1932 _ => None,1933 }1934 });19351936 self.note_type_err(1937 &mut diag,1938 &obligation.cause,1939 secondary_span,1940 values.map(|(_, normalized_ty, expected_ty)| {1941 obligation.param_env.and(infer::ValuePairs::Terms(ExpectedFound::new(1942 expected_ty,1943 normalized_ty,1944 )))1945 }),1946 err,1947 false,1948 Some(span),1949 );1950 if mention_bounds {1951 self.note_obligation_cause(&mut diag, obligation);1952 }1953 diag.emit_err()1954 })1955 }19561957 fn maybe_detailed_projection_msg(1958 &self,1959 mut span: Span,1960 projection_term: ty::AliasTerm<'tcx>,1961 normalized_ty: ty::Term<'tcx>,1962 expected_ty: ty::Term<'tcx>,1963 long_ty_path: &mut Option<PathBuf>,1964 ) -> Option<(String, Span, Option<Span>)> {1965 if !projection_term.kind.is_trait_projection() {1966 return None;1967 }19681969 let projection_def_id = projection_term.expect_projection_def_id();1970 let trait_def_id = projection_term.trait_def_id(self.tcx);1971 let self_ty = projection_term.self_ty();19721973 with_forced_trimmed_paths! {1974 if self.tcx.is_lang_item(projection_def_id, LangItem::FnOnceOutput) {1975 let (span, closure_span) = if let ty::Closure(def_id, _) = *self_ty.kind() {1976 let def_span = self.tcx.def_span(def_id);1977 if let Some(local_def_id) = def_id.as_local()1978 && let node = self.tcx.hir_node_by_def_id(local_def_id)1979 && let Some(fn_decl) = node.fn_decl()1980 && let Some(id) = node.body_id()1981 {1982 span = match fn_decl.output {1983 hir::FnRetTy::Return(ty) => ty.span,1984 hir::FnRetTy::DefaultReturn(_) => {1985 let body = self.tcx.hir_body(id);1986 match body.value.kind {1987 hir::ExprKind::Block(1988 hir::Block { expr: Some(expr), .. },1989 _,1990 ) => expr.span,1991 hir::ExprKind::Block(1992 hir::Block {1993 expr: None, stmts: [.., last], ..1994 },1995 _,1996 ) => last.span,1997 _ => body.value.span,1998 }1999 }2000 };
Findings
✓ No findings reported for this file.