Skip to content

Commit b5ffbd3

Browse files
authored
Rollup merge of rust-lang#101424 - compiler-errors:operator-err-sugg, r=TaKO8Ki
Adjust and slightly generalize operator error suggestion (in no particular order) * Stop passing around a whole extra `ProjectionPredicate` * Add spaces around `=` in `Trait<..., Output = Ty>` suggestion * Some code clean-ups, including * add `lang_item_for_op` to turn a `Op` into a `DefId` * avoid `SourceMap` because we don't really need to render an expr * Remove `TypeParamVisitor` in favor of just checking `ty.has_param_types_or_consts` -- this acts a bit differently, but shouldn't cause erroneous suggestions (actually might generalize them a bit) * We now suggest `Output = Ty` in the `where` clause suggestion when we fail to add `Struct<T>` and `T`. I can split this out into more PRs if needed, but they're all just miscellaneous generalizations, changes, and nitpicks I saw when messing with this operator code.
2 parents 1561922 + 48281b0 commit b5ffbd3

File tree

16 files changed

+234
-254
lines changed

16 files changed

+234
-254
lines changed

Diff for: compiler/rustc_middle/src/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub mod util;
1212
use crate::infer::canonical::Canonical;
1313
use crate::ty::abstract_const::NotConstEvaluatable;
1414
use crate::ty::subst::SubstsRef;
15-
use crate::ty::{self, AdtKind, Predicate, Ty, TyCtxt};
15+
use crate::ty::{self, AdtKind, Ty, TyCtxt};
1616

1717
use rustc_data_structures::sync::Lrc;
1818
use rustc_errors::{Applicability, Diagnostic};
@@ -416,7 +416,7 @@ pub enum ObligationCauseCode<'tcx> {
416416
BinOp {
417417
rhs_span: Option<Span>,
418418
is_lit: bool,
419-
output_pred: Option<Predicate<'tcx>>,
419+
output_ty: Option<Ty<'tcx>>,
420420
},
421421
}
422422

Diff for: compiler/rustc_middle/src/ty/diagnostics.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,25 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
102102
generics: &hir::Generics<'_>,
103103
err: &mut Diagnostic,
104104
trait_pred: PolyTraitPredicate<'tcx>,
105+
associated_ty: Option<(&'static str, Ty<'tcx>)>,
105106
) -> bool {
106107
if !trait_pred.is_suggestable(tcx, false) {
107108
return false;
108109
}
109110

110111
let param_name = trait_pred.skip_binder().self_ty().to_string();
111-
let constraint = trait_pred.print_modifiers_and_trait_path().to_string();
112+
let mut constraint = trait_pred.print_modifiers_and_trait_path().to_string();
113+
114+
if let Some((name, term)) = associated_ty {
115+
// FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
116+
// That should be extracted into a helper function.
117+
if constraint.ends_with('>') {
118+
constraint = format!("{}, {} = {}>", &constraint[..constraint.len() - 1], name, term);
119+
} else {
120+
constraint.push_str(&format!("<{} = {}>", name, term));
121+
}
122+
}
123+
112124
let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
113125

114126
// Skip, there is a param named Self

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ use rustc_middle::hir::map;
2525
use rustc_middle::ty::{
2626
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
2727
GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable,
28-
ProjectionPredicate, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
29-
TypeVisitable,
28+
ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
3029
};
3130
use rustc_middle::ty::{TypeAndMut, TypeckResults};
3231
use rustc_session::Limit;
@@ -174,7 +173,7 @@ pub trait InferCtxtExt<'tcx> {
174173
&self,
175174
err: &mut Diagnostic,
176175
trait_pred: ty::PolyTraitPredicate<'tcx>,
177-
proj_pred: Option<ty::PolyProjectionPredicate<'tcx>>,
176+
associated_item: Option<(&'static str, Ty<'tcx>)>,
178177
body_id: hir::HirId,
179178
);
180179

