Skip to content

Commit

Permalink
visit enum init when the enum variable doesn't have any parameters
Browse files Browse the repository at this point in the history
this will fix #101208
  • Loading branch information
Yiming Lei committed Oct 12, 2022
1 parent 538f118 commit b31086a
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 5 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_hir_analysis/src/check/compare_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ fn compare_predicate_entailment<'tcx>(
terr,
false,
false,
false,
);

return Err(diag.emit());
Expand Down Expand Up @@ -516,6 +517,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
terr,
false,
false,
false,
);
return Err(diag.emit());
}
Expand Down Expand Up @@ -1383,6 +1385,7 @@ pub(crate) fn raw_compare_const_impl<'tcx>(
terr,
false,
false,
false,
);
return Err(diag.emit());
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
e,
false,
true,
false,
);
}
}
Expand Down
77 changes: 72 additions & 5 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore-tidy-filelength
//! Error Reporting Code for the inference engine
//!
//! Because of the way inference, and in particular region inference,
Expand Down Expand Up @@ -64,8 +65,12 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, Mul
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::walk_block;
use rustc_hir::intravisit::walk_expr;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::Node;
use rustc_hir::HirId;
use rustc_hir::{Expr, Node};
use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
Expand Down Expand Up @@ -620,13 +625,55 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
_ => (), // FIXME(#22750) handle traits and stuff
}
}
fn note_enum_suggestion(
&self,
err: &mut Diagnostic,
span: Span,
body_id: HirId,
arg_size: usize,
) {
let body_node = self.tcx.hir().get(body_id);
let hir::Node::Expr(&hir::Expr{kind:hir::ExprKind::Block(body_expr, ..), ..}) = body_node else {return ()};
struct FindExprVisitor<'tcx> {
target_span: Span,
size: usize,
terr: &'tcx mut Diagnostic,
}
impl<'tcx> Visitor<'tcx> for FindExprVisitor<'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
if expr.span == self.target_span {
let mut suggest_vec = vec![];
let mut i = 0;
suggest_vec.push((expr.span.shrink_to_hi(), "(".to_string()));
while i < self.size {
suggest_vec.push((expr.span.shrink_to_hi(), "_".to_string()));
if i != self.size - 1 {
suggest_vec.push((expr.span.shrink_to_hi(), ",".to_string()));
}
i = i + 1;
}
suggest_vec.push((expr.span.shrink_to_hi(), ")".to_string()));

self.terr.multipart_suggestion(
"use parentheses to instantiate this tuple variant",
suggest_vec,
Applicability::MachineApplicable,
);
}
walk_expr(self, expr);
}
}
let mut visitor = FindExprVisitor { target_span: span, size: arg_size, terr: err };
walk_block(&mut visitor, body_expr);
}

fn note_error_origin(
&self,
err: &mut Diagnostic,
cause: &ObligationCause<'tcx>,
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
terr: TypeError<'tcx>,
detect_enum_noparm: bool,
) {
match *cause.code() {
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
Expand All @@ -640,8 +687,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
{
err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
} else {
err.span_label(span, format!("this expression has type `{}`", ty));
}
err.span_label(span, format!("this expression has type `{}`", ty));
if detect_enum_noparm &&
let ty::FnDef(def_id, substs) = ty.kind(){
let sig = self.tcx.bound_fn_sig(*def_id).subst(self.tcx, substs);
let sig = self.tcx.erase_late_bound_regions(sig);
self.note_enum_suggestion(err, span, cause.body_id, sig.inputs().len());
}
}
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
&& ty.is_box() && ty.boxed_ty() == found
Expand Down Expand Up @@ -1490,6 +1543,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
terr: TypeError<'tcx>,
swap_secondary_and_primary: bool,
prefer_label: bool,
detect_enum_noparm: bool,
) {
let span = cause.span();

Expand Down Expand Up @@ -1940,7 +1994,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {

// It reads better to have the error origin as the final
// thing.
self.note_error_origin(diag, cause, exp_found, terr);
self.note_error_origin(diag, cause, exp_found, terr, detect_enum_noparm);

debug!(?diag);
}
Expand Down Expand Up @@ -2260,6 +2314,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {

let span = trace.cause.span();
let failure_code = trace.cause.as_failure_code(terr);
let mut detect_enum_noparm = false;
let mut diag = match failure_code {
FailureCode::Error0038(did) => {
let violations = self.tcx.object_safety_violations(did);
Expand Down Expand Up @@ -2314,6 +2369,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
}
(ty::FnDef(_, _), ty::Adt(adt_id, _)) if adt_id.is_enum() => {
detect_enum_noparm = true;
}
_ => {}
}
}
Expand All @@ -2334,7 +2392,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
}
};
self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false);
self.note_type_err(
&mut diag,
&trace.cause,
None,
Some(trace.values),
terr,
false,
false,
detect_enum_noparm,
);
diag
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err,
true,
false,
false,
);
self.note_obligation_cause(&mut diag, obligation);
diag.emit();
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/type/issue-101208.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
enum E {
One(i32, i32)
}
fn main() {
let var = E::One;
if let E::One(var1, var2) = var {
//~^ ERROR 0308
println!("{var1} {var2}");
}
}
18 changes: 18 additions & 0 deletions src/test/ui/type/issue-101208.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0308]: mismatched types
--> $DIR/issue-101208.rs:6:12
|
LL | if let E::One(var1, var2) = var {
| ^^^^^^^^^^^^^^^^^^ --- this expression has type `fn(i32, i32) -> E {E::One}`
| |
| expected fn item, found enum `E`
|
= note: expected fn item `fn(i32, i32) -> E {E::One}`
found enum `E`
help: use parentheses to instantiate this tuple variant
|
LL | if let E::One(var1, var2) = var(_,_) {
| +

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

0 comments on commit b31086a

Please sign in to comment.