diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
5 files changed, 108 insertions, 74 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index bc654c24b2f..90469227a26 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -241,14 +241,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } None => { - self.re_infer(def, lifetime.span).unwrap_or_else(|| { + self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| { debug!(?lifetime, "unelided lifetime in signature"); // This indicates an illegal lifetime // elision. `resolve_lifetime` should have // reported an error in this case -- but if // not, let's error out. - tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature"); + tcx.sess.delay_span_bug(lifetime.ident.span, "unelided lifetime in signature"); // Supply some dummy value. We don't have an // `re_error`, annoyingly, so use `'static`. @@ -961,9 +961,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::GenericBound::Outlives(lifetime) => { let region = self.ast_region_to_region(lifetime, None); - bounds - .region_bounds - .push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span)); + bounds.region_bounds.push(( + ty::Binder::bind_with_vars(region, bound_vars), + lifetime.ident.span, + )); } } } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index b369a1eb109..639f81f20bf 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -398,7 +398,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {} Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {} Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => { - self.has_late_bound_regions = Some(lt.span); + self.has_late_bound_regions = Some(lt.ident.span); } } } diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index da1c04f3f7b..c11eed7ad9e 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -595,7 +595,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.visit_poly_trait_ref(bound); } }); - match lifetime.name { + match lifetime.res { LifetimeName::ImplicitObjectLifetimeDefault => { // If the user does not write *anything*, we // use the object lifetime defaulting @@ -686,7 +686,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { if !parent_id.is_owner() { struct_span_err!( self.tcx.sess, - lifetime.span, + lifetime.ident.span, E0657, "`impl Trait` can only capture lifetimes bound at the fn or impl level" ) @@ -698,7 +698,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) = self.tcx.hir().get(parent_id) { let mut err = self.tcx.sess.struct_span_err( - lifetime.span, + lifetime.ident.span, "higher kinded lifetime bounds on nested opaque types are not supported yet", ); err.span_note(self.tcx.def_span(def_id), "lifetime declared here"); @@ -802,9 +802,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { - match lifetime_ref.name { + match lifetime_ref.res { hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static), - hir::LifetimeName::Param(param_def_id, _) => { + hir::LifetimeName::Param(param_def_id) => { self.resolve_lifetime_ref(param_def_id, lifetime_ref) } // If we've already reported an error, just ignore `lifetime_ref`. @@ -912,27 +912,27 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.visit_lifetime(lifetime); walk_list!(this, visit_param_bound, bounds); - if lifetime.name != hir::LifetimeName::Static { + if lifetime.res != hir::LifetimeName::Static { for bound in bounds { let hir::GenericBound::Outlives(ref lt) = bound else { continue; }; - if lt.name != hir::LifetimeName::Static { + if lt.res != hir::LifetimeName::Static { continue; } this.insert_lifetime(lt, Region::Static); this.tcx .sess .struct_span_warn( - lifetime.span, + lifetime.ident.span, &format!( "unnecessary lifetime parameter `{}`", - lifetime.name.ident(), + lifetime.ident, ), ) .help(&format!( "you can use the `'static` lifetime directly, in place of `{}`", - lifetime.name.ident(), + lifetime.ident, )) .emit(); } @@ -1043,7 +1043,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje for bound in bound.bounds { if let hir::GenericBound::Outlives(ref lifetime) = *bound { - set.insert(lifetime.name.normalize_to_macros_2_0()); + set.insert(lifetime.res); } } } @@ -1051,7 +1051,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje match set { Set1::Empty => ObjectLifetimeDefault::Empty, Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static, - Set1::One(hir::LifetimeName::Param(param_def_id, _)) => { + Set1::One(hir::LifetimeName::Param(param_def_id)) => { ObjectLifetimeDefault::Param(param_def_id.to_def_id()) } _ => ObjectLifetimeDefault::Ambiguous, @@ -1195,42 +1195,50 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in // regular fns. if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin - && let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name + && let hir::LifetimeName::Param(_) = lifetime_ref.res + && lifetime_ref.is_anonymous() && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) && !self.tcx.features().anonymous_lifetime_in_impl_trait { let mut diag = rustc_session::parse::feature_err( &self.tcx.sess.parse_sess, sym::anonymous_lifetime_in_impl_trait, - lifetime_ref.span, + lifetime_ref.ident.span, "anonymous lifetimes in `impl Trait` are unstable", ); - match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) { - Some(generics) => { - - let new_param_sugg_tuple; - - new_param_sugg_tuple = match generics.span_for_param_suggestion() { - Some(_) => { - Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned())) - }, - None => Some((generics.span, "<'a>".to_owned())) - }; - - let mut multi_sugg_vec = vec![(lifetime_ref.span.shrink_to_hi(), "'a ".to_owned())]; - - if let Some(new_tuple) = new_param_sugg_tuple{ - multi_sugg_vec.push(new_tuple); - } - - diag.span_label(lifetime_ref.span, "expected named lifetime parameter"); - diag.multipart_suggestion("consider introducing a named lifetime parameter", - multi_sugg_vec, - rustc_errors::Applicability::MaybeIncorrect); - - }, - None => { } + if let Some(generics) = + self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) + { + let new_param_sugg = if let Some(span) = + generics.span_for_lifetime_suggestion() + { + (span, "'a, ".to_owned()) + } else { + (generics.span, "<'a>".to_owned()) + }; + + let lifetime_sugg = match lifetime_ref.suggestion_position() { + (hir::LifetimeSuggestionPosition::Normal, span) => (span, "'a".to_owned()), + (hir::LifetimeSuggestionPosition::Ampersand, span) => (span, "'a ".to_owned()), + (hir::LifetimeSuggestionPosition::ElidedPath, span) => (span, "<'a>".to_owned()), + (hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => (span, "'a, ".to_owned()), + (hir::LifetimeSuggestionPosition::ObjectDefault, span) => (span, "+ 'a".to_owned()), + }; + let suggestions = vec![ + lifetime_sugg, + new_param_sugg, + ]; + + diag.span_label( + lifetime_ref.ident.span, + "expected named lifetime parameter", + ); + diag.multipart_suggestion( + "consider introducing a named lifetime parameter", + suggestions, + rustc_errors::Applicability::MaybeIncorrect, + ); } diag.emit(); @@ -1287,7 +1295,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), .. } => { let mut err = self.tcx.sess.struct_span_err( - lifetime_ref.span, + lifetime_ref.ident.span, "`impl Trait` can only mention lifetimes bound at the fn or impl level", ); err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here"); @@ -1307,7 +1315,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } self.tcx.sess.delay_span_bug( - lifetime_ref.span, + lifetime_ref.ident.span, &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,), ); } @@ -1625,10 +1633,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) { - debug!( - node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id), - span = ?self.tcx.sess.source_map().span_to_diagnostic_string(lifetime_ref.span) - ); + debug!(span = ?lifetime_ref.ident.span); self.map.defs.insert(lifetime_ref.hir_id, def); } @@ -1839,7 +1844,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< } fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) { - if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name { + if let hir::LifetimeName::Param(def_id) = lifetime_ref.res { self.regions.insert(def_id); } } @@ -1852,7 +1857,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet< impl<'v> Visitor<'v> for AllCollector { fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) { - if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name { + if let hir::LifetimeName::Param(def_id) = lifetime_ref.res { self.regions.insert(def_id); } } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 9417a2620d1..45e241f4e09 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -229,7 +229,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP predicates.extend(region_pred.bounds.iter().map(|bound| { let (r2, span) = match bound { hir::GenericBound::Outlives(lt) => { - (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.span) + (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span) } _ => bug!(), }; diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 9c77387c238..4451db19f5c 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -296,25 +296,35 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ) -> String { debug!(?path_hir_id); + // If there was already a lifetime among the arguments, just replicate that one. + if let Some(lt) = self.gen_args.args.iter().find_map(|arg| match arg { + hir::GenericArg::Lifetime(lt) => Some(lt), + _ => None, + }) { + return std::iter::repeat(lt.to_string()) + .take(num_params_to_take) + .collect::<Vec<_>>() + .join(", "); + } + let mut ret = Vec::new(); + let mut ty_id = None; for (id, node) in self.tcx.hir().parent_iter(path_hir_id) { debug!(?id); - let params = if let Some(generics) = node.generics() { - generics.params - } else if let hir::Node::Ty(ty) = node - && let hir::TyKind::BareFn(bare_fn) = ty.kind - { - bare_fn.generic_params - } else { - &[] - }; - ret.extend(params.iter().filter_map(|p| { - let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } - = p.kind - else { return None }; - let hir::ParamName::Plain(name) = p.name else { return None }; - Some(name.to_string()) - })); + if let hir::Node::Ty(_) = node { + ty_id = Some(id); + } + + // Suggest `'_` when in function parameter or elided function return. + if let Some(fn_decl) = node.fn_decl() && let Some(ty_id) = ty_id { + let in_arg = fn_decl.inputs.iter().any(|t| t.hir_id == ty_id); + let in_ret = matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id); + + if in_arg || (in_ret && fn_decl.lifetime_elision_allowed) { + return std::iter::repeat("'_".to_owned()).take(num_params_to_take).collect::<Vec<_>>().join(", "); + } + } + // Suggest `'static` when in const/static item-like. if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. }, @@ -334,11 +344,29 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { }) | hir::Node::AnonConst(..) = node { - ret.extend( - std::iter::repeat("'static".to_owned()) - .take(num_params_to_take.saturating_sub(ret.len())), - ); + return std::iter::repeat("'static".to_owned()) + .take(num_params_to_take.saturating_sub(ret.len())) + .collect::<Vec<_>>() + .join(", "); } + + let params = if let Some(generics) = node.generics() { + generics.params + } else if let hir::Node::Ty(ty) = node + && let hir::TyKind::BareFn(bare_fn) = ty.kind + { + bare_fn.generic_params + } else { + &[] + }; + ret.extend(params.iter().filter_map(|p| { + let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } + = p.kind + else { return None }; + let hir::ParamName::Plain(name) = p.name else { return None }; + Some(name.to_string()) + })); + if ret.len() >= num_params_to_take { return ret[..num_params_to_take].join(", "); } |
