diff options
| author | bors <bors@rust-lang.org> | 2024-02-18 06:02:16 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-02-18 06:02:16 +0000 |
| commit | 23a3d777c8a95715977608c827de63e7738fa228 (patch) | |
| tree | 5949d078451a4e3375461cbd56d7992ac6ef41c9 /compiler | |
| parent | d3df8ff85121146f2ac5e863e0c9eaba4bf35d32 (diff) | |
| parent | 5628786484217e92f511c74b0a0427ff71562e43 (diff) | |
| download | rust-23a3d777c8a95715977608c827de63e7738fa228.tar.gz rust-23a3d777c8a95715977608c827de63e7738fa228.zip | |
Auto merge of #121252 - fmease:rollup-x7zogl8, r=fmease
Rollup of 7 pull requests Successful merges: - #120526 (rustdoc: Correctly handle long crate names on mobile) - #121100 (Detect when method call on argument could be removed to fulfill failed trait bound) - #121160 (rustdoc: fix and refactor HTML rendering a bit) - #121198 (Add more checks for `unnamed_fields` during HIR analysis) - #121218 (Fix missing trait impls for type in rustc docs) - #121221 (AstConv: Refactor lowering of associated item bindings a bit) - #121237 (Use better heuristic for printing Cargo specific diagnostics) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/errors.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/messages.ftl | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/bounds.rs | 164 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/errors.rs | 45 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/mod.rs | 91 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/errors.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/errors.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_incremental/src/persist/fs.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/context/diagnostics.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_session/src/utils.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs | 20 |
15 files changed, 210 insertions, 195 deletions
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 3d7903b5efb..e42a8bd9ed9 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -362,8 +362,11 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for LinkingFailed<'_> { // which by now we have no way to translate. if contains_undefined_ref { diag.note(fluent::codegen_ssa_extern_funcs_not_found) - .note(fluent::codegen_ssa_specify_libraries_to_link) - .note(fluent::codegen_ssa_use_cargo_directive); + .note(fluent::codegen_ssa_specify_libraries_to_link); + + if rustc_session::utils::was_invoked_from_cargo() { + diag.note(fluent::codegen_ssa_use_cargo_directive); + } } diag } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 77044df9a40..fcb15925f6a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2998,6 +2998,12 @@ impl<'hir> Item<'hir> { ItemId { owner_id: self.owner_id } } + /// Check if this is an [`ItemKind::Enum`], [`ItemKind::Struct`] or + /// [`ItemKind::Union`]. + pub fn is_adt(&self) -> bool { + matches!(self.kind, ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..)) + } + expect_methods_self_kind! { expect_extern_crate, Option<Symbol>, ItemKind::ExternCrate(s), *s; diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index a61cfd0e4ce..f32b14aca23 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -198,6 +198,8 @@ hir_analysis_invalid_union_field = hir_analysis_invalid_union_field_sugg = wrap the field type in `ManuallyDrop<...>` +hir_analysis_invalid_unnamed_field_ty = unnamed fields can only have struct or union types + hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl .label = const parameter declared here diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index dab1e2d5253..6940b4a5045 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -9,9 +9,7 @@ use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; use smallvec::SmallVec; -use crate::astconv::{ - AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter, -}; +use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter}; use crate::bounds::Bounds; use crate::errors; @@ -238,7 +236,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { &self, hir_ref_id: hir::HirId, trait_ref: ty::PolyTraitRef<'tcx>, - binding: &ConvertedBinding<'_, 'tcx>, + binding: &hir::TypeBinding<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, dup_bindings: &mut FxIndexMap<DefId, Span>, @@ -263,21 +261,20 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let tcx = self.tcx(); - let assoc_kind = - if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { - ty::AssocKind::Fn - } else if let ConvertedBindingKind::Equality(term) = binding.kind - && let ty::TermKind::Const(_) = term.node.unpack() - { - ty::AssocKind::Const - } else { - ty::AssocKind::Type - }; + let assoc_kind = if binding.gen_args.parenthesized + == hir::GenericArgsParentheses::ReturnTypeNotation + { + ty::AssocKind::Fn + } else if let hir::TypeBindingKind::Equality { term: hir::Term::Const(_) } = binding.kind { + ty::AssocKind::Const + } else { + ty::AssocKind::Type + }; let candidate = if self.trait_defines_associated_item_named( trait_ref.def_id(), assoc_kind, - binding.item_name, + binding.ident, ) { // Simple case: The assoc item is defined in the current trait. trait_ref @@ -289,14 +286,14 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { trait_ref.skip_binder().print_only_trait_name(), None, assoc_kind, - binding.item_name, + binding.ident, path_span, - Some(&binding), + Some(binding), )? }; let (assoc_ident, def_scope) = - tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); + tcx.adjust_ident_and_get_scope(binding.ident, candidate.def_id(), hir_ref_id); // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` // instead of calling `filter_by_name_and_kind` which would needlessly normalize the @@ -312,7 +309,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { .dcx() .struct_span_err( binding.span, - format!("{} `{}` is private", assoc_item.kind, binding.item_name), + format!("{} `{}` is private", assoc_item.kind, binding.ident), ) .with_span_label(binding.span, format!("private {}", assoc_item.kind)) .emit(); @@ -327,7 +324,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { tcx.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified { span: binding.span, prev_span: *prev_span, - item_name: binding.item_name, + item_name: binding.ident, def_path: tcx.def_path_str(assoc_item.container_id(tcx)), }); }) @@ -390,14 +387,12 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { { alias_ty } else { - return Err(self.tcx().dcx().emit_err( - crate::errors::ReturnTypeNotationOnNonRpitit { - span: binding.span, - ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), - fn_span: tcx.hir().span_if_local(assoc_item.def_id), - note: (), - }, - )); + return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit { + span: binding.span, + ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), + fn_span: tcx.hir().span_if_local(assoc_item.def_id), + note: (), + })); }; // Finally, move the fn return type's bound vars over to account for the early bound @@ -410,9 +405,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let bound_vars = tcx.late_bound_vars(binding.hir_id); ty::Binder::bind_with_vars(instantiation_output, bound_vars) } else { - // Append the generic arguments of the associated type to the `trait_ref`. + // Create the generic arguments for the associated type or constant by joining the + // parent arguments (the arguments of the trait) and the own arguments (the ones of + // the associated item itself) and construct an alias type using them. candidate.map_bound(|trait_ref| { - let ident = Ident::new(assoc_item.name, binding.item_name.span); + let ident = Ident::new(assoc_item.name, binding.ident.span); let item_segment = hir::PathSegment { ident, hir_id: binding.hir_id, @@ -421,77 +418,82 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { infer_args: false, }; - let args_trait_ref_and_assoc_item = self.create_args_for_associated_item( + let alias_args = self.create_args_for_associated_item( path_span, assoc_item.def_id, &item_segment, trait_ref.args, ); + debug!(?alias_args); - debug!(?args_trait_ref_and_assoc_item); - - ty::AliasTy::new(tcx, assoc_item.def_id, args_trait_ref_and_assoc_item) + // Note that we're indeed also using `AliasTy` (alias *type*) for associated + // *constants* to represent *const projections*. Alias *term* would be a more + // appropriate name but alas. + ty::AliasTy::new(tcx, assoc_item.def_id, alias_args) }) }; - if !speculative { - // Find any late-bound regions declared in `ty` that are not - // declared in the trait-ref or assoc_item. These are not well-formed. - // - // Example: - // - // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad - // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok - if let ConvertedBindingKind::Equality(ty) = binding.kind { - let late_bound_in_trait_ref = - tcx.collect_constrained_late_bound_regions(&projection_ty); - let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty.node)); - debug!(?late_bound_in_trait_ref); - debug!(?late_bound_in_ty); - - // FIXME: point at the type params that don't have appropriate lifetimes: - // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); - // ---- ---- ^^^^^^^ - self.validate_late_bound_regions( - late_bound_in_trait_ref, - late_bound_in_ty, - |br_name| { - struct_span_code_err!( - tcx.dcx(), - binding.span, - E0582, - "binding for associated type `{}` references {}, \ - which does not appear in the trait input types", - binding.item_name, - br_name - ) - }, - ); - } - } - match binding.kind { - ConvertedBindingKind::Equality(..) if let ty::AssocKind::Fn = assoc_kind => { - return Err(self.tcx().dcx().emit_err( - crate::errors::ReturnTypeNotationEqualityBound { span: binding.span }, - )); + hir::TypeBindingKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => { + return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound { + span: binding.span, + })); } - ConvertedBindingKind::Equality(term) => { + hir::TypeBindingKind::Equality { term } => { + let term = match term { + hir::Term::Ty(ty) => self.ast_ty_to_ty(ty).into(), + hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(), + }; + + if !speculative { + // Find any late-bound regions declared in `ty` that are not + // declared in the trait-ref or assoc_item. These are not well-formed. + // + // Example: + // + // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad + // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok + let late_bound_in_projection_ty = + tcx.collect_constrained_late_bound_regions(&projection_ty); + let late_bound_in_term = + tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(term)); + debug!(?late_bound_in_projection_ty); + debug!(?late_bound_in_term); + + // FIXME: point at the type params that don't have appropriate lifetimes: + // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); + // ---- ---- ^^^^^^^ + // NOTE(associated_const_equality): This error should be impossible to trigger + // with associated const equality bounds. + self.validate_late_bound_regions( + late_bound_in_projection_ty, + late_bound_in_term, + |br_name| { + struct_span_code_err!( + tcx.dcx(), + binding.span, + E0582, + "binding for associated type `{}` references {}, \ + which does not appear in the trait input types", + binding.ident, + br_name + ) + }, + ); + } + // "Desugar" a constraint like `T: Iterator<Item = u32>` this to // the "projection predicate" for: // // `<T as Iterator>::Item = u32` bounds.push_projection_bound( tcx, - projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { - projection_ty, - term: term.node, - }), + projection_ty + .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), binding.span, ); } - ConvertedBindingKind::Constraint(ast_bounds) => { + hir::TypeBindingKind::Constraint { bounds: ast_bounds } => { // "Desugar" a constraint like `T: Iterator<Item: Debug>` to // // `<T as Iterator>::Item: Debug` diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index ea8d364bba6..ad34c31ef8f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -1,4 +1,4 @@ -use crate::astconv::{AstConv, ConvertedBindingKind}; +use crate::astconv::AstConv; use crate::errors::{ self, AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, ParenthesizedFnTraitExpansion, @@ -111,7 +111,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assoc_kind: ty::AssocKind, assoc_name: Ident, span: Span, - binding: Option<&super::ConvertedBinding<'_, 'tcx>>, + binding: Option<&hir::TypeBinding<'tcx>>, ) -> ErrorGuaranteed where I: Iterator<Item = ty::PolyTraitRef<'tcx>>, @@ -243,7 +243,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { None, ) && suggested_name != assoc_name.name { - // We suggested constraining a type parameter, but the associated type on it + // We suggested constraining a type parameter, but the associated item on it // was also not an exact match, so we also suggest changing it. err.span_suggestion_verbose( assoc_name.span, @@ -258,16 +258,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - // If we still couldn't find any associated type, and only one associated type exists, + // If we still couldn't find any associated item, and only one associated item exists, // suggests using it. if let [candidate_name] = all_candidate_names.as_slice() { - // this should still compile, except on `#![feature(associated_type_defaults)]` - // where it could suggests `type A = Self::A`, thus recursing infinitely - let applicability = if tcx.features().associated_type_defaults { - Applicability::Unspecified - } else { - Applicability::MaybeIncorrect - }; + // This should still compile, except on `#![feature(associated_type_defaults)]` + // where it could suggests `type A = Self::A`, thus recursing infinitely. + let applicability = + if assoc_kind == ty::AssocKind::Type && tcx.features().associated_type_defaults { + Applicability::Unspecified + } else { + Applicability::MaybeIncorrect + }; err.sugg = Some(errors::AssocItemNotFoundSugg::Other { span: assoc_name.span, @@ -289,13 +290,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assoc_kind: ty::AssocKind, ident: Ident, span: Span, - binding: Option<&super::ConvertedBinding<'_, 'tcx>>, + binding: Option<&hir::TypeBinding<'tcx>>, ) -> ErrorGuaranteed { let tcx = self.tcx(); let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind && let Some(binding) = binding - && let ConvertedBindingKind::Constraint(_) = binding.kind + && let hir::TypeBindingKind::Constraint { .. } = binding.kind { let lo = if binding.gen_args.span_ext.is_dummy() { ident.span @@ -309,25 +310,29 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // FIXME(associated_const_equality): This has quite a few false positives and negatives. let wrap_in_braces_sugg = if let Some(binding) = binding - && let ConvertedBindingKind::Equality(term) = binding.kind - && let ty::TermKind::Ty(ty) = term.node.unpack() + && let hir::TypeBindingKind::Equality { term: hir::Term::Ty(hir_ty) } = binding.kind + && let ty = self.ast_ty_to_ty(hir_ty) && (ty.is_enum() || ty.references_error()) && tcx.features().associated_const_equality { Some(errors::AssocKindMismatchWrapInBracesSugg { - lo: term.span.shrink_to_lo(), - hi: term.span.shrink_to_hi(), + lo: hir_ty.span.shrink_to_lo(), + hi: hir_ty.span.shrink_to_hi(), }) } else { None }; // For equality bounds, we want to blame the term (RHS) instead of the item (LHS) since - // one can argue that that's more “untuitive” to the user. + // one can argue that that's more “intuitive” to the user. let (span, expected_because_label, expected, got) = if let Some(binding) = binding - && let ConvertedBindingKind::Equality(term) = binding.kind + && let hir::TypeBindingKind::Equality { term } = binding.kind { - (term.span, Some(ident.span), assoc_item.kind, assoc_kind) + let span = match term { + hir::Term::Ty(ty) => ty.span, + hir::Term::Const(ct) => tcx.def_span(ct.def_id), + }; + (span, Some(ident.span), assoc_item.kind, assoc_kind) } else { (ident.span, None, assoc_kind, assoc_item.kind) }; diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 94c49453cdc..3ccf78567ed 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -35,7 +35,6 @@ 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::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{sym, BytePos, Span, DUMMY_SP}; use rustc_target::spec::abi; @@ -151,21 +150,6 @@ pub trait AstConv<'tcx> { fn infcx(&self) -> Option<&InferCtxt<'tcx>>; } -#[derive(Debug)] -struct ConvertedBinding<'a, 'tcx> { - hir_id: hir::HirId, - item_name: Ident, - kind: ConvertedBindingKind<'a, 'tcx>, - gen_args: &'tcx GenericArgs<'tcx>, - span: Span, -} - -#[derive(Debug)] -enum ConvertedBindingKind<'a, 'tcx> { - Equality(Spanned<ty::Term<'tcx>>), - Constraint(&'a [hir::GenericBound<'tcx>]), -} - /// New-typed boolean indicating whether explicit late-bound lifetimes /// are present in a set of generic arguments. /// @@ -316,7 +300,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Given the type/lifetime/const arguments provided to some path (along with /// an implicit `Self`, if this is a trait reference), returns the complete /// set of generic arguments. This may involve applying defaulted type parameters. - /// Constraints on associated types are created from `create_assoc_bindings_for_generic_args`. + /// + /// Constraints on associated types are not converted here but + /// separately in `add_predicates_for_ast_type_binding`. /// /// Example: /// @@ -329,8 +315,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// 2. The path in question is the path to the trait `std::ops::Index`, /// which will have been resolved to a `def_id` /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type - /// parameters are returned in the `GenericArgsRef`, the associated type bindings like - /// `Output = u32` are returned from `create_assoc_bindings_for_generic_args`. + /// parameters are returned in the `GenericArgsRef` + /// 4. Associated type bindings like `Output = u32` are contained in `generic_args.bindings`. /// /// Note that the type listing given here is *exactly* what the user provided. /// @@ -591,52 +577,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (args, arg_count) } - fn create_assoc_bindings_for_generic_args<'a>( - &self, - generic_args: &'a hir::GenericArgs<'tcx>, - ) -> Vec<ConvertedBinding<'a, 'tcx>> { - // Convert associated-type bindings or constraints into a separate vector. - // Example: Given this: - // - // T: Iterator<Item = u32> - // - // The `T` is passed in as a self-type; the `Item = u32` is - // not a "type parameter" of the `Iterator` trait, but rather - // a restriction on `<T as Iterator>::Item`, so it is passed - // back separately. - let assoc_bindings = generic_args - .bindings - .iter() - .map(|binding| { - let kind = match &binding.kind { - hir::TypeBindingKind::Equality { term } => match term { - hir::Term::Ty(ty) => ConvertedBindingKind::Equality(respan( - ty.span, - self.ast_ty_to_ty(ty).into(), - )), - hir::Term::Const(c) => { - let span = self.tcx().def_span(c.def_id); - let c = Const::from_anon_const(self.tcx(), c.def_id); - ConvertedBindingKind::Equality(respan(span, c.into())) - } - }, - hir::TypeBindingKind::Constraint { bounds } => { - ConvertedBindingKind::Constraint(bounds) - } - }; - ConvertedBinding { - hir_id: binding.hir_id, - item_name: binding.ident, - kind, - gen_args: binding.gen_args, - span: binding.span, - } - }) - .collect(); - - assoc_bindings - } - pub fn create_args_for_associated_item( &self, span: Span, @@ -742,18 +682,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); debug!(?bound_vars); - let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); - let poly_trait_ref = ty::Binder::bind_with_vars( ty::TraitRef::new(tcx, trait_def_id, generic_args), bound_vars, ); - debug!(?poly_trait_ref, ?assoc_bindings); + debug!(?poly_trait_ref); bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); let mut dup_bindings = FxIndexMap::default(); - for binding in &assoc_bindings { + for binding in args.bindings { // Don't register additional associated type bounds for negative bounds, // since we should have emitten an error for them earlier, and they will // not be well-formed! @@ -1029,7 +967,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assoc_kind: ty::AssocKind, assoc_name: Ident, span: Span, - binding: Option<&ConvertedBinding<'_, 'tcx>>, + binding: Option<&hir::TypeBinding<'tcx>>, ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> where I: Iterator<Item = ty::PolyTraitRef<'tcx>>, @@ -1069,7 +1007,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Provide a more specific error code index entry for equality bindings. err.code( if let Some(binding) = binding - && let ConvertedBindingKind::Equality(_) = binding.kind + && let hir::TypeBindingKind::Equality { .. } = binding.kind { E0222 } else { @@ -1094,16 +1032,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); if let Some(binding) = binding { match binding.kind { - ConvertedBindingKind::Equality(term) => { + hir::TypeBindingKind::Equality { term } => { + let term: ty::Term<'_> = match term { + hir::Term::Ty(ty) => self.ast_ty_to_ty(ty).into(), + hir::Term::Const(ct) => { + ty::Const::from_anon_const(tcx, ct.def_id).into() + } + }; // FIXME(#97583): This isn't syntactically well-formed! where_bounds.push(format!( " T: {trait}::{assoc_name} = {term}", trait = bound.print_only_trait_path(), - term = term.node, )); } // FIXME: Provide a suggestion. - ConvertedBindingKind::Constraint(_bounds) => {} + hir::TypeBindingKind::Constraint { bounds: _ } => {} } } else { err.span_suggestion_verbose( diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1410273e3bc..2c367b15df2 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -129,17 +129,20 @@ fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) { for field in variant.fields.iter().filter(|f| f.is_unnamed()) { let field_ty = tcx.type_of(field.did).instantiate_identity(); if let Some(adt) = field_ty.ty_adt_def() - && !adt.is_anonymous() - && !adt.repr().c() + && !adt.is_enum() { - let field_ty_span = tcx.def_span(adt.did()); - tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { - span: tcx.def_span(field.did), - field_ty_span, - field_ty, - field_adt_kind: adt.descr(), - sugg_span: field_ty_span.shrink_to_lo(), - }); + if !adt.is_anonymous() && !adt.repr().c() { + let field_ty_span = tcx.def_span(adt.did()); + tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { + span: tcx.def_span(field.did), + field_ty_span, + field_ty, + field_adt_kind: adt.descr(), + sugg_span: field_ty_span.shrink_to_lo(), + }); + } + } else { + tcx.dcx().emit_err(errors::InvalidUnnamedFieldTy { span: tcx.def_span(field.did) }); } } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 43f0af5bd1d..a5ef1490bce 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -943,7 +943,15 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> { } } hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => { - self.check_field_in_nested_adt(self.tcx.adt_def(res.def_id()), field.span); + // If this is a direct path to an ADT, we can check it + // If this is a type alias or non-ADT, `check_unnamed_fields` should verify it + if let Some(def_id) = res.opt_def_id() + && let Some(local) = def_id.as_local() + && let Node::Item(item) = self.tcx.hir_node_by_def_id(local) + && item.is_adt() + { + self.check_field_in_nested_adt(self.tcx.adt_def(def_id), field.span); + } } // Abort due to errors (there must be an error if an unnamed field // has any type kind other than an anonymous adt or a named adt) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 6a505b96197..3bd7687a544 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -662,6 +662,13 @@ pub(crate) struct InvalidUnionField { } #[derive(Diagnostic)] +#[diag(hir_analysis_invalid_unnamed_field_ty)] +pub struct InvalidUnnamedFieldTy { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(hir_analysis_return_type_notation_on_non_rpitit)] pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { #[primary_span] diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 10e12d01b1f..1af0b75bd23 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -293,7 +293,7 @@ pub enum HelpUseLatestEdition { impl HelpUseLatestEdition { pub fn new() -> Self { let edition = LATEST_STABLE_EDITION; - if std::env::var_os("CARGO").is_some() { + if rustc_session::utils::was_invoked_from_cargo() { Self::Cargo { edition } } else { Self::Standalone { edition } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 2578f284dee..23d29916922 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -492,7 +492,7 @@ fn lock_directory( lock_err, session_dir, is_unsupported_lock, - is_cargo: std::env::var_os("CARGO").map(|_| ()), + is_cargo: rustc_session::utils::was_invoked_from_cargo().then_some(()), })) } } diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 0fa61c5d87e..5af2b6daec1 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -205,7 +205,7 @@ pub(super) fn builtin( Vec::new() }; - let is_from_cargo = std::env::var_os("CARGO").is_some(); + let is_from_cargo = rustc_session::utils::was_invoked_from_cargo(); let mut is_feature_cfg = name == sym::feature; if is_feature_cfg && is_from_cargo { @@ -340,7 +340,7 @@ pub(super) fn builtin( .copied() .flatten() .collect(); - let is_from_cargo = std::env::var_os("CARGO").is_some(); + let is_from_cargo = rustc_session::utils::was_invoked_from_cargo(); // Show the full list if all possible values for a given name, but don't do it // for names as the possibilities could be very long diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 3c3a8d6fbb9..674f7218ea6 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2545,7 +2545,7 @@ pub enum HelpUseLatestEdition { impl HelpUseLatestEdition { pub fn new() -> Self { let edition = LATEST_STABLE_EDITION; - if std::env::var_os("CARGO").is_some() { + if rustc_session::utils::was_invoked_from_cargo() { Self::Cargo { edition } } else { Self::Standalone { edition } diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index f76c69af526..50ebbdccf67 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -1,7 +1,10 @@ use crate::session::Session; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_fs_util::try_canonicalize; -use std::path::{Path, PathBuf}; +use std::{ + path::{Path, PathBuf}, + sync::OnceLock, +}; impl Session { pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> { @@ -158,3 +161,18 @@ pub fn extra_compiler_flags() -> Option<(Vec<String>, bool)> { if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None } } + +/// Returns whenever rustc was launched by Cargo as opposed to another build system. +/// +/// To be used in diagnostics to avoid printing Cargo specific suggestions to other +/// build systems (like Bazel, Buck2, Makefile, ...). +pub fn was_invoked_from_cargo() -> bool { + static FROM_CARGO: OnceLock<bool> = OnceLock::new(); + + // To be able to detect Cargo, we use the simplest and least intrusive + // way: we check whenever the `CARGO_CRATE_NAME` env is set. + // + // Note that it is common in Makefiles to define the `CARGO` env even + // though we may not have been called by Cargo, so we avoid using it. + *FROM_CARGO.get_or_init(|| std::env::var_os("CARGO_CRATE_NAME").is_some()) +} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 0472981086e..2d85f84f480 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3689,6 +3689,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let Node::Expr(expr) = tcx.hir_node(arg_hir_id) && let Some(typeck_results) = &self.typeck_results { + if let hir::Expr { kind: hir::ExprKind::MethodCall(_, rcvr, _, _), .. } = expr + && let Some(ty) = typeck_results.node_type_opt(rcvr.hir_id) + && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred() + && let pred = failed_pred.map_bound(|pred| pred.with_self_ty(tcx, ty)) + && self.predicate_must_hold_modulo_regions(&Obligation::misc( + tcx, expr.span, body_id, param_env, pred, + )) + { + err.span_suggestion_verbose( + expr.span.with_lo(rcvr.span.hi()), + format!( + "consider removing this method call, as the receiver has type `{ty}` and \ + `{pred}` trivially holds", + ), + "", + Applicability::MaybeIncorrect, + ); + } if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr { let inner_expr = expr.peel_blocks(); let ty = typeck_results @@ -3824,7 +3842,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - if let Node::Expr(expr) = tcx.hir_node(call_hir_id) { + if let Node::Expr(expr) = call_node { if let hir::ExprKind::Call(hir::Expr { span, .. }, _) | hir::ExprKind::MethodCall( hir::PathSegment { ident: Ident { span, .. }, .. }, |
