Skip to content

Commit

Permalink
Auto merge of rust-lang#106616 - compiler-errors:rollup-emcj0o3, r=co…
Browse files Browse the repository at this point in the history
…mpiler-errors

Rollup of 8 pull requests

Successful merges:

 - rust-lang#104163 (Don't derive Debug for `OnceWith` & `RepeatWith`)
 - rust-lang#106131 (Mention "signature" rather than "fn pointer" when impl/trait methods are incompatible)
 - rust-lang#106363 (Structured suggestion for `&mut dyn Iterator` when possible)
 - rust-lang#106497 (Suggest using clone when we have &T and T implemented Clone)
 - rust-lang#106584 (Document that `Vec::from_raw_parts[_in]` must be given a pointer from the correct allocator.)
 - rust-lang#106600 (Suppress type errors that come from private fields)
 - rust-lang#106602 (Add goml scripts to tidy checks)
 - rust-lang#106606 (Do not emit structured suggestion for turbofish with wrong span)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 9, 2023
2 parents a377893 + 5e8e97f commit 2e677c0
Show file tree
Hide file tree
Showing 75 changed files with 594 additions and 204 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_error_messages/locales/en-US/infer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not ge
infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
.found = found `{$found}`
.expected = expected `{$expected}`
.expected_found = expected `{$expected}`
{" "}found `{$found}`
.expected_found = expected signature `{$expected}`
{" "}found signature `{$found}`
infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
Expand Down
36 changes: 14 additions & 22 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ fn compare_method_predicate_entailment<'tcx>(
let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig));

let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
let impl_fty = ocx.normalize(&norm_cause, param_env, unnormalized_impl_fty);
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
debug!("compare_impl_method: impl_fty={:?}", impl_sig);

let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
Expand All @@ -294,18 +294,17 @@ fn compare_method_predicate_entailment<'tcx>(
// type would be more appropriate. In other places we have a `Vec<Span>`
// corresponding to their `Vec<Predicate>`, but we don't have that here.
// Fixing this would improve the output of test `issue-83765.rs`.
let result = ocx.sup(&cause, param_env, trait_fty, impl_fty);
let result = ocx.sup(&cause, param_env, trait_sig, impl_sig);

if let Err(terr) = result {
debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed");

let emitted = report_trait_method_mismatch(
&infcx,
cause,
terr,
(trait_m, trait_fty),
(impl_m, impl_fty),
trait_sig,
(trait_m, trait_sig),
(impl_m, impl_sig),
impl_trait_ref,
);
return Err(emitted);
Expand Down Expand Up @@ -484,7 +483,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
let param_env = tcx.param_env(def_id);

// First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later.
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
Expand Down Expand Up @@ -577,14 +577,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(

debug!(?trait_sig, ?impl_sig, "equating function signatures");

let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));

