Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 9 pull requests #105721

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bc92321
Suggest constraining type parameter with `Clone`
estebank Dec 14, 2022
0fb8d84
Suggest `#[derive(Clone)]`
estebank Dec 14, 2022
687b4d9
Add regression test for #104678
JohnTitor Dec 14, 2022
5f5ae17
Consider discriminant fields that are ordered before variant fields
compiler-errors Dec 12, 2022
bdc3c4b
Make print_type_sizes test not use feature(start)
compiler-errors Dec 12, 2022
10368c6
Point at method chains on `E0271` errors
estebank Dec 13, 2022
36b60e7
Use `with_forced_trimmed_paths` more
estebank Dec 13, 2022
50e269f
Shorten trimmed display of closures
estebank Dec 14, 2022
e9ef36a
Trim paths in E0599
estebank Dec 14, 2022
7f8fdf4
Consider lifetimes when comparing assoc types in method chain
estebank Dec 14, 2022
ae60015
Use impl's def id when calculating type to specify UFCS
compiler-errors Nov 12, 2022
1225a65
drive-by: Fix path spans
compiler-errors Nov 12, 2022
7bf36de
Make report_projection_error more term agnostic
compiler-errors Dec 12, 2022
cfa6a93
Auto traits in dyn are suggestable
compiler-errors Dec 12, 2022
34d194d
Highlight conflicting param-env candidates, again
compiler-errors Nov 15, 2022
d10f6b4
Add test
compiler-errors Dec 5, 2022
c99f1b7
Run `x test tidy` sooner in mingw-check
jyn514 Dec 14, 2022
fc6d59d
Make `RUN_CHECK_WITH_PARALLEL_QUERIES` the last thing to run
jyn514 Dec 14, 2022
0277c72
Rollup merge of #104334 - compiler-errors:ufcs-sugg-wrong-def-id, r=e…
matthiaskrgr Dec 14, 2022
52d6fbc
Rollup merge of #105285 - compiler-errors:conflicting-param-env-2, r=…
matthiaskrgr Dec 14, 2022
d9e36a4
Rollup merge of #105623 - compiler-errors:generator-type-size-fix, r=…
matthiaskrgr Dec 14, 2022
68badbd
Rollup merge of #105627 - compiler-errors:dyn-auto-suggestable, r=dav…
matthiaskrgr Dec 14, 2022
d2b716d
Rollup merge of #105633 - compiler-errors:term-agnostic, r=oli-obk
matthiaskrgr Dec 14, 2022
2a5d257
Rollup merge of #105674 - estebank:iterator-chains, r=oli-obk
matthiaskrgr Dec 14, 2022
1fcd973
Rollup merge of #105679 - estebank:suggest-clone, r=compiler-errors
matthiaskrgr Dec 14, 2022
e657bbc
Rollup merge of #105692 - JohnTitor:issue-104678, r=compiler-errors
matthiaskrgr Dec 14, 2022
98b80fc
Rollup merge of #105714 - jyn514:tidy-first, r=Mark-Simulacrum
matthiaskrgr Dec 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer;
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
use rustc_middle::ty::{
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::symbol::sym;
use rustc_span::Span;
Expand Down Expand Up @@ -1276,17 +1278,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
// Check that we're in fact trying to clone into the expected type
&& self.can_coerce(*pointee_ty, expected_ty)
&& let predicate = ty::Binder::dummy(ty::TraitRef {
def_id: clone_trait_did,
substs: self.tcx.mk_substs([expected_ty.into()].iter()),
})
.without_const()
.to_predicate(self.tcx)
// And the expected type doesn't implement `Clone`
&& !self.predicate_must_hold_considering_regions(&traits::Obligation {
cause: traits::ObligationCause::dummy(),
param_env: self.param_env,
recursion_depth: 0,
predicate: ty::Binder::dummy(ty::TraitRef {
def_id: clone_trait_did,
substs: self.tcx.mk_substs([expected_ty.into()].iter()),
})
.without_const()
.to_predicate(self.tcx),
predicate,
})
{
diag.span_note(
Expand All @@ -1295,6 +1298,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead"
),
);
let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id);
if let ty::Param(param) = expected_ty.kind()
&& let Some(generics) = self.tcx.hir().get_generics(owner)
{
suggest_constraining_type_params(
self.tcx,
generics,
diag,
vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
);
} else {
self.suggest_derive(diag, &[(predicate, None, None)]);
}
}
}

