| author | bors <bors@rust-lang.org> 2024-07-26 08:26:17 UTC |
| committer | bors <bors@rust-lang.org> 2024-07-26 08:26:17 UTC |
| log | 83d67685acb520fe68d5d5adde4b25fb725490de |
| tree | c9d069da3bff063adb089082f8703c2c4c993d83 |
| parent | 6ef11b81c2c02c3c4b7556d1991a98572fe9af87 |
| parent | 97eade42f73f9ba081df3811e0ecfd2510e79aff |
Rollup of 7 pull requests
Successful merges:
- #126575 (Make it crystal clear what lint `type_alias_bounds` actually signifies)
- #127017 (Extend rules of dead code analysis for impls for adts to impls for types refer to adts)
- #127523 (Migrate `dump-ice-to-disk` and `panic-abort-eh_frame` `run-make` tests to rmake)
- #127557 (Add a label to point to the lacking macro name definition)
- #127989 (Migrate `interdependent-c-libraries`, `compiler-rt-works-on-mingw` and `incr-foreign-head-span` `run-make` tests to rmake)
- #128099 (migrate tests/run-make/extern-flag-disambiguates to rmake)
- #128170 (Make Clone::clone a lang item)
r? `@ghost`
`@rustbot` modify labels: rollup59 files changed, 1205 insertions(+), 664 deletions(-)
compiler/rustc_hir/src/lang_items.rs+1| ... | @@ -162,6 +162,7 @@ language_item_table! { | ... | @@ -162,6 +162,7 @@ language_item_table! { |
| 162 | StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None; | 162 | StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None; |
| 163 | Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0); | 163 | Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0); |
| 164 | Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None; | 164 | Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None; |
| 165 | CloneFn, sym::clone_fn, clone_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; | ||
| 165 | Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0); | 166 | Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0); |
| 166 | DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None; | 167 | DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None; |
| 167 | /// The associated item of the `DiscriminantKind` trait. | 168 | /// The associated item of the `DiscriminantKind` trait. |
compiler/rustc_hir_analysis/messages.ftl+9-4| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$ty_param_name}` | 1 | hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$qself}` |
| 2 | .label = ambiguous associated {$assoc_kind} `{$assoc_name}` | 2 | .label = ambiguous associated {$assoc_kind} `{$assoc_name}` |
| 3 | 3 | ||
| 4 | hir_analysis_ambiguous_lifetime_bound = | 4 | hir_analysis_ambiguous_lifetime_bound = |
| ... | @@ -12,16 +12,21 @@ hir_analysis_assoc_item_is_private = {$kind} `{$name}` is private | ... | @@ -12,16 +12,21 @@ hir_analysis_assoc_item_is_private = {$kind} `{$name}` is private |
| 12 | .label = private {$kind} | 12 | .label = private {$kind} |
| 13 | .defined_here_label = the {$kind} is defined here | 13 | .defined_here_label = the {$kind} is defined here |
| 14 | 14 | ||
| 15 | hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}` | 15 | hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$qself}` |
| 16 | 16 | ||
| 17 | hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named -> | 17 | hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named -> |
| 18 | [true] an | 18 | [true] an |
| 19 | *[false] a similarly named | 19 | *[false] a similarly named |
| 20 | } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}` | 20 | } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}` |
| 21 | hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found | 21 | hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found |
| 22 | hir_analysis_assoc_item_not_found_other_sugg = `{$ty_param_name}` has the following associated {$assoc_kind} | 22 | hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind} |
| 23 | hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg = | ||
| 24 | consider fully qualifying{$identically_named -> | ||
| 25 | [true] {""} | ||
| 26 | *[false] {" "}and renaming | ||
| 27 | } the associated {$assoc_kind} | ||
| 23 | hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}` | 28 | hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}` |
| 24 | hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = and also change the associated {$assoc_kind} name | 29 | hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = ...and changing the associated {$assoc_kind} name |
| 25 | hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name | 30 | hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name |
| 26 | 31 | ||
| 27 | hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got} | 32 | hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got} |
compiler/rustc_hir_analysis/src/errors.rs+25-6| ... | @@ -22,7 +22,7 @@ pub struct AmbiguousAssocItem<'a> { | ... | @@ -22,7 +22,7 @@ pub struct AmbiguousAssocItem<'a> { |
| 22 | pub span: Span, | 22 | pub span: Span, |
| 23 | pub assoc_kind: &'static str, | 23 | pub assoc_kind: &'static str, |
| 24 | pub assoc_name: Ident, | 24 | pub assoc_name: Ident, |
| 25 | pub ty_param_name: &'a str, | 25 | pub qself: &'a str, |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | #[derive(Diagnostic)] | 28 | #[derive(Diagnostic)] |
| ... | @@ -75,7 +75,7 @@ pub struct AssocItemNotFound<'a> { | ... | @@ -75,7 +75,7 @@ pub struct AssocItemNotFound<'a> { |
| 75 | pub span: Span, | 75 | pub span: Span, |
| 76 | pub assoc_name: Ident, | 76 | pub assoc_name: Ident, |
| 77 | pub assoc_kind: &'static str, | 77 | pub assoc_kind: &'static str, |
| 78 | pub ty_param_name: &'a str, | 78 | pub qself: &'a str, |
| 79 | #[subdiagnostic] | 79 | #[subdiagnostic] |
| 80 | pub label: Option<AssocItemNotFoundLabel<'a>>, | 80 | pub label: Option<AssocItemNotFoundLabel<'a>>, |
| 81 | #[subdiagnostic] | 81 | #[subdiagnostic] |
| ... | @@ -126,13 +126,32 @@ pub enum AssocItemNotFoundSugg<'a> { | ... | @@ -126,13 +126,32 @@ pub enum AssocItemNotFoundSugg<'a> { |
| 126 | assoc_kind: &'static str, | 126 | assoc_kind: &'static str, |
| 127 | suggested_name: Symbol, | 127 | suggested_name: Symbol, |
| 128 | }, | 128 | }, |
| 129 | #[suggestion(hir_analysis_assoc_item_not_found_other_sugg, code = "{suggested_name}")] | 129 | #[multipart_suggestion( |
| 130 | hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg, | ||
| 131 | style = "verbose" | ||
| 132 | )] | ||
| 133 | SimilarInOtherTraitQPath { | ||
| 134 | #[suggestion_part(code = "<")] | ||
| 135 | lo: Span, | ||
| 136 | #[suggestion_part(code = " as {trait_ref}>")] | ||
| 137 | mi: Span, | ||
| 138 | #[suggestion_part(code = "{suggested_name}")] | ||
| 139 | hi: Option<Span>, | ||
| 140 | trait_ref: String, | ||
| 141 | suggested_name: Symbol, | ||
| 142 | identically_named: bool, | ||
| 143 | #[applicability] | ||
| 144 | applicability: Applicability, | ||
| 145 | }, | ||
| 146 | #[suggestion( | ||
| 147 | hir_analysis_assoc_item_not_found_other_sugg, | ||
| 148 | code = "{suggested_name}", | ||
| 149 | applicability = "maybe-incorrect" | ||
| 150 | )] | ||
| 130 | Other { | 151 | Other { |
| 131 | #[primary_span] | 152 | #[primary_span] |
| 132 | span: Span, | 153 | span: Span, |
| 133 | #[applicability] | 154 | qself: &'a str, |
| 134 | applicability: Applicability, | ||
| 135 | ty_param_name: &'a str, | ||
| 136 | assoc_kind: &'static str, | 155 | assoc_kind: &'static str, |
| 137 | suggested_name: Symbol, | 156 | suggested_name: Symbol, |
| 138 | }, | 157 | }, |
compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs+3-6| ... | @@ -6,7 +6,6 @@ use rustc_hir as hir; | ... | @@ -6,7 +6,6 @@ use rustc_hir as hir; |
| 6 | use rustc_hir::def::{DefKind, Res}; | 6 | use rustc_hir::def::{DefKind, Res}; |
| 7 | use rustc_hir::def_id::{DefId, LocalDefId}; | 7 | use rustc_hir::def_id::{DefId, LocalDefId}; |
| 8 | use rustc_middle::bug; | 8 | use rustc_middle::bug; |
| 9 | use rustc_middle::ty::print::PrintTraitRefExt as _; | ||
| 10 | use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt}; | 9 | use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt}; |
| 11 | use rustc_span::symbol::Ident; | 10 | use rustc_span::symbol::Ident; |
| 12 | use rustc_span::{ErrorGuaranteed, Span, Symbol}; | 11 | use rustc_span::{ErrorGuaranteed, Span, Symbol}; |
| ... | @@ -16,9 +15,8 @@ use smallvec::SmallVec; | ... | @@ -16,9 +15,8 @@ use smallvec::SmallVec; |
| 16 | 15 | ||
| 17 | use crate::bounds::Bounds; | 16 | use crate::bounds::Bounds; |
| 18 | use crate::errors; | 17 | use crate::errors; |
| 19 | use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter}; | 18 | use crate::hir_ty_lowering::HirTyLowerer; |
| 20 | 19 | use crate::hir_ty_lowering::{AssocItemQSelf, OnlySelfBounds, PredicateFilter, RegionInferReason}; | |
| 21 | use super::RegionInferReason; | ||
| 22 | 20 | ||
| 23 | impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | 21 | impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 24 | /// Add a `Sized` bound to the `bounds` if appropriate. | 22 | /// Add a `Sized` bound to the `bounds` if appropriate. |
| ... | @@ -288,8 +286,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -288,8 +286,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 288 | // one that does define it. | 286 | // one that does define it. |
| 289 | self.probe_single_bound_for_assoc_item( | 287 | self.probe_single_bound_for_assoc_item( |
| 290 | || traits::supertraits(tcx, trait_ref), | 288 | || traits::supertraits(tcx, trait_ref), |
| 291 | trait_ref.skip_binder().print_only_trait_name(), | 289 | AssocItemQSelf::Trait(trait_ref.def_id()), |
| 292 | None, | ||
| 293 | assoc_kind, | 290 | assoc_kind, |
| 294 | constraint.ident, | 291 | constraint.ident, |
| 295 | path_span, | 292 | path_span, |
compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs+78-49| ... | @@ -3,7 +3,7 @@ use crate::errors::{ | ... | @@ -3,7 +3,7 @@ use crate::errors::{ |
| 3 | ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits, | 3 | ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits, |
| 4 | }; | 4 | }; |
| 5 | use crate::fluent_generated as fluent; | 5 | use crate::fluent_generated as fluent; |
| 6 | use crate::hir_ty_lowering::HirTyLowerer; | 6 | use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; |
| 7 | use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; | 7 | use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; |
| 8 | use rustc_data_structures::sorted_map::SortedMap; | 8 | use rustc_data_structures::sorted_map::SortedMap; |
| 9 | use rustc_data_structures::unord::UnordMap; | 9 | use rustc_data_structures::unord::UnordMap; |
| ... | @@ -11,9 +11,9 @@ use rustc_errors::MultiSpan; | ... | @@ -11,9 +11,9 @@ use rustc_errors::MultiSpan; |
| 11 | use rustc_errors::{ | 11 | use rustc_errors::{ |
| 12 | codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, | 12 | codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, |
| 13 | }; | 13 | }; |
| 14 | use rustc_hir as hir; | ||
| 14 | use rustc_hir::def::{DefKind, Res}; | 15 | use rustc_hir::def::{DefKind, Res}; |
| 15 | use rustc_hir::def_id::{DefId, LocalDefId}; | 16 | use rustc_hir::def_id::DefId; |
| 16 | use rustc_hir::{self as hir, Node}; | ||
| 17 | use rustc_middle::bug; | 17 | use rustc_middle::bug; |
| 18 | use rustc_middle::query::Key; | 18 | use rustc_middle::query::Key; |
| 19 | use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; | 19 | use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; |
| ... | @@ -116,8 +116,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -116,8 +116,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 116 | pub(super) fn complain_about_assoc_item_not_found<I>( | 116 | pub(super) fn complain_about_assoc_item_not_found<I>( |
| 117 | &self, | 117 | &self, |
| 118 | all_candidates: impl Fn() -> I, | 118 | all_candidates: impl Fn() -> I, |
| 119 | ty_param_name: &str, | 119 | qself: AssocItemQSelf, |
| 120 | ty_param_def_id: Option<LocalDefId>, | ||
| 121 | assoc_kind: ty::AssocKind, | 120 | assoc_kind: ty::AssocKind, |
| 122 | assoc_name: Ident, | 121 | assoc_name: Ident, |
| 123 | span: Span, | 122 | span: Span, |
| ... | @@ -139,7 +138,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -139,7 +138,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 139 | ); | 138 | ); |
| 140 | } | 139 | } |
| 141 | 140 | ||
| 142 | let assoc_kind_str = super::assoc_kind_str(assoc_kind); | 141 | let assoc_kind_str = assoc_kind_str(assoc_kind); |
| 142 | let qself_str = qself.to_string(tcx); | ||
| 143 | 143 | ||
| 144 | // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a | 144 | // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a |
| 145 | // valid span, so we point at the whole path segment instead. | 145 | // valid span, so we point at the whole path segment instead. |
| ... | @@ -149,7 +149,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -149,7 +149,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 149 | span: if is_dummy { span } else { assoc_name.span }, | 149 | span: if is_dummy { span } else { assoc_name.span }, |
| 150 | assoc_name, | 150 | assoc_name, |
| 151 | assoc_kind: assoc_kind_str, | 151 | assoc_kind: assoc_kind_str, |
| 152 | ty_param_name, | 152 | qself: &qself_str, |
| 153 | label: None, | 153 | label: None, |
| 154 | sugg: None, | 154 | sugg: None, |
| 155 | }; | 155 | }; |
| ... | @@ -219,19 +219,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -219,19 +219,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 219 | suggested_name, | 219 | suggested_name, |
| 220 | identically_named: suggested_name == assoc_name.name, | 220 | identically_named: suggested_name == assoc_name.name, |
| 221 | }); | 221 | }); |
| 222 | let hir = tcx.hir(); | 222 | if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself |
| 223 | if let Some(def_id) = ty_param_def_id | 223 | // Not using `self.item_def_id()` here as that would yield the opaque type itself if we're |
| 224 | && let parent = hir.get_parent_item(tcx.local_def_id_to_hir_id(def_id)) | 224 | // inside an opaque type while we're interested in the overarching type alias (TAIT). |
| 225 | && let Some(generics) = hir.get_generics(parent.def_id) | 225 | // FIXME: However, for trait aliases, this incorrectly returns the enclosing module... |
| 226 | && let item_def_id = | ||
| 227 | tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id)) | ||
| 228 | // FIXME: ...which obviously won't have any generics. | ||
| 229 | && let Some(generics) = tcx.hir().get_generics(item_def_id.def_id) | ||
| 226 | { | 230 | { |
| 227 | if generics.bounds_for_param(def_id).flat_map(|pred| pred.bounds.iter()).any( | 231 | // FIXME: Suggest adding supertrait bounds if we have a `Self` type param. |
| 228 | |b| match b { | 232 | // FIXME(trait_alias): Suggest adding `Self: Trait` to |
| 233 | // `trait Alias = where Self::Proj:;` with `trait Trait { type Proj; }`. | ||
| 234 | if generics | ||
| 235 | .bounds_for_param(ty_param_def_id) | ||
| 236 | .flat_map(|pred| pred.bounds.iter()) | ||
| 237 | .any(|b| match b { | ||
| 229 | hir::GenericBound::Trait(t, ..) => { | 238 | hir::GenericBound::Trait(t, ..) => { |
| 230 | t.trait_ref.trait_def_id() == Some(best_trait) | 239 | t.trait_ref.trait_def_id() == Some(best_trait) |
| 231 | } | 240 | } |
| 232 | _ => false, | 241 | _ => false, |
| 233 | }, | 242 | }) |
| 234 | ) { | 243 | { |
| 235 | // The type param already has a bound for `trait_name`, we just need to | 244 | // The type param already has a bound for `trait_name`, we just need to |
| 236 | // change the associated item. | 245 | // change the associated item. |
| 237 | err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait { | 246 | err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait { |
| ... | @@ -242,48 +251,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -242,48 +251,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 242 | return self.dcx().emit_err(err); | 251 | return self.dcx().emit_err(err); |
| 243 | } | 252 | } |
| 244 | 253 | ||
| 245 | let mut err = self.dcx().create_err(err); | 254 | let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..]; |
| 246 | if suggest_constraining_type_param( | 255 | let mut trait_ref = trait_name.clone(); |
| 247 | tcx, | 256 | let applicability = if let [arg, args @ ..] = trait_args { |
| 248 | generics, | 257 | use std::fmt::Write; |
| 249 | &mut err, | 258 | write!(trait_ref, "</* {arg}").unwrap(); |
| 250 | &ty_param_name, | 259 | args.iter().try_for_each(|arg| write!(trait_ref, ", {arg}")).unwrap(); |
| 251 | &trait_name, | 260 | trait_ref += " */>"; |
| 252 | None, | 261 | Applicability::HasPlaceholders |
| 253 | None, | 262 | } else { |
| 254 | ) && suggested_name != assoc_name.name | 263 | Applicability::MaybeIncorrect |
| 264 | }; | ||
| 265 | |||
| 266 | let identically_named = suggested_name == assoc_name.name; | ||
| 267 | |||
| 268 | if let DefKind::TyAlias = tcx.def_kind(item_def_id) | ||
| 269 | && !tcx.type_alias_is_lazy(item_def_id) | ||
| 255 | { | 270 | { |
| 256 | // We suggested constraining a type parameter, but the associated item on it | 271 | err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath { |
| 257 | // was also not an exact match, so we also suggest changing it. | 272 | lo: ty_param_span.shrink_to_lo(), |
| 258 | err.span_suggestion_verbose( | 273 | mi: ty_param_span.shrink_to_hi(), |
| 259 | assoc_name.span, | 274 | hi: (!identically_named).then_some(assoc_name.span), |
| 260 | fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, | 275 | trait_ref, |
| 276 | identically_named, | ||
| 261 | suggested_name, | 277 | suggested_name, |
| 262 | Applicability::MaybeIncorrect, | 278 | applicability, |
| 263 | ); | 279 | }); |
| 280 | } else { | ||
| 281 | let mut err = self.dcx().create_err(err); | ||
| 282 | if suggest_constraining_type_param( | ||
| 283 | tcx, generics, &mut err, &qself_str, &trait_ref, None, None, | ||
| 284 | ) && !identically_named | ||
| 285 | { | ||
| 286 | // We suggested constraining a type parameter, but the associated item on it | ||
| 287 | // was also not an exact match, so we also suggest changing it. | ||
| 288 | err.span_suggestion_verbose( | ||
| 289 | assoc_name.span, | ||
| 290 | fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, | ||
| 291 | suggested_name, | ||
| 292 | Applicability::MaybeIncorrect, | ||
| 293 | ); | ||
| 294 | } | ||
| 295 | return err.emit(); | ||
| 264 | } | 296 | } |
| 265 | return err.emit(); | ||
| 266 | } | 297 | } |
| 267 | return self.dcx().emit_err(err); | 298 | return self.dcx().emit_err(err); |
| 268 | } | 299 | } |
| 269 | } | 300 | } |
| 270 | 301 | ||
| 271 | // If we still couldn't find any associated item, and only one associated item exists, | 302 | // If we still couldn't find any associated item, and only one associated item exists, |
| 272 | // suggests using it. | 303 | // suggest using it. |
| 273 | if let [candidate_name] = all_candidate_names.as_slice() { | 304 | if let [candidate_name] = all_candidate_names.as_slice() { |
| 274 | // This should still compile, except on `#![feature(associated_type_defaults)]` | ||
| 275 | // where it could suggests `type A = Self::A`, thus recursing infinitely. | ||
| 276 | let applicability = | ||
| 277 | if assoc_kind == ty::AssocKind::Type && tcx.features().associated_type_defaults { | ||
| 278 | Applicability::Unspecified | ||
| 279 | } else { | ||
| 280 | Applicability::MaybeIncorrect | ||
| 281 | }; | ||
| 282 | |||
| 283 | err.sugg = Some(errors::AssocItemNotFoundSugg::Other { | 305 | err.sugg = Some(errors::AssocItemNotFoundSugg::Other { |
| 284 | span: assoc_name.span, | 306 | span: assoc_name.span, |
| 285 | applicability, | 307 | qself: &qself_str, |
| 286 | ty_param_name, | ||
| 287 | assoc_kind: assoc_kind_str, | 308 | assoc_kind: assoc_kind_str, |
| 288 | suggested_name: *candidate_name, | 309 | suggested_name: *candidate_name, |
| 289 | }); | 310 | }); |
| ... | @@ -349,10 +370,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -349,10 +370,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 349 | 370 | ||
| 350 | self.dcx().emit_err(errors::AssocKindMismatch { | 371 | self.dcx().emit_err(errors::AssocKindMismatch { |
| 351 | span, | 372 | span, |
| 352 | expected: super::assoc_kind_str(expected), | 373 | expected: assoc_kind_str(expected), |
| 353 | got: super::assoc_kind_str(got), | 374 | got: assoc_kind_str(got), |
| 354 | expected_because_label, | 375 | expected_because_label, |
| 355 | assoc_kind: super::assoc_kind_str(assoc_item.kind), | 376 | assoc_kind: assoc_kind_str(assoc_item.kind), |
| 356 | def_span: tcx.def_span(assoc_item.def_id), | 377 | def_span: tcx.def_span(assoc_item.def_id), |
| 357 | bound_on_assoc_const_label, | 378 | bound_on_assoc_const_label, |
| 358 | wrap_in_braces_sugg, | 379 | wrap_in_braces_sugg, |
| ... | @@ -746,7 +767,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -746,7 +767,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 746 | if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) { | 767 | if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) { |
| 747 | let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id)); | 768 | let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id)); |
| 748 | in_expr_or_pat = match grandparent { | 769 | in_expr_or_pat = match grandparent { |
| 749 | Node::Expr(_) | Node::Pat(_) => true, | 770 | hir::Node::Expr(_) | hir::Node::Pat(_) => true, |
| 750 | _ => false, | 771 | _ => false, |
| 751 | }; | 772 | }; |
| 752 | match bound.trait_ref.path.segments { | 773 | match bound.trait_ref.path.segments { |
| ... | @@ -1612,3 +1633,11 @@ fn generics_args_err_extend<'a>( | ... | @@ -1612,3 +1633,11 @@ fn generics_args_err_extend<'a>( |
| 1612 | _ => {} | 1633 | _ => {} |
| 1613 | } | 1634 | } |
| 1614 | } | 1635 | } |
| 1636 | |||
| 1637 | pub(super) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str { | ||
| 1638 | match kind { | ||
| 1639 | ty::AssocKind::Fn => "function", | ||
| 1640 | ty::AssocKind::Const => "constant", | ||
| 1641 | ty::AssocKind::Type => "type", | ||
| 1642 | } | ||
| 1643 | } |
compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs+41-36| ... | @@ -55,7 +55,6 @@ use rustc_trait_selection::infer::InferCtxtExt; | ... | @@ -55,7 +55,6 @@ use rustc_trait_selection::infer::InferCtxtExt; |
| 55 | use rustc_trait_selection::traits::wf::object_region_bounds; | 55 | use rustc_trait_selection::traits::wf::object_region_bounds; |
| 56 | use rustc_trait_selection::traits::{self, ObligationCtxt}; | 56 | use rustc_trait_selection::traits::{self, ObligationCtxt}; |
| 57 | 57 | ||
| 58 | use std::fmt::Display; | ||
| 59 | use std::slice; | 58 | use std::slice; |
| 60 | 59 | ||
| 61 | /// A path segment that is semantically allowed to have generic arguments. | 60 | /// A path segment that is semantically allowed to have generic arguments. |
| ... | @@ -193,6 +192,25 @@ pub trait HirTyLowerer<'tcx> { | ... | @@ -193,6 +192,25 @@ pub trait HirTyLowerer<'tcx> { |
| 193 | } | 192 | } |
| 194 | } | 193 | } |
| 195 | 194 | ||
| 195 | /// The "qualified self" of an associated item path. | ||
| 196 | /// | ||
| 197 | /// For diagnostic purposes only. | ||
| 198 | enum AssocItemQSelf { | ||
| 199 | Trait(DefId), | ||
| 200 | TyParam(LocalDefId, Span), | ||
| 201 | SelfTyAlias, | ||
| 202 | } | ||
| 203 | |||
| 204 | impl AssocItemQSelf { | ||
| 205 | fn to_string(&self, tcx: TyCtxt<'_>) -> String { | ||
| 206 | match *self { | ||
| 207 | Self::Trait(def_id) => tcx.def_path_str(def_id), | ||
| 208 | Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(), | ||
| 209 | Self::SelfTyAlias => kw::SelfUpper.to_string(), | ||
| 210 | } | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 196 | /// New-typed boolean indicating whether explicit late-bound lifetimes | 214 | /// New-typed boolean indicating whether explicit late-bound lifetimes |
| 197 | /// are present in a set of generic arguments. | 215 | /// are present in a set of generic arguments. |
| 198 | /// | 216 | /// |
| ... | @@ -802,6 +820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -802,6 +820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 802 | fn probe_single_ty_param_bound_for_assoc_ty( | 820 | fn probe_single_ty_param_bound_for_assoc_ty( |
| 803 | &self, | 821 | &self, |
| 804 | ty_param_def_id: LocalDefId, | 822 | ty_param_def_id: LocalDefId, |
| 823 | ty_param_span: Span, | ||
| 805 | assoc_name: Ident, | 824 | assoc_name: Ident, |
| 806 | span: Span, | 825 | span: Span, |
| 807 | ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> { | 826 | ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> { |
| ... | @@ -811,19 +830,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -811,19 +830,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 811 | let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_name).predicates; | 830 | let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_name).predicates; |
| 812 | debug!("predicates={:#?}", predicates); | 831 | debug!("predicates={:#?}", predicates); |
| 813 | 832 | ||
| 814 | let param_name = tcx.hir().ty_param_name(ty_param_def_id); | ||
| 815 | self.probe_single_bound_for_assoc_item( | 833 | self.probe_single_bound_for_assoc_item( |
| 816 | || { | 834 | || { |
| 817 | traits::transitive_bounds_that_define_assoc_item( | 835 | let trait_refs = predicates |
| 818 | tcx, | 836 | .iter() |
| 819 | predicates | 837 | .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))); |
| 820 | .iter() | 838 | traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name) |
| 821 | .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))), | ||
| 822 | assoc_name, | ||
| 823 | ) | ||
| 824 | }, | 839 | }, |
| 825 | param_name, | 840 | AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span), |
| 826 | Some(ty_param_def_id), | ||
| 827 | ty::AssocKind::Type, | 841 | ty::AssocKind::Type, |
| 828 | assoc_name, | 842 | assoc_name, |
| 829 | span, | 843 | span, |
| ... | @@ -835,12 +849,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -835,12 +849,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 835 | /// | 849 | /// |
| 836 | /// This fails if there is no such bound in the list of candidates or if there are multiple | 850 | /// This fails if there is no such bound in the list of candidates or if there are multiple |
| 837 | /// candidates in which case it reports ambiguity. | 851 | /// candidates in which case it reports ambiguity. |
| 838 | #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, constraint), ret)] | 852 | #[instrument(level = "debug", skip(self, all_candidates, qself, constraint), ret)] |
| 839 | fn probe_single_bound_for_assoc_item<I>( | 853 | fn probe_single_bound_for_assoc_item<I>( |
| 840 | &self, | 854 | &self, |
| 841 | all_candidates: impl Fn() -> I, | 855 | all_candidates: impl Fn() -> I, |
| 842 | ty_param_name: impl Display, | 856 | qself: AssocItemQSelf, |
| 843 | ty_param_def_id: Option<LocalDefId>, | ||
| 844 | assoc_kind: ty::AssocKind, | 857 | assoc_kind: ty::AssocKind, |
| 845 | assoc_name: Ident, | 858 | assoc_name: Ident, |
| 846 | span: Span, | 859 | span: Span, |
| ... | @@ -858,8 +871,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -858,8 +871,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 858 | let Some(bound) = matching_candidates.next() else { | 871 | let Some(bound) = matching_candidates.next() else { |
| 859 | let reported = self.complain_about_assoc_item_not_found( | 872 | let reported = self.complain_about_assoc_item_not_found( |
| 860 | all_candidates, | 873 | all_candidates, |
| 861 | &ty_param_name.to_string(), | 874 | qself, |
| 862 | ty_param_def_id, | ||
| 863 | assoc_kind, | 875 | assoc_kind, |
| 864 | assoc_name, | 876 | assoc_name, |
| 865 | span, | 877 | span, |
| ... | @@ -872,13 +884,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -872,13 +884,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 872 | if let Some(bound2) = matching_candidates.next() { | 884 | if let Some(bound2) = matching_candidates.next() { |
| 873 | debug!(?bound2); | 885 | debug!(?bound2); |
| 874 | 886 | ||
| 875 | let assoc_kind_str = assoc_kind_str(assoc_kind); | 887 | let assoc_kind_str = errors::assoc_kind_str(assoc_kind); |
| 876 | let ty_param_name = &ty_param_name.to_string(); | 888 | let qself_str = qself.to_string(tcx); |
| 877 | let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem { | 889 | let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem { |
| 878 | span, | 890 | span, |
| 879 | assoc_kind: assoc_kind_str, | 891 | assoc_kind: assoc_kind_str, |
| 880 | assoc_name, | 892 | assoc_name, |
| 881 | ty_param_name, | 893 | qself: &qself_str, |
| 882 | }); | 894 | }); |
| 883 | // Provide a more specific error code index entry for equality bindings. | 895 | // Provide a more specific error code index entry for equality bindings. |
| 884 | err.code( | 896 | err.code( |
| ... | @@ -929,7 +941,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -929,7 +941,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 929 | err.span_suggestion_verbose( | 941 | err.span_suggestion_verbose( |
| 930 | span.with_hi(assoc_name.span.lo()), | 942 | span.with_hi(assoc_name.span.lo()), |
| 931 | "use fully-qualified syntax to disambiguate", | 943 | "use fully-qualified syntax to disambiguate", |
| 932 | format!("<{ty_param_name} as {}>::", bound.print_only_trait_path()), | 944 | format!("<{qself_str} as {}>::", bound.print_only_trait_path()), |
| 933 | Applicability::MaybeIncorrect, | 945 | Applicability::MaybeIncorrect, |
| 934 | ); | 946 | ); |
| 935 | } | 947 | } |
| ... | @@ -943,7 +955,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -943,7 +955,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 943 | if !where_bounds.is_empty() { | 955 | if !where_bounds.is_empty() { |
| 944 | err.help(format!( | 956 | err.help(format!( |
| 945 | "consider introducing a new type parameter `T` and adding `where` constraints:\ | 957 | "consider introducing a new type parameter `T` and adding `where` constraints:\ |
| 946 | \n where\n T: {ty_param_name},\n{}", | 958 | \n where\n T: {qself_str},\n{}", |
| 947 | where_bounds.join(",\n"), | 959 | where_bounds.join(",\n"), |
| 948 | )); | 960 | )); |
| 949 | } | 961 | } |
| ... | @@ -997,11 +1009,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -997,11 +1009,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 997 | let tcx = self.tcx(); | 1009 | let tcx = self.tcx(); |
| 998 | 1010 | ||
| 999 | let assoc_ident = assoc_segment.ident; | 1011 | let assoc_ident = assoc_segment.ident; |
| 1000 | let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind { | ||
| 1001 | path.res | ||
| 1002 | } else { | ||
| 1003 | Res::Err | ||
| 1004 | }; | ||
| 1005 | 1012 | ||
| 1006 | // Check if we have an enum variant or an inherent associated type. | 1013 | // Check if we have an enum variant or an inherent associated type. |
| 1007 | let mut variant_resolution = None; | 1014 | let mut variant_resolution = None; |
| ... | @@ -1038,6 +1045,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -1038,6 +1045,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 1038 | } | 1045 | } |
| 1039 | } | 1046 | } |
| 1040 | 1047 | ||
| 1048 | let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind { | ||
| 1049 | path.res | ||
| 1050 | } else { | ||
| 1051 | Res::Err | ||
| 1052 | }; | ||
| 1053 | |||
| 1041 | // Find the type of the associated item, and the trait where the associated | 1054 | // Find the type of the associated item, and the trait where the associated |
| 1042 | // item is declared. | 1055 | // item is declared. |
| 1043 | let bound = match (&qself_ty.kind(), qself_res) { | 1056 | let bound = match (&qself_ty.kind(), qself_res) { |
| ... | @@ -1056,8 +1069,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -1056,8 +1069,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 1056 | ty::Binder::dummy(trait_ref.instantiate_identity()), | 1069 | ty::Binder::dummy(trait_ref.instantiate_identity()), |
| 1057 | ) | 1070 | ) |
| 1058 | }, | 1071 | }, |
| 1059 | kw::SelfUpper, | 1072 | AssocItemQSelf::SelfTyAlias, |
| 1060 | None, | ||
| 1061 | ty::AssocKind::Type, | 1073 | ty::AssocKind::Type, |
| 1062 | assoc_ident, | 1074 | assoc_ident, |
| 1063 | span, | 1075 | span, |
| ... | @@ -1069,6 +1081,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -1069,6 +1081,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 1069 | Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did), | 1081 | Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did), |
| 1070 | ) => self.probe_single_ty_param_bound_for_assoc_ty( | 1082 | ) => self.probe_single_ty_param_bound_for_assoc_ty( |
| 1071 | param_did.expect_local(), | 1083 | param_did.expect_local(), |
| 1084 | qself.span, | ||
| 1072 | assoc_ident, | 1085 | assoc_ident, |
| 1073 | span, | 1086 | span, |
| 1074 | )?, | 1087 | )?, |
| ... | @@ -2522,11 +2535,3 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | ... | @@ -2522,11 +2535,3 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 2522 | Some(r) | 2535 | Some(r) |
| 2523 | } | 2536 | } |
| 2524 | } | 2537 | } |
| 2525 | |||
| 2526 | fn assoc_kind_str(kind: ty::AssocKind) -> &'static str { | ||
| 2527 | match kind { | ||
| 2528 | ty::AssocKind::Fn => "function", | ||
| 2529 | ty::AssocKind::Const => "constant", | ||
| 2530 | ty::AssocKind::Type => "type", | ||
| 2531 | } | ||
| 2532 | } |
compiler/rustc_lint/messages.ftl+12-7| ... | @@ -144,13 +144,18 @@ lint_builtin_special_module_name_used_main = found module declaration for main.r | ... | @@ -144,13 +144,18 @@ lint_builtin_special_module_name_used_main = found module declaration for main.r |
| 144 | 144 | ||
| 145 | lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters | 145 | lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters |
| 146 | 146 | ||
| 147 | lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases | 147 | lint_builtin_type_alias_bounds_enable_feat_help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics |
| 148 | 148 | lint_builtin_type_alias_bounds_label = will not be checked at usage sites of the type alias | |
| 149 | lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases | 149 | lint_builtin_type_alias_bounds_limitation_note = this is a known limitation of the type checker that may be lifted in a future edition. |
| 150 | .suggestion = the bound will not be checked when the type alias is used, and should be removed | 150 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 151 | 151 | lint_builtin_type_alias_bounds_param_bounds = bounds on generic parameters in type aliases are not enforced | |
| 152 | lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases | 152 | .suggestion = remove {$count -> |
| 153 | .suggestion = the clause will not be checked when the type alias is used, and should be removed | 153 | [one] this bound |
| 154 | *[other] these bounds | ||
| 155 | } | ||
| 156 | lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg = fully qualify this associated type | ||
| 157 | lint_builtin_type_alias_bounds_where_clause = where clauses on type aliases are not enforced | ||
| 158 | .suggestion = remove this where clause | ||
| 154 | 159 | ||
| 155 | lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed | 160 | lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed |
| 156 | lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | 161 | lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done |
compiler/rustc_lint/src/builtin.rs+87-52| ... | @@ -31,12 +31,11 @@ use crate::{ | ... | @@ -31,12 +31,11 @@ use crate::{ |
| 31 | BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, | 31 | BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, |
| 32 | BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, | 32 | BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, |
| 33 | BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, | 33 | BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, |
| 34 | BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds, | 34 | BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds, |
| 35 | BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause, | ||
| 36 | BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, | 35 | BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, |
| 37 | BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, | 36 | BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, |
| 38 | BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, | 37 | BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, |
| 39 | BuiltinWhileTrue, InvalidAsmLabel, SuggestChangingAssocTypes, | 38 | BuiltinWhileTrue, InvalidAsmLabel, |
| 40 | }, | 39 | }, |
| 41 | EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, | 40 | EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, |
| 42 | }; | 41 | }; |
| ... | @@ -1391,64 +1390,80 @@ declare_lint! { | ... | @@ -1391,64 +1390,80 @@ declare_lint! { |
| 1391 | /// | 1390 | /// |
| 1392 | /// ### Explanation | 1391 | /// ### Explanation |
| 1393 | /// | 1392 | /// |
| 1394 | /// The trait bounds in a type alias are currently ignored, and should not | 1393 | /// Trait and lifetime bounds on generic parameters and in where clauses of |
| 1395 | /// be included to avoid confusion. This was previously allowed | 1394 | /// type aliases are not checked at usage sites of the type alias. Moreover, |
| 1396 | /// unintentionally; this may become a hard error in the future. | 1395 | /// they are not thoroughly checked for correctness at their definition site |
| 1396 | /// either similar to the aliased type. | ||
| 1397 | /// | ||
| 1398 | /// This is a known limitation of the type checker that may be lifted in a | ||
| 1399 | /// future edition. Permitting such bounds in light of this was unintentional. | ||
| 1400 | /// | ||
| 1401 | /// While these bounds may have secondary effects such as enabling the use of | ||
| 1402 | /// "shorthand" associated type paths[^1] and affecting the default trait | ||
| 1403 | /// object lifetime[^2] of trait object types passed to the type alias, this | ||
| 1404 | /// should not have been allowed until the aforementioned restrictions of the | ||
| 1405 | /// type checker have been lifted. | ||
| 1406 | /// | ||
| 1407 | /// Using such bounds is highly discouraged as they are actively misleading. | ||
| 1408 | /// | ||
| 1409 | /// [^1]: I.e., paths of the form `T::Assoc` where `T` is a type parameter | ||
| 1410 | /// bounded by trait `Trait` which defines an associated type called `Assoc` | ||
| 1411 | /// as opposed to a fully qualified path of the form `<T as Trait>::Assoc`. | ||
| 1412 | /// [^2]: <https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes> | ||
| 1397 | TYPE_ALIAS_BOUNDS, | 1413 | TYPE_ALIAS_BOUNDS, |
| 1398 | Warn, | 1414 | Warn, |
| 1399 | "bounds in type aliases are not enforced" | 1415 | "bounds in type aliases are not enforced" |
| 1400 | } | 1416 | } |
| 1401 | 1417 | ||
| 1402 | declare_lint_pass!( | 1418 | declare_lint_pass!(TypeAliasBounds => [TYPE_ALIAS_BOUNDS]); |
| 1403 | /// Lint for trait and lifetime bounds in type aliases being mostly ignored. | ||
| 1404 | /// They are relevant when using associated types, but otherwise neither checked | ||
| 1405 | /// at definition site nor enforced at use site. | ||
| 1406 | TypeAliasBounds => [TYPE_ALIAS_BOUNDS] | ||
| 1407 | ); | ||
| 1408 | 1419 | ||
| 1409 | impl TypeAliasBounds { | 1420 | impl TypeAliasBounds { |
| 1410 | pub(crate) fn is_type_variable_assoc(qpath: &hir::QPath<'_>) -> bool { | 1421 | pub(crate) fn affects_object_lifetime_defaults(pred: &hir::WherePredicate<'_>) -> bool { |
| 1411 | match *qpath { | 1422 | // Bounds of the form `T: 'a` with `T` type param affect object lifetime defaults. |
| 1412 | hir::QPath::TypeRelative(ty, _) => { | 1423 | if let hir::WherePredicate::BoundPredicate(pred) = pred |
| 1413 | // If this is a type variable, we found a `T::Assoc`. | 1424 | && pred.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Outlives(_))) |
| 1414 | match ty.kind { | 1425 | && pred.bound_generic_params.is_empty() // indeed, even if absent from the RHS |
| 1415 | hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { | 1426 | && pred.bounded_ty.as_generic_param().is_some() |
| 1416 | matches!(path.res, Res::Def(DefKind::TyParam, _)) | 1427 | { |
| 1417 | } | 1428 | return true; |
| 1418 | _ => false, | ||
| 1419 | } | ||
| 1420 | } | ||
| 1421 | hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => false, | ||
| 1422 | } | 1429 | } |
| 1430 | false | ||
| 1423 | } | 1431 | } |
| 1424 | } | 1432 | } |
| 1425 | 1433 | ||
| 1426 | impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { | 1434 | impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { |
| 1427 | fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { | 1435 | fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { |
| 1428 | let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return }; | 1436 | let hir::ItemKind::TyAlias(hir_ty, generics) = item.kind else { return }; |
| 1429 | 1437 | ||
| 1430 | // Bounds of lazy type aliases and TAITs are respected. | 1438 | // There must not be a where clause. |
| 1431 | if cx.tcx.type_alias_is_lazy(item.owner_id) { | 1439 | if generics.predicates.is_empty() { |
| 1432 | return; | 1440 | return; |
| 1433 | } | 1441 | } |
| 1434 | 1442 | ||
| 1435 | let ty = cx.tcx.type_of(item.owner_id).skip_binder(); | 1443 | // Bounds of lazy type aliases and TAITs are respected. |
| 1436 | if ty.has_inherent_projections() { | 1444 | if cx.tcx.type_alias_is_lazy(item.owner_id) { |
| 1437 | // Bounds of type aliases that contain opaque types or inherent projections are | ||
| 1438 | // respected. E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = | ||
| 1439 | // Type::Inherent;`. | ||
| 1440 | return; | 1445 | return; |
| 1441 | } | 1446 | } |
| 1442 | 1447 | ||
| 1443 | // There must not be a where clause | 1448 | // FIXME(generic_const_exprs): Revisit this before stabilization. |
| 1444 | if type_alias_generics.predicates.is_empty() { | 1449 | // See also `tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs`. |
| 1450 | let ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); | ||
| 1451 | if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) | ||
| 1452 | && cx.tcx.features().generic_const_exprs | ||
| 1453 | { | ||
| 1445 | return; | 1454 | return; |
| 1446 | } | 1455 | } |
| 1447 | 1456 | ||
| 1457 | // NOTE(inherent_associated_types): While we currently do take some bounds in type | ||
| 1458 | // aliases into consideration during IAT *selection*, we don't perform full use+def | ||
| 1459 | // site wfchecking for such type aliases. Therefore TAB should still trigger. | ||
| 1460 | // See also `tests/ui/associated-inherent-types/type-alias-bounds.rs`. | ||
| 1461 | |||
| 1448 | let mut where_spans = Vec::new(); | 1462 | let mut where_spans = Vec::new(); |
| 1449 | let mut inline_spans = Vec::new(); | 1463 | let mut inline_spans = Vec::new(); |
| 1450 | let mut inline_sugg = Vec::new(); | 1464 | let mut inline_sugg = Vec::new(); |
| 1451 | for p in type_alias_generics.predicates { | 1465 | |
| 1466 | for p in generics.predicates { | ||
| 1452 | let span = p.span(); | 1467 | let span = p.span(); |
| 1453 | if p.in_where_clause() { | 1468 | if p.in_where_clause() { |
| 1454 | where_spans.push(span); | 1469 | where_spans.push(span); |
| ... | @@ -1460,37 +1475,57 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { | ... | @@ -1460,37 +1475,57 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { |
| 1460 | } | 1475 | } |
| 1461 | } | 1476 | } |
| 1462 | 1477 | ||
| 1463 | let mut suggested_changing_assoc_types = false; | 1478 | let mut ty = Some(hir_ty); |
| 1464 | if !where_spans.is_empty() { | 1479 | let enable_feat_help = cx.tcx.sess.is_nightly_build(); |
| 1465 | let sub = (!suggested_changing_assoc_types).then(|| { | 1480 | |
| 1466 | suggested_changing_assoc_types = true; | 1481 | if let [.., label_sp] = *where_spans { |
| 1467 | SuggestChangingAssocTypes { ty: hir_ty } | ||
| 1468 | }); | ||
| 1469 | cx.emit_span_lint( | 1482 | cx.emit_span_lint( |
| 1470 | TYPE_ALIAS_BOUNDS, | 1483 | TYPE_ALIAS_BOUNDS, |
| 1471 | where_spans, | 1484 | where_spans, |
| 1472 | BuiltinTypeAliasWhereClause { | 1485 | BuiltinTypeAliasBounds { |
| 1473 | suggestion: type_alias_generics.where_clause_span, | 1486 | in_where_clause: true, |
| 1474 | sub, | 1487 | label: label_sp, |
| 1488 | enable_feat_help, | ||
| 1489 | suggestions: vec![(generics.where_clause_span, String::new())], | ||
| 1490 | preds: generics.predicates, | ||
| 1491 | ty: ty.take(), | ||
| 1475 | }, | 1492 | }, |
| 1476 | ); | 1493 | ); |
| 1477 | } | 1494 | } |
| 1478 | 1495 | if let [.., label_sp] = *inline_spans { | |
| 1479 | if !inline_spans.is_empty() { | ||
| 1480 | let suggestion = BuiltinTypeAliasGenericBoundsSuggestion { suggestions: inline_sugg }; | ||
| 1481 | let sub = (!suggested_changing_assoc_types).then(|| { | ||
| 1482 | suggested_changing_assoc_types = true; | ||
| 1483 | SuggestChangingAssocTypes { ty: hir_ty } | ||
| 1484 | }); | ||
| 1485 | cx.emit_span_lint( | 1496 | cx.emit_span_lint( |
| 1486 | TYPE_ALIAS_BOUNDS, | 1497 | TYPE_ALIAS_BOUNDS, |
| 1487 | inline_spans, | 1498 | inline_spans, |
| 1488 | BuiltinTypeAliasGenericBounds { suggestion, sub }, | 1499 | BuiltinTypeAliasBounds { |
| 1500 | in_where_clause: false, | ||
| 1501 | label: label_sp, | ||
| 1502 | enable_feat_help, | ||
| 1503 | suggestions: inline_sugg, | ||
| 1504 | preds: generics.predicates, | ||
| 1505 | ty, | ||
| 1506 | }, | ||
| 1489 | ); | 1507 | ); |
| 1490 | } | 1508 | } |
| 1491 | } | 1509 | } |
| 1492 | } | 1510 | } |
| 1493 | 1511 | ||
| 1512 | pub(crate) struct ShorthandAssocTyCollector { | ||
| 1513 | pub(crate) qselves: Vec<Span>, | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | impl hir::intravisit::Visitor<'_> for ShorthandAssocTyCollector { | ||
| 1517 | fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, _: Span) { | ||
| 1518 | // Look for "type-parameter shorthand-associated-types". I.e., paths of the | ||
| 1519 | // form `T::Assoc` with `T` type param. These are reliant on trait bounds. | ||
| 1520 | if let hir::QPath::TypeRelative(qself, _) = qpath | ||
| 1521 | && qself.as_generic_param().is_some() | ||
| 1522 | { | ||
| 1523 | self.qselves.push(qself.span); | ||
| 1524 | } | ||
| 1525 | hir::intravisit::walk_qpath(self, qpath, id) | ||
| 1526 | } | ||
| 1527 | } | ||
| 1528 | |||
| 1494 | declare_lint! { | 1529 | declare_lint! { |
| 1495 | /// The `trivial_bounds` lint detects trait bounds that don't depend on | 1530 | /// The `trivial_bounds` lint detects trait bounds that don't depend on |
| 1496 | /// any type parameters. | 1531 | /// any type parameters. |
compiler/rustc_lint/src/lints.rs+67-74| ... | @@ -2,14 +2,16 @@ | ... | @@ -2,14 +2,16 @@ |
| 2 | #![allow(rustc::untranslatable_diagnostic)] | 2 | #![allow(rustc::untranslatable_diagnostic)] |
| 3 | use std::num::NonZero; | 3 | use std::num::NonZero; |
| 4 | 4 | ||
| 5 | use crate::errors::RequestedLevel; | 5 | use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds}; |
| 6 | use crate::errors::{OverruledAttributeSub, RequestedLevel}; | ||
| 6 | use crate::fluent_generated as fluent; | 7 | use crate::fluent_generated as fluent; |
| 8 | use crate::LateContext; | ||
| 7 | use rustc_errors::{ | 9 | use rustc_errors::{ |
| 8 | codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, | 10 | codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, |
| 9 | ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp, | 11 | ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp, |
| 10 | Subdiagnostic, SuggestionStyle, | 12 | Subdiagnostic, SuggestionStyle, |
| 11 | }; | 13 | }; |
| 12 | use rustc_hir::{def::Namespace, def_id::DefId}; | 14 | use rustc_hir::{self as hir, def::Namespace, def_id::DefId}; |
| 13 | use rustc_macros::{LintDiagnostic, Subdiagnostic}; | 15 | use rustc_macros::{LintDiagnostic, Subdiagnostic}; |
| 14 | use rustc_middle::ty::{ | 16 | use rustc_middle::ty::{ |
| 15 | inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt, | 17 | inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt, |
| ... | @@ -22,10 +24,6 @@ use rustc_span::{ | ... | @@ -22,10 +24,6 @@ use rustc_span::{ |
| 22 | Span, Symbol, | 24 | Span, Symbol, |
| 23 | }; | 25 | }; |
| 24 | 26 | ||
| 25 | use crate::{ | ||
| 26 | builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext, | ||
| 27 | }; | ||
| 28 | |||
| 29 | // array_into_iter.rs | 27 | // array_into_iter.rs |
| 30 | #[derive(LintDiagnostic)] | 28 | #[derive(LintDiagnostic)] |
| 31 | #[diag(lint_shadowed_into_iter)] | 29 | #[diag(lint_shadowed_into_iter)] |
| ... | @@ -263,62 +261,6 @@ pub struct BuiltinUnreachablePub<'a> { | ... | @@ -263,62 +261,6 @@ pub struct BuiltinUnreachablePub<'a> { |
| 263 | pub help: Option<()>, | 261 | pub help: Option<()>, |
| 264 | } | 262 | } |
| 265 | 263 | ||
| 266 | pub struct SuggestChangingAssocTypes<'a, 'b> { | ||
| 267 | pub ty: &'a rustc_hir::Ty<'b>, | ||
| 268 | } | ||
| 269 | |||
| 270 | impl<'a, 'b> Subdiagnostic for SuggestChangingAssocTypes<'a, 'b> { | ||
| 271 | fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( | ||
| 272 | self, | ||
| 273 | diag: &mut Diag<'_, G>, | ||
| 274 | _f: &F, | ||
| 275 | ) { | ||
| 276 | // Access to associates types should use `<T as Bound>::Assoc`, which does not need a | ||
| 277 | // bound. Let's see if this type does that. | ||
| 278 | |||
| 279 | // We use a HIR visitor to walk the type. | ||
| 280 | use rustc_hir::intravisit::{self, Visitor}; | ||
| 281 | struct WalkAssocTypes<'a, 'b, G: EmissionGuarantee> { | ||
| 282 | err: &'a mut Diag<'b, G>, | ||
| 283 | } | ||
| 284 | impl<'a, 'b, G: EmissionGuarantee> Visitor<'_> for WalkAssocTypes<'a, 'b, G> { | ||
| 285 | fn visit_qpath( | ||
| 286 | &mut self, | ||
| 287 | qpath: &rustc_hir::QPath<'_>, | ||
| 288 | id: rustc_hir::HirId, | ||
| 289 | span: Span, | ||
| 290 | ) { | ||
| 291 | if TypeAliasBounds::is_type_variable_assoc(qpath) { | ||
| 292 | self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help); | ||
| 293 | } | ||
| 294 | intravisit::walk_qpath(self, qpath, id) | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | // Let's go for a walk! | ||
| 299 | let mut visitor = WalkAssocTypes { err: diag }; | ||
| 300 | visitor.visit_ty(self.ty); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | #[derive(LintDiagnostic)] | ||
| 305 | #[diag(lint_builtin_type_alias_where_clause)] | ||
| 306 | pub struct BuiltinTypeAliasWhereClause<'a, 'b> { | ||
| 307 | #[suggestion(code = "", applicability = "machine-applicable")] | ||
| 308 | pub suggestion: Span, | ||
| 309 | #[subdiagnostic] | ||
| 310 | pub sub: Option<SuggestChangingAssocTypes<'a, 'b>>, | ||
| 311 | } | ||
| 312 | |||
| 313 | #[derive(LintDiagnostic)] | ||
| 314 | #[diag(lint_builtin_type_alias_generic_bounds)] | ||
| 315 | pub struct BuiltinTypeAliasGenericBounds<'a, 'b> { | ||
| 316 | #[subdiagnostic] | ||
| 317 | pub suggestion: BuiltinTypeAliasGenericBoundsSuggestion, | ||
| 318 | #[subdiagnostic] | ||
| 319 | pub sub: Option<SuggestChangingAssocTypes<'a, 'b>>, | ||
| 320 | } | ||
| 321 | |||
| 322 | #[derive(LintDiagnostic)] | 264 | #[derive(LintDiagnostic)] |
| 323 | #[diag(lint_macro_expr_fragment_specifier_2024_migration)] | 265 | #[diag(lint_macro_expr_fragment_specifier_2024_migration)] |
| 324 | pub struct MacroExprFragment2024 { | 266 | pub struct MacroExprFragment2024 { |
| ... | @@ -326,21 +268,72 @@ pub struct MacroExprFragment2024 { | ... | @@ -326,21 +268,72 @@ pub struct MacroExprFragment2024 { |
| 326 | pub suggestion: Span, | 268 | pub suggestion: Span, |
| 327 | } | 269 | } |
| 328 | 270 | ||
| 329 | pub struct BuiltinTypeAliasGenericBoundsSuggestion { | 271 | pub struct BuiltinTypeAliasBounds<'a, 'hir> { |
| 272 | pub in_where_clause: bool, | ||
| 273 | pub label: Span, | ||
| 274 | pub enable_feat_help: bool, | ||
| 330 | pub suggestions: Vec<(Span, String)>, | 275 | pub suggestions: Vec<(Span, String)>, |
| 276 | pub preds: &'hir [hir::WherePredicate<'hir>], | ||
| 277 | pub ty: Option<&'a hir::Ty<'hir>>, | ||
| 331 | } | 278 | } |
| 332 | 279 | ||
| 333 | impl Subdiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { | 280 | impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_, '_> { |
| 334 | fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( | 281 | fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { |
| 335 | self, | 282 | diag.primary_message(if self.in_where_clause { |
| 336 | diag: &mut Diag<'_, G>, | 283 | fluent::lint_builtin_type_alias_bounds_where_clause |
| 337 | _f: &F, | 284 | } else { |
| 338 | ) { | 285 | fluent::lint_builtin_type_alias_bounds_param_bounds |
| 339 | diag.multipart_suggestion( | 286 | }); |
| 340 | fluent::lint_suggestion, | 287 | diag.span_label(self.label, fluent::lint_builtin_type_alias_bounds_label); |
| 341 | self.suggestions, | 288 | diag.note(fluent::lint_builtin_type_alias_bounds_limitation_note); |
| 342 | Applicability::MachineApplicable, | 289 | if self.enable_feat_help { |
| 343 | ); | 290 | diag.help(fluent::lint_builtin_type_alias_bounds_enable_feat_help); |
| 291 | } | ||
| 292 | |||
| 293 | // We perform the walk in here instead of in `<TypeAliasBounds as LateLintPass>` to | ||
| 294 | // avoid doing throwaway work in case the lint ends up getting suppressed. | ||
| 295 | let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() }; | ||
| 296 | if let Some(ty) = self.ty { | ||
| 297 | hir::intravisit::Visitor::visit_ty(&mut collector, ty); | ||
| 298 | } | ||
| 299 | |||
| 300 | let affect_object_lifetime_defaults = self | ||
| 301 | .preds | ||
| 302 | .iter() | ||
| 303 | .filter(|pred| pred.in_where_clause() == self.in_where_clause) | ||
| 304 | .any(|pred| TypeAliasBounds::affects_object_lifetime_defaults(pred)); | ||
| 305 | |||
| 306 | // If there are any shorthand assoc tys, then the bounds can't be removed automatically. | ||
| 307 | // The user first needs to fully qualify the assoc tys. | ||
| 308 | let applicability = if !collector.qselves.is_empty() || affect_object_lifetime_defaults { | ||
| 309 | Applicability::MaybeIncorrect | ||
| 310 | } else { | ||
| 311 | Applicability::MachineApplicable | ||
| 312 | }; | ||
| 313 | |||
| 314 | diag.arg("count", self.suggestions.len()); | ||
| 315 | diag.multipart_suggestion(fluent::lint_suggestion, self.suggestions, applicability); | ||
| 316 | |||
| 317 | // Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via | ||
| 318 | // `<T as /* Trait */>::Assoc` to remove their reliance on any type param bounds. | ||
| 319 | // | ||
| 320 | // Instead of attempting to figure out the necessary trait ref, just use a | ||
| 321 | // placeholder. Since we don't record type-dependent resolutions for non-body | ||
| 322 | // items like type aliases, we can't simply deduce the corresp. trait from | ||
| 323 | // the HIR path alone without rerunning parts of HIR ty lowering here | ||
| 324 | // (namely `probe_single_ty_param_bound_for_assoc_ty`) which is infeasible. | ||
| 325 | // | ||
| 326 | // (We could employ some simple heuristics but that's likely not worth it). | ||
| 327 | for qself in collector.qselves { | ||
| 328 | diag.multipart_suggestion( | ||
| 329 | fluent::lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg, | ||
| 330 | vec![ | ||
| 331 | (qself.shrink_to_lo(), "<".into()), | ||
| 332 | (qself.shrink_to_hi(), " as /* Trait */>".into()), | ||
| 333 | ], | ||
| 334 | Applicability::HasPlaceholders, | ||
| 335 | ); | ||
| 336 | } | ||
| 344 | } | 337 | } |
| 345 | } | 338 | } |
| 346 | 339 |
compiler/rustc_mir_transform/src/instsimplify.rs+2-2| ... | @@ -3,6 +3,7 @@ | ... | @@ -3,6 +3,7 @@ |
| 3 | use crate::simplify::simplify_duplicate_switch_targets; | 3 | use crate::simplify::simplify_duplicate_switch_targets; |
| 4 | use crate::take_array; | 4 | use crate::take_array; |
| 5 | use rustc_ast::attr; | 5 | use rustc_ast::attr; |
| 6 | use rustc_hir::LangItem; | ||
| 6 | use rustc_middle::bug; | 7 | use rustc_middle::bug; |
| 7 | use rustc_middle::mir::*; | 8 | use rustc_middle::mir::*; |
| 8 | use rustc_middle::ty::layout; | 9 | use rustc_middle::ty::layout; |
| ... | @@ -271,8 +272,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { | ... | @@ -271,8 +272,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { |
| 271 | return; | 272 | return; |
| 272 | } | 273 | } |
| 273 | 274 | ||
| 274 | let trait_def_id = self.tcx.trait_of_item(fn_def_id); | 275 | if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn) { |
| 275 | if trait_def_id.is_none() || trait_def_id != self.tcx.lang_items().clone_trait() { | ||
| 276 | return; | 276 | return; |
| 277 | } | 277 | } |
| 278 | 278 |
compiler/rustc_passes/src/dead.rs+22-10| ... | @@ -54,7 +54,24 @@ impl Publicness { | ... | @@ -54,7 +54,24 @@ impl Publicness { |
| 54 | } | 54 | } |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool { | 57 | fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> { |
| 58 | match ty.kind { | ||
| 59 | TyKind::Path(hir::QPath::Resolved(_, path)) => { | ||
| 60 | if let Res::Def(def_kind, def_id) = path.res | ||
| 61 | && let Some(local_def_id) = def_id.as_local() | ||
| 62 | { | ||
| 63 | Some((local_def_id, def_kind)) | ||
| 64 | } else { | ||
| 65 | None | ||
| 66 | } | ||
| 67 | } | ||
| 68 | TyKind::Slice(ty) | TyKind::Array(ty, _) => adt_of(ty), | ||
| 69 | TyKind::Ptr(ty) | TyKind::Ref(_, ty) => adt_of(ty.ty), | ||
| 70 | _ => None, | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool { | ||
| 58 | // treat PhantomData and positional ZST as public, | 75 | // treat PhantomData and positional ZST as public, |
| 59 | // we don't want to lint types which only have them, | 76 | // we don't want to lint types which only have them, |
| 60 | // cause it's a common way to use such types to check things like well-formedness | 77 | // cause it's a common way to use such types to check things like well-formedness |
| ... | @@ -79,10 +96,7 @@ fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool { | ... | @@ -79,10 +96,7 @@ fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool { |
| 79 | /// for enum and union, just check they are public, | 96 | /// for enum and union, just check they are public, |
| 80 | /// and doesn't solve types like &T for now, just skip them | 97 | /// and doesn't solve types like &T for now, just skip them |
| 81 | fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness { | 98 | fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness { |
| 82 | if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind | 99 | if let Some((def_id, def_kind)) = adt_of(ty) { |
| 83 | && let Res::Def(def_kind, def_id) = path.res | ||
| 84 | && def_id.is_local() | ||
| 85 | { | ||
| 86 | return match def_kind { | 100 | return match def_kind { |
| 87 | DefKind::Enum | DefKind::Union => { | 101 | DefKind::Enum | DefKind::Union => { |
| 88 | let ty_is_public = tcx.visibility(def_id).is_public(); | 102 | let ty_is_public = tcx.visibility(def_id).is_public(); |
| ... | @@ -565,10 +579,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { | ... | @@ -565,10 +579,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { |
| 565 | } | 579 | } |
| 566 | 580 | ||
| 567 | fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool { | 581 | fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool { |
| 568 | if let TyKind::Path(hir::QPath::Resolved(_, path)) = | 582 | if let Some((local_def_id, def_kind)) = |
| 569 | self.tcx.hir().item(impl_id).expect_impl().self_ty.kind | 583 | adt_of(self.tcx.hir().item(impl_id).expect_impl().self_ty) |
| 570 | && let Res::Def(def_kind, def_id) = path.res | ||
| 571 | && let Some(local_def_id) = def_id.as_local() | ||
| 572 | && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) | 584 | && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) |
| 573 | { | 585 | { |
| 574 | if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id | 586 | if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id |
| ... | @@ -915,7 +927,7 @@ fn create_and_seed_worklist( | ... | @@ -915,7 +927,7 @@ fn create_and_seed_worklist( |
| 915 | match tcx.def_kind(id) { | 927 | match tcx.def_kind(id) { |
| 916 | DefKind::Impl { .. } => false, | 928 | DefKind::Impl { .. } => false, |
| 917 | DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), | 929 | DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), |
| 918 | DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), | 930 | DefKind::Struct => struct_all_fields_are_public(tcx, id) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), |
| 919 | _ => true | 931 | _ => true |
| 920 | }) | 932 | }) |
| 921 | .map(|id| (id, ComesFromAllowExpect::No)) | 933 | .map(|id| (id, ComesFromAllowExpect::No)) |
compiler/rustc_resolve/src/diagnostics.rs+4-1| ... | @@ -1448,7 +1448,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { | ... | @@ -1448,7 +1448,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { |
| 1448 | ); | 1448 | ); |
| 1449 | 1449 | ||
| 1450 | if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules { | 1450 | if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules { |
| 1451 | err.subdiagnostic(MaybeMissingMacroRulesName { span: ident.span }); | 1451 | let label_span = ident.span.shrink_to_hi(); |
| 1452 | let mut spans = MultiSpan::from_span(label_span); | ||
| 1453 | spans.push_span_label(label_span, "put a macro name here"); | ||
| 1454 | err.subdiagnostic(MaybeMissingMacroRulesName { spans: spans }); | ||
| 1452 | return; | 1455 | return; |
| 1453 | } | 1456 | } |
| 1454 | 1457 |
compiler/rustc_resolve/src/errors.rs+1-1| ... | @@ -669,7 +669,7 @@ pub(crate) struct MacroSuggMovePosition { | ... | @@ -669,7 +669,7 @@ pub(crate) struct MacroSuggMovePosition { |
| 669 | #[note(resolve_missing_macro_rules_name)] | 669 | #[note(resolve_missing_macro_rules_name)] |
| 670 | pub(crate) struct MaybeMissingMacroRulesName { | 670 | pub(crate) struct MaybeMissingMacroRulesName { |
| 671 | #[primary_span] | 671 | #[primary_span] |
| 672 | pub(crate) span: Span, | 672 | pub(crate) spans: MultiSpan, |
| 673 | } | 673 | } |
| 674 | 674 | ||
| 675 | #[derive(Subdiagnostic)] | 675 | #[derive(Subdiagnostic)] |
compiler/rustc_span/src/symbol.rs+1| ... | @@ -557,6 +557,7 @@ symbols! { | ... | @@ -557,6 +557,7 @@ symbols! { |
| 557 | clobber_abi, | 557 | clobber_abi, |
| 558 | clone, | 558 | clone, |
| 559 | clone_closures, | 559 | clone_closures, |
| 560 | clone_fn, | ||
| 560 | clone_from, | 561 | clone_from, |
| 561 | closure, | 562 | closure, |
| 562 | closure_lifetime_binder, | 563 | closure_lifetime_binder, |
compiler/rustc_type_ir/src/visit.rs-4| ... | @@ -241,10 +241,6 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> { | ... | @@ -241,10 +241,6 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> { |
| 241 | self.has_type_flags(TypeFlags::HAS_ALIAS) | 241 | self.has_type_flags(TypeFlags::HAS_ALIAS) |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | fn has_inherent_projections(&self) -> bool { | ||
| 245 | self.has_type_flags(TypeFlags::HAS_TY_INHERENT) | ||
| 246 | } | ||
| 247 | |||
| 248 | fn has_opaque_types(&self) -> bool { | 244 | fn has_opaque_types(&self) -> bool { |
| 249 | self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) | 245 | self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) |
| 250 | } | 246 | } |
library/core/src/clone.rs+3| ... | @@ -160,6 +160,9 @@ pub trait Clone: Sized { | ... | @@ -160,6 +160,9 @@ pub trait Clone: Sized { |
| 160 | /// ``` | 160 | /// ``` |
| 161 | #[stable(feature = "rust1", since = "1.0.0")] | 161 | #[stable(feature = "rust1", since = "1.0.0")] |
| 162 | #[must_use = "cloning is often expensive and is not expected to have side effects"] | 162 | #[must_use = "cloning is often expensive and is not expected to have side effects"] |
| 163 | // Clone::clone is special because the compiler generates MIR to implement it for some types. | ||
| 164 | // See InstanceKind::CloneShim. | ||
| 165 | #[cfg_attr(not(bootstrap), lang = "clone_fn")] | ||
| 163 | fn clone(&self) -> Self; | 166 | fn clone(&self) -> Self; |
| 164 | 167 | ||
| 165 | /// Performs copy-assignment from `source`. | 168 | /// Performs copy-assignment from `source`. |
src/tools/compiletest/src/command-list.rs+1| ... | @@ -201,6 +201,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ | ... | @@ -201,6 +201,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ |
| 201 | "only-wasm32-wasip1", | 201 | "only-wasm32-wasip1", |
| 202 | "only-watchos", | 202 | "only-watchos", |
| 203 | "only-windows", | 203 | "only-windows", |
| 204 | "only-windows-gnu", | ||
| 204 | "only-x86", | 205 | "only-x86", |
| 205 | "only-x86_64", | 206 | "only-x86_64", |
| 206 | "only-x86_64-fortanix-unknown-sgx", | 207 | "only-x86_64-fortanix-unknown-sgx", |
src/tools/run-make-support/src/external_deps/cc.rs+23| ... | @@ -15,6 +15,13 @@ pub fn cc() -> Cc { | ... | @@ -15,6 +15,13 @@ pub fn cc() -> Cc { |
| 15 | Cc::new() | 15 | Cc::new() |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | /// Construct a new platform-specific CXX compiler invocation. | ||
| 19 | /// CXX_DEFAULT_FLAGS is passed from compiletest. | ||
| 20 | #[track_caller] | ||
| 21 | pub fn cxx() -> Cc { | ||
| 22 | Cc::new_cxx() | ||
| 23 | } | ||
| 24 | |||
| 18 | /// A platform-specific C compiler invocation builder. The specific C compiler used is | 25 | /// A platform-specific C compiler invocation builder. The specific C compiler used is |
| 19 | /// passed down from compiletest. | 26 | /// passed down from compiletest. |
| 20 | #[derive(Debug)] | 27 | #[derive(Debug)] |
| ... | @@ -44,6 +51,22 @@ impl Cc { | ... | @@ -44,6 +51,22 @@ impl Cc { |
| 44 | Self { cmd } | 51 | Self { cmd } |
| 45 | } | 52 | } |
| 46 | 53 | ||
| 54 | /// Construct a new platform-specific CXX compiler invocation. | ||
| 55 | /// CXX_DEFAULT_FLAGS is passed from compiletest. | ||
| 56 | #[track_caller] | ||
| 57 | pub fn new_cxx() -> Self { | ||
| 58 | let compiler = env_var("CXX"); | ||
| 59 | |||
| 60 | let mut cmd = Command::new(compiler); | ||
| 61 | |||
| 62 | let default_cflags = env_var("CXX_DEFAULT_FLAGS"); | ||
| 63 | for flag in default_cflags.split(char::is_whitespace) { | ||
| 64 | cmd.arg(flag); | ||
| 65 | } | ||
| 66 | |||
| 67 | Self { cmd } | ||
| 68 | } | ||
| 69 | |||
| 47 | /// Specify path of the input file. | 70 | /// Specify path of the input file. |
| 48 | pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self { | 71 | pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self { |
| 49 | self.cmd.arg(path.as_ref()); | 72 | self.cmd.arg(path.as_ref()); |
src/tools/run-make-support/src/lib.rs+1-1| ... | @@ -44,7 +44,7 @@ pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rust | ... | @@ -44,7 +44,7 @@ pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rust |
| 44 | 44 | ||
| 45 | // These rely on external dependencies. | 45 | // These rely on external dependencies. |
| 46 | pub use c_build::{build_native_dynamic_lib, build_native_static_lib}; | 46 | pub use c_build::{build_native_dynamic_lib, build_native_static_lib}; |
| 47 | pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc}; | 47 | pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; |
| 48 | pub use clang::{clang, Clang}; | 48 | pub use clang::{clang, Clang}; |
| 49 | pub use htmldocck::htmldocck; | 49 | pub use htmldocck::htmldocck; |
| 50 | pub use llvm::{ | 50 | pub use llvm::{ |
src/tools/tidy/src/allowed_run_make_makefiles.txt-6| ... | @@ -2,7 +2,6 @@ run-make/branch-protection-check-IBT/Makefile | ... | @@ -2,7 +2,6 @@ run-make/branch-protection-check-IBT/Makefile |
| 2 | run-make/c-unwind-abi-catch-lib-panic/Makefile | 2 | run-make/c-unwind-abi-catch-lib-panic/Makefile |
| 3 | run-make/cat-and-grep-sanity-check/Makefile | 3 | run-make/cat-and-grep-sanity-check/Makefile |
| 4 | run-make/cdylib-dylib-linkage/Makefile | 4 | run-make/cdylib-dylib-linkage/Makefile |
| 5 | run-make/compiler-rt-works-on-mingw/Makefile | ||
| 6 | run-make/cross-lang-lto-clang/Makefile | 5 | run-make/cross-lang-lto-clang/Makefile |
| 7 | run-make/cross-lang-lto-pgo-smoketest/Makefile | 6 | run-make/cross-lang-lto-pgo-smoketest/Makefile |
| 8 | run-make/cross-lang-lto-upstream-rlibs/Makefile | 7 | run-make/cross-lang-lto-upstream-rlibs/Makefile |
| ... | @@ -10,18 +9,14 @@ run-make/cross-lang-lto/Makefile | ... | @@ -10,18 +9,14 @@ run-make/cross-lang-lto/Makefile |
| 10 | run-make/dep-info-doesnt-run-much/Makefile | 9 | run-make/dep-info-doesnt-run-much/Makefile |
| 11 | run-make/dep-info-spaces/Makefile | 10 | run-make/dep-info-spaces/Makefile |
| 12 | run-make/dep-info/Makefile | 11 | run-make/dep-info/Makefile |
| 13 | run-make/dump-ice-to-disk/Makefile | ||
| 14 | run-make/emit-to-stdout/Makefile | 12 | run-make/emit-to-stdout/Makefile |
| 15 | run-make/export-executable-symbols/Makefile | 13 | run-make/export-executable-symbols/Makefile |
| 16 | run-make/extern-flag-disambiguates/Makefile | ||
| 17 | run-make/extern-fn-reachable/Makefile | 14 | run-make/extern-fn-reachable/Makefile |
| 18 | run-make/fmt-write-bloat/Makefile | 15 | run-make/fmt-write-bloat/Makefile |
| 19 | run-make/foreign-double-unwind/Makefile | 16 | run-make/foreign-double-unwind/Makefile |
| 20 | run-make/foreign-exceptions/Makefile | 17 | run-make/foreign-exceptions/Makefile |
| 21 | run-make/foreign-rust-exceptions/Makefile | 18 | run-make/foreign-rust-exceptions/Makefile |
| 22 | run-make/incr-add-rust-src-component/Makefile | 19 | run-make/incr-add-rust-src-component/Makefile |
| 23 | run-make/incr-foreign-head-span/Makefile | ||
| 24 | run-make/interdependent-c-libraries/Makefile | ||
| 25 | run-make/issue-35164/Makefile | 20 | run-make/issue-35164/Makefile |
| 26 | run-make/issue-36710/Makefile | 21 | run-make/issue-36710/Makefile |
| 27 | run-make/issue-47551/Makefile | 22 | run-make/issue-47551/Makefile |
| ... | @@ -42,7 +37,6 @@ run-make/native-link-modifier-bundle/Makefile | ... | @@ -42,7 +37,6 @@ run-make/native-link-modifier-bundle/Makefile |
| 42 | run-make/native-link-modifier-whole-archive/Makefile | 37 | run-make/native-link-modifier-whole-archive/Makefile |
| 43 | run-make/no-alloc-shim/Makefile | 38 | run-make/no-alloc-shim/Makefile |
| 44 | run-make/no-builtins-attribute/Makefile | 39 | run-make/no-builtins-attribute/Makefile |
| 45 | run-make/panic-abort-eh_frame/Makefile | ||
| 46 | run-make/pdb-buildinfo-cl-cmd/Makefile | 40 | run-make/pdb-buildinfo-cl-cmd/Makefile |
| 47 | run-make/pgo-gen-lto/Makefile | 41 | run-make/pgo-gen-lto/Makefile |
| 48 | run-make/pgo-indirect-call-promotion/Makefile | 42 | run-make/pgo-indirect-call-promotion/Makefile |
tests/run-make/README.md+5| ... | @@ -41,3 +41,8 @@ The setup for the `rmake.rs` version is a 3-stage process: | ... | @@ -41,3 +41,8 @@ The setup for the `rmake.rs` version is a 3-stage process: |
| 41 | 41 | ||
| 42 | [`run_make_support`]: ../../src/tools/run-make-support | 42 | [`run_make_support`]: ../../src/tools/run-make-support |
| 43 | [extern_prelude]: https://doc.rust-lang.org/reference/names/preludes.html#extern-prelude | 43 | [extern_prelude]: https://doc.rust-lang.org/reference/names/preludes.html#extern-prelude |
| 44 | |||
| 45 | ### Formatting | ||
| 46 | |||
| 47 | Note that files under `tests/` are not formatted by `./x fmt`, | ||
| 48 | use `rustfmt tests/path/to/file.rs` to format a specific file if desired. |
tests/run-make/compiler-rt-works-on-mingw/Makefile deleted-9| ... | @@ -1,9 +0,0 @@ | ||
| 1 | include ../tools.mk | ||
| 2 | |||
| 3 | # only-windows-gnu | ||
| 4 | |||
| 5 | all: | ||
| 6 | 	$(CXX) foo.cpp -c -o $(TMPDIR)/foo.o | ||
| 7 | 	$(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o | ||
| 8 | 	$(RUSTC) foo.rs -lfoo -lstdc++ | ||
| 9 | 	$(call RUN,foo) | ||
tests/run-make/compiler-rt-works-on-mingw/rmake.rs created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | // `compiler-rt` ("runtime") is a suite of LLVM features compatible with rustc. | ||
| 2 | // After building it was enabled on Windows-gnu in #29874, this test is a basic smoke test to | ||
| 3 | // check if building and linking to it can work at all. | ||
| 4 | // See https://github.com/rust-lang/rust/pull/29478 | ||
| 5 | |||
| 6 | //@ only-windows-gnu | ||
| 7 | |||
| 8 | use run_make_support::{cxx, is_msvc, llvm_ar, run, rustc, static_lib_name}; | ||
| 9 | |||
| 10 | fn main() { | ||
| 11 | cxx().input("foo.cpp").arg("-c").out_exe("foo.o").run(); | ||
| 12 | llvm_ar().obj_to_ar().output_input(static_lib_name("foo"), "foo.o").run(); | ||
| 13 | rustc().input("foo.rs").arg("-lfoo").arg("-lstdc++").run(); | ||
| 14 | run("foo"); | ||
| 15 | } | ||
tests/run-make/dump-ice-to-disk/Makefile deleted-10| ... | @@ -1,10 +0,0 @@ | ||
| 1 | include ../tools.mk | ||
| 2 | |||
| 3 | # ignore-windows | ||
| 4 | |||
| 5 | export RUSTC := $(RUSTC_ORIGINAL) | ||
| 6 | export LD_LIBRARY_PATH := $(HOST_RPATH_DIR) | ||
| 7 | export TMPDIR := $(TMPDIR) | ||
| 8 | |||
| 9 | all: | ||
| 10 | 	bash check.sh | ||
tests/run-make/dump-ice-to-disk/check.sh deleted-64| ... | @@ -1,64 +0,0 @@ | ||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | # Default nightly behavior (write ICE to current directory) | ||
| 4 | # FIXME(estebank): these are failing on CI, but passing locally. | ||
| 5 | # $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-default.log 2>&1 | ||
| 6 | # default=$(cat ./rustc-ice-*.txt | wc -l) | ||
| 7 | # rm ./rustc-ice-*.txt | ||
| 8 | |||
| 9 | # Explicit directory set | ||
| 10 | export RUSTC_ICE=$TMPDIR | ||
| 11 | $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-default-set.log 2>&1 | ||
| 12 | default_set=$(cat $TMPDIR/rustc-ice-*.txt | wc -l) | ||
| 13 | content=$(cat $TMPDIR/rustc-ice-*.txt) | ||
| 14 | # Ensure that the ICE dump path doesn't contain `:` because they cause problems on Windows | ||
| 15 | windows_safe=$(echo rustc-ice-*.txt | grep ':') | ||
| 16 | if [ ! -z "$windows_safe" ]; then | ||
| 17 | exit 1 | ||
| 18 | fi | ||
| 19 | |||
| 20 | rm $TMPDIR/rustc-ice-*.txt | ||
| 21 | RUST_BACKTRACE=short $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-short.log 2>&1 | ||
| 22 | short=$(cat $TMPDIR/rustc-ice-*.txt | wc -l) | ||
| 23 | rm $TMPDIR/rustc-ice-*.txt | ||
| 24 | RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-full.log 2>&1 | ||
| 25 | full=$(cat $TMPDIR/rustc-ice-*.txt | wc -l) | ||
| 26 | rm $TMPDIR/rustc-ice-*.txt | ||
| 27 | |||
| 28 | # Explicitly disabling ICE dump | ||
| 29 | export RUSTC_ICE=0 | ||
| 30 | $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-disabled.log 2>&1 | ||
| 31 | should_be_empty_tmp=$(ls -l $TMPDIR/rustc-ice-*.txt 2>/dev/null | wc -l) | ||
| 32 | should_be_empty_dot=$(ls -l ./rustc-ice-*.txt 2>/dev/null | wc -l) | ||
| 33 | |||
| 34 | echo "#### ICE Dump content:" | ||
| 35 | echo $content | ||
| 36 | echo "#### default length:" | ||
| 37 | echo $default | ||
| 38 | echo "#### short length:" | ||
| 39 | echo $short | ||
| 40 | echo "#### default_set length:" | ||
| 41 | echo $default_set | ||
| 42 | echo "#### full length:" | ||
| 43 | echo $full | ||
| 44 | echo "#### should_be_empty_dot length:" | ||
| 45 | echo $should_be_empty_dot | ||
| 46 | echo "#### should_be_empty_tmp length:" | ||
| 47 | echo $should_be_empty_tmp | ||
| 48 | |||
| 49 | ## Verify that a the ICE dump file is created in the appropriate directories, that | ||
| 50 | ## their lengths are the same regardless of other backtrace configuration options, | ||
| 51 | ## that the file is not created when asked to (RUSTC_ICE=0) and that the file | ||
| 52 | ## contains at least part of the expected content. | ||
| 53 | if [ $short -eq $default_set ] && | ||
| 54 | #[ $default -eq $short ] && | ||
| 55 | [ $default_set -eq $full ] && | ||
| 56 | [[ $content == *"thread 'rustc' panicked at "* ]] && | ||
| 57 | [[ $content == *"stack backtrace:"* ]] && | ||
| 58 | #[ $default -gt 0 ] && | ||
| 59 | [ $should_be_empty_dot -eq 0 ] && | ||
| 60 | [ $should_be_empty_tmp -eq 0 ]; then | ||
| 61 | exit 0 | ||
| 62 | else | ||
| 63 | exit 1 | ||
| 64 | fi | ||
tests/run-make/dump-ice-to-disk/lib.rs created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | fn func(s: &str) { | ||
| 2 | println!("{}", s); | ||
| 3 | } | ||
| 4 | |||
| 5 | fn main() { | ||
| 6 | func(1); | ||
| 7 | } | ||
tests/run-make/dump-ice-to-disk/rmake.rs created+81| ... | @@ -0,0 +1,81 @@ | ||
| 1 | // This test checks if internal compilation error (ICE) log files work as expected. | ||
| 2 | // - Get the number of lines from the log files without any configuration options, | ||
| 3 | // then check that the line count doesn't change if the backtrace gets configured to be short | ||
| 4 | // or full. | ||
| 5 | // - Check that disabling ICE logging results in zero files created. | ||
| 6 | // - Check that the ICE files contain some of the expected strings. | ||
| 7 | // See https://github.com/rust-lang/rust/pull/108714 | ||
| 8 | |||
| 9 | use run_make_support::{cwd, has_extension, has_prefix, rfs, rustc, shallow_find_files}; | ||
| 10 | |||
| 11 | fn main() { | ||
| 12 | rustc().input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); | ||
| 13 | let default = get_text_from_ice(".").lines().count(); | ||
| 14 | clear_ice_files(); | ||
| 15 | |||
| 16 | rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); | ||
| 17 | let ice_text = get_text_from_ice(cwd()); | ||
| 18 | let default_set = ice_text.lines().count(); | ||
| 19 | let content = ice_text; | ||
| 20 | let ice_files = shallow_find_files(cwd(), |path| { | ||
| 21 | has_prefix(path, "rustc-ice") && has_extension(path, "txt") | ||
| 22 | }); | ||
| 23 | assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file. | ||
| 24 | let ice_file_name = | ||
| 25 | ice_files.first().and_then(|f| f.file_name()).and_then(|n| n.to_str()).unwrap(); | ||
| 26 | // Ensure that the ICE dump path doesn't contain `:`, because they cause problems on Windows. | ||
| 27 | assert!(!ice_file_name.contains(":"), "{ice_file_name}"); | ||
| 28 | |||
| 29 | clear_ice_files(); | ||
| 30 | rustc() | ||
| 31 | .env("RUSTC_ICE", cwd()) | ||
| 32 | .input("lib.rs") | ||
| 33 | .env("RUST_BACKTRACE", "short") | ||
| 34 | .arg("-Ztreat-err-as-bug=1") | ||
| 35 | .run_fail(); | ||
| 36 | let short = get_text_from_ice(cwd()).lines().count(); | ||
| 37 | clear_ice_files(); | ||
| 38 | rustc() | ||
| 39 | .env("RUSTC_ICE", cwd()) | ||
| 40 | .input("lib.rs") | ||
| 41 | .env("RUST_BACKTRACE", "full") | ||
| 42 | .arg("-Ztreat-err-as-bug=1") | ||
| 43 | .run_fail(); | ||
| 44 | let full = get_text_from_ice(cwd()).lines().count(); | ||
| 45 | clear_ice_files(); | ||
| 46 | |||
| 47 | // The ICE dump is explicitly disabled. Therefore, this should produce no files. | ||
| 48 | rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); | ||
| 49 | let ice_files = shallow_find_files(cwd(), |path| { | ||
| 50 | has_prefix(path, "rustc-ice") && has_extension(path, "txt") | ||
| 51 | }); | ||
| 52 | assert!(ice_files.is_empty()); // There should be 0 ICE files. | ||
| 53 | |||
| 54 | // The line count should not change. | ||
| 55 | assert_eq!(short, default_set); | ||
| 56 | assert_eq!(short, default); | ||
| 57 | assert_eq!(full, default_set); | ||
| 58 | assert!(default > 0); | ||
| 59 | // Some of the expected strings in an ICE file should appear. | ||
| 60 | assert!(content.contains("thread 'rustc' panicked at")); | ||
| 61 | assert!(content.contains("stack backtrace:")); | ||
| 62 | } | ||
| 63 | |||
| 64 | fn clear_ice_files() { | ||
| 65 | let ice_files = shallow_find_files(cwd(), |path| { | ||
| 66 | has_prefix(path, "rustc-ice") && has_extension(path, "txt") | ||
| 67 | }); | ||
| 68 | for file in ice_files { | ||
| 69 | rfs::remove_file(file); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | #[track_caller] | ||
| 74 | fn get_text_from_ice(dir: impl AsRef<std::path::Path>) -> String { | ||
| 75 | let ice_files = | ||
| 76 | shallow_find_files(dir, |path| has_prefix(path, "rustc-ice") && has_extension(path, "txt")); | ||
| 77 | assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file. | ||
| 78 | let ice_file = ice_files.get(0).unwrap(); | ||
| 79 | let output = rfs::read_to_string(ice_file); | ||
| 80 | output | ||
| 81 | } | ||
tests/run-make/dump-ice-to-disk/src/lib.rs deleted-7| ... | @@ -1,7 +0,0 @@ | ||
| 1 | fn func(s: &str) { | ||
| 2 | println!("{}", s); | ||
| 3 | } | ||
| 4 | |||
| 5 | fn main() { | ||
| 6 | func(1); | ||
| 7 | } | ||
tests/run-make/extern-flag-disambiguates/Makefile deleted-26| ... | @@ -1,26 +0,0 @@ | ||
| 1 | # ignore-cross-compile | ||
| 2 | include ../tools.mk | ||
| 3 | |||
| 4 | # Attempt to build this dependency tree: | ||
| 5 | # | ||
| 6 | #	A.1 A.2 | ||
| 7 | #	 |\ | | ||
| 8 | #	 | \ | | ||
| 9 | # B \ C | ||
| 10 | # \ | / | ||
| 11 | # \|/ | ||
| 12 | # D | ||
| 13 | # | ||
| 14 | # Note that A.1 and A.2 are crates with the same name. | ||
| 15 | |||
| 16 | all: | ||
| 17 | 	$(RUSTC) -C metadata=1 -C extra-filename=-1 a.rs | ||
| 18 | 	$(RUSTC) -C metadata=2 -C extra-filename=-2 a.rs | ||
| 19 | 	$(RUSTC) b.rs --extern a=$(TMPDIR)/liba-1.rlib | ||
| 20 | 	$(RUSTC) c.rs --extern a=$(TMPDIR)/liba-2.rlib | ||
| 21 | 	@echo before | ||
| 22 | 	$(RUSTC) --cfg before d.rs --extern a=$(TMPDIR)/liba-1.rlib | ||
| 23 | 	$(call RUN,d) | ||
| 24 | 	@echo after | ||
| 25 | 	$(RUSTC) --cfg after d.rs --extern a=$(TMPDIR)/liba-1.rlib | ||
| 26 | 	$(call RUN,d) | ||
tests/run-make/extern-flag-disambiguates/rmake.rs created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | //@ ignore-cross-compile | ||
| 2 | |||
| 3 | use run_make_support::{cwd, run, rustc}; | ||
| 4 | |||
| 5 | // Attempt to build this dependency tree: | ||
| 6 | // | ||
| 7 | // A.1 A.2 | ||
| 8 | // |\ | | ||
| 9 | // | \ | | ||
| 10 | // B \ C | ||
| 11 | // \ | / | ||
| 12 | // \|/ | ||
| 13 | // D | ||
| 14 | // | ||
| 15 | // Note that A.1 and A.2 are crates with the same name. | ||
| 16 | |||
| 17 | // original Makefile at https://github.com/rust-lang/rust/issues/14469 | ||
| 18 | |||
| 19 | fn main() { | ||
| 20 | rustc().metadata("1").extra_filename("-1").input("a.rs").run(); | ||
| 21 | rustc().metadata("2").extra_filename("-2").input("a.rs").run(); | ||
| 22 | rustc().input("b.rs").extern_("a", "liba-1.rlib").run(); | ||
| 23 | rustc().input("c.rs").extern_("a", "liba-2.rlib").run(); | ||
| 24 | println!("before"); | ||
| 25 | rustc().cfg("before").input("d.rs").extern_("a", "liba-1.rlib").run(); | ||
| 26 | run("d"); | ||
| 27 | println!("after"); | ||
| 28 | rustc().cfg("after").input("d.rs").extern_("a", "liba-1.rlib").run(); | ||
| 29 | run("d"); | ||
| 30 | } | ||
tests/run-make/incr-foreign-head-span/Makefile deleted-21| ... | @@ -1,21 +0,0 @@ | ||
| 1 | include ../tools.mk | ||
| 2 | |||
| 3 | # ignore-none no-std is not supported | ||
| 4 | # ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std' | ||
| 5 | |||
| 6 | # Ensure that modifying a crate on disk (without recompiling it) | ||
| 7 | # does not cause ICEs in downstream crates. | ||
| 8 | # Previously, we would call `SourceMap.guess_head_span` on a span | ||
| 9 | # from an external crate, which would cause us to read an upstream | ||
| 10 | # source file from disk during compilation of a downstream crate | ||
| 11 | # See #86480 for more details | ||
| 12 | |||
| 13 | INCR=$(TMPDIR)/incr | ||
| 14 | |||
| 15 | all: | ||
| 16 | 	cp first_crate.rs second_crate.rs $(TMPDIR) | ||
| 17 | 	$(RUSTC) $(TMPDIR)/first_crate.rs -C incremental=$(INCR) --target $(TARGET) --crate-type lib | ||
| 18 | 	$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --extern first_crate=$(TMPDIR)/libfirst_crate.rlib --crate-type lib | ||
| 19 | 	rm $(TMPDIR)/first_crate.rs | ||
| 20 | 	$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib | ||
| 21 | |||
tests/run-make/incr-foreign-head-span/rmake.rs created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | // Ensure that modifying a crate on disk (without recompiling it) | ||
| 2 | // does not cause ICEs (internal compiler errors) in downstream crates. | ||
| 3 | // Previously, we would call `SourceMap.guess_head_span` on a span | ||
| 4 | // from an external crate, which would cause us to read an upstream | ||
| 5 | // source file from disk during compilation of a downstream crate. | ||
| 6 | // See https://github.com/rust-lang/rust/issues/86480 | ||
| 7 | |||
| 8 | //@ ignore-none | ||
| 9 | // Reason: no-std is not supported | ||
| 10 | //@ ignore-nvptx64-nvidia-cuda | ||
| 11 | // Reason: can't find crate for 'std' | ||
| 12 | |||
| 13 | use run_make_support::{rfs, rust_lib_name, rustc}; | ||
| 14 | |||
| 15 | fn main() { | ||
| 16 | rustc().input("first_crate.rs").incremental("incr").crate_type("lib").run(); | ||
| 17 | rustc() | ||
| 18 | .input("second_crate.rs") | ||
| 19 | .incremental("incr") | ||
| 20 | .extern_("first_crate", rust_lib_name("first_crate")) | ||
| 21 | .crate_type("lib") | ||
| 22 | .run(); | ||
| 23 | rfs::remove_file("first_crate.rs"); | ||
| 24 | rustc().input("second_crate.rs").incremental("incr").cfg("second_run").crate_type("lib").run(); | ||
| 25 | } | ||
tests/run-make/interdependent-c-libraries/Makefile deleted-15| ... | @@ -1,15 +0,0 @@ | ||
| 1 | # ignore-cross-compile | ||
| 2 | include ../tools.mk | ||
| 3 | |||
| 4 | # The rust crate foo will link to the native library foo, while the rust crate | ||
| 5 | # bar will link to the native library bar. There is also a dependency between | ||
| 6 | # the native library bar to the natibe library foo. | ||
| 7 | # | ||
| 8 | # This test ensures that the ordering of -lfoo and -lbar on the command line is | ||
| 9 | # correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo' | ||
| 10 | # library will be stripped out, and the linkage will fail. | ||
| 11 | |||
| 12 | all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar) | ||
| 13 | 	$(RUSTC) foo.rs | ||
| 14 | 	$(RUSTC) bar.rs | ||
| 15 | 	$(RUSTC) main.rs --print link-args | ||
tests/run-make/interdependent-c-libraries/rmake.rs created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | // The rust crate foo will link to the native library foo, while the rust crate | ||
| 2 | // bar will link to the native library bar. There is also a dependency between | ||
| 3 | // the native library bar to the natibe library foo. | ||
| 4 | // This test ensures that the ordering of -lfoo and -lbar on the command line is | ||
| 5 | // correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo' | ||
| 6 | // library will be stripped out, and the linkage will fail. | ||
| 7 | // See https://github.com/rust-lang/rust/commit/e6072fa0c4c22d62acf3dcb78c8ee260a1368bd7 | ||
| 8 | |||
| 9 | //@ ignore-cross-compile | ||
| 10 | // Reason: linkage still fails as the object files produced are not in the correct | ||
| 11 | // format in the `build_native_static_lib` step | ||
| 12 | |||
| 13 | use run_make_support::{build_native_static_lib, rustc}; | ||
| 14 | |||
| 15 | fn main() { | ||
| 16 | build_native_static_lib("foo"); | ||
| 17 | build_native_static_lib("bar"); | ||
| 18 | rustc().input("foo.rs").run(); | ||
| 19 | rustc().input("bar.rs").run(); | ||
| 20 | rustc().input("main.rs").print("link-args").run(); | ||
| 21 | } | ||
tests/run-make/panic-abort-eh_frame/Makefile deleted-10| ... | @@ -1,10 +0,0 @@ | ||
| 1 | # only-linux | ||
| 2 | # | ||
| 3 | # This test ensures that `panic=abort` code (without `C-unwind`, that is) should not have any | ||
| 4 | # unwinding related `.eh_frame` sections emitted. | ||
| 5 | |||
| 6 | include ../tools.mk | ||
| 7 | |||
| 8 | all: | ||
| 9 | 	$(RUSTC) foo.rs --crate-type=lib --emit=obj=$(TMPDIR)/foo.o -Cpanic=abort --edition 2021 -Z validate-mir | ||
| 10 | 	objdump --dwarf=frames $(TMPDIR)/foo.o | $(CGREP) -v 'DW_CFA' | ||
tests/run-make/panic-abort-eh_frame/rmake.rs created+24| ... | @@ -0,0 +1,24 @@ | ||
| 1 | // An `.eh_frame` section in an object file is a symptom of an UnwindAction::Terminate | ||
| 2 | // being inserted, useful for determining whether or not unwinding is necessary. | ||
| 3 | // This is useless when panics would NEVER unwind due to -C panic=abort. This section should | ||
| 4 | // therefore never appear in the emit file of a -C panic=abort compilation, and this test | ||
| 5 | // checks that this is respected. | ||
| 6 | // See https://github.com/rust-lang/rust/pull/112403 | ||
| 7 | |||
| 8 | //@ only-linux | ||
| 9 | // FIXME(Oneirical): the DW_CFA symbol appears on Windows-gnu, because uwtable | ||
| 10 | // is forced to true on Windows targets (see #128136). | ||
| 11 | |||
| 12 | use run_make_support::{llvm_objdump, rustc}; | ||
| 13 | |||
| 14 | fn main() { | ||
| 15 | rustc() | ||
| 16 | .input("foo.rs") | ||
| 17 | .crate_type("lib") | ||
| 18 | .emit("obj=foo.o") | ||
| 19 | .panic("abort") | ||
| 20 | .edition("2021") | ||
| 21 | .arg("-Zvalidate-mir") | ||
| 22 | .run(); | ||
| 23 | llvm_objdump().arg("--dwarf=frames").input("foo.o").run().assert_stdout_not_contains("DW_CFA"); | ||
| 24 | } | ||
tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs deleted-20| ... | @@ -1,20 +0,0 @@ | ||
| 1 | //@ compile-flags: --crate-type=lib | ||
| 2 | //@ check-pass | ||
| 3 | |||
| 4 | #![feature(inherent_associated_types)] | ||
| 5 | #![allow(incomplete_features)] | ||
| 6 | |||
| 7 | // Bounds on the self type play a major role in the resolution of inherent associated types (*). | ||
| 8 | // As a result of that, if a type alias contains any then its bounds have to be respected and the | ||
| 9 | // lint `type_alias_bounds` should not fire. | ||
| 10 | |||
| 11 | #![deny(type_alias_bounds)] | ||
| 12 | |||
| 13 | pub type Alias<T: Bound> = (Source<T>::Assoc,); | ||
| 14 | |||
| 15 | pub struct Source<T>(T); | ||
| 16 | pub trait Bound {} | ||
| 17 | |||
| 18 | impl<T: Bound> Source<T> { | ||
| 19 | pub type Assoc = (); | ||
| 20 | } | ||
tests/ui/associated-inherent-types/type-alias-bounds.rs created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | //@ compile-flags: --crate-type=lib | ||
| 2 | //@ check-pass | ||
| 3 | |||
| 4 | #![feature(inherent_associated_types)] | ||
| 5 | #![allow(incomplete_features)] | ||
| 6 | |||
| 7 | // FIXME(inherent_associated_types): | ||
| 8 | // While we currently do take some clauses of the ParamEnv into consideration | ||
| 9 | // when performing IAT selection, we do not perform full well-formedness checking | ||
| 10 | // for (eager) type alias definition and usage sites. | ||
| 11 | // | ||
| 12 | // Therefore it's *correct* for lint `type_alias_bounds` to fire here despite the | ||
| 13 | // fact that removing `Bound` from `T` in `Alias` would lead to an error! | ||
| 14 | // | ||
| 15 | // Obviously, the present situation isn't ideal and we should fix it in one way | ||
| 16 | // or another. Either we somehow delay IAT selection until after HIR ty lowering | ||
| 17 | // to avoid the need to specify any bounds inside (eager) type aliases or we | ||
| 18 | // force the overarching type alias to be *lazy* (similar to TAITs) which would | ||
| 19 | // automatically lead to full wfchecking and lint TAB getting suppressed. | ||
| 20 | |||
| 21 | pub type Alias<T: Bound> = (Source<T>::Assoc,); | ||
| 22 | //~^ WARN bounds on generic parameters in type aliases are not enforced | ||
| 23 | |||
| 24 | pub struct Source<T>(T); | ||
| 25 | pub trait Bound {} | ||
| 26 | |||
| 27 | impl<T: Bound> Source<T> { | ||
| 28 | pub type Assoc = (); | ||
| 29 | } | ||
tests/ui/associated-inherent-types/type-alias-bounds.stderr created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | warning: bounds on generic parameters in type aliases are not enforced | ||
| 2 | --> $DIR/type-alias-bounds.rs:21:19 | ||
| 3 | | | ||
| 4 | LL | pub type Alias<T: Bound> = (Source<T>::Assoc,); | ||
| 5 | | --^^^^^ | ||
| 6 | | | | | ||
| 7 | | | will not be checked at usage sites of the type alias | ||
| 8 | | help: remove this bound | ||
| 9 | | | ||
| 10 | = note: this is a known limitation of the type checker that may be lifted in a future edition. | ||
| 11 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information | ||
| 12 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 13 | = note: `#[warn(type_alias_bounds)]` on by default | ||
| 14 | |||
| 15 | warning: 1 warning emitted | ||
| 16 | |||
tests/ui/associated-type-bounds/type-alias.stderr+108-96| ... | @@ -1,147 +1,159 @@ | ... | @@ -1,147 +1,159 @@ |
| 1 | warning: where clauses are not enforced in type aliases | 1 | warning: where clauses on type aliases are not enforced |
| 2 | --> $DIR/type-alias.rs:3:25 | 2 | --> $DIR/type-alias.rs:3:25 |
| 3 | | | 3 | | |
| 4 | LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T; | 4 | LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T; |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^ | 5 | | ------^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | | | 6 | | | | |
| 7 | | | will not be checked at usage sites of the type alias | ||
| 8 | | help: remove this where clause | ||
| 9 | | | ||
| 10 | = note: this is a known limitation of the type checker that may be lifted in a future edition. | ||
| 11 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information | ||
| 12 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 7 | = note: `#[warn(type_alias_bounds)]` on by default | 13 | = note: `#[warn(type_alias_bounds)]` on by default |
| 8 | help: the clause will not be checked when the type alias is used, and should be removed | ||
| 9 | | | ||
| 10 | LL - type _TaWhere1<T> where T: Iterator<Item: Copy> = T; | ||
| 11 | LL + type _TaWhere1<T> = T; | ||
| 12 | | | ||
| 13 | 14 | ||
| 14 | warning: where clauses are not enforced in type aliases | 15 | warning: where clauses on type aliases are not enforced |
| 15 | --> $DIR/type-alias.rs:4:25 | 16 | --> $DIR/type-alias.rs:4:25 |
| 16 | | | 17 | | |
| 17 | LL | type _TaWhere2<T> where T: Iterator<Item: 'static> = T; | 18 | LL | type _TaWhere2<T> where T: Iterator<Item: 'static> = T; |
| 18 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | 19 | | ------^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 19 | | | 20 | | | | |
| 20 | help: the clause will not be checked when the type alias is used, and should be removed | 21 | | | will not be checked at usage sites of the type alias |
| 21 | | | 22 | | help: remove this where clause |
| 22 | LL - type _TaWhere2<T> where T: Iterator<Item: 'static> = T; | 23 | | |
| 23 | LL + type _TaWhere2<T> = T; | 24 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 24 | | | 25 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 26 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 25 | 27 | ||
| 26 | warning: where clauses are not enforced in type aliases | 28 | warning: where clauses on type aliases are not enforced |
| 27 | --> $DIR/type-alias.rs:5:25 | 29 | --> $DIR/type-alias.rs:5:25 |
| 28 | | | 30 | | |
| 29 | LL | type _TaWhere3<T> where T: Iterator<Item: 'static> = T; | 31 | LL | type _TaWhere3<T> where T: Iterator<Item: 'static> = T; |
| 30 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | 32 | | ------^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 31 | | | 33 | | | | |
| 32 | help: the clause will not be checked when the type alias is used, and should be removed | 34 | | | will not be checked at usage sites of the type alias |
| 33 | | | 35 | | help: remove this where clause |
| 34 | LL - type _TaWhere3<T> where T: Iterator<Item: 'static> = T; | 36 | | |
| 35 | LL + type _TaWhere3<T> = T; | 37 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 36 | | | 38 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 39 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 37 | 40 | ||
| 38 | warning: where clauses are not enforced in type aliases | 41 | warning: where clauses on type aliases are not enforced |
| 39 | --> $DIR/type-alias.rs:6:25 | 42 | --> $DIR/type-alias.rs:6:25 |
| 40 | | | 43 | | |
| 41 | LL | type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T; | 44 | LL | type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T; |
| 42 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 45 | | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 43 | | | 46 | | | | |
| 44 | help: the clause will not be checked when the type alias is used, and should be removed | 47 | | | will not be checked at usage sites of the type alias |
| 45 | | | 48 | | help: remove this where clause |
| 46 | LL - type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T; | 49 | | |
| 47 | LL + type _TaWhere4<T> = T; | 50 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 48 | | | 51 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 52 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 49 | 53 | ||
| 50 | warning: where clauses are not enforced in type aliases | 54 | warning: where clauses on type aliases are not enforced |
| 51 | --> $DIR/type-alias.rs:7:25 | 55 | --> $DIR/type-alias.rs:7:25 |
| 52 | | | 56 | | |
| 53 | LL | type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T; | 57 | LL | type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T; |
| 54 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 58 | | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 55 | | | 59 | | | | |
| 56 | help: the clause will not be checked when the type alias is used, and should be removed | 60 | | | will not be checked at usage sites of the type alias |
| 57 | | | 61 | | help: remove this where clause |
| 58 | LL - type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T; | 62 | | |
| 59 | LL + type _TaWhere5<T> = T; | 63 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 60 | | | 64 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 65 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 61 | 66 | ||
| 62 | warning: where clauses are not enforced in type aliases | 67 | warning: where clauses on type aliases are not enforced |
| 63 | --> $DIR/type-alias.rs:8:25 | 68 | --> $DIR/type-alias.rs:8:25 |
| 64 | | | 69 | | |
| 65 | LL | type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T; | 70 | LL | type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T; |
| 66 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 71 | | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 67 | | | 72 | | | | |
| 68 | help: the clause will not be checked when the type alias is used, and should be removed | 73 | | | will not be checked at usage sites of the type alias |
| 69 | | | 74 | | help: remove this where clause |
| 70 | LL - type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T; | 75 | | |
| 71 | LL + type _TaWhere6<T> = T; | 76 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 72 | | | 77 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 78 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 73 | 79 | ||
| 74 | warning: bounds on generic parameters are not enforced in type aliases | 80 | warning: bounds on generic parameters in type aliases are not enforced |
| 75 | --> $DIR/type-alias.rs:10:20 | 81 | --> $DIR/type-alias.rs:10:20 |
| 76 | | | 82 | | |
| 77 | LL | type _TaInline1<T: Iterator<Item: Copy>> = T; | 83 | LL | type _TaInline1<T: Iterator<Item: Copy>> = T; |
| 78 | | ^^^^^^^^^^^^^^^^^^^^ | 84 | | --^^^^^^^^^^^^^^^^^^^^ |
| 79 | | | 85 | | | | |
| 80 | help: the bound will not be checked when the type alias is used, and should be removed | 86 | | | will not be checked at usage sites of the type alias |
| 81 | | | 87 | | help: remove this bound |
| 82 | LL - type _TaInline1<T: Iterator<Item: Copy>> = T; | 88 | | |
| 83 | LL + type _TaInline1<T> = T; | 89 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 84 | | | 90 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 91 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 85 | 92 | ||
| 86 | warning: bounds on generic parameters are not enforced in type aliases | 93 | warning: bounds on generic parameters in type aliases are not enforced |
| 87 | --> $DIR/type-alias.rs:11:20 | 94 | --> $DIR/type-alias.rs:11:20 |
| 88 | | | 95 | | |
| 89 | LL | type _TaInline2<T: Iterator<Item: 'static>> = T; | 96 | LL | type _TaInline2<T: Iterator<Item: 'static>> = T; |
| 90 | | ^^^^^^^^^^^^^^^^^^^^^^^ | 97 | | --^^^^^^^^^^^^^^^^^^^^^^^ |
| 91 | | | 98 | | | | |
| 92 | help: the bound will not be checked when the type alias is used, and should be removed | 99 | | | will not be checked at usage sites of the type alias |
| 93 | | | 100 | | help: remove this bound |
| 94 | LL - type _TaInline2<T: Iterator<Item: 'static>> = T; | 101 | | |
| 95 | LL + type _TaInline2<T> = T; | 102 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 96 | | | 103 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 104 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 97 | 105 | ||
| 98 | warning: bounds on generic parameters are not enforced in type aliases | 106 | warning: bounds on generic parameters in type aliases are not enforced |
| 99 | --> $DIR/type-alias.rs:12:20 | 107 | --> $DIR/type-alias.rs:12:20 |
| 100 | | | 108 | | |
| 101 | LL | type _TaInline3<T: Iterator<Item: 'static>> = T; | 109 | LL | type _TaInline3<T: Iterator<Item: 'static>> = T; |
| 102 | | ^^^^^^^^^^^^^^^^^^^^^^^ | 110 | | --^^^^^^^^^^^^^^^^^^^^^^^ |
| 103 | | | 111 | | | | |
| 104 | help: the bound will not be checked when the type alias is used, and should be removed | 112 | | | will not be checked at usage sites of the type alias |
| 105 | | | 113 | | help: remove this bound |
| 106 | LL - type _TaInline3<T: Iterator<Item: 'static>> = T; | 114 | | |
| 107 | LL + type _TaInline3<T> = T; | 115 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 108 | | | 116 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 117 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 109 | 118 | ||
| 110 | warning: bounds on generic parameters are not enforced in type aliases | 119 | warning: bounds on generic parameters in type aliases are not enforced |
| 111 | --> $DIR/type-alias.rs:13:20 | 120 | --> $DIR/type-alias.rs:13:20 |
| 112 | | | 121 | | |
| 113 | LL | type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T; | 122 | LL | type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T; |
| 114 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 123 | | --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 115 | | | 124 | | | | |
| 116 | help: the bound will not be checked when the type alias is used, and should be removed | 125 | | | will not be checked at usage sites of the type alias |
| 117 | | | 126 | | help: remove this bound |
| 118 | LL - type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T; | 127 | | |
| 119 | LL + type _TaInline4<T> = T; | 128 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 120 | | | 129 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 130 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 121 | 131 | ||
| 122 | warning: bounds on generic parameters are not enforced in type aliases | 132 | warning: bounds on generic parameters in type aliases are not enforced |
| 123 | --> $DIR/type-alias.rs:14:20 | 133 | --> $DIR/type-alias.rs:14:20 |
| 124 | | | 134 | | |
| 125 | LL | type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T; | 135 | LL | type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T; |
| 126 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 136 | | --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 127 | | | 137 | | | | |
| 128 | help: the bound will not be checked when the type alias is used, and should be removed | 138 | | | will not be checked at usage sites of the type alias |
| 129 | | | 139 | | help: remove this bound |
| 130 | LL - type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T; | 140 | | |
| 131 | LL + type _TaInline5<T> = T; | 141 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 132 | | | 142 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 143 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 133 | 144 | ||
| 134 | warning: bounds on generic parameters are not enforced in type aliases | 145 | warning: bounds on generic parameters in type aliases are not enforced |
| 135 | --> $DIR/type-alias.rs:15:20 | 146 | --> $DIR/type-alias.rs:15:20 |
| 136 | | | 147 | | |
| 137 | LL | type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T; | 148 | LL | type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T; |
| 138 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 149 | | --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 139 | | | 150 | | | | |
| 140 | help: the bound will not be checked when the type alias is used, and should be removed | 151 | | | will not be checked at usage sites of the type alias |
| 141 | | | 152 | | help: remove this bound |
| 142 | LL - type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T; | 153 | | |
| 143 | LL + type _TaInline6<T> = T; | 154 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 144 | | | 155 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 156 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 145 | 157 | ||
| 146 | warning: 12 warnings emitted | 158 | warning: 12 warnings emitted |
| 147 | 159 |
tests/ui/const-generics/generic_const_exprs/type-alias-bounds.neg.stderr created+63| ... | @@ -0,0 +1,63 @@ | ||
| 1 | error[E0277]: the trait bound `String: Copy` is not satisfied | ||
| 2 | --> $DIR/type-alias-bounds.rs:23:12 | ||
| 3 | | | ||
| 4 | LL | let _: AliasConstUnused<String>; | ||
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | ||
| 6 | | | ||
| 7 | note: required by a bound in `ct_unused_0::AliasConstUnused` | ||
| 8 | --> $DIR/type-alias-bounds.rs:20:30 | ||
| 9 | | | ||
| 10 | LL | type AliasConstUnused<T: Copy> = (T, I32<{ DATA }>); | ||
| 11 | | ^^^^ required by this bound in `AliasConstUnused` | ||
| 12 | |||
| 13 | error[E0277]: the trait bound `String: Copy` is not satisfied | ||
| 14 | --> $DIR/type-alias-bounds.rs:31:12 | ||
| 15 | | | ||
| 16 | LL | let _: AliasConstUnused; | ||
| 17 | | ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | ||
| 18 | | | ||
| 19 | note: required by a bound in `ct_unused_1::AliasConstUnused` | ||
| 20 | --> $DIR/type-alias-bounds.rs:29:41 | ||
| 21 | | | ||
| 22 | LL | type AliasConstUnused where String: Copy = I32<{ 0; 0 }>; | ||
| 23 | | ^^^^ required by this bound in `AliasConstUnused` | ||
| 24 | |||
| 25 | error[E0277]: the trait bound `String: Copy` is not satisfied | ||
| 26 | --> $DIR/type-alias-bounds.rs:39:12 | ||
| 27 | | | ||
| 28 | LL | let _: AliasFnUnused<String>; | ||
| 29 | | ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | ||
| 30 | | | ||
| 31 | note: required by a bound in `AliasFnUnused` | ||
| 32 | --> $DIR/type-alias-bounds.rs:36:27 | ||
| 33 | | | ||
| 34 | LL | type AliasFnUnused<T: Copy> = (T, I32<{ code() }>); | ||
| 35 | | ^^^^ required by this bound in `AliasFnUnused` | ||
| 36 | |||
| 37 | error[E0277]: the trait bound `String: Copy` is not satisfied | ||
| 38 | --> $DIR/type-alias-bounds.rs:57:12 | ||
| 39 | | | ||
| 40 | LL | let _: AliasAssocConstUsed<String>; | ||
| 41 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | ||
| 42 | | | ||
| 43 | note: required by a bound in `AliasAssocConstUsed` | ||
| 44 | --> $DIR/type-alias-bounds.rs:55:41 | ||
| 45 | | | ||
| 46 | LL | type AliasAssocConstUsed<T: Trait + Copy> = I32<{ T::DATA }>; | ||
| 47 | | ^^^^ required by this bound in `AliasAssocConstUsed` | ||
| 48 | |||
| 49 | error[E0277]: the trait bound `String: Copy` is not satisfied | ||
| 50 | --> $DIR/type-alias-bounds.rs:65:12 | ||
| 51 | | | ||
| 52 | LL | let _: AliasFnUsed<String>; | ||
| 53 | | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | ||
| 54 | | | ||
| 55 | note: required by a bound in `AliasFnUsed` | ||
| 56 | --> $DIR/type-alias-bounds.rs:62:33 | ||
| 57 | | | ||
| 58 | LL | type AliasFnUsed<T: Trait + Copy> = I32<{ code::<T>() }>; | ||
| 59 | | ^^^^ required by this bound in `AliasFnUsed` | ||
| 60 | |||
| 61 | error: aborting due to 5 previous errors | ||
| 62 | |||
| 63 | For more information about this error, try `rustc --explain E0277`. | ||
tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs created+71| ... | @@ -0,0 +1,71 @@ | ||
| 1 | //@ revisions: pos neg | ||
| 2 | //@[pos] check-pass | ||
| 3 | |||
| 4 | #![feature(generic_const_exprs)] | ||
| 5 | #![feature(trivial_bounds)] // only used in test case `ct_unused_1` | ||
| 6 | #![allow(incomplete_features)] | ||
| 7 | |||
| 8 | // FIXME(generic_const_exprs): Revisit this before stabilization. | ||
| 9 | // Check that we don't emit the lint `type_alias_bounds` for (eager) type aliases | ||
| 10 | // whose RHS contains a const projection (aka uneval'ed const). | ||
| 11 | // Since anon consts inherit the parent generics and predicates and we effectively | ||
| 12 | // check them before and after instantiaton for well-formedness, the type alias | ||
| 13 | // bounds are in every sense "enforced". | ||
| 14 | // Note that the test cases whose name ends in "unused" just demonstrate that this | ||
| 15 | // holds even if the const projections don't "visibly" capture any generics and/or | ||
| 16 | // predicates. | ||
| 17 | #![deny(type_alias_bounds)] | ||
| 18 | |||
| 19 | fn ct_unused_0() { | ||
| 20 | type AliasConstUnused<T: Copy> = (T, I32<{ DATA }>); | ||
| 21 | const DATA: i32 = 0; | ||
| 22 | #[cfg(neg)] | ||
| 23 | let _: AliasConstUnused<String>; | ||
| 24 | //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied | ||
| 25 | } | ||
| 26 | |||
| 27 | fn ct_unused_1() { | ||
| 28 | #[allow(trivial_bounds)] | ||
| 29 | type AliasConstUnused where String: Copy = I32<{ 0; 0 }>; | ||
| 30 | #[cfg(neg)] | ||
| 31 | let _: AliasConstUnused; | ||
| 32 | //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied | ||
| 33 | } | ||
| 34 | |||
| 35 | fn fn_unused() { | ||
| 36 | type AliasFnUnused<T: Copy> = (T, I32<{ code() }>); | ||
| 37 | const fn code() -> i32 { 0 } | ||
| 38 | #[cfg(neg)] | ||
| 39 | let _: AliasFnUnused<String>; | ||
| 40 | //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied | ||
| 41 | } | ||
| 42 | |||
| 43 | trait Trait { | ||
| 44 | type Proj; | ||
| 45 | const DATA: i32; | ||
| 46 | } | ||
| 47 | |||
| 48 | impl Trait for String { | ||
| 49 | type Proj = i32; | ||
| 50 | const DATA: i32 = 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | // Regression test for issue #94398. | ||
| 54 | fn assoc_ct_used() { | ||
| 55 | type AliasAssocConstUsed<T: Trait + Copy> = I32<{ T::DATA }>; | ||
| 56 | #[cfg(neg)] | ||
| 57 | let _: AliasAssocConstUsed<String>; | ||
| 58 | //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied | ||
| 59 | } | ||
| 60 | |||
| 61 | fn fn_used() { | ||
| 62 | type AliasFnUsed<T: Trait + Copy> = I32<{ code::<T>() }>; | ||
| 63 | const fn code<T: Trait>() -> i32 { T::DATA } | ||
| 64 | #[cfg(neg)] | ||
| 65 | let _: AliasFnUsed<String>; | ||
| 66 | //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied | ||
| 67 | } | ||
| 68 | |||
| 69 | struct I32<const N: i32>; | ||
| 70 | |||
| 71 | fn main() {} | ||
tests/ui/lint/dead-code/unused-impl-for-non-adts.rs created+45| ... | @@ -0,0 +1,45 @@ | ||
| 1 | #![deny(dead_code)] | ||
| 2 | |||
| 3 | struct Foo; //~ ERROR struct `Foo` is never constructed | ||
| 4 | |||
| 5 | trait Trait { //~ ERROR trait `Trait` is never used | ||
| 6 | fn foo(&self) {} | ||
| 7 | } | ||
| 8 | |||
| 9 | impl Trait for Foo {} | ||
| 10 | |||
| 11 | impl Trait for [Foo] {} | ||
| 12 | impl<const N: usize> Trait for [Foo; N] {} | ||
| 13 | |||
| 14 | impl Trait for *const Foo {} | ||
| 15 | impl Trait for *mut Foo {} | ||
| 16 | |||
| 17 | impl Trait for &Foo {} | ||
| 18 | impl Trait for &&Foo {} | ||
| 19 | impl Trait for &mut Foo {} | ||
| 20 | |||
| 21 | impl Trait for [&Foo] {} | ||
| 22 | impl Trait for &[Foo] {} | ||
| 23 | impl Trait for &*const Foo {} | ||
| 24 | |||
| 25 | pub trait Trait2 { | ||
| 26 | fn foo(&self) {} | ||
| 27 | } | ||
| 28 | |||
| 29 | impl Trait2 for Foo {} | ||
| 30 | |||
| 31 | impl Trait2 for [Foo] {} | ||
| 32 | impl<const N: usize> Trait2 for [Foo; N] {} | ||
| 33 | |||
| 34 | impl Trait2 for *const Foo {} | ||
| 35 | impl Trait2 for *mut Foo {} | ||
| 36 | |||
| 37 | impl Trait2 for &Foo {} | ||
| 38 | impl Trait2 for &&Foo {} | ||
| 39 | impl Trait2 for &mut Foo {} | ||
| 40 | |||
| 41 | impl Trait2 for [&Foo] {} | ||
| 42 | impl Trait2 for &[Foo] {} | ||
| 43 | impl Trait2 for &*const Foo {} | ||
| 44 | |||
| 45 | fn main() {} | ||
tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | error: struct `Foo` is never constructed | ||
| 2 | --> $DIR/unused-impl-for-non-adts.rs:3:8 | ||
| 3 | | | ||
| 4 | LL | struct Foo; | ||
| 5 | | ^^^ | ||
| 6 | | | ||
| 7 | note: the lint level is defined here | ||
| 8 | --> $DIR/unused-impl-for-non-adts.rs:1:9 | ||
| 9 | | | ||
| 10 | LL | #![deny(dead_code)] | ||
| 11 | | ^^^^^^^^^ | ||
| 12 | |||
| 13 | error: trait `Trait` is never used | ||
| 14 | --> $DIR/unused-impl-for-non-adts.rs:5:7 | ||
| 15 | | | ||
| 16 | LL | trait Trait { | ||
| 17 | | ^^^^^ | ||
| 18 | |||
| 19 | error: aborting due to 2 previous errors | ||
| 20 | |||
tests/ui/macros/issue-118786.rs+1| ... | @@ -7,6 +7,7 @@ macro_rules! make_macro { | ... | @@ -7,6 +7,7 @@ macro_rules! make_macro { |
| 7 | macro_rules! $macro_name { | 7 | macro_rules! $macro_name { |
| 8 | //~^ ERROR macro expansion ignores token `{` and any following | 8 | //~^ ERROR macro expansion ignores token `{` and any following |
| 9 | //~| ERROR cannot find macro `macro_rules` in this scope | 9 | //~| ERROR cannot find macro `macro_rules` in this scope |
| 10 | //~| put a macro name here | ||
| 10 | () => {} | 11 | () => {} |
| 11 | } | 12 | } |
| 12 | } | 13 | } |
tests/ui/macros/issue-118786.stderr+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | error: macros that expand to items must be delimited with braces or followed by a semicolon | 1 | error: macros that expand to items must be delimited with braces or followed by a semicolon |
| 2 | --> $DIR/issue-118786.rs:15:13 | 2 | --> $DIR/issue-118786.rs:16:13 |
| 3 | | | 3 | | |
| 4 | LL | make_macro!((meow)); | 4 | LL | make_macro!((meow)); |
| 5 | | ^^^^^^ | 5 | | ^^^^^^ |
| ... | @@ -34,10 +34,10 @@ LL | make_macro!((meow)); | ... | @@ -34,10 +34,10 @@ LL | make_macro!((meow)); |
| 34 | | ------------------- in this macro invocation | 34 | | ------------------- in this macro invocation |
| 35 | | | 35 | | |
| 36 | note: maybe you have forgotten to define a name for this `macro_rules!` | 36 | note: maybe you have forgotten to define a name for this `macro_rules!` |
| 37 | --> $DIR/issue-118786.rs:7:9 | 37 | --> $DIR/issue-118786.rs:7:20 |
| 38 | | | 38 | | |
| 39 | LL | macro_rules! $macro_name { | 39 | LL | macro_rules! $macro_name { |
| 40 | | ^^^^^^^^^^^ | 40 | | ^ put a macro name here |
| 41 | ... | 41 | ... |
| 42 | LL | make_macro!((meow)); | 42 | LL | make_macro!((meow)); |
| 43 | | ------------------- in this macro invocation | 43 | | ------------------- in this macro invocation |
tests/ui/privacy/private-in-public-warn.rs+2-2| ... | @@ -39,7 +39,7 @@ mod traits { | ... | @@ -39,7 +39,7 @@ mod traits { |
| 39 | pub trait PubTr {} | 39 | pub trait PubTr {} |
| 40 | 40 | ||
| 41 | pub type Alias<T: PrivTr> = T; //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Alias` | 41 | pub type Alias<T: PrivTr> = T; //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Alias` |
| 42 | //~^ WARNING bounds on generic parameters are not enforced in type aliases | 42 | //~^ WARNING bounds on generic parameters in type aliases are not enforced |
| 43 | pub trait Tr1: PrivTr {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr1` | 43 | pub trait Tr1: PrivTr {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr1` |
| 44 | pub trait Tr2<T: PrivTr> {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr2` | 44 | pub trait Tr2<T: PrivTr> {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr2` |
| 45 | pub trait Tr3 { | 45 | pub trait Tr3 { |
| ... | @@ -58,7 +58,7 @@ mod traits_where { | ... | @@ -58,7 +58,7 @@ mod traits_where { |
| 58 | 58 | ||
| 59 | pub type Alias<T> where T: PrivTr = T; | 59 | pub type Alias<T> where T: PrivTr = T; |
| 60 | //~^ ERROR trait `traits_where::PrivTr` is more private than the item `traits_where::Alias` | 60 | //~^ ERROR trait `traits_where::PrivTr` is more private than the item `traits_where::Alias` |
| 61 | //~| WARNING where clauses are not enforced in type aliases | 61 | //~| WARNING where clauses on type aliases are not enforced |
| 62 | pub trait Tr2<T> where T: PrivTr {} | 62 | pub trait Tr2<T> where T: PrivTr {} |
| 63 | //~^ ERROR trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2` | 63 | //~^ ERROR trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2` |
| 64 | pub trait Tr3 { | 64 | pub trait Tr3 { |
tests/ui/privacy/private-in-public-warn.stderr+18-16| ... | @@ -395,30 +395,32 @@ note: but type `Priv2` is only usable at visibility `pub(self)` | ... | @@ -395,30 +395,32 @@ note: but type `Priv2` is only usable at visibility `pub(self)` |
| 395 | LL | struct Priv2; | 395 | LL | struct Priv2; |
| 396 | | ^^^^^^^^^^^^ | 396 | | ^^^^^^^^^^^^ |
| 397 | 397 | ||
| 398 | warning: bounds on generic parameters are not enforced in type aliases | 398 | warning: bounds on generic parameters in type aliases are not enforced |
| 399 | --> $DIR/private-in-public-warn.rs:41:23 | 399 | --> $DIR/private-in-public-warn.rs:41:23 |
| 400 | | | 400 | | |
| 401 | LL | pub type Alias<T: PrivTr> = T; | 401 | LL | pub type Alias<T: PrivTr> = T; |
| 402 | | ^^^^^^ | 402 | | --^^^^^^ |
| 403 | | | 403 | | | | |
| 404 | | | will not be checked at usage sites of the type alias | ||
| 405 | | help: remove this bound | ||
| 406 | | | ||
| 407 | = note: this is a known limitation of the type checker that may be lifted in a future edition. | ||
| 408 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information | ||
| 409 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 404 | = note: `#[warn(type_alias_bounds)]` on by default | 410 | = note: `#[warn(type_alias_bounds)]` on by default |
| 405 | help: the bound will not be checked when the type alias is used, and should be removed | ||
| 406 | | | ||
| 407 | LL - pub type Alias<T: PrivTr> = T; | ||
| 408 | LL + pub type Alias<T> = T; | ||
| 409 | | | ||
| 410 | 411 | ||
| 411 | warning: where clauses are not enforced in type aliases | 412 | warning: where clauses on type aliases are not enforced |
| 412 | --> $DIR/private-in-public-warn.rs:59:29 | 413 | --> $DIR/private-in-public-warn.rs:59:29 |
| 413 | | | 414 | | |
| 414 | LL | pub type Alias<T> where T: PrivTr = T; | 415 | LL | pub type Alias<T> where T: PrivTr = T; |
| 415 | | ^^^^^^^^^ | 416 | | ------^^^^^^^^^ |
| 416 | | | 417 | | | | |
| 417 | help: the clause will not be checked when the type alias is used, and should be removed | 418 | | | will not be checked at usage sites of the type alias |
| 418 | | | 419 | | help: remove this where clause |
| 419 | LL - pub type Alias<T> where T: PrivTr = T; | 420 | | |
| 420 | LL + pub type Alias<T> = T; | 421 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 421 | | | 422 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 423 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 422 | 424 | ||
| 423 | error: aborting due to 34 previous errors; 2 warnings emitted | 425 | error: aborting due to 34 previous errors; 2 warnings emitted |
| 424 | 426 |
tests/ui/resolve/issue-118295.rs+6| ... | @@ -1,5 +1,11 @@ | ... | @@ -1,5 +1,11 @@ |
| 1 | macro_rules! {} | 1 | macro_rules! {} |
| 2 | //~^ ERROR cannot find macro `macro_rules` in this scope | 2 | //~^ ERROR cannot find macro `macro_rules` in this scope |
| 3 | //~| NOTE maybe you have forgotten to define a name for this `macro_rules!` | 3 | //~| NOTE maybe you have forgotten to define a name for this `macro_rules!` |
| 4 | //~| put a macro name here | ||
| 5 | |||
| 6 | macro_rules!{} | ||
| 7 | //~^ ERROR cannot find macro `macro_rules` in this scope | ||
| 8 | //~| NOTE maybe you have forgotten to define a name for this `macro_rules!` | ||
| 9 | //~| put a macro name here | ||
| 4 | 10 | ||
| 5 | fn main() {} | 11 | fn main() {} |
tests/ui/resolve/issue-118295.stderr+15-3| ... | @@ -1,14 +1,26 @@ | ... | @@ -1,14 +1,26 @@ |
| 1 | error: cannot find macro `macro_rules` in this scope | 1 | error: cannot find macro `macro_rules` in this scope |
| 2 | --> $DIR/issue-118295.rs:1:1 | 2 | --> $DIR/issue-118295.rs:6:1 |
| 3 | | | 3 | | |
| 4 | LL | macro_rules! {} | 4 | LL | macro_rules!{} |
| 5 | | ^^^^^^^^^^^ | 5 | | ^^^^^^^^^^^ |
| 6 | | | 6 | | |
| 7 | note: maybe you have forgotten to define a name for this `macro_rules!` | 7 | note: maybe you have forgotten to define a name for this `macro_rules!` |
| 8 | --> $DIR/issue-118295.rs:6:12 | ||
| 9 | | | ||
| 10 | LL | macro_rules!{} | ||
| 11 | | ^ put a macro name here | ||
| 12 | |||
| 13 | error: cannot find macro `macro_rules` in this scope | ||
| 8 | --> $DIR/issue-118295.rs:1:1 | 14 | --> $DIR/issue-118295.rs:1:1 |
| 9 | | | 15 | | |
| 10 | LL | macro_rules! {} | 16 | LL | macro_rules! {} |
| 11 | | ^^^^^^^^^^^ | 17 | | ^^^^^^^^^^^ |
| 18 | | | ||
| 19 | note: maybe you have forgotten to define a name for this `macro_rules!` | ||
| 20 | --> $DIR/issue-118295.rs:1:12 | ||
| 21 | | | ||
| 22 | LL | macro_rules! {} | ||
| 23 | | ^ put a macro name here | ||
| 12 | 24 | ||
| 13 | error: aborting due to 1 previous error | 25 | error: aborting due to 2 previous errors |
| 14 | 26 |
tests/ui/resolve/issue-55673.stderr+1-1| ... | @@ -19,7 +19,7 @@ help: consider further restricting type parameter `T` | ... | @@ -19,7 +19,7 @@ help: consider further restricting type parameter `T` |
| 19 | | | 19 | | |
| 20 | LL | T::Baa: std::fmt::Debug, T: Foo | 20 | LL | T::Baa: std::fmt::Debug, T: Foo |
| 21 | | ~~~~~~~~ | 21 | | ~~~~~~~~ |
| 22 | help: and also change the associated type name | 22 | help: ...and changing the associated type name |
| 23 | | | 23 | | |
| 24 | LL | T::Bar: std::fmt::Debug, | 24 | LL | T::Bar: std::fmt::Debug, |
| 25 | | ~~~ | 25 | | ~~~ |
tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr+9-8| ... | @@ -24,18 +24,19 @@ warning: trait bound i32: Foo does not depend on any type or lifetime parameters | ... | @@ -24,18 +24,19 @@ warning: trait bound i32: Foo does not depend on any type or lifetime parameters |
| 24 | LL | union U where i32: Foo { f: i32 } | 24 | LL | union U where i32: Foo { f: i32 } |
| 25 | | ^^^ | 25 | | ^^^ |
| 26 | 26 | ||
| 27 | warning: where clauses are not enforced in type aliases | 27 | warning: where clauses on type aliases are not enforced |
| 28 | --> $DIR/trivial-bounds-inconsistent.rs:22:14 | 28 | --> $DIR/trivial-bounds-inconsistent.rs:22:14 |
| 29 | | | 29 | | |
| 30 | LL | type Y where i32: Foo = (); | 30 | LL | type Y where i32: Foo = (); |
| 31 | | ^^^^^^^^ | 31 | | ------^^^^^^^^ |
| 32 | | | 32 | | | | |
| 33 | | | will not be checked at usage sites of the type alias | ||
| 34 | | help: remove this where clause | ||
| 35 | | | ||
| 36 | = note: this is a known limitation of the type checker that may be lifted in a future edition. | ||
| 37 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information | ||
| 38 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 33 | = note: `#[warn(type_alias_bounds)]` on by default | 39 | = note: `#[warn(type_alias_bounds)]` on by default |
| 34 | help: the clause will not be checked when the type alias is used, and should be removed | ||
| 35 | | | ||
| 36 | LL - type Y where i32: Foo = (); | ||
| 37 | LL + type Y = (); | ||
| 38 | | | ||
| 39 | 40 | ||
| 40 | warning: trait bound i32: Foo does not depend on any type or lifetime parameters | 41 | warning: trait bound i32: Foo does not depend on any type or lifetime parameters |
| 41 | --> $DIR/trivial-bounds-inconsistent.rs:22:19 | 42 | --> $DIR/trivial-bounds-inconsistent.rs:22:19 |
tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.eager.stderr created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | error[E0220]: associated type `Assoc` not found for `T` | ||
| 2 | --> $DIR/unresolved-assoc-ty-suggest-trait.rs:9:22 | ||
| 3 | | | ||
| 4 | LL | type AssocOf<T> = T::Assoc; | ||
| 5 | | ^^^^^ there is an associated type `Assoc` in the trait `Trait` | ||
| 6 | | | ||
| 7 | help: consider fully qualifying the associated type | ||
| 8 | | | ||
| 9 | LL | type AssocOf<T> = <T as Trait>::Assoc; | ||
| 10 | | + +++++++++ | ||
| 11 | |||
| 12 | error[E0220]: associated type `Assok` not found for `T` | ||
| 13 | --> $DIR/unresolved-assoc-ty-suggest-trait.rs:13:22 | ||
| 14 | | | ||
| 15 | LL | type AssokOf<T> = T::Assok; | ||
| 16 | | ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait` | ||
| 17 | | | ||
| 18 | help: consider fully qualifying and renaming the associated type | ||
| 19 | | | ||
| 20 | LL | type AssokOf<T> = <T as Trait>::Assoc; | ||
| 21 | | + +++++++++ ~~~~~ | ||
| 22 | |||
| 23 | error[E0220]: associated type `Proj` not found for `T` | ||
| 24 | --> $DIR/unresolved-assoc-ty-suggest-trait.rs:22:21 | ||
| 25 | | | ||
| 26 | LL | type ProjOf<T> = T::Proj; | ||
| 27 | | ^^^^ there is an associated type `Proj` in the trait `Parametrized` | ||
| 28 | | | ||
| 29 | help: consider fully qualifying the associated type | ||
| 30 | | | ||
| 31 | LL | type ProjOf<T> = <T as Parametrized</* 'a, T, N */>>::Proj; | ||
| 32 | | + ++++++++++++++++++++++++++++++++ | ||
| 33 | |||
| 34 | error: aborting due to 3 previous errors | ||
| 35 | |||
| 36 | For more information about this error, try `rustc --explain E0220`. | ||
tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr created+40| ... | @@ -0,0 +1,40 @@ | ||
| 1 | error[E0220]: associated type `Assoc` not found for `T` | ||
| 2 | --> $DIR/unresolved-assoc-ty-suggest-trait.rs:9:22 | ||
| 3 | | | ||
| 4 | LL | type AssocOf<T> = T::Assoc; | ||
| 5 | | ^^^^^ there is an associated type `Assoc` in the trait `Trait` | ||
| 6 | | | ||
| 7 | help: consider restricting type parameter `T` | ||
| 8 | | | ||
| 9 | LL | type AssocOf<T: Trait> = T::Assoc; | ||
| 10 | | +++++++ | ||
| 11 | |||
| 12 | error[E0220]: associated type `Assok` not found for `T` | ||
| 13 | --> $DIR/unresolved-assoc-ty-suggest-trait.rs:13:22 | ||
| 14 | | | ||
| 15 | LL | type AssokOf<T> = T::Assok; | ||
| 16 | | ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait` | ||
| 17 | | | ||
| 18 | help: consider restricting type parameter `T` | ||
| 19 | | | ||
| 20 | LL | type AssokOf<T: Trait> = T::Assok; | ||
| 21 | | +++++++ | ||
| 22 | help: ...and changing the associated type name | ||
| 23 | | | ||
| 24 | LL | type AssokOf<T> = T::Assoc; | ||
| 25 | | ~~~~~ | ||
| 26 | |||
| 27 | error[E0220]: associated type `Proj` not found for `T` | ||
| 28 | --> $DIR/unresolved-assoc-ty-suggest-trait.rs:22:21 | ||
| 29 | | | ||
| 30 | LL | type ProjOf<T> = T::Proj; | ||
| 31 | | ^^^^ there is an associated type `Proj` in the trait `Parametrized` | ||
| 32 | | | ||
| 33 | help: consider restricting type parameter `T` | ||
| 34 | | | ||
| 35 | LL | type ProjOf<T: Parametrized</* 'a, T, N */>> = T::Proj; | ||
| 36 | | ++++++++++++++++++++++++++++++ | ||
| 37 | |||
| 38 | error: aborting due to 3 previous errors | ||
| 39 | |||
| 40 | For more information about this error, try `rustc --explain E0220`. | ||
tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | // Ensure that we don't suggest *type alias bounds* for **eager** type aliases. | ||
| 2 | // issue: rust-lang/rust#125789 | ||
| 3 | |||
| 4 | //@ revisions: eager lazy | ||
| 5 | #![cfg_attr(lazy, feature(lazy_type_alias), allow(incomplete_features))] | ||
| 6 | |||
| 7 | trait Trait { type Assoc; } | ||
| 8 | |||
| 9 | type AssocOf<T> = T::Assoc; //~ ERROR associated type `Assoc` not found for `T` | ||
| 10 | //[eager]~^ HELP consider fully qualifying the associated type | ||
| 11 | //[lazy]~| HELP consider restricting type parameter `T` | ||
| 12 | |||
| 13 | type AssokOf<T> = T::Assok; //~ ERROR associated type `Assok` not found for `T` | ||
| 14 | //[eager]~^ HELP consider fully qualifying and renaming the associated type | ||
| 15 | //[lazy]~| HELP consider restricting type parameter `T` | ||
| 16 | //[lazy]~| HELP and changing the associated type name | ||
| 17 | |||
| 18 | trait Parametrized<'a, T, const N: usize> { | ||
| 19 | type Proj; | ||
| 20 | } | ||
| 21 | |||
| 22 | type ProjOf<T> = T::Proj; //~ ERROR associated type `Proj` not found for `T` | ||
| 23 | //[eager]~^ HELP consider fully qualifying the associated type | ||
| 24 | //[lazy]~| HELP consider restricting type parameter `T` | ||
| 25 | |||
| 26 | fn main() {} | ||
tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs+1-1| ... | @@ -3,6 +3,6 @@ | ... | @@ -3,6 +3,6 @@ |
| 3 | 3 | ||
| 4 | //@ check-pass | 4 | //@ check-pass |
| 5 | pub type T<P: Send + Send + Send> = P; | 5 | pub type T<P: Send + Send + Send> = P; |
| 6 | //~^ WARN bounds on generic parameters are not enforced in type aliases | 6 | //~^ WARN bounds on generic parameters in type aliases are not enforced |
| 7 | 7 | ||
| 8 | fn main() {} | 8 | fn main() {} |
tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr+8-7| ... | @@ -1,15 +1,16 @@ | ... | @@ -1,15 +1,16 @@ |
| 1 | warning: bounds on generic parameters are not enforced in type aliases | 1 | warning: bounds on generic parameters in type aliases are not enforced |
| 2 | --> $DIR/issue-67690-type-alias-bound-diagnostic-crash.rs:5:15 | 2 | --> $DIR/issue-67690-type-alias-bound-diagnostic-crash.rs:5:15 |
| 3 | | | 3 | | |
| 4 | LL | pub type T<P: Send + Send + Send> = P; | 4 | LL | pub type T<P: Send + Send + Send> = P; |
| 5 | | ^^^^ ^^^^ ^^^^ | 5 | | --^^^^---^^^^---^^^^ |
| 6 | | | | | ||
| 7 | | | will not be checked at usage sites of the type alias | ||
| 8 | | help: remove this bound | ||
| 6 | | | 9 | | |
| 10 | = note: this is a known limitation of the type checker that may be lifted in a future edition. | ||
| 11 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information | ||
| 12 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 7 | = note: `#[warn(type_alias_bounds)]` on by default | 13 | = note: `#[warn(type_alias_bounds)]` on by default |
| 8 | help: the bound will not be checked when the type alias is used, and should be removed | ||
| 9 | | | ||
| 10 | LL - pub type T<P: Send + Send + Send> = P; | ||
| 11 | LL + pub type T<P> = P; | ||
| 12 | | | ||
| 13 | 14 | ||
| 14 | warning: 1 warning emitted | 15 | warning: 1 warning emitted |
| 15 | 16 |
tests/ui/type/type-alias-bounds.rs+11-10| ... | @@ -6,15 +6,15 @@ | ... | @@ -6,15 +6,15 @@ |
| 6 | use std::rc::Rc; | 6 | use std::rc::Rc; |
| 7 | 7 | ||
| 8 | type SVec<T: Send + Send> = Vec<T>; | 8 | type SVec<T: Send + Send> = Vec<T>; |
| 9 | //~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] | 9 | //~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds] |
| 10 | type S2Vec<T> where T: Send = Vec<T>; | 10 | type S2Vec<T> where T: Send = Vec<T>; |
| 11 | //~^ WARN where clauses are not enforced in type aliases [type_alias_bounds] | 11 | //~^ WARN where clauses on type aliases are not enforced [type_alias_bounds] |
| 12 | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); | 12 | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); |
| 13 | //~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] | 13 | //~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds] |
| 14 | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>); | 14 | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>); |
| 15 | //~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] | 15 | //~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds] |
| 16 | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>); | 16 | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>); |
| 17 | //~^ WARN where clauses are not enforced in type aliases [type_alias_bounds] | 17 | //~^ WARN where clauses on type aliases are not enforced [type_alias_bounds] |
| 18 | 18 | ||
| 19 | static STATIC: u32 = 0; | 19 | static STATIC: u32 = 0; |
| 20 | 20 | ||
| ... | @@ -42,10 +42,11 @@ fn foo<'a>(y: &'a i32) { | ... | @@ -42,10 +42,11 @@ fn foo<'a>(y: &'a i32) { |
| 42 | struct Sendable<T: Send>(T); | 42 | struct Sendable<T: Send>(T); |
| 43 | type MySendable<T> = Sendable<T>; // no error here! | 43 | type MySendable<T> = Sendable<T>; // no error here! |
| 44 | 44 | ||
| 45 | // However, bounds *are* taken into account when accessing associated types | 45 | // Bounds on type params do enable shorthand type alias paths. |
| 46 | // However, that doesn't actually mean that they are properly enforced. | ||
| 46 | trait Bound { type Assoc; } | 47 | trait Bound { type Assoc; } |
| 47 | type T1<U: Bound> = U::Assoc; //~ WARN not enforced in type aliases | 48 | type T1<U: Bound> = U::Assoc; //~ WARN are not enforced |
| 48 | type T2<U> where U: Bound = U::Assoc; //~ WARN not enforced in type aliases | 49 | type T2<U> where U: Bound = U::Assoc; //~ WARN are not enforced |
| 49 | 50 | ||
| 50 | // This errors: | 51 | // This errors: |
| 51 | // `type T3<U> = U::Assoc;` | 52 | // `type T3<U> = U::Assoc;` |
| ... | @@ -53,7 +54,7 @@ type T2<U> where U: Bound = U::Assoc; //~ WARN not enforced in type aliases | ... | @@ -53,7 +54,7 @@ type T2<U> where U: Bound = U::Assoc; //~ WARN not enforced in type aliases |
| 53 | type T4<U> = <U as Bound>::Assoc; | 54 | type T4<U> = <U as Bound>::Assoc; |
| 54 | 55 | ||
| 55 | // Make sure the help about associated types is not shown incorrectly | 56 | // Make sure the help about associated types is not shown incorrectly |
| 56 | type T5<U: Bound> = <U as Bound>::Assoc; //~ WARN not enforced in type aliases | 57 | type T5<U: Bound> = <U as Bound>::Assoc; //~ WARN are not enforced |
| 57 | type T6<U: Bound> = ::std::vec::Vec<U>; //~ WARN not enforced in type aliases | 58 | type T6<U: Bound> = ::std::vec::Vec<U>; //~ WARN are not enforced |
| 58 | 59 | ||
| 59 | fn main() {} | 60 | fn main() {} |
tests/ui/type/type-alias-bounds.stderr+87-76| ... | @@ -1,121 +1,132 @@ | ... | @@ -1,121 +1,132 @@ |
| 1 | warning: bounds on generic parameters are not enforced in type aliases | 1 | warning: bounds on generic parameters in type aliases are not enforced |
| 2 | --> $DIR/type-alias-bounds.rs:8:14 | 2 | --> $DIR/type-alias-bounds.rs:8:14 |
| 3 | | | 3 | | |
| 4 | LL | type SVec<T: Send + Send> = Vec<T>; | 4 | LL | type SVec<T: Send + Send> = Vec<T>; |
| 5 | | ^^^^ ^^^^ | 5 | | --^^^^---^^^^ |
| 6 | | | 6 | | | | |
| 7 | | | will not be checked at usage sites of the type alias | ||
| 8 | | help: remove this bound | ||
| 9 | | | ||
| 10 | = note: this is a known limitation of the type checker that may be lifted in a future edition. | ||
| 11 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information | ||
| 12 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 7 | = note: `#[warn(type_alias_bounds)]` on by default | 13 | = note: `#[warn(type_alias_bounds)]` on by default |
| 8 | help: the bound will not be checked when the type alias is used, and should be removed | ||
| 9 | | | ||
| 10 | LL - type SVec<T: Send + Send> = Vec<T>; | ||
| 11 | LL + type SVec<T> = Vec<T>; | ||
| 12 | | | ||
| 13 | 14 | ||
| 14 | warning: where clauses are not enforced in type aliases | 15 | warning: where clauses on type aliases are not enforced |
| 15 | --> $DIR/type-alias-bounds.rs:10:21 | 16 | --> $DIR/type-alias-bounds.rs:10:21 |
| 16 | | | 17 | | |
| 17 | LL | type S2Vec<T> where T: Send = Vec<T>; | 18 | LL | type S2Vec<T> where T: Send = Vec<T>; |
| 18 | | ^^^^^^^ | 19 | | ------^^^^^^^ |
| 19 | | | 20 | | | | |
| 20 | help: the clause will not be checked when the type alias is used, and should be removed | 21 | | | will not be checked at usage sites of the type alias |
| 21 | | | 22 | | help: remove this where clause |
| 22 | LL - type S2Vec<T> where T: Send = Vec<T>; | 23 | | |
| 23 | LL + type S2Vec<T> = Vec<T>; | 24 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 24 | | | 25 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 26 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 25 | 27 | ||
| 26 | warning: bounds on generic parameters are not enforced in type aliases | 28 | warning: bounds on generic parameters in type aliases are not enforced |
| 27 | --> $DIR/type-alias-bounds.rs:12:19 | 29 | --> $DIR/type-alias-bounds.rs:12:19 |
| 28 | | | 30 | | |
| 29 | LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); | 31 | LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); |
| 30 | | ^^ ^^ | 32 | | --^^---^^ |
| 31 | | | 33 | | | | |
| 32 | help: the bound will not be checked when the type alias is used, and should be removed | 34 | | | will not be checked at usage sites of the type alias |
| 33 | | | 35 | | help: remove this bound |
| 34 | LL - type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); | 36 | | |
| 35 | LL + type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>); | 37 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 36 | | | 38 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 39 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 37 | 40 | ||
| 38 | warning: bounds on generic parameters are not enforced in type aliases | 41 | warning: bounds on generic parameters in type aliases are not enforced |
| 39 | --> $DIR/type-alias-bounds.rs:14:18 | 42 | --> $DIR/type-alias-bounds.rs:14:18 |
| 40 | | | 43 | | |
| 41 | LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>); | 44 | LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>); |
| 42 | | ^^ ^^ | 45 | | --^^---^^ |
| 43 | | | 46 | | | | |
| 44 | help: the bound will not be checked when the type alias is used, and should be removed | 47 | | | will not be checked at usage sites of the type alias |
| 45 | | | 48 | | help: remove this bound |
| 46 | LL - type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>); | 49 | | |
| 47 | LL + type WVec<'b, T> = (&'b u32, Vec<T>); | 50 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 48 | | | 51 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 52 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 49 | 53 | ||
| 50 | warning: where clauses are not enforced in type aliases | 54 | warning: where clauses on type aliases are not enforced |
| 51 | --> $DIR/type-alias-bounds.rs:16:25 | 55 | --> $DIR/type-alias-bounds.rs:16:25 |
| 52 | | | 56 | | |
| 53 | LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>); | 57 | LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>); |
| 54 | | ^^^^^ ^^^^^ | 58 | | ------^^^^^--^^^^^ |
| 55 | | | 59 | | | | |
| 56 | help: the clause will not be checked when the type alias is used, and should be removed | 60 | | | will not be checked at usage sites of the type alias |
| 57 | | | 61 | | help: remove this where clause |
| 58 | LL - type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>); | 62 | | |
| 59 | LL + type W2Vec<'b, T> = (&'b u32, Vec<T>); | 63 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 60 | | | 64 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 65 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 61 | 66 | ||
| 62 | warning: bounds on generic parameters are not enforced in type aliases | 67 | warning: bounds on generic parameters in type aliases are not enforced |
| 63 | --> $DIR/type-alias-bounds.rs:47:12 | 68 | --> $DIR/type-alias-bounds.rs:48:12 |
| 64 | | | 69 | | |
| 65 | LL | type T1<U: Bound> = U::Assoc; | 70 | LL | type T1<U: Bound> = U::Assoc; |
| 66 | | ^^^^^ | 71 | | ^^^^^ will not be checked at usage sites of the type alias |
| 67 | | | 72 | | |
| 68 | help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases | 73 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 69 | --> $DIR/type-alias-bounds.rs:47:21 | 74 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 70 | | | 75 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics |
| 71 | LL | type T1<U: Bound> = U::Assoc; | 76 | help: remove this bound |
| 72 | | ^^^^^^^^ | ||
| 73 | help: the bound will not be checked when the type alias is used, and should be removed | ||
| 74 | | | 77 | | |
| 75 | LL - type T1<U: Bound> = U::Assoc; | 78 | LL - type T1<U: Bound> = U::Assoc; |
| 76 | LL + type T1<U> = U::Assoc; | 79 | LL + type T1<U> = U::Assoc; |
| 77 | | | 80 | | |
| 81 | help: fully qualify this associated type | ||
| 82 | | | ||
| 83 | LL | type T1<U: Bound> = <U as /* Trait */>::Assoc; | ||
| 84 | | + +++++++++++++++ | ||
| 78 | 85 | ||
| 79 | warning: where clauses are not enforced in type aliases | 86 | warning: where clauses on type aliases are not enforced |
| 80 | --> $DIR/type-alias-bounds.rs:48:18 | 87 | --> $DIR/type-alias-bounds.rs:49:18 |
| 81 | | | 88 | | |
| 82 | LL | type T2<U> where U: Bound = U::Assoc; | 89 | LL | type T2<U> where U: Bound = U::Assoc; |
| 83 | | ^^^^^^^^ | 90 | | ^^^^^^^^ will not be checked at usage sites of the type alias |
| 84 | | | 91 | | |
| 85 | help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases | 92 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 86 | --> $DIR/type-alias-bounds.rs:48:29 | 93 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 87 | | | 94 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics |
| 88 | LL | type T2<U> where U: Bound = U::Assoc; | 95 | help: remove this where clause |
| 89 | | ^^^^^^^^ | ||
| 90 | help: the clause will not be checked when the type alias is used, and should be removed | ||
| 91 | | | 96 | | |
| 92 | LL - type T2<U> where U: Bound = U::Assoc; | 97 | LL - type T2<U> where U: Bound = U::Assoc; |
| 93 | LL + type T2<U> = U::Assoc; | 98 | LL + type T2<U> = U::Assoc; |
| 94 | | | 99 | | |
| 100 | help: fully qualify this associated type | ||
| 101 | | | ||
| 102 | LL | type T2<U> where U: Bound = <U as /* Trait */>::Assoc; | ||
| 103 | | + +++++++++++++++ | ||
| 95 | 104 | ||
| 96 | warning: bounds on generic parameters are not enforced in type aliases | 105 | warning: bounds on generic parameters in type aliases are not enforced |
| 97 | --> $DIR/type-alias-bounds.rs:56:12 | 106 | --> $DIR/type-alias-bounds.rs:57:12 |
| 98 | | | 107 | | |
| 99 | LL | type T5<U: Bound> = <U as Bound>::Assoc; | 108 | LL | type T5<U: Bound> = <U as Bound>::Assoc; |
| 100 | | ^^^^^ | 109 | | --^^^^^ |
| 101 | | | 110 | | | | |
| 102 | help: the bound will not be checked when the type alias is used, and should be removed | 111 | | | will not be checked at usage sites of the type alias |
| 103 | | | 112 | | help: remove this bound |
| 104 | LL - type T5<U: Bound> = <U as Bound>::Assoc; | 113 | | |
| 105 | LL + type T5<U> = <U as Bound>::Assoc; | 114 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 106 | | | 115 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 116 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 107 | 117 | ||
| 108 | warning: bounds on generic parameters are not enforced in type aliases | 118 | warning: bounds on generic parameters in type aliases are not enforced |
| 109 | --> $DIR/type-alias-bounds.rs:57:12 | 119 | --> $DIR/type-alias-bounds.rs:58:12 |
| 110 | | | 120 | | |
| 111 | LL | type T6<U: Bound> = ::std::vec::Vec<U>; | 121 | LL | type T6<U: Bound> = ::std::vec::Vec<U>; |
| 112 | | ^^^^^ | 122 | | --^^^^^ |
| 113 | | | 123 | | | | |
| 114 | help: the bound will not be checked when the type alias is used, and should be removed | 124 | | | will not be checked at usage sites of the type alias |
| 115 | | | 125 | | help: remove this bound |
| 116 | LL - type T6<U: Bound> = ::std::vec::Vec<U>; | 126 | | |
| 117 | LL + type T6<U> = ::std::vec::Vec<U>; | 127 | = note: this is a known limitation of the type checker that may be lifted in a future edition. |
| 118 | | | 128 | see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information |
| 129 | = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics | ||
| 119 | 130 | ||
| 120 | warning: 9 warnings emitted | 131 | warning: 9 warnings emitted |
| 121 | 132 |