diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src')
11 files changed, 164 insertions, 149 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 1db05ced8d2..022d549a9df 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -1303,7 +1303,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { && let Some(args) = self.node_args_opt(expr.hir_id) && args.iter().any(|arg| self.generic_arg_contains_target(arg)) && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) - && self.tecx.tcx.trait_of_item(def_id).is_some() + && self.tecx.tcx.trait_of_assoc(def_id).is_some() && !has_impl_trait(def_id) // FIXME(fn_delegation): In delegation item argument spans are equal to last path // segment. This leads to ICE's when emitting `multipart_suggestion`. diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 772a7f01332..2a3268d3339 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -104,10 +104,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ty::AssocKind::Fn { .. } => { if let Some(hir_id) = assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id)) + && let Some(decl) = self.tcx().hir_fn_decl_by_hir_id(hir_id) { - if let Some(decl) = self.tcx().hir_fn_decl_by_hir_id(hir_id) { - visitor.visit_fn_decl(decl); - } + visitor.visit_fn_decl(decl); } } _ => {} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index c0daf08ce07..44baa213b28 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -91,51 +91,51 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) { // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with // some modifications due to that being in typeck and this being in infer. - if let ObligationCauseCode::Pattern { .. } = cause.code() { - if let ty::Adt(expected_adt, args) = exp_found.expected.kind() { - let compatible_variants: Vec<_> = expected_adt - .variants() - .iter() - .filter(|variant| { - variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn) - }) - .filter_map(|variant| { - let sole_field = &variant.single_field(); - let sole_field_ty = sole_field.ty(self.tcx, args); - if self.same_type_modulo_infer(sole_field_ty, exp_found.found) { - let variant_path = - with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id)); - // FIXME #56861: DRYer prelude filtering - if let Some(path) = variant_path.strip_prefix("std::prelude::") { - if let Some((_, path)) = path.split_once("::") { - return Some(path.to_string()); - } - } - Some(variant_path) - } else { - None + if let ObligationCauseCode::Pattern { .. } = cause.code() + && let ty::Adt(expected_adt, args) = exp_found.expected.kind() + { + let compatible_variants: Vec<_> = expected_adt + .variants() + .iter() + .filter(|variant| { + variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn) + }) + .filter_map(|variant| { + let sole_field = &variant.single_field(); + let sole_field_ty = sole_field.ty(self.tcx, args); + if self.same_type_modulo_infer(sole_field_ty, exp_found.found) { + let variant_path = + with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id)); + // FIXME #56861: DRYer prelude filtering + if let Some(path) = variant_path.strip_prefix("std::prelude::") + && let Some((_, path)) = path.split_once("::") + { + return Some(path.to_string()); } - }) - .collect(); - match &compatible_variants[..] { - [] => {} - [variant] => { - let sugg = SuggestTuplePatternOne { - variant: variant.to_owned(), - span_low: cause.span.shrink_to_lo(), - span_high: cause.span.shrink_to_hi(), - }; - diag.subdiagnostic(sugg); - } - _ => { - // More than one matching variant. - let sugg = SuggestTuplePatternMany { - path: self.tcx.def_path_str(expected_adt.did()), - cause_span: cause.span, - compatible_variants, - }; - diag.subdiagnostic(sugg); + Some(variant_path) + } else { + None } + }) + .collect(); + match &compatible_variants[..] { + [] => {} + [variant] => { + let sugg = SuggestTuplePatternOne { + variant: variant.to_owned(), + span_low: cause.span.shrink_to_lo(), + span_high: cause.span.shrink_to_hi(), + }; + diag.subdiagnostic(sugg); + } + _ => { + // More than one matching variant. + let sugg = SuggestTuplePatternMany { + path: self.tcx.def_path_str(expected_adt.did()), + cause_span: cause.span, + compatible_variants, + }; + diag.subdiagnostic(sugg); } } } @@ -288,19 +288,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .filter(|field| field.vis.is_accessible_from(field.did, self.tcx)) .map(|field| (field.name, field.ty(self.tcx, expected_args))) .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found)) + && let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - let suggestion = if expected_def.is_struct() { - SuggestAccessingField::Safe { span, snippet, name, ty } - } else if expected_def.is_union() { - SuggestAccessingField::Unsafe { span, snippet, name, ty } - } else { - return; - }; - diag.subdiagnostic(suggestion); - } - } + let suggestion = if expected_def.is_struct() { + SuggestAccessingField::Safe { span, snippet, name, ty } + } else if expected_def.is_union() { + SuggestAccessingField::Unsafe { span, snippet, name, ty } + } else { + return; + }; + diag.subdiagnostic(suggestion); } } } @@ -540,38 +538,35 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) -> Option<SuggestAsRefKind> { if let (ty::Adt(exp_def, exp_args), ty::Ref(_, found_ty, _)) = (expected.kind(), found.kind()) + && let ty::Adt(found_def, found_args) = *found_ty.kind() { - if let ty::Adt(found_def, found_args) = *found_ty.kind() { - if exp_def == &found_def { - let have_as_ref = &[ - (sym::Option, SuggestAsRefKind::Option), - (sym::Result, SuggestAsRefKind::Result), - ]; - if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| { - self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg) - }) { - let mut show_suggestion = true; - for (exp_ty, found_ty) in - std::iter::zip(exp_args.types(), found_args.types()) - { - match *exp_ty.kind() { - ty::Ref(_, exp_ty, _) => { - match (exp_ty.kind(), found_ty.kind()) { - (_, ty::Param(_)) - | (_, ty::Infer(_)) - | (ty::Param(_), _) - | (ty::Infer(_), _) => {} - _ if self.same_type_modulo_infer(exp_ty, found_ty) => {} - _ => show_suggestion = false, - }; - } - ty::Param(_) | ty::Infer(_) => {} - _ => show_suggestion = false, + if exp_def == &found_def { + let have_as_ref = &[ + (sym::Option, SuggestAsRefKind::Option), + (sym::Result, SuggestAsRefKind::Result), + ]; + if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| { + self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg) + }) { + let mut show_suggestion = true; + for (exp_ty, found_ty) in std::iter::zip(exp_args.types(), found_args.types()) { + match *exp_ty.kind() { + ty::Ref(_, exp_ty, _) => { + match (exp_ty.kind(), found_ty.kind()) { + (_, ty::Param(_)) + | (_, ty::Infer(_)) + | (ty::Param(_), _) + | (ty::Infer(_), _) => {} + _ if self.same_type_modulo_infer(exp_ty, found_ty) => {} + _ => show_suggestion = false, + }; } + ty::Param(_) | ty::Infer(_) => {} + _ => show_suggestion = false, } - if show_suggestion { - return Some(*msg); - } + } + if show_suggestion { + return Some(*msg); } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 98f67257fd1..cdf1402252a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -360,7 +360,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }, ] = path.segments && data.trait_ref.def_id == *trait_id - && self.tcx.trait_of_item(*item_id) == Some(*trait_id) + && self.tcx.trait_of_assoc(*item_id) == Some(*trait_id) && let None = self.tainted_by_errors() { let assoc_item = self.tcx.associated_item(item_id); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 2344bc79f21..5765dfd891d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -381,15 +381,15 @@ impl IgnoredDiagnosticOption { old: Option<Span>, option_name: &'static str, ) { - if let (Some(new_item), Some(old_item)) = (new, old) { - if let Some(item_def_id) = item_def_id.as_local() { - tcx.emit_node_span_lint( - MALFORMED_DIAGNOSTIC_ATTRIBUTES, - tcx.local_def_id_to_hir_id(item_def_id), - new_item, - IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name }, - ); - } + if let (Some(new_item), Some(old_item)) = (new, old) + && let Some(item_def_id) = item_def_id.as_local() + { + tcx.emit_node_span_lint( + MALFORMED_DIAGNOSTIC_ATTRIBUTES, + tcx.local_def_id_to_hir_id(item_def_id), + new_item, + IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name }, + ); } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index bf7d4257b62..c182fd99b17 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -987,7 +987,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { else { return false; }; - if self.tcx.trait_of_item(did) != Some(clone_trait) { + if self.tcx.trait_of_assoc(did) != Some(clone_trait) { return false; } Some(ident.span) @@ -2213,26 +2213,26 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span: Span, trait_ref: DefId, ) { - if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) { - if let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind { - err.note(format!( - "{}s cannot be accessed directly on a `trait`, they can only be \ + if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) + && let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind + { + err.note(format!( + "{}s cannot be accessed directly on a `trait`, they can only be \ accessed through a specific `impl`", - self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id) - )); + self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id) + )); - if !assoc_item.is_impl_trait_in_trait() { - err.span_suggestion_verbose( - span, - "use the fully qualified path to an implementation", - format!( - "<Type as {}>::{}", - self.tcx.def_path_str(trait_ref), - assoc_item.name() - ), - Applicability::HasPlaceholders, - ); - } + if !assoc_item.is_impl_trait_in_trait() { + err.span_suggestion_verbose( + span, + "use the fully qualified path to an implementation", + format!( + "<Type as {}>::{}", + self.tcx.def_path_str(trait_ref), + assoc_item.name() + ), + Applicability::HasPlaceholders, + ); } } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 3ce0f025512..01bdae7435d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -197,6 +197,12 @@ where delegate.compute_goal_fast_path(goal, obligation.cause.span) { match certainty { + // This fast path doesn't depend on region identity so it doesn't + // matter if the goal contains inference variables or not, so we + // don't need to call `push_hir_typeck_potentially_region_dependent_goal` + // here. + // + // Only goals proven via the trait solver should be region dependent. Certainty::Yes => {} Certainty::Maybe(_) => { self.obligations.register(obligation, None); @@ -207,7 +213,7 @@ where let result = delegate.evaluate_root_goal(goal, obligation.cause.span, stalled_on); self.inspect_evaluated_obligation(infcx, &obligation, &result); - let GoalEvaluation { certainty, has_changed, stalled_on } = match result { + let GoalEvaluation { goal, certainty, has_changed, stalled_on } = match result { Ok(result) => result, Err(NoSolution) => { errors.push(E::from_solver_error( @@ -218,6 +224,10 @@ where } }; + // We've resolved the goal in `evaluate_root_goal`, avoid redoing this work + // in the next iteration. This does not resolve the inference variables + // constrained by evaluating the goal. + obligation.predicate = goal.predicate; if has_changed == HasChanged::Yes { // We increment the recursion depth here to track the number of times // this goal has resulted in inference progress. This doesn't precisely @@ -230,7 +240,22 @@ where } match certainty { - Certainty::Yes => {} + Certainty::Yes => { + // Goals may depend on structural identity. Region uniquification at the + // start of MIR borrowck may cause things to no longer be so, potentially + // causing an ICE. + // + // While we uniquify root goals in HIR this does not handle cases where + // regions are hidden inside of a type or const inference variable. + // + // FIXME(-Znext-solver): This does not handle inference variables hidden + // inside of an opaque type, e.g. if there's `Opaque = (?x, ?x)` in the + // storage, we can also rely on structural identity of `?x` even if we + // later uniquify it in MIR borrowck. + if infcx.in_hir_typeck && obligation.has_non_region_infer() { + infcx.push_hir_typeck_potentially_region_dependent_goal(obligation); + } + } Certainty::Maybe(_) => self.obligations.register(obligation, stalled_on), } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f50f01a285b..07e78da37b3 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -695,15 +695,14 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { source: CandidateSource::Impl(def_id), result: Ok(_), } = cand.kind() + && let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id) { - if let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id) { - let message = infcx - .tcx - .get_attr(def_id, sym::rustc_reservation_impl) - .and_then(|a| a.value_str()); - if let Some(message) = message { - self.causes.insert(IntercrateAmbiguityCause::ReservationImpl { message }); - } + let message = infcx + .tcx + .get_attr(def_id, sym::rustc_reservation_impl) + .and_then(|a| a.value_str()); + if let Some(message) = message { + self.causes.insert(IntercrateAmbiguityCause::ReservationImpl { message }); } } } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 91c41544f78..9b5e59ce0fd 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -759,7 +759,7 @@ fn instantiate_and_check_impossible_predicates<'tcx>( // Specifically check trait fulfillment to avoid an error when trying to resolve // associated items. - if let Some(trait_def_id) = tcx.trait_of_item(key.0) { + if let Some(trait_def_id) = tcx.trait_of_assoc(key.0) { let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, key.1); predicates.push(trait_ref.upcast(tcx)); } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 28b5b7cf391..581191b2036 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1507,7 +1507,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); let item_def_id = obligation.predicate.def_id; - let trait_def_id = tcx.trait_of_item(item_def_id).unwrap(); + let trait_def_id = tcx.trait_of_assoc(item_def_id).unwrap(); let args = tcx.mk_args(&[self_ty.into()]); let (term, obligations) = if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) { let discriminant_def_id = diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f90316f520b..d7c3543cb3f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -781,16 +781,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self, &project_obligation, ) - { - if let Some(cached_res) = self + && let Some(cached_res) = self .infcx .inner .borrow_mut() .projection_cache() .is_complete(key) - { - break 'compute_res Ok(cached_res); - } + { + break 'compute_res Ok(cached_res); } // Need to explicitly set the depth of nested goals here as @@ -1436,24 +1434,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { let tcx = self.tcx(); // Treat reservation impls as ambiguity. - if let ImplCandidate(def_id) = candidate { - if let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) { - if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes { - let message = tcx - .get_attr(def_id, sym::rustc_reservation_impl) - .and_then(|a| a.value_str()); - if let Some(message) = message { - debug!( - "filter_reservation_impls: \ + if let ImplCandidate(def_id) = candidate + && let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) + { + if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes { + let message = + tcx.get_attr(def_id, sym::rustc_reservation_impl).and_then(|a| a.value_str()); + if let Some(message) = message { + debug!( + "filter_reservation_impls: \ reservation impl ambiguity on {:?}", - def_id - ); - intercrate_ambiguity_clauses - .insert(IntercrateAmbiguityCause::ReservationImpl { message }); - } + def_id + ); + intercrate_ambiguity_clauses + .insert(IntercrateAmbiguityCause::ReservationImpl { message }); } - return Ok(None); } + return Ok(None); } Ok(Some(candidate)) } |