Expand Down
24 changes: 17 additions & 7 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::print::with_crate_prefix;
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
use rustc_span::symbol::{kw, sym, Ident};
Expand Down Expand Up @@ -270,7 +270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;

let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
let ty_str = self.ty_to_string(rcvr_ty);
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
let is_method = mode == Mode::MethodCall;
let item_kind = if is_method {
"method"
Expand Down Expand Up @@ -565,7 +565,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let term = pred.skip_binder().term;

let obligation = format!("{} = {}", projection_ty, term);
let quiet = format!("{} = {}", quiet_projection_ty, term);
let quiet = with_forced_trimmed_paths!(format!(
"{} = {}",
quiet_projection_ty, term
));

bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
Some((obligation, projection_ty.self_ty()))
Expand All @@ -575,7 +578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let self_ty = p.self_ty();
let path = p.print_only_trait_path();
let obligation = format!("{}: {}", self_ty, path);
let quiet = format!("_: {}", path);
let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
bound_span_label(self_ty, &obligation, &quiet);
Some((obligation, self_ty))
}
Expand Down Expand Up @@ -798,7 +801,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(None, None)
};
let primary_message = primary_message.unwrap_or_else(|| format!(
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
but its trait bounds were not satisfied"
));
err.set_primary_message(&primary_message);
if let Some(label) = label {
Expand Down Expand Up @@ -895,7 +899,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
} else {
err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
err.span_label(
span,
format!(
"{item_kind} cannot be called on `{ty_str}` due to unsatisfied \
trait bounds",
),
);
}
};

Expand Down Expand Up @@ -1843,7 +1853,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.suggest_derive(err, &preds);
}

fn suggest_derive(
pub fn suggest_derive(
&self,
err: &mut Diagnostic,
unsatisfied_predicates: &[(
Expand Down
15 changes: 2 additions & 13 deletions compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use std::ops::ControlFlow;

use crate::ty::{
visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst,
InferTy, Opaque, PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
};

use rustc_data_structures::fx::FxHashMap;
Expand Down Expand Up @@ -469,17 +469,6 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
}
}

Dynamic(dty, _, _) => {
for pred in *dty {
match pred.skip_binder() {
ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {
// Okay
}
_ => return ControlFlow::Break(()),
}
}
}

Param(param) => {
// FIXME: It would be nice to make this not use string manipulation,
// but it's pretty hard to do this, since `ty::ParamTy` is missing
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rustc_session::config::TrimmedDefPaths;
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
use rustc_session::Limit;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::FileNameDisplayPreference;
use rustc_target::abi::Size;
use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
Expand Down Expand Up @@ -818,11 +819,16 @@ pub trait PrettyPrinter<'tcx>:
p!("@", print_def_path(did.to_def_id(), substs));
} else {
let span = self.tcx().def_span(did);
let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
FileNameDisplayPreference::Short
} else {
FileNameDisplayPreference::Remapped
};
p!(write(
"@{}",
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
self.tcx().sess.source_map().span_to_embeddable_string(span)
self.tcx().sess.source_map().span_to_string(span, preference)
));
}
} else {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ impl RealFileName {
FileNameDisplayPreference::Remapped => {
self.remapped_path_if_available().to_string_lossy()
}
FileNameDisplayPreference::Short => self
.local_path_if_available()
.file_name()
.map_or_else(|| "".into(), |f| f.to_string_lossy()),
}
}
}
Expand Down Expand Up @@ -302,6 +306,9 @@ pub enum FileNameDisplayPreference {
/// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
/// This is appropriate for use in user-facing output (such as diagnostics).
Local,
/// Display only the filename, as a way to reduce the verbosity of the output.
/// This is appropriate for use in user-facing output (such as diagnostics).
Short,
}