@@ -467,7 +466,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
467466
&self,
468467
mut err: &mut Diagnostic,
469468
trait_pred: ty::PolyTraitPredicate<'tcx>,
470-
proj_pred: Option<ty::PolyProjectionPredicate<'tcx>>,
469+
associated_ty: Option<(&'static str, Ty<'tcx>)>,
471470
body_id: hir::HirId,
472471
) {
473472
let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
@@ -604,21 +603,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
604603
trait_pred.print_modifiers_and_trait_path().to_string()
605604
);
606605

607-
if let Some(proj_pred) = proj_pred {
608-
let ProjectionPredicate { projection_ty, term } = proj_pred.skip_binder();
609-
let item = self.tcx.associated_item(projection_ty.item_def_id);
610-
606+
if let Some((name, term)) = associated_ty {
611607
// FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
612608
// That should be extracted into a helper function.
613609
if constraint.ends_with('>') {
614610
constraint = format!(
615-
"{}, {}={}>",
611+
"{}, {} = {}>",
616612
&constraint[..constraint.len() - 1],
617-
item.name,
613+
name,
618614
term
619615
);
620616
} else {
621-
constraint.push_str(&format!("<{}={}>", item.name, term));
617+
constraint.push_str(&format!("<{} = {}>", name, term));
622618
}
623619
}
624620

@@ -648,7 +644,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
648644
..
649645
}) if !param_ty => {
650646
// Missing generic type parameter bound.
651-
if suggest_arbitrary_trait_bound(self.tcx, generics, &mut err, trait_pred) {
647+
if suggest_arbitrary_trait_bound(
648+
self.tcx,
649+
generics,
650+
&mut err,
651+
trait_pred,
652+
associated_ty,
653+
) {
652654
return;
653655
}
654656
}

Diff for: compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409409
rhs_span: opt_input_expr.map(|expr| expr.span),
410410
is_lit: opt_input_expr
411411
.map_or(false, |expr| matches!(expr.kind, ExprKind::Lit(_))),
412-
output_pred: None,
412+
output_ty: None,
413413
},
414414
),
415415
self.param_env,

Diff for: compiler/rustc_typeck/src/check/method/mod.rs

+4-22
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ use rustc_hir::def_id::DefId;
2020
use rustc_infer::infer::{self, InferOk};
2121
use rustc_middle::ty::subst::Subst;
2222
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
23-
use rustc_middle::ty::{
24-
self, AssocKind, DefIdTree, GenericParamDefKind, ProjectionPredicate, ProjectionTy,
25-
ToPredicate, Ty, TypeVisitable,
26-
};
23+
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable};
2724
use rustc_span::symbol::Ident;
2825
use rustc_span::Span;
2926
use rustc_trait_selection::traits;
@@ -337,22 +334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
337334

338335
// Construct an obligation
339336
let poly_trait_ref = ty::Binder::dummy(trait_ref);
340-
let opt_output_ty =
341-
expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty));
342-
let opt_output_assoc_item = self.tcx.associated_items(trait_def_id).find_by_name_and_kind(
343-
self.tcx,
344-
Ident::from_str("Output"),
345-
AssocKind::Type,
346-
trait_def_id,
347-
);
348-
let output_pred =
349-
opt_output_ty.zip(opt_output_assoc_item).map(|(output_ty, output_assoc_item)| {
350-
ty::Binder::dummy(ty::PredicateKind::Projection(ProjectionPredicate {
351-
projection_ty: ProjectionTy { substs, item_def_id: output_assoc_item.def_id },
352-
term: output_ty.into(),
353-
}))
354-
.to_predicate(self.tcx)
355-
});
337+
let output_ty = expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty));
356338

357339
(
358340
traits::Obligation::new(
@@ -363,7 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
363345
rhs_span: opt_input_expr.map(|expr| expr.span),
364346
is_lit: opt_input_expr
365347
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
366-
output_pred,
348+
output_ty,
367349
},
368350
),
369351
self.param_env,
@@ -518,7 +500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
518500
rhs_span: opt_input_expr.map(|expr| expr.span),
519501
is_lit: opt_input_expr
520502
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
521-
output_pred: None,
503+
output_ty: None,
522504
},
523505
)
524506
} else {

0 commit comments

Comments
 (0)