Skip to content

Commit ba28ff7

Browse files
committed
Auto merge of #161031 - jhpratt:rollup-XTZ644V, r=jhpratt
Rollup of 8 pull requests Successful merges: - #159593 (merge ambiguity errors that blame the same inference variable) - #160687 (Experiment: Add `core::cmp::smallest` and `core::cmp::largest`) - #160856 (Replace infers and non-rigid aliases with `Ty/Const::Error` if param env normalization fails) - #160961 (bootstrap: Overhaul matching of command-line selectors to steps) - #160975 (Remove target argument from get_proc_macros) - #161023 (bootstrap: Replace the `exit!` macro with a function `helpers::exit_process`) - #160932 (Make tidy::Version public) - #161029 (mailmap: Update my default email)
2 parents 1e5ee35 + 5a3fcad commit ba28ff7

94 files changed

Lines changed: 1210 additions & 903 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.mailmap

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,8 +687,9 @@ Tomas Koutsky <tomas@stepnivlk.net>
687687
Tomasz Miąsko <tomasz.miasko@gmail.com>
688688
Torsten Weber <TorstenWeber12@gmail.com>
689689
Torsten Weber <TorstenWeber12@gmail.com> <torstenweber12@gmail.com>
690-
Trevor Gross <tmgross@umich.edu> <t.gross35@gmail.com>
691-
Trevor Gross <tmgross@umich.edu> <tgross@intrepidcs.com>
690+
Trevor Gross <tg@trevorgross.com> <t.gross35@gmail.com>
691+
Trevor Gross <tg@trevorgross.com> <tgross@intrepidcs.com>
692+
Trevor Gross <tg@trevorgross.com> <tmgross@umich.edu>
692693
Trevor Spiteri <tspiteri@ieee.org> <trevor.spiteri@um.edu.mt>
693694
Tshepang Mbambo <hopsi@tuta.io> <tshepang@gmail.com>
694695
Ty Overby <ty@pre-alpha.com>

compiler/rustc_metadata/src/locator.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -970,17 +970,19 @@ fn get_flavor_from_path(path: &Path) -> CrateFlavor {
970970
}
971971
}
972972

