diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_hir_typeck/src/pat.rs | 106 |
1 files changed, 49 insertions, 57 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ea90da4a6..decd317d9 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -19,7 +19,6 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, DUMMY_SP}; -use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::{ObligationCause, Pattern}; use ty::VariantDef; @@ -402,6 +401,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + if self.tcx.features().string_deref_patterns && let hir::ExprKind::Lit(Spanned { node: ast::LitKind::Str(..), .. }) = lt.kind { + let tcx = self.tcx; + let expected = self.resolve_vars_if_possible(expected); + pat_ty = match expected.kind() { + ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => expected, + ty::Str => tcx.mk_static_str(), + _ => pat_ty, + }; + } + // Somewhat surprising: in this case, the subtyping relation goes the // opposite way as the other cases. Actually what we really want is not // a subtyping relation at all but rather that there exists a LUB @@ -693,7 +702,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut_var_suggestion = 'block: { - if !matches!(mutbl, ast::Mutability::Mut) { + if mutbl.is_not() { break 'block None; } @@ -740,7 +749,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), vec![ (pat.span.until(inner.span), "".to_owned()), - (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())), + (ty_span.shrink_to_lo(), mutbl.ref_prefix_str().to_owned()), ], Applicability::MachineApplicable ); @@ -840,12 +849,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (res, opt_ty, segments) = path_resolution; match res { Res::Err => { - self.set_tainted_by_errors(); - return tcx.ty_error(); + let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted"); + self.set_tainted_by_errors(e); + return tcx.ty_error_with_guaranteed(e); } - Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => { - report_unexpected_variant_res(tcx, res, qpath, pat.span); - return tcx.ty_error(); + Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => { + let expected = "unit struct, unit variant or constant"; + let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected); + return tcx.ty_error_with_guaranteed(e); } Res::SelfCtor(..) | Res::Def( @@ -986,65 +997,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ti: TopInfo<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let on_error = || { + let on_error = |e| { for pat in subpats { - self.check_pat(pat, tcx.ty_error(), def_bm, ti); + self.check_pat(pat, tcx.ty_error_with_guaranteed(e), def_bm, ti); } }; let report_unexpected_res = |res: Res| { - let sm = tcx.sess.source_map(); - let path_str = sm - .span_to_snippet(sm.span_until_char(pat.span, '(')) - .map_or_else(|_| String::new(), |s| format!(" `{}`", s.trim_end())); - let msg = format!( - "expected tuple struct or tuple variant, found {}{}", - res.descr(), - path_str - ); - - let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{msg}"); - match res { - Res::Def(DefKind::Fn | DefKind::AssocFn, _) => { - err.span_label(pat.span, "`fn` calls are not allowed in patterns"); - err.help( - "for more information, visit \ - https://doc.rust-lang.org/book/ch18-00-patterns.html", - ); - } - _ => { - err.span_label(pat.span, "not a tuple variant or struct"); - } - } - err.emit(); - on_error(); + let expected = "tuple struct or tuple variant"; + let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0164", expected); + on_error(e); + e }; // Resolve the path and check the definition for errors. let (res, opt_ty, segments) = self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); if res == Res::Err { - self.set_tainted_by_errors(); - on_error(); - return self.tcx.ty_error(); + let e = tcx.sess.delay_span_bug(pat.span, "`Res:Err` but no error emitted"); + self.set_tainted_by_errors(e); + on_error(e); + return tcx.ty_error_with_guaranteed(e); } // Type-check the path. let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id); if !pat_ty.is_fn() { - report_unexpected_res(res); - return tcx.ty_error(); + let e = report_unexpected_res(res); + return tcx.ty_error_with_guaranteed(e); } let variant = match res { Res::Err => { - self.set_tainted_by_errors(); - on_error(); - return tcx.ty_error(); + let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted"); + self.set_tainted_by_errors(e); + on_error(e); + return tcx.ty_error_with_guaranteed(e); } Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { - report_unexpected_res(res); - return tcx.ty_error(); + let e = report_unexpected_res(res); + return tcx.ty_error_with_guaranteed(e); } Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res), _ => bug!("unexpected pattern resolution: {:?}", res), @@ -1083,9 +1075,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else { // Pattern has wrong number of fields. - self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err); - on_error(); - return tcx.ty_error(); + let e = self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err); + on_error(e); + return tcx.ty_error_with_guaranteed(e); } pat_ty } @@ -1099,7 +1091,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fields: &'tcx [ty::FieldDef], expected: Ty<'tcx>, had_err: bool, - ) { + ) -> ErrorGuaranteed { let subpats_ending = pluralize!(subpats.len()); let fields_ending = pluralize!(fields.len()); @@ -1246,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - err.emit(); + err.emit() } fn check_pat_tuple( @@ -1278,12 +1270,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) { - err.emit(); + let reported = err.emit(); // Walk subpatterns with an expected type of `err` in this case to silence // further errors being emitted when using the bindings. #50333 - let element_tys_iter = (0..max_len).map(|_| tcx.ty_error()); + let element_tys_iter = (0..max_len).map(|_| tcx.ty_error_with_guaranteed(reported)); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, tcx.ty_error(), def_bm, ti); + self.check_pat(elem, tcx.ty_error_with_guaranteed(reported), def_bm, ti); } tcx.mk_tup(element_tys_iter) } else { @@ -1468,8 +1460,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // if this is a tuple struct, then all field names will be numbers // so if any fields in a struct pattern use shorthand syntax, they will // be invalid identifiers (for example, Foo { 0, 1 }). - if let (CtorKind::Fn, PatKind::Struct(qpath, field_patterns, ..)) = - (variant.ctor_kind, &pat.kind) + if let (Some(CtorKind::Fn), PatKind::Struct(qpath, field_patterns, ..)) = + (variant.ctor_kind(), &pat.kind) { let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand); if has_shorthand_field_name { @@ -1646,7 +1638,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fields: &'tcx [hir::PatField<'tcx>], variant: &ty::VariantDef, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { - if let (CtorKind::Fn, PatKind::Struct(qpath, ..)) = (variant.ctor_kind, &pat.kind) { + if let (Some(CtorKind::Fn), PatKind::Struct(qpath, ..)) = (variant.ctor_kind(), &pat.kind) { let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| { s.print_qpath(qpath, false) }); @@ -2132,7 +2124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let ty::Array(..) | ty::Slice(..) = ty.kind() { err.help("the semantics of slice patterns changed recently; see issue #62254"); - } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span) + } else if self.autoderef(span, expected_ty) .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) && let (Some(span), true) = (ti.span, ti.origin_expr) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) |