diff options
Diffstat (limited to 'compiler')
18 files changed, 221 insertions, 293 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index c999b06b0ab..2cbab90aa61 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -392,15 +392,7 @@ pub struct Generics { impl Default for Generics { /// Creates an instance of `Generics`. fn default() -> Generics { - Generics { - params: Vec::new(), - where_clause: WhereClause { - has_where_token: false, - predicates: Vec::new(), - span: DUMMY_SP, - }, - span: DUMMY_SP, - } + Generics { params: Vec::new(), where_clause: Default::default(), span: DUMMY_SP } } } @@ -415,6 +407,12 @@ pub struct WhereClause { pub span: Span, } +impl Default for WhereClause { + fn default() -> WhereClause { + WhereClause { has_where_token: false, predicates: Vec::new(), span: DUMMY_SP } + } +} + /// A single predicate in a where-clause. #[derive(Clone, Encodable, Decodable, Debug)] pub enum WherePredicate { diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 345db700298..240167146e1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -1,4 +1,3 @@ -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; @@ -19,7 +18,6 @@ pub fn expand_deriving_copy( path: path_std!(marker::Copy), skip_path_as_bound: false, additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: true, methods: Vec::new(), associated_types: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 55cbb654723..2f19fbcac7d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -75,7 +75,6 @@ pub fn expand_deriving_clone( path: path_std!(clone::Clone), skip_path_as_bound: false, additional_bounds: bounds, - generics: Bounds::empty(), supports_unions: true, methods: vec![MethodDef { name: sym::clone, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 6190b7a8c77..a0b836171be 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -28,7 +28,6 @@ pub fn expand_deriving_eq( path: path_std!(cmp::Eq), skip_path_as_bound: false, additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: true, methods: vec![MethodDef { name: sym::assert_receiver_is_total_eq, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index d2412b20a09..52780981248 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -22,7 +22,6 @@ pub fn expand_deriving_ord( path: path_std!(cmp::Ord), skip_path_as_bound: false, additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: false, methods: vec![MethodDef { name: sym::cmp, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 353f28fc45f..34de4a620b4 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -86,7 +86,6 @@ pub fn expand_deriving_partial_eq( path: path_std!(cmp::PartialEq), skip_path_as_bound: false, additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: false, methods, associated_types: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index e7458b23ef3..6cc8f26df55 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -40,7 +40,6 @@ pub fn expand_deriving_partial_ord( path: path_std!(cmp::PartialOrd), skip_path_as_bound: false, additional_bounds: vec![], - generics: Bounds::empty(), supports_unions: false, methods: vec![partial_cmp_def], associated_types: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index e6d5759bb52..544d971b27a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -23,7 +23,6 @@ pub fn expand_deriving_debug( path: path_std!(fmt::Debug), skip_path_as_bound: false, additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: false, methods: vec![MethodDef { name: sym::fmt, diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 37aa665e5c6..6d14875a983 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -26,7 +26,6 @@ pub fn expand_deriving_rustc_decodable( path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global), skip_path_as_bound: false, additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: false, methods: vec![MethodDef { name: sym::decode, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 234957ab8a1..93f297ad88b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -27,7 +27,6 @@ pub fn expand_deriving_default( path: Path::new(vec![kw::Default, sym::Default]), skip_path_as_bound: has_a_default_variant(item), additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: false, methods: vec![MethodDef { name: kw::Default, diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index baacaa8b979..9a46ca81537 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -110,7 +110,6 @@ pub fn expand_deriving_rustc_encodable( path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global), skip_path_as_bound: false, additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: false, methods: vec![MethodDef { name: sym::encode, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 3972c3b4934..f48c49f411c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -195,9 +195,6 @@ pub struct TraitDef<'a> { /// other than the current trait pub additional_bounds: Vec<Ty>, - /// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder` - pub generics: Bounds, - /// Can this trait be derived for unions? pub supports_unions: bool, @@ -583,19 +580,21 @@ impl<'a> TraitDef<'a> { }) }); - let Generics { mut params, mut where_clause, .. } = - self.generics.to_generics(cx, self.span, type_ident, generics); + let mut where_clause = ast::WhereClause::default(); where_clause.span = generics.where_clause.span; let ctxt = self.span.ctxt(); let span = generics.span.with_ctxt(ctxt); // Create the generic parameters - params.extend(generics.params.iter().map(|param| match ¶m.kind { - GenericParamKind::Lifetime { .. } => param.clone(), - GenericParamKind::Type { .. } => { - // I don't think this can be moved out of the loop, since - // a GenericBound requires an ast id - let bounds: Vec<_> = + let params: Vec<_> = generics + .params + .iter() + .map(|param| match ¶m.kind { + GenericParamKind::Lifetime { .. } => param.clone(), + GenericParamKind::Type { .. } => { + // I don't think this can be moved out of the loop, since + // a GenericBound requires an ast id + let bounds: Vec<_> = // extra restrictions on the generics parameters to the // type being derived upon self.additional_bounds.iter().map(|p| { @@ -608,21 +607,22 @@ impl<'a> TraitDef<'a> { param.bounds.iter().cloned() ).collect(); - cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None) - } - GenericParamKind::Const { ty, kw_span, .. } => { - let const_nodefault_kind = GenericParamKind::Const { - ty: ty.clone(), - kw_span: kw_span.with_ctxt(ctxt), - - // We can't have default values inside impl block - default: None, - }; - let mut param_clone = param.clone(); - param_clone.kind = const_nodefault_kind; - param_clone - } - })); + cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None) + } + GenericParamKind::Const { ty, kw_span, .. } => { + let const_nodefault_kind = GenericParamKind::Const { + ty: ty.clone(), + kw_span: kw_span.with_ctxt(ctxt), + + // We can't have default values inside impl block + default: None, + }; + let mut param_clone = param.clone(); + param_clone.kind = const_nodefault_kind; + param_clone + } + }) + .collect(); // and similarly for where clauses where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| { @@ -1062,18 +1062,15 @@ impl<'a> MethodDef<'a> { trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, true); mk_body(cx, selflike_fields) } else { - // Neither packed nor copy. Need to use ref patterns. + // Packed and not copy. Need to use ref patterns. let prefixes: Vec<_> = (0..selflike_args.len()).map(|i| format!("__self_{}", i)).collect(); - let addr_of = always_copy; - let selflike_fields = - trait_.create_struct_pattern_fields(cx, struct_def, &prefixes, addr_of); + let selflike_fields = trait_.create_struct_pattern_fields(cx, struct_def, &prefixes); let mut body = mk_body(cx, selflike_fields); let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]); - let by_ref = ByRef::from(is_packed && !always_copy); let patterns = - trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, by_ref); + trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, ByRef::Yes); // Do the let-destructuring. let mut stmts: Vec<_> = iter::zip(selflike_args, patterns) @@ -1254,9 +1251,7 @@ impl<'a> MethodDef<'a> { // A single arm has form (&VariantK, &VariantK, ...) => BodyK // (see "Final wrinkle" note below for why.) - let addr_of = false; // because enums can't be repr(packed) - let fields = - trait_.create_struct_pattern_fields(cx, &variant.data, &prefixes, addr_of); + let fields = trait_.create_struct_pattern_fields(cx, &variant.data, &prefixes); let sp = variant.span.with_ctxt(trait_.span.ctxt()); let variant_path = cx.path(sp, vec![type_ident, variant.ident]); @@ -1519,15 +1514,13 @@ impl<'a> TraitDef<'a> { cx: &mut ExtCtxt<'_>, struct_def: &'a VariantData, prefixes: &[String], - addr_of: bool, ) -> Vec<FieldInfo> { self.create_fields(struct_def, |i, _struct_field, sp| { prefixes .iter() .map(|prefix| { let ident = self.mk_pattern_ident(prefix, i); - let expr = cx.expr_path(cx.path_ident(sp, ident)); - if addr_of { cx.expr_addr_of(sp, expr) } else { expr } + cx.expr_path(cx.path_ident(sp, ident)) }) .collect() }) diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 8fb1a4ba262..c136bb7141a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -25,7 +25,6 @@ pub fn expand_deriving_hash( path, skip_path_as_bound: false, additional_bounds: Vec::new(), - generics: Bounds::empty(), supports_unions: false, methods: vec![MethodDef { name: sym::hash, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 43a5145b7e7..edfe12963dc 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -20,11 +20,10 @@ use rustc_infer::infer::{ }; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; 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::{ - self, DefIdTree, GenericArg, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable, -}; +use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; @@ -263,15 +262,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) => { let tcx = self.tcx; - let actual = self.resolve_vars_if_possible(rcvr_ty); - let ty_str = self.ty_to_string(actual); + let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); + let ty_str = self.ty_to_string(rcvr_ty); let is_method = mode == Mode::MethodCall; let item_kind = if is_method { "method" - } else if actual.is_enum() { + } else if rcvr_ty.is_enum() { "variant or associated item" } else { - match (item_name.as_str().chars().next(), actual.is_fresh_ty()) { + match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) { (Some(name), false) if name.is_lowercase() => "function or associated item", (Some(_), false) => "associated item", (Some(_), true) | (None, false) => "variant or associated item", @@ -280,9 +279,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if self.suggest_wrapping_range_with_parens( - tcx, actual, source, span, item_name, &ty_str, + tcx, rcvr_ty, source, span, item_name, &ty_str, ) || self.suggest_constraining_numerical_ty( - tcx, actual, source, span, item_kind, item_name, &ty_str, + tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str, ) { return None; } @@ -290,9 +289,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Don't show generic arguments when the method can't be found in any implementation (#81576). let mut ty_str_reported = ty_str.clone(); - if let ty::Adt(_, generics) = actual.kind() { + if let ty::Adt(_, generics) = rcvr_ty.kind() { if generics.len() > 0 { - let mut autoderef = self.autoderef(span, actual); + let mut autoderef = self.autoderef(span, rcvr_ty); let candidate_found = autoderef.any(|(ty, _)| { if let ty::Adt(adt_def, _) = ty.kind() { self.tcx @@ -321,16 +320,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "no {} named `{}` found for {} `{}` in the current scope", item_kind, item_name, - actual.prefix_string(self.tcx), + rcvr_ty.prefix_string(self.tcx), ty_str_reported, ); - if actual.references_error() { + if rcvr_ty.references_error() { err.downgrade_to_delayed_bug(); } if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source { self.suggest_await_before_method( - &mut err, item_name, actual, cal, span, + &mut err, item_name, rcvr_ty, cal, span, ); } if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) { @@ -341,7 +340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - if let ty::RawPtr(_) = &actual.kind() { + if let ty::RawPtr(_) = &rcvr_ty.kind() { err.note( "try using `<*const T>::as_ref()` to get a reference to the \ type behind the pointer: https://doc.rust-lang.org/std/\ @@ -353,7 +352,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - let ty_span = match actual.kind() { + let ty_span = match rcvr_ty.kind() { ty::Param(param_type) => Some( param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()), ), @@ -365,7 +364,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, format!( "{item_kind} `{item_name}` not found for this {}", - actual.prefix_string(self.tcx) + rcvr_ty.prefix_string(self.tcx) ), ); } @@ -398,122 +397,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { custom_span_label = true; } if static_candidates.len() == 1 { - let mut has_unsuggestable_args = false; - let ty_str = if let Some(CandidateSource::Impl(impl_did)) = - static_candidates.get(0) - { - // When the "method" is resolved through dereferencing, we really want the - // original type that has the associated function for accurate suggestions. - // (#61411) - let ty = tcx.at(span).type_of(*impl_did); - match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { - (ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => { - // If there are any inferred arguments, (`{integer}`), we should replace - // them with underscores to allow the compiler to infer them - let infer_substs: Vec<GenericArg<'_>> = substs - .into_iter() - .map(|arg| { - if !arg.is_suggestable(tcx, true) { - has_unsuggestable_args = true; - match arg.unpack() { - GenericArgKind::Lifetime(_) => self - .next_region_var(RegionVariableOrigin::MiscVariable( - rustc_span::DUMMY_SP, - )) - .into(), - GenericArgKind::Type(_) => self - .next_ty_var(TypeVariableOrigin { - span: rustc_span::DUMMY_SP, - kind: TypeVariableOriginKind::MiscVariable, - }) - .into(), - GenericArgKind::Const(arg) => self - .next_const_var( - arg.ty(), - ConstVariableOrigin { - span: rustc_span::DUMMY_SP, - kind: ConstVariableOriginKind::MiscVariable, - }, - ) - .into(), - } - } else { - arg - } - }) - .collect::<Vec<_>>(); - - tcx.value_path_str_with_substs( - def_actual.did(), - tcx.intern_substs(&infer_substs), - ) - } - _ => self.ty_to_value_string(ty.peel_refs()), - } - } else { - self.ty_to_value_string(actual.peel_refs()) - }; - if let SelfSource::MethodCall(_) = source { - let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) && - let Some(assoc) = self.associated_value(*impl_did, item_name) { - let sig = self.tcx.fn_sig(assoc.def_id); - if let Some(first) = sig.inputs().skip_binder().get(0) { - if first.peel_refs() == rcvr_ty.peel_refs() { - None - } else { - Some(if first.is_region_ptr() { - if first.is_mutable_ptr() { "&mut " } else { "&" } - } else { - "" - }) - } - } else { - None - } - } else { - None - }; - let mut applicability = Applicability::MachineApplicable; - let args = if let Some((receiver, args)) = args { - // The first arg is the same kind as the receiver - let explicit_args = if first_arg.is_some() { - std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>() - } else { - // There is no `Self` kind to infer the arguments from - if has_unsuggestable_args { - applicability = Applicability::HasPlaceholders; - } - args.iter().collect() - }; - format!( - "({}{})", - first_arg.unwrap_or(""), - explicit_args - .iter() - .map(|arg| tcx - .sess - .source_map() - .span_to_snippet(arg.span) - .unwrap_or_else(|_| { - applicability = Applicability::HasPlaceholders; - "_".to_owned() - })) - .collect::<Vec<_>>() - .join(", "), - ) - } else { - applicability = Applicability::HasPlaceholders; - "(...)".to_owned() - }; - err.span_suggestion( - sugg_span, - "use associated function syntax instead", - format!("{}::{}{}", ty_str, item_name, args), - applicability, - ); - } else { - err.help(&format!("try with `{}::{}`", ty_str, item_name,)); - } + self.suggest_associated_call_syntax( + &mut err, + &static_candidates, + rcvr_ty, + source, + item_name, + args, + sugg_span, + ); report_candidates(span, &mut err, &mut static_candidates, sugg_span); } else if static_candidates.len() > 1 { @@ -523,7 +415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut bound_spans = vec![]; let mut restrict_type_params = false; let mut unsatisfied_bounds = false; - if item_name.name == sym::count && self.is_slice_ty(actual, span) { + if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { let msg = "consider using `len` instead"; if let SelfSource::MethodCall(_expr) = source { err.span_suggestion_short( @@ -537,7 +429,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) { let iterator_trait = self.tcx.def_path_str(iterator_trait); - err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement")); + err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement")); } } else if !unsatisfied_predicates.is_empty() { let mut type_params = FxHashMap::default(); @@ -876,7 +768,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|(_, path)| path) .collect::<Vec<_>>() .join("\n"); - let actual_prefix = actual.prefix_string(self.tcx); + let actual_prefix = rcvr_ty.prefix_string(self.tcx); info!("unimplemented_traits.len() == {}", unimplemented_traits.len()); let (primary_message, label) = if unimplemented_traits.len() == 1 && unimplemented_traits_only { @@ -885,7 +777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .next() .map(|(_, (trait_ref, obligation))| { if trait_ref.self_ty().references_error() - || actual.references_error() + || rcvr_ty.references_error() { // Avoid crashing. return (None, None); @@ -921,7 +813,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let label_span_not_found = |err: &mut Diagnostic| { if unsatisfied_predicates.is_empty() { err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); - let is_string_or_ref_str = match actual.kind() { + let is_string_or_ref_str = match rcvr_ty.kind() { ty::Ref(_, ty, _) => { ty.is_str() || matches!( @@ -957,7 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // different from the received one // So we avoid suggestion method with Box<Self> // for instance - self.tcx.at(span).type_of(*def_id) != actual + self.tcx.at(span).type_of(*def_id) != rcvr_ty && self.tcx.at(span).type_of(*def_id) != rcvr_ty } (Mode::Path, false, _) => true, @@ -1017,10 +909,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Don't suggest (for example) `expr.field.clone()` if `expr.clone()` // can't be called due to `typeof(expr): Clone` not holding. if unsatisfied_predicates.is_empty() { - self.suggest_calling_method_on_field(&mut err, source, span, actual, item_name); + self.suggest_calling_method_on_field( + &mut err, source, span, rcvr_ty, item_name, + ); } - self.check_for_inner_self(&mut err, source, span, actual, item_name); + self.check_for_inner_self(&mut err, source, span, rcvr_ty, item_name); bound_spans.sort(); bound_spans.dedup(); @@ -1028,7 +922,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(span, &msg); } - if actual.is_numeric() && actual.is_fresh() || restrict_type_params { + if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params { } else { self.suggest_traits_to_import( &mut err, @@ -1046,8 +940,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Don't emit a suggestion if we found an actual method // that had unsatisfied trait bounds - if unsatisfied_predicates.is_empty() && actual.is_enum() { - let adt_def = actual.ty_adt_def().expect("enum is not an ADT"); + if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() { + let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT"); if let Some(suggestion) = lev_distance::find_best_match_for_name( &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(), item_name.name, @@ -1062,7 +956,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if item_name.name == sym::as_str && actual.peel_refs().is_str() { + if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() { let msg = "remove this method call"; let mut fallback_span = true; if let SelfSource::MethodCall(expr) = source { @@ -1178,6 +1072,138 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } + /// Suggest calling `Ty::method` if `.method()` isn't found because the method + /// doesn't take a `self` receiver. + fn suggest_associated_call_syntax( + &self, + err: &mut Diagnostic, + static_candidates: &Vec<CandidateSource>, + rcvr_ty: Ty<'tcx>, + source: SelfSource<'tcx>, + item_name: Ident, + args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>, + sugg_span: Span, + ) { + let mut has_unsuggestable_args = false; + let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) { + // When the "method" is resolved through dereferencing, we really want the + // original type that has the associated function for accurate suggestions. + // (#61411) + let impl_ty = self.tcx.type_of(*impl_did); + let target_ty = self + .autoderef(sugg_span, rcvr_ty) + .find(|(rcvr_ty, _)| { + DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer } + .types_may_unify(*rcvr_ty, impl_ty) + }) + .map_or(impl_ty, |(ty, _)| ty) + .peel_refs(); + if let ty::Adt(def, substs) = target_ty.kind() { + // If there are any inferred arguments, (`{integer}`), we should replace + // them with underscores to allow the compiler to infer them + let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| { + if !arg.is_suggestable(self.tcx, true) { + has_unsuggestable_args = true; + match arg.unpack() { + GenericArgKind::Lifetime(_) => self + .next_region_var(RegionVariableOrigin::MiscVariable( + rustc_span::DUMMY_SP, + )) + .into(), + GenericArgKind::Type(_) => self + .next_ty_var(TypeVariableOrigin { + span: rustc_span::DUMMY_SP, + kind: TypeVariableOriginKind::MiscVariable, + }) + .into(), + GenericArgKind::Const(arg) => self + .next_const_var( + arg.ty(), + ConstVariableOrigin { + span: rustc_span::DUMMY_SP, + kind: ConstVariableOriginKind::MiscVariable, + }, + ) + .into(), + } + } else { + arg + } + })); + + self.tcx.value_path_str_with_substs(def.did(), infer_substs) + } else { + self.ty_to_value_string(target_ty) + } + } else { + self.ty_to_value_string(rcvr_ty.peel_refs()) + }; + if let SelfSource::MethodCall(_) = source { + let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) + && let Some(assoc) = self.associated_value(*impl_did, item_name) + && assoc.kind == ty::AssocKind::Fn + { + let sig = self.tcx.fn_sig(assoc.def_id); + if let Some(first) = sig.inputs().skip_binder().get(0) { + if first.peel_refs() == rcvr_ty.peel_refs() { + None + } else { + Some(if first.is_region_ptr() { + if first.is_mutable_ptr() { "&mut " } else { "&" } + } else { + "" + }) + } + } else { + None + } + } else { + None + }; + let mut applicability = Applicability::MachineApplicable; + let args = if let Some((receiver, args)) = args { + // The first arg is the same kind as the receiver + let explicit_args = if first_arg.is_some() { + std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>() + } else { + // There is no `Self` kind to infer the arguments from + if has_unsuggestable_args { + applicability = Applicability::HasPlaceholders; + } + args.iter().collect() + }; + format!( + "({}{})", + first_arg.unwrap_or(""), + explicit_args + .iter() + .map(|arg| self + .tcx + .sess + .source_map() + .span_to_snippet(arg.span) + .unwrap_or_else(|_| { + applicability = Applicability::HasPlaceholders; + "_".to_owned() + })) + .collect::<Vec<_>>() + .join(", "), + ) + } else { + applicability = Applicability::HasPlaceholders; + "(...)".to_owned() + }; + err.span_suggestion( + sugg_span, + "use associated function syntax instead", + format!("{}::{}{}", ty_str, item_name, args), + applicability, + ); + } else { + err.help(&format!("try with `{}::{}`", ty_str, item_name,)); + } + } + /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`. fn suggest_calling_field_as_fn( diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 78f355ec3d0..c8939256bbb 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -11,7 +11,8 @@ declare_lint! { /// scope. /// /// ### Example - /// ``` + /// + /// ```rust /// struct SomeStruct; /// impl Drop for SomeStruct { /// fn drop(&mut self) { diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 0d9b5a57b69..85c520a7911 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -9,7 +9,7 @@ #include "llvm/IR/IntrinsicsARM.h" #include "llvm/IR/Mangler.h" #if LLVM_VERSION_GE(16, 0) -#include "llvm/IR/ModRef.h" +#include "llvm/Support/ModRef.h" #endif #include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b48db73618b..bad6d587907 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -170,8 +170,6 @@ symbols! { Count, Cow, Debug, - DebugStruct, - DebugTuple, Decodable, Decoder, DecorateLint, @@ -190,9 +188,6 @@ symbols! { Error, File, FileType, - Fn, - FnMut, - FnOnce, FormatSpec, Formatter, From, @@ -211,7 +206,6 @@ symbols! { Input, Into, IntoDiagnostic, - IntoFuture, IntoIterator, IoRead, IoWrite, @@ -256,7 +250,6 @@ symbols! { Pointer, Poll, ProcMacro, - ProcMacroHack, ProceduralMasqueradeDummyType, Range, RangeFrom, @@ -332,7 +325,6 @@ symbols! { abi_vectorcall, abi_x86_interrupt, abort, - aborts, add, add_assign, add_with_overflow, @@ -344,7 +336,6 @@ symbols! { align, align_offset, alignment, - alignstack, all, alloc, alloc_error_handler, @@ -433,7 +424,6 @@ symbols! { bool, borrowck_graphviz_format, borrowck_graphviz_postflow, - borrowck_graphviz_preflow, box_free, box_patterns, box_syntax, @@ -462,7 +452,6 @@ symbols! { cfg_doctest, cfg_eval, cfg_hide, - cfg_macro, cfg_panic, cfg_sanitize, cfg_target_abi, @@ -470,7 +459,6 @@ symbols! { cfg_target_feature, cfg_target_has_atomic, cfg_target_has_atomic_equal_alignment, - cfg_target_has_atomic_load_store, cfg_target_thread_local, cfg_target_vendor, cfg_version, @@ -495,19 +483,15 @@ symbols! { cold, collapse_debuginfo, column, - column_macro, - compare_and_swap, compare_exchange, compare_exchange_weak, compile_error, - compile_error_macro, compiler, compiler_builtins, compiler_fence, concat, concat_bytes, concat_idents, - concat_macro, conservative_impl_trait, console, const_allocate, @@ -528,7 +512,6 @@ symbols! { const_fn_unsize, const_for, const_format_args, - const_generic_defaults, const_generics, const_generics_defaults, const_if_match, @@ -547,22 +530,19 @@ symbols! { const_trait, const_trait_bound_opt_out, const_trait_impl, - const_transmute, const_try, constant, constructor, - contents, context, - convert, copy, copy_closures, copy_nonoverlapping, copysignf32, copysignf64, core, - core_intrinsics, core_panic, core_panic_2015_macro, + core_panic_2021_macro, core_panic_macro, cosf32, cosf64, @@ -598,7 +578,6 @@ symbols! { debug_assertions, debug_struct, debug_struct_fields_finish, - debug_trait_builder, debug_tuple, debug_tuple_fields_finish, debugger_visualizer, @@ -630,7 +609,6 @@ symbols! { discriminant_type, discriminant_value, dispatch_from_dyn, - display_trait, div, div_assign, doc, @@ -661,7 +639,6 @@ symbols! { dyn_star, dyn_trait, e, - edition_macro_pats, edition_panic, eh_catch_typeinfo, eh_personality, @@ -674,7 +651,6 @@ symbols! { encode, end, env, - env_macro, eprint_macro, eprintln_macro, eq, @@ -724,9 +700,7 @@ symbols! { field, field_init_shorthand, file, - file_macro, fill, - finish, flags, float, float_to_int_unchecked, @@ -735,8 +709,6 @@ symbols! { fmaf32, fmaf64, fmt, - fmt_as_str, - fmt_internals, fmul_fast, fn_align, fn_must_use, @@ -751,7 +723,6 @@ symbols! { format_args_macro, format_args_nl, format_macro, - fp, freeze, freg, frem_fast, @@ -814,7 +785,6 @@ symbols! { ignore, impl_header_lifetime_elision, impl_lint_pass, - impl_macros, impl_trait_in_bindings, impl_trait_in_fn_trait_return, implied_by, @@ -826,7 +796,6 @@ symbols! { include, include_bytes, include_bytes_macro, - include_macro, include_str, include_str_macro, inclusive_range_syntax, @@ -844,7 +813,6 @@ symbols! { instruction_set, integer_: "integer", integral, - intel, into_future, into_iter, intra_doc_pointers, @@ -881,7 +849,6 @@ symbols! { lifetimes, likely, line, - line_macro, link, link_args, link_cfg, @@ -926,7 +893,6 @@ symbols! { masked, match_beginning_vert, match_default_bindings, - matches_macro, maxnumf32, maxnumf64, may_dangle, @@ -965,7 +931,6 @@ symbols! { modifiers, module, module_path, - module_path_macro, more_qualified_paths, more_struct_aliases, movbe_target_feature, @@ -1035,7 +1000,6 @@ symbols! { non_exhaustive, non_exhaustive_omitted_patterns_lint, non_modrs_mods, - none_error, nontemporal_store, noop_method_borrow, noop_method_clone, @@ -1060,7 +1024,6 @@ symbols! { optin_builtin_traits, option, option_env, - option_env_macro, options, or, or_patterns, @@ -1103,7 +1066,6 @@ symbols! { plugins, pointee_trait, pointer, - pointer_trait_fmt, poll, position, post_dash_lto: "post-lto", @@ -1130,7 +1092,6 @@ symbols! { proc_dash_macro: "proc-macro", proc_macro, proc_macro_attribute, - proc_macro_def_site, proc_macro_derive, proc_macro_expr, proc_macro_gen, @@ -1231,9 +1192,6 @@ symbols! { rust_cold_cc, rust_eh_catch_typeinfo, rust_eh_personality, - rust_eh_register_frames, - rust_eh_unregister_frames, - rust_oom, rustc, rustc_allocator, rustc_allocator_zeroed, @@ -1306,7 +1264,6 @@ symbols! { rustc_serialize, rustc_skip_array_during_method_dispatch, rustc_specialization_trait, - rustc_stable, rustc_std_internal_symbol, rustc_strict_coherence, rustc_symbol_name, @@ -1434,7 +1391,6 @@ symbols! { static_recursion, staticlib, std, - std_inject, std_panic, std_panic_2015_macro, std_panic_macro, @@ -1449,7 +1405,6 @@ symbols! { str_trim_start, strict_provenance, stringify, - stringify_macro, struct_field_attributes, struct_inherit, struct_variant, @@ -1477,10 +1432,8 @@ symbols! { target_has_atomic_load_store, target_os, target_pointer_width, - target_target_vendor, target_thread_local, target_vendor, - task, tbm_target_feature, termination, termination_trait, @@ -1492,7 +1445,6 @@ symbols! { test_removed_feature, test_runner, test_unstable_lint, - then_with, thread, thread_local, thread_local_macro, @@ -1524,7 +1476,6 @@ symbols! { try_trait_v2, tt, tuple, - tuple_from_req, tuple_indexing, tuple_trait, two_phase, @@ -1568,7 +1519,6 @@ symbols! { unreachable_2015, unreachable_2015_macro, unreachable_2021, - unreachable_2021_macro, unreachable_code, unreachable_display, unreachable_macro, @@ -1587,7 +1537,6 @@ symbols! { from crates.io via `Cargo.toml` instead?", untagged_unions, unused_imports, - unused_qualifications, unwind, unwind_attributes, unwind_safe_trait, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 98c13ffdafb..41b252a8265 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -650,41 +650,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { )) ); - if is_try_conversion { - let none_error = self - .tcx - .get_diagnostic_item(sym::none_error) - .map(|def_id| tcx.type_of(def_id)); - let should_convert_option_to_result = - Some(trait_ref.skip_binder().substs.type_at(1)) == none_error; - let should_convert_result_to_option = - Some(trait_ref.self_ty().skip_binder()) == none_error; - if should_convert_option_to_result { - err.span_suggestion_verbose( - span.shrink_to_lo(), - "consider converting the `Option<T>` into a `Result<T, _>` \ - using `Option::ok_or` or `Option::ok_or_else`", - ".ok_or_else(|| /* error value */)", - Applicability::HasPlaceholders, - ); - } else if should_convert_result_to_option { - err.span_suggestion_verbose( - span.shrink_to_lo(), - "consider converting the `Result<T, _>` into an `Option<T>` \ - using `Result::ok`", - ".ok()", - Applicability::MachineApplicable, - ); - } - if let Some(ret_span) = self.return_type_span(&obligation) { - err.span_label( - ret_span, - &format!( - "expected `{}` because of this", - trait_ref.skip_binder().self_ty() - ), - ); - } + if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) { + err.span_label( + ret_span, + &format!( + "expected `{}` because of this", + trait_ref.skip_binder().self_ty() + ), + ); } if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() { |