973-
/// A function to fetch about all macros inside a proc-macro crate.
973+
/// A function to fetch all macros inside a proc-macro crate.
974974
///
975975
/// Used by rust-analyzer-proc-macro-srv.
976976
pub fn get_proc_macros(
977-
target: &Target,
978977
path: &Path,
979978
metadata_loader: &dyn MetadataLoader,
980979
cfg_version: &'static str,
981980
) -> IoResult<Vec<(ProcMacroClient, ProcMacroKind)>> {
981+
let host_tuple = TargetTuple::from_tuple(config::host_tuple());
982+
let (host, _) = Target::search(&host_tuple, Path::new(""), false).unwrap();
983+
982984
let metadata =
983-
get_metadata_section(target, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None)
985+
get_metadata_section(&host, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None)
984986
.map_err(|err| io::Error::other(err.to_string()))?;
985987
let stable_crate_id = metadata.get_root().stable_crate_id();
986988

compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs

Lines changed: 149 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use tracing::{debug, instrument};
2020
use crate::error_reporting::TypeErrCtxt;
2121
use crate::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
2222
use crate::error_reporting::traits::{FindExprBySpan, to_pretty_impl_header};
23-
use crate::traits::ObligationCtxt;
2423
use crate::traits::query::evaluate_obligation::InferCtxtExt;
24+
use crate::traits::{FulfillmentError, ObligationCtxt};
2525

2626
#[derive(Debug)]
2727
pub enum CandidateSource {
@@ -174,10 +174,43 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
174174
}
175175

176176
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
177+
/// The term of an ambiguous obligation's predicate that gets blamed for the
178+
/// missing type annotation: the first one still containing inference variables.
179+
///
180+
/// Besides `maybe_report_ambiguity` pointing its diagnostics at this term,
181+
/// `report_fulfillment_errors` merges the ambiguity errors whose blamed terms
182+
/// share an inference variable into a single diagnostic.
183+
pub(super) fn ambiguity_term(&self, predicate: ty::Predicate<'tcx>) -> Option<ty::Term<'tcx>> {
184+
match predicate.kind().skip_binder() {
185+
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => data
186+
.trait_ref
187+
.args
188+
.iter()
189+
.filter_map(ty::GenericArg::as_term)
190+
.find(|term| term.has_non_region_infer()),
191+
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => data
192+
.projection_term
193+
.args
194+
.iter()
195+
.filter_map(ty::GenericArg::as_term)
196+
.chain([data.term])
197+
.find(|term| term.has_non_region_infer()),
198+
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => Some(term),
199+
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
200+
data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer())
201+
}
202+
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) => Some(ct.into()),
203+
ty::PredicateKind::Subtype(data) => Some(data.a.into()),
204+
ty::PredicateKind::NormalizesTo(data) if data.term.is_infer() => Some(data.term),
205+
_ => None,
206+
}
207+
}
208+
177209
#[instrument(skip(self), level = "debug")]
178210
pub(super) fn maybe_report_ambiguity(
179211
&self,
180212
obligation: &PredicateObligation<'tcx>,
213+
related: &[&FulfillmentError<'tcx>],
181214
) -> ErrorGuaranteed {
182215
// Unable to successfully determine, probably means
183216
// insufficient type information, but could mean
@@ -255,12 +288,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
255288
// Pick the first generic parameter that still contains inference variables as the one
256289
// we're going to emit an error for. If there are none (see above), fall back to
257290
// a more general error.
258-
let term = data
259-
.trait_ref
260-
.args
261-
.iter()
262-
.filter_map(ty::GenericArg::as_term)
263-
.find(|s| s.has_non_region_infer());
291+
let term = self.ambiguity_term(predicate);
264292

265293
let mut err = if let Some(term) = term {
266294
let candidates: Vec<_> = self
@@ -306,34 +334,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
306334
.with_long_ty_path(long_ty_path)
307335
};
308336

309-
let mut ambiguities = compute_applicable_impls_for_diagnostics(
310-
self.infcx,
311-
&obligation.with(self.tcx, trait_pred),
312-
false,
313-
);
314-
let has_non_region_infer = trait_pred
315-
.skip_binder()
316-
.trait_ref
317-
.args
318-
.types()
319-
.any(|t| !t.is_ty_or_numeric_infer());
320-
// It doesn't make sense to talk about applicable impls if there are more than a
321-
// handful of them. If there are a lot of them, but only a few of them have no type
322-
// params, we only show those, as they are more likely to be useful/intended.
323-
if ambiguities.len() > 5 {
324-
let infcx = self.infcx;
325-
if !ambiguities.iter().all(|option| match option {
326-
CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
327-
CandidateSource::ParamEnv(_) => true,
328-
}) {
329-
// If not all are blanket impls, we filter blanked impls out.
330-
ambiguities.retain(|option| match option {
331-
CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
332-
CandidateSource::ParamEnv(_) => true,
333-
});
334-
}
335-
}
336-
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
337+
if let Some(ambiguities) = self.applicable_impls_to_mention(obligation, trait_pred)
338+
{
337339
if let Some(e) = self.tainted_by_errors()
338340
&& term.is_none()
339341
{
@@ -590,13 +592,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
590592
// other `Foo` impls are incoherent.
591593
return guar;
592594
}
593-
let term = data
594-
.projection_term
595-
.args
596-
.iter()
597-
.filter_map(ty::GenericArg::as_term)
598-
.chain([data.term])
599-
.find(|g| g.has_non_region_infer());
595+
let term = self.ambiguity_term(predicate);
600596
let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
601597
if let Some(term) = term {
602598
self.emit_inference_failure_err(
@@ -621,16 +617,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
621617
}
622618
}
623619

624-
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
620+
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(_)) => {
625621
if let Err(e) = predicate.error_reported() {
626622
return e;
627623
}
628624
if let Some(e) = self.tainted_by_errors() {
629625
return e;
630626
}
631-
let term =
632-
data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
633-
if let Some(term) = term {
627+
if let Some(term) = self.ambiguity_term(predicate) {
634628
self.emit_inference_failure_err(
635629
obligation.cause.body_def_id,
636630
span,
@@ -713,10 +707,119 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
713707
.with_long_ty_path(long_ty_path)
714708
}
715709
};
710+
711+
// The related obligations are ambiguous because of the same inference variable,
712+
// so they belong to this diagnostic: annotating the variable has to satisfy all
713+
// of them at once. Mention their requirements, except for bookkeeping predicates
714+
// (`WellFormed`, sizedness, ...) whose mention wouldn't be actionable.
715+
let mut mentioned = vec![predicate];
716+
let mut mentioned_strs: Vec<String> = vec![];
717+
for &error in related {
718+
let related_pred = self.resolve_vars_if_possible(error.obligation.predicate);
719+
if mentioned.contains(&related_pred) {
720+
continue;
721+
}
722+
let note = match related_pred.kind().skip_binder() {
723+
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data))
724+
if !matches!(
725+
self.tcx.as_lang_item(data.def_id()),
726+
Some(LangItem::Sized | LangItem::MetaSized | LangItem::PointeeSized)
727+
) =>
728+
{
729+
let clause = related_pred.kind().rebind(data);
730+
if let ty::Infer(_) = clause.self_ty().skip_binder().kind() {
731+
let tr = self.tcx.short_string(
732+
clause.print_modifiers_and_trait_path(),
733+
&mut err.long_ty_path(),
734+
);
735+
format!("the type must also implement `{tr}`")
736+
} else {
737+
let pred = self.tcx.short_string(related_pred, &mut err.long_ty_path());
738+
let note = format!("cannot satisfy `{pred}`");
739+
// The self type is known, so the `impl`s that could have applied to it are
740+
// few and worth pointing at, like the blamed bound does. When it is still
741+
// an inference variable the list is every `impl` of the trait, which is
742+
// why the branch above only names the trait.
743+
//
744+
// `tainted_by_errors` is checked because `annotate_source_of_ambiguity`
745+
// downgrades the whole diagnostic once an error was already emitted.
746+
if !mentioned_strs.contains(&note)
747+
&& self.tainted_by_errors().is_none()
748+
&& let Some(ambiguities) =
749+
self.applicable_impls_to_mention(&error.obligation, clause)
750+
{
751+
self.annotate_source_of_ambiguity(&mut err, &ambiguities, related_pred);
752+
mentioned_strs.push(note);
753+
mentioned.push(related_pred);
754+
continue;
755+
}
756+
note
757+
}
758+
}
759+
ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
760+
let pred = self.tcx.short_string(related_pred, &mut err.long_ty_path());
761+
format!("cannot satisfy `{pred}`")
762+
}
763+
_ => {
764+
mentioned.push(related_pred);
765+
continue;
766+
}
767+
};
768+
// Two predicates can print identically (e.g. `From<?0>` and `From<?1>` both show as
769+
// `From<_>`); only emit each unique note string once.
770+
if !mentioned_strs.contains(&note) {
771+
err.note(note.clone());
772+
mentioned_strs.push(note);
773+
}
774+
mentioned.push(related_pred);
775+
}
776+
716777
self.note_obligation_cause(&mut err, obligation);
778+
// The merged errors are not reported on their own anymore, so the bounds they came from
779+
// have to be explained here too. Causes shared with the blamed obligation are already
780+
// described by the call above.
781+
for &error in related {
782+
if error.obligation.cause.code() != obligation.cause.code() {
783+
self.note_obligation_cause(&mut err, &error.obligation);
784+
}
785+
}
717786
err.emit()
718787
}
719788

789+
/// The `impl`s and `where` clauses that could have satisfied `trait_pred`, when listing them
790+
/// is likely to help. `None` means the caller should describe the bound some other way.
791+
fn applicable_impls_to_mention(
792+
&self,
793+
obligation: &PredicateObligation<'tcx>,
794+
trait_pred: ty::PolyTraitPredicate<'tcx>,
795+
) -> Option<Vec<CandidateSource>> {
796+
let mut ambiguities = compute_applicable_impls_for_diagnostics(
797+
self.infcx,
798+
&obligation.with(self.tcx, trait_pred),
799+
false,
800+
);
801+
let has_non_region_infer =
802+
trait_pred.skip_binder().trait_ref.args.types().any(|t| !t.is_ty_or_numeric_infer());
803+
// It doesn't make sense to talk about applicable impls if there are more than a
804+
// handful of them. If there are a lot of them, but only a few of them have no type
805+
// params, we only show those, as they are more likely to be useful/intended.
806+
if ambiguities.len() > 5 {
807+
let infcx = self.infcx;
808+
if !ambiguities.iter().all(|option| match option {
809+
CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
810+
CandidateSource::ParamEnv(_) => true,
811+
}) {
812+
// If not all are blanket impls, we filter blanked impls out.
813+
ambiguities.retain(|option| match option {
814+
CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
815+
CandidateSource::ParamEnv(_) => true,
816+
});
817+
}
818+
}
819+
(ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer)
820+
.then_some(ambiguities)
821+
}
822+
720823
fn annotate_source_of_ambiguity(
721824
&self,
722825
err: &mut Diag<'_>,

0 commit comments

Comments
 (0)