// Unify the whole function signature. We need to do this to fully infer
// the lifetimes of the return type, but do this after unifying just the
// return types, since we want to avoid duplicating errors from
// `compare_method_predicate_entailment`.
match ocx.eq(&cause, param_env, trait_fty, impl_fty) {
match ocx.eq(&cause, param_env, trait_sig, impl_sig) {
Ok(()) => {}
Err(terr) => {
// This function gets called during `compare_method_predicate_entailment` when normalizing a
Expand All @@ -595,9 +592,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
infcx,
cause,
terr,
(trait_m, trait_fty),
(impl_m, impl_fty),
trait_sig,
(trait_m, trait_sig),
(impl_m, impl_sig),
impl_trait_ref,
);
return Err(emitted);
Expand Down Expand Up @@ -771,9 +767,8 @@ fn report_trait_method_mismatch<'tcx>(
infcx: &InferCtxt<'tcx>,
mut cause: ObligationCause<'tcx>,
terr: TypeError<'tcx>,
(trait_m, trait_fty): (&ty::AssocItem, Ty<'tcx>),
(impl_m, impl_fty): (&ty::AssocItem, Ty<'tcx>),
trait_sig: ty::FnSig<'tcx>,
(trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
(impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
impl_trait_ref: ty::TraitRef<'tcx>,
) -> ErrorGuaranteed {
let tcx = infcx.tcx;
Expand Down Expand Up @@ -858,10 +853,7 @@ fn report_trait_method_mismatch<'tcx>(
&mut diag,
&cause,
trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
Some(infer::ValuePairs::Terms(ExpectedFound {
expected: trait_fty.into(),
found: impl_fty.into(),
})),
Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
terr,
false,
false,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected);
if !suggested {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2217,7 +2217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
return field_ty;
}
private_candidate = Some((adjustments, base_def.did(), field_ty));
private_candidate = Some((adjustments, base_def.did()));
}
}
ty::Tuple(tys) => {
Expand All @@ -2240,12 +2240,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));

if let Some((adjustments, did, field_ty)) = private_candidate {
if let Some((adjustments, did)) = private_candidate {
// (#90483) apply adjustments to avoid ExprUseVisitor from
// creating erroneous projection.
self.apply_adjustments(base, adjustments);
self.ban_private_field_access(expr, base_ty, field, did);
return field_ty;
return self.tcx().ty_error();
}

if field.name == kw::Empty {
Expand Down
30 changes: 30 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

pub(crate) fn suggest_clone_for_ref(
&self,
diag: &mut Diagnostic,
expr: &hir::Expr<'_>,
expr_ty: Ty<'tcx>,
expected_ty: Ty<'tcx>,
) -> bool {
if let ty::Ref(_, inner_ty, hir::Mutability::Not) = expr_ty.kind()
&& let Some(clone_trait_def) = self.tcx.lang_items().clone_trait()
&& expected_ty == *inner_ty
&& self
.infcx
.type_implements_trait(
clone_trait_def,
[self.tcx.erase_regions(expected_ty)],
self.param_env
)
.must_apply_modulo_regions()
{
diag.span_suggestion_verbose(
expr.span.shrink_to_hi(),
"consider using clone here",
".clone()",
Applicability::MachineApplicable,
);
return true;
}
false
}

pub(crate) fn suggest_copied_or_cloned(
&self,
diag: &mut Diagnostic,
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_hir_typeck/src/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ pub enum MethodError<'tcx> {
PrivateMatch(DefKind, DefId, Vec<DefId>),

// Found a `Self: Sized` bound where `Self` is a trait object.
IllegalSizedBound(Vec<DefId>, bool, Span),
IllegalSizedBound {
candidates: Vec<DefId>,
needs_mut: bool,
bound_span: Span,
self_expr: &'tcx hir::Expr<'tcx>,
},

// Found a match, but the return type is wrong
BadReturnType,
Expand Down Expand Up @@ -112,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Err(NoMatch(..)) => false,
Err(Ambiguity(..)) => true,
Err(PrivateMatch(..)) => allow_private,
Err(IllegalSizedBound(..)) => true,
Err(IllegalSizedBound { .. }) => true,
Err(BadReturnType) => bug!("no return type expectations but got BadReturnType"),
}
}
Expand Down Expand Up @@ -236,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => Vec::new(),
};

return Err(IllegalSizedBound(candidates, needs_mut, span));
return Err(IllegalSizedBound { candidates, needs_mut, bound_span: span, self_expr });
}

Ok(result.callee)
Expand Down
41 changes: 37 additions & 4 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.emit();
}

MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
let msg = if needs_mut {
with_forced_trimmed_paths!(format!(
"the `{item_name}` method cannot be invoked on `{rcvr_ty}`"
))
} else {
format!("the `{item_name}` method cannot be invoked on a trait object")
};
let mut err = self.sess().struct_span_err(span, &msg);
err.span_label(bound_span, "this has a `Sized` requirement");
if !needs_mut {
err.span_label(bound_span, "this has a `Sized` requirement");
}
if !candidates.is_empty() {
let help = format!(
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \
Expand All @@ -197,7 +205,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
*region,
ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
);
err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
let msg = format!("you need `{}` instead of `{}`", trait_type, rcvr_ty);
let mut kind = &self_expr.kind;
while let hir::ExprKind::AddrOf(_, _, expr)
| hir::ExprKind::Unary(hir::UnOp::Deref, expr) = kind
{
kind = &expr.kind;
}
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
&& let hir::def::Res::Local(hir_id) = path.res
&& let Some(hir::Node::Pat(b)) = self.tcx.hir().find(hir_id)
&& let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id)
&& let Some(node) = self.tcx.hir().find_parent(p.hir_id)
&& let Some(decl) = node.fn_decl()
&& let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span)
&& let hir::TyKind::Ref(_, mut_ty) = &ty.kind
&& let hir::Mutability::Not = mut_ty.mutbl
{
err.span_suggestion_verbose(
mut_ty.ty.span.shrink_to_lo(),
&msg,
"mut ",
Applicability::MachineApplicable,
);
} else {
err.help(&msg);
}
}
}
err.emit();
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,3 +427,15 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
}
}
}

impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
fn to_trace(
_: TyCtxt<'tcx>,
cause: &ObligationCause<'tcx>,
a_is_expected: bool,
a: Self,
b: Self,
) -> TypeTrace<'tcx> {
TypeTrace { cause: cause.clone(), values: Sigs(ExpectedFound::new(a_is_expected, a, b)) }
}
}
20 changes: 18 additions & 2 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1428,8 +1428,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
impl<'tcx> OpaqueTypesVisitor<'tcx> {
fn visit_expected_found(
tcx: TyCtxt<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
expected: impl TypeVisitable<'tcx>,
found: impl TypeVisitable<'tcx>,
ignore_span: Span,
) -> Self {
let mut types_visitor = OpaqueTypesVisitor {
Expand Down Expand Up @@ -1569,6 +1569,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
_ => (false, Mismatch::Fixed("type")),
}
}
ValuePairs::Sigs(infer::ExpectedFound { expected, found }) => {
OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span)
.report(diag);
(false, Mismatch::Fixed("signature"))
}
ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => {
(false, Mismatch::Fixed("trait"))
}
Expand Down Expand Up @@ -2040,6 +2045,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ret => ret,
}
}
infer::Sigs(exp_found) => {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
}
let (exp, fnd) = self.cmp_fn_sig(
&ty::Binder::dummy(exp_found.expected),
&ty::Binder::dummy(exp_found.found),
);
Some((exp, fnd, None, None))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff};
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::Subtype;
use crate::infer::{Subtype, ValuePairs};
use crate::traits::ObligationCauseCode::CompareImplItemObligation;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::print::RegionHighlightMode;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::Span;
Expand All @@ -23,22 +24,27 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let error = self.error.as_ref()?;
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
if let RegionResolutionError::SubSupConflict(
_,
var_origin,
sub_origin,
_sub,
sup_origin,
_sup,
_,
) = error.clone()
_,
var_origin,
sub_origin,
_sub,
sup_origin,
_sup,
_,
) = error.clone()
&& let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
&& let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty()
&& let sup_expected_found @ Some(_) = sup_trace.values.ty()
&& let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code()
&& sup_expected_found == sub_expected_found
&& sub_trace.values == sup_trace.values
&& let ValuePairs::Sigs(ExpectedFound { expected, found }) = sub_trace.values
{
let guar =
self.emit_err(var_origin.span(), sub_expected, sub_found, *trait_item_def_id);
// FIXME(compiler-errors): Don't like that this needs `Ty`s, but
// all of the region highlighting machinery only deals with those.
let guar = self.emit_err(
var_origin.span(),
self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(expected)),
self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(found)),
*trait_item_def_id,
);
return Some(guar);
}
None
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ pub enum ValuePairs<'tcx> {
Terms(ExpectedFound<ty::Term<'tcx>>),
TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
Sigs(ExpectedFound<ty::FnSig<'tcx>>),
}

impl<'tcx> ValuePairs<'tcx> {
Expand Down
Loading

0 comments on commit 2e677c0

Please sign in to comment.