From ef24de24a82fe681581cc130f342363c47c0969a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:48 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_hir_analysis/src/astconv/bounds.rs | 66 +++++++------ compiler/rustc_hir_analysis/src/astconv/errors.rs | 107 ++++++++++++++++++--- .../rustc_hir_analysis/src/astconv/generics.rs | 24 +++-- compiler/rustc_hir_analysis/src/astconv/lint.rs | 27 ++++-- compiler/rustc_hir_analysis/src/astconv/mod.rs | 91 +++++++++++++----- .../src/astconv/object_safety.rs | 2 +- 6 files changed, 232 insertions(+), 85 deletions(-) (limited to 'compiler/rustc_hir_analysis/src/astconv') diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 21611e9c5..3e700f2da 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; +use smallvec::SmallVec; use crate::astconv::{ AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter, @@ -28,15 +29,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let tcx = self.tcx(); // Try to find an unbound in bounds. - let mut unbound = None; + let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| { for ab in ast_bounds { if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { - if unbound.is_none() { - unbound = Some(&ptr.trait_ref); - } else { - tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { span }); - } + unbounds.push(ptr) } } }; @@ -51,33 +48,41 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } } + if unbounds.len() > 1 { + tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { + spans: unbounds.iter().map(|ptr| ptr.span).collect(), + }); + } + let sized_def_id = tcx.lang_items().sized_trait(); - match (&sized_def_id, unbound) { - (Some(sized_def_id), Some(tpb)) - if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) => - { - // There was in fact a `?Sized` bound, return without doing anything - return; - } - (_, Some(_)) => { - // There was a `?Trait` bound, but it was not `?Sized`; warn. - tcx.sess.span_warn( - span, - "default bound relaxed for a type parameter, but \ - this does nothing because the given bound is not \ - a default; only `?Sized` is supported", - ); - // Otherwise, add implicitly sized if `Sized` is available. - } - _ => { - // There was no `?Sized` bound; add implicitly sized if `Sized` is available. + + let mut seen_sized_unbound = false; + for unbound in unbounds { + if let Some(sized_def_id) = sized_def_id { + if unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) { + seen_sized_unbound = true; + continue; + } } + // There was a `?Trait` bound, but it was not `?Sized`; warn. + tcx.sess.span_warn( + unbound.span, + "relaxing a default bound only does something for `?Sized`; \ + all other traits are not bound by default", + ); } + + // If the above loop finished there was no `?Sized` bound; add implicitly sized if `Sized` is available. if sized_def_id.is_none() { // No lang item for `Sized`, so we can't add it as a bound. return; } - bounds.push_sized(tcx, self_ty, span); + if seen_sized_unbound { + // There was in fact a `?Sized` bound, return without doing anything + } else { + // There was no `?Sized` bound; add implicitly sized if `Sized` is available. + bounds.push_sized(tcx, self_ty, span); + } } /// This helper takes a *converted* parameter type (`param_ty`) @@ -284,6 +289,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { self.one_bound_for_assoc_type( || traits::supertraits(tcx, trait_ref), trait_ref.skip_binder().print_only_trait_name(), + None, binding.item_name, path_span, match binding.kind { @@ -447,7 +453,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { debug!(?args_trait_ref_and_assoc_item); - tcx.mk_alias_ty(assoc_item.def_id, args_trait_ref_and_assoc_item) + ty::AliasTy::new(tcx, assoc_item.def_id, args_trait_ref_and_assoc_item) }) }; @@ -517,8 +523,10 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ); if let DefKind::AssocConst = def_kind - && let Some(t) = term.ty() && (t.is_enum() || t.references_error()) - && tcx.features().associated_const_equality { + && let Some(t) = term.ty() + && (t.is_enum() || t.references_error()) + && tcx.features().associated_const_equality + { err.span_suggestion( binding.span, "if equating a const, try wrapping with braces", diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index ed4dde419..32be7e083 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -3,17 +3,18 @@ use crate::errors::{ AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, ParenthesizedFnTraitExpansion, }; +use crate::traits::error_reporting::report_object_safety_error; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::FulfillmentError; -use rustc_middle::ty::TyCtxt; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt}; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol, DUMMY_SP}; +use rustc_trait_selection::traits::object_safety_violations_for_assoc_item; use std::collections::BTreeSet; @@ -102,6 +103,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, all_candidates: impl Fn() -> I, ty_param_name: &str, + ty_param_def_id: Option, assoc_name: Ident, span: Span, ) -> ErrorGuaranteed @@ -190,13 +192,61 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) .collect::>()[..] { + let trait_name = self.tcx().def_path_str(*best_trait); + let an = if suggested_name != assoc_name.name { "a similarly named" } else { "an" }; err.span_label( assoc_name.span, format!( - "there is a similarly named associated type `{suggested_name}` in the trait `{}`", - self.tcx().def_path_str(*best_trait) + "there is {an} associated type `{suggested_name}` in the \ + trait `{trait_name}`", ), ); + let hir = self.tcx().hir(); + if let Some(def_id) = ty_param_def_id + && let parent = hir.get_parent_item(hir.local_def_id_to_hir_id(def_id)) + && let Some(generics) = hir.get_generics(parent.def_id) + { + if generics.bounds_for_param(def_id) + .flat_map(|pred| pred.bounds.iter()) + .any(|b| match b { + hir::GenericBound::Trait(t, ..) => { + t.trait_ref.trait_def_id().as_ref() == Some(best_trait) + } + _ => false, + }) + { + // The type param already has a bound for `trait_name`, we just need to + // change the associated type. + err.span_suggestion_verbose( + assoc_name.span, + format!( + "change the associated type name to use `{suggested_name}` from \ + `{trait_name}`", + ), + suggested_name.to_string(), + Applicability::MaybeIncorrect, + ); + } else if suggest_constraining_type_param( + self.tcx(), + generics, + &mut err, + &ty_param_name, + &trait_name, + None, + None, + ) + && suggested_name != assoc_name.name + { + // We suggested constraining a type parameter, but the associated type on it + // was also not an exact match, so we also suggest changing it. + err.span_suggestion_verbose( + assoc_name.span, + "and also change the associated type name", + suggested_name.to_string(), + Applicability::MaybeIncorrect, + ); + } + } return err.emit(); } } @@ -389,7 +439,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); let quiet_projection_ty = - tcx.mk_alias_ty(projection_ty.def_id, args_with_infer_self); + ty::AliasTy::new(tcx, projection_ty.def_id, args_with_infer_self); let term = pred.skip_binder().term; @@ -472,24 +522,33 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect()) }) .collect(); - let mut names = vec![]; + let mut names: FxHashMap> = Default::default(); + let mut names_len = 0; // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and // `issue-22560.rs`. let mut trait_bound_spans: Vec = vec![]; + let mut object_safety_violations = false; for (span, items) in &associated_types { if !items.is_empty() { trait_bound_spans.push(*span); } for assoc_item in items { let trait_def_id = assoc_item.container_id(tcx); - names.push(format!( - "`{}` (from trait `{}`)", - assoc_item.name, - tcx.def_path_str(trait_def_id), - )); + names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name); + names_len += 1; + + let violations = + object_safety_violations_for_assoc_item(tcx, trait_def_id, *assoc_item); + if !violations.is_empty() { + report_object_safety_error(tcx, *span, trait_def_id, &violations).emit(); + object_safety_violations = true; + } } } + if object_safety_violations { + return; + } if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) { match bound.trait_ref.path.segments { // FIXME: `trait_ref.path.span` can point to a full path with multiple @@ -525,15 +584,35 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { _ => {} } } + + let mut names = names + .into_iter() + .map(|(trait_, mut assocs)| { + assocs.sort(); + format!( + "{} in `{trait_}`", + match &assocs[..] { + [] => String::new(), + [only] => format!("`{only}`"), + [assocs @ .., last] => format!( + "{} and `{last}`", + assocs.iter().map(|a| format!("`{a}`")).collect::>().join(", ") + ), + } + ) + }) + .collect::>(); names.sort(); + let names = names.join(", "); + trait_bound_spans.sort(); let mut err = struct_span_err!( tcx.sess, trait_bound_spans, E0191, "the value of the associated type{} {} must be specified", - pluralize!(names.len()), - names.join(", "), + pluralize!(names_len), + names, ); let mut suggestions = vec![]; let mut types_count = 0; diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index e3621ef93..d29a27ece 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -429,12 +429,22 @@ pub(crate) fn check_generic_arg_count( .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })) .count(); let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count; + let synth_const_param_count = gen_params + .params + .iter() + .filter(|param| { + matches!(param.kind, ty::GenericParamDefKind::Const { is_host_effect: true, .. }) + }) + .count(); + let named_const_param_count = param_counts.consts - synth_const_param_count; let infer_lifetimes = (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params(); - if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() { - prohibit_assoc_ty_binding(tcx, b.span, None); - } + if gen_pos != GenericArgPosition::Type + && let Some(b) = gen_args.bindings.first() + { + prohibit_assoc_ty_binding(tcx, b.span, None); + } let explicit_late_bound = prohibit_explicit_late_bound_lifetimes(tcx, gen_params, gen_args, gen_pos); @@ -571,11 +581,13 @@ pub(crate) fn check_generic_arg_count( debug!(?expected_min); debug!(arg_counts.lifetimes=?gen_args.num_lifetime_params()); + let provided = gen_args.num_generic_params(); + check_types_and_consts( expected_min, - param_counts.consts + named_type_param_count, - param_counts.consts + named_type_param_count + synth_type_param_count, - gen_args.num_generic_params(), + named_const_param_count + named_type_param_count, + named_const_param_count + named_type_param_count + synth_type_param_count, + provided, param_counts.lifetimes + has_self as usize, gen_args.num_lifetime_params(), ) diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 1bd1270be..bc57bbcca 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -18,18 +18,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { - self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, .. + self_ty: impl_self_ty, + of_trait: Some(of_trait_ref), + generics, + .. }), .. - }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id + }) = tcx.hir().get_by_def_id(parent_id) + && self_ty.hir_id == impl_self_ty.hir_id { if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { return; } let of_trait_span = of_trait_ref.path.span; // make sure that we are not calling unwrap to abort during the compilation - let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; }; - let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; + let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { + return; + }; + let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { + return; + }; // check if the trait has generics, to make a correct suggestion let param_name = generics.params.next_type_param_name(None); @@ -39,13 +47,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (generics.span, format!("<{param_name}: {impl_trait_name}>")) }; diag.multipart_suggestion( - format!("alternatively use a blanket \ + format!( + "alternatively use a blanket \ implementation to implement `{of_trait_name}` for \ - all types that also implement `{impl_trait_name}`"), - vec![ - (self_ty.span, param_name), - add_generic_sugg, - ], + all types that also implement `{impl_trait_name}`" + ), + vec![(self_ty.span, param_name), add_generic_sugg], Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 56b1fd369..2fcb45ef8 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -36,7 +36,7 @@ use rustc_middle::ty::{ use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::{sym, Span, DUMMY_SP}; +use rustc_span::{sym, BytePos, Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt}; @@ -567,9 +567,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); if let ty::BoundConstness::ConstIfConst = constness - && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) + && generics.has_self + && !tcx.has_attr(def_id, sym::const_trait) { - tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } ); + tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span }); } (args, arg_count) @@ -915,7 +916,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Type aliases defined in crates that have the // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will // then actually instantiate the where bounds of. - let alias_ty = tcx.mk_alias_ty(did, args); + let alias_ty = ty::AliasTy::new(tcx, did, args); Ty::new_alias(tcx, ty::Weak, alias_ty) } else { tcx.at(span).type_of(did).instantiate(tcx, args) @@ -1017,7 +1018,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } err.span_suggestions( span, - "use the fully-qualified path", + "use fully-qualified syntax", suggestions, Applicability::MachineApplicable, ); @@ -1061,6 +1062,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) }, param_name, + Some(ty_param_def_id), assoc_name, span, None, @@ -1074,6 +1076,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, all_candidates: impl Fn() -> I, ty_param_name: impl Display, + ty_param_def_id: Option, assoc_name: Ident, span: Span, is_equality: Option>, @@ -1088,13 +1091,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name) }); - let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) { + let (mut bound, mut next_cand) = match (matching_candidates.next(), const_candidates.next()) + { (Some(bound), _) => (bound, matching_candidates.next()), (None, Some(bound)) => (bound, const_candidates.next()), (None, None) => { let reported = self.complain_about_assoc_type_not_found( all_candidates, &ty_param_name.to_string(), + ty_param_def_id, assoc_name, span, ); @@ -1103,6 +1108,37 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; debug!(?bound); + // look for a candidate that is not the same as our first bound, disregarding + // whether the bound is const. + while let Some(mut bound2) = next_cand { + debug!(?bound2); + let tcx = self.tcx(); + if bound2.bound_vars() != bound.bound_vars() { + break; + } + + let generics = tcx.generics_of(bound.def_id()); + let Some(host_index) = generics.host_effect_index else { break }; + + // always return the bound that contains the host param. + if let ty::ConstKind::Param(_) = bound2.skip_binder().args.const_at(host_index).kind() { + (bound, bound2) = (bound2, bound); + } + + let unconsted_args = bound + .skip_binder() + .args + .iter() + .enumerate() + .map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg }); + + if unconsted_args.eq(bound2.skip_binder().args.iter()) { + next_cand = matching_candidates.next().or_else(|| const_candidates.next()); + } else { + break; + } + } + if let Some(bound2) = next_cand { debug!(?bound2); @@ -1142,30 +1178,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_label( bound_span, format!( - "ambiguous `{}` from `{}`", - assoc_name, + "ambiguous `{assoc_name}` from `{}`", bound.print_only_trait_path(), ), ); if let Some(constraint) = &is_equality { where_bounds.push(format!( - " T: {trait}::{assoc} = {constraint}", + " T: {trait}::{assoc_name} = {constraint}", trait=bound.print_only_trait_path(), - assoc=assoc_name, - constraint=constraint, )); } else { err.span_suggestion_verbose( span.with_hi(assoc_name.span.lo()), - "use fully qualified syntax to disambiguate", - format!("<{} as {}>::", ty_param_name, bound.print_only_trait_path()), + "use fully-qualified syntax to disambiguate", + format!("<{ty_param_name} as {}>::", bound.print_only_trait_path()), Applicability::MaybeIncorrect, ); } } else { err.note(format!( - "associated type `{}` could derive from `{}`", - ty_param_name, + "associated type `{ty_param_name}` could derive from `{}`", bound.print_only_trait_path(), )); } @@ -1173,8 +1205,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if !where_bounds.is_empty() { err.help(format!( "consider introducing a new type parameter `T` and adding `where` constraints:\ - \n where\n T: {},\n{}", - ty_param_name, + \n where\n T: {ty_param_name},\n{}", where_bounds.join(",\n"), )); } @@ -1275,8 +1306,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return; }; // Get the span of the generics args *including* the leading `::`. - let args_span = - assoc_segment.ident.span.shrink_to_hi().to(args.span_ext); + // We do so by stretching args.span_ext to the left by 2. Earlier + // it was done based on the end of assoc segment but that sometimes + // led to impossible spans and caused issues like #116473 + let args_span = args.span_ext.with_lo(args.span_ext.lo() - BytePos(2)); if tcx.generics_of(adt_def.did()).count() == 0 { // FIXME(estebank): we could also verify that the arguments being // work for the `enum`, instead of just looking if it takes *any*. @@ -1394,6 +1427,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) }, kw::SelfUpper, + None, assoc_ident, span, None, @@ -1684,7 +1718,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .chain(args.into_iter().skip(parent_args.len())), ); - let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, args)); + let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args)); return Ok(Some((ty, assoc_item))); } @@ -1917,9 +1951,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { Some(( match segment.res { - Res::PrimTy(ty) => format!("{} `{}`", segment.res.descr(), ty.name()), + Res::PrimTy(ty) => { + format!("{} `{}`", segment.res.descr(), ty.name()) + } Res::Def(_, def_id) - if let Some(name) = self.tcx().opt_item_name(def_id) => { + if let Some(name) = self.tcx().opt_item_name(def_id) => + { format!("{} `{name}`", segment.res.descr()) } Res::Err => "this type".to_string(), @@ -2249,7 +2286,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.note(msg); } for segment in path.segments { - if let Some(args) = segment.args && segment.ident.name == kw::SelfUpper { + if let Some(args) = segment.args + && segment.ident.name == kw::SelfUpper + { if generics == 0 { // FIXME(estebank): we could also verify that the arguments being // work for the `enum`, instead of just looking if it takes *any*. @@ -2631,7 +2670,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .iter() .enumerate() .map(|(i, a)| { - if let hir::TyKind::Infer = a.kind && !self.allow_ty_infer() { + if let hir::TyKind::Infer = a.kind + && !self.allow_ty_infer() + { if let Some(suggested_ty) = self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) { @@ -2660,7 +2701,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_ty_to_ty(output) } } - hir::FnRetTy::DefaultReturn(..) => Ty::new_unit(tcx,), + hir::FnRetTy::DefaultReturn(..) => Ty::new_unit(tcx), }; debug!(?output_ty); diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 30c2ab8f5..00ff3f836 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -380,7 +380,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, E0228, "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound" + from context; please supply an explicit bound" ); let e = if borrowed { // We will have already emitted an error E0106 complaining about a -- cgit v1.2.3