pub struct FileNameDisplay<'a> {
Expand Down
15 changes: 11 additions & 4 deletions compiler/rustc_span/src/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,20 +438,27 @@ impl SourceMap {
}
}

fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String {
pub fn span_to_string(
&self,
sp: Span,
filename_display_pref: FileNameDisplayPreference,
) -> String {
if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
return "no-location".to_string();
}

let lo = self.lookup_char_pos(sp.lo());
let hi = self.lookup_char_pos(sp.hi());
format!(
"{}:{}:{}: {}:{}",
"{}:{}:{}{}",
lo.file.name.display(filename_display_pref),
lo.line,
lo.col.to_usize() + 1,
hi.line,
hi.col.to_usize() + 1,
if let FileNameDisplayPreference::Short = filename_display_pref {
String::new()
} else {
format!(": {}:{}", hi.line, hi.col.to_usize() + 1)
}
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,101 @@
use rustc_hir::def_id::DefId;
use rustc_infer::infer::InferCtxt;
use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
use rustc_infer::traits::util::elaborate_predicates_with_span;
use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
use rustc_span::DUMMY_SP;
use rustc_middle::ty;
use rustc_span::{Span, DUMMY_SP};

use crate::traits::ObligationCtxt;

pub enum Ambiguity {
DefId(DefId),
ParamEnv(Span),
}

pub fn recompute_applicable_impls<'tcx>(
infcx: &InferCtxt<'tcx>,
obligation: &TraitObligation<'tcx>,
) -> Vec<DefId> {
) -> Vec<Ambiguity> {
let tcx = infcx.tcx;
let param_env = obligation.param_env;
let dummy_cause = ObligationCause::dummy();

let impl_may_apply = |impl_def_id| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let placeholder_obligation =
infcx.replace_bound_vars_with_placeholders(obligation.predicate);
let obligation_trait_ref =
ocx.normalize(&dummy_cause, param_env, placeholder_obligation.trait_ref);
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);

let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);

if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
if let Err(_) =
ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
{
return false;
}

let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
ocx.register_obligations(
impl_predicates
.predicates
.iter()
.map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
}));

ocx.select_where_possible().is_empty()
};

let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let placeholder_obligation =
infcx.replace_bound_vars_with_placeholders(obligation.predicate);
let obligation_trait_ref =
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);

let param_env_predicate = infcx.replace_bound_vars_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::HigherRankedType,
poly_trait_predicate,
);
let param_env_trait_ref =
ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);

if let Err(_) =
ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref)
{
return false;
}

ocx.select_where_possible().is_empty()
};

let mut impls = Vec::new();
let mut ambiguities = Vec::new();

tcx.for_each_relevant_impl(
obligation.predicate.def_id(),
obligation.predicate.skip_binder().trait_ref.self_ty(),
|impl_def_id| {
if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
impls.push(impl_def_id)
if infcx.probe(|_| impl_may_apply(impl_def_id)) {
ambiguities.push(Ambiguity::DefId(impl_def_id))
}
},
);
impls

let predicates =
tcx.predicates_of(obligation.cause.body_id.owner.to_def_id()).instantiate_identity(tcx);
for obligation in
elaborate_predicates_with_span(tcx, std::iter::zip(predicates.predicates, predicates.spans))
{
let kind = obligation.predicate.kind();
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
&& param_env_candidate_may_apply(kind.rebind(trait_pred))
{
if kind.rebind(trait_pred.trait_ref) == ty::TraitRef::identity(tcx, trait_pred.def_id()) {
ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id())))
} else {
ambiguities.push(Ambiguity::ParamEnv(obligation.cause.span))
}
}
}

ambiguities
}
Loading