diff --git a/.mailmap b/.mailmap index d1e5b3f519591..9166494632a00 100644 --- a/.mailmap +++ b/.mailmap @@ -491,7 +491,6 @@ Milan Landaverde mjptree Ms2ger msizanoen1 -mu001999 Mukilan Thiagarajan Nadrieril Feneanar Nadrieril Feneanar @@ -603,6 +602,7 @@ Robert Habermeier Robert Millar Roc Yu Rohit Joshi Rohit Joshi +Roland Xu Ross Smyth <18294397+RossSmyth@users.noreply.github.com> Ross Smyth <18294397+RossSmyth@users.noreply.github.com> Ross Smyth <18294397+RossSmyth@users.noreply.github.com> diff --git a/Cargo.lock b/Cargo.lock index 2f05b186b3fc9..c50e836574641 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3554,9 +3554,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-literal-escaper" -version = "0.0.7" +version = "0.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be87abb9e40db7466e0681dc8ecd9dcfd40360cb10b4c8fe24a7c4c3669b198" +checksum = "bfe6f213fb658c8fb95baabd5420393438cf5a98d707f5dd701d9197c705f71e" [[package]] name = "rustc-main" diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index a09c36efe01f6..c60f666d3bfad 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" # tidy-alphabetical-start bitflags = "2.4.1" memchr = "2.7.6" -rustc-literal-escaper = "0.0.7" +rustc-literal-escaper = "0.0.8" rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 3ead3b86cb591..fc466246bf137 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -194,7 +194,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return self.generate_delegation_error(span, delegation); } - let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method); + let mut generics = self.uplift_delegation_generics(delegation, sig_id); let (body_id, call_expr_id, unused_target_expr) = self.lower_delegation_body( delegation, @@ -404,10 +404,10 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::InferDelegationSig::Output(self.arena.alloc(hir::DelegationInfo { call_expr_id, call_path_res: self.get_resolution_id(call_path_node_id), - child_args_segment_id: generics.child.args_segment_id, - parent_args_segment_id: generics.parent.args_segment_id, - self_ty_id: generics.self_ty_id, - propagate_self_ty: generics.propagate_self_ty, + child_seg_id: generics.child.args_segment_id, + child_seg_id_for_sig: generics.child.segment_id_for_sig(), + parent_seg_id_for_sig: generics.parent.segment_id_for_sig(), + self_ty_propagation_kind: generics.self_ty_propagation_kind, group_id: { let id = match source { DelegationSource::Single => None, @@ -625,20 +625,40 @@ impl<'hir> LoweringContext<'_, 'hir> { }), ); - hir::QPath::Resolved(ty, self.arena.alloc(new_path)) - } - hir::QPath::TypeRelative(ty, segment) => { - let segment = self.process_segment(span, segment, &mut generics.child); + // Explicitly create `Self` self-type in case of infers or static + // free-to-trait reuses. + let ty = match generics.self_ty_propagation_kind { + Some(hir::DelegationSelfTyPropagationKind::SelfParam) => { + let self_param = generics.parent.generics.find_self_param(); + let path = self.create_generic_arg_path(self_param); + let kind = hir::TyKind::Path(path); + + let ty = match ty { + Some(ty) => hir::Ty { kind, ..ty.clone() }, + None => hir::Ty { kind, hir_id: self.next_id(), span }, + }; + + Some(&*self.arena.alloc(ty)) + } + _ => ty, + }; - hir::QPath::TypeRelative(ty, self.arena.alloc(segment)) + hir::QPath::Resolved(ty, self.arena.alloc(new_path)) } + hir::QPath::TypeRelative(..) => unreachable!("until inherent methods are supported"), }; - generics.self_ty_id = match new_path { - hir::QPath::Resolved(ty, _) => ty, - hir::QPath::TypeRelative(ty, _) => Some(ty), + if let Some(hir::DelegationSelfTyPropagationKind::SelfTy(id)) = + generics.self_ty_propagation_kind.as_mut() + { + *id = match new_path { + hir::QPath::Resolved(ty, _) => { + ty.expect("must contain self type as `SelfTy` propagation kind is specified") + } + hir::QPath::TypeRelative(ty, _) => ty, + } + .hir_id; } - .map(|ty| ty.hir_id); let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(new_path), span)); let args = self.arena.alloc_from_iter(args); @@ -662,25 +682,38 @@ impl<'hir> LoweringContext<'_, 'hir> { segment: &hir::PathSegment<'hir>, result: &mut GenericsGenerationResult<'hir>, ) -> hir::PathSegment<'hir> { - let details = result.generics.args_propagation_details(); - - // Always uplift generic params, because if they are not empty then they - // should be generated in delegation. - let generics = result.generics.into_hir_generics(self, span); - let segment = if details.should_propagate { - let args = generics.into_generic_args(self, span); - - // Needed for better error messages (`trait-impl-wrong-args-count.rs` test). - let args = if args.is_empty() { None } else { Some(args) }; - - hir::PathSegment { args, ..segment.clone() } - } else { - segment.clone() - }; + let infer_indices = result.generics.infer_indices(); + result.generics.into_hir_generics(self, span); + + let mut segment = segment.clone(); + let mut args_iter = result.generics.create_args_iterator(); + + let new_args = segment + .args + .filter(|args| !args.is_empty()) + .map(|args| { + self.arena.alloc_from_iter(args.args.iter().enumerate().map(|(idx, arg)| { + if infer_indices.contains(&idx) { + args_iter.next(self, |_| arg.hir_id()).expect("arg must exist for infer") + } else { + *arg + } + })) + }) + .unwrap_or_else(|| self.arena.alloc_from_iter(args_iter.consume_all(self))); + + // Needed for better error messages (`trait-impl-wrong-args-count.rs` test). + segment.args = (!new_args.is_empty()).then(|| { + &*self.arena.alloc(hir::GenericArgs { + args: new_args, + constraints: &[], + parenthesized: hir::GenericArgsParentheses::No, + span_ext: segment.args.map_or(span, |args| args.span_ext), + }) + }); - if details.use_args_in_sig_inheritance { - result.args_segment_id = Some(segment.hir_id); - } + result.args_segment_id = segment.hir_id; + result.use_for_sig_inheritance = !result.generics.is_trait_impl(); segment } diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs index f8e3528750035..79a3961c22a53 100644 --- a/compiler/rustc_ast_lowering/src/delegation/generics.rs +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -1,6 +1,7 @@ use hir::HirId; use hir::def::{DefKind, Res}; use rustc_ast::*; +use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::GenericParamDefKind; @@ -9,21 +10,7 @@ use rustc_span::symbol::kw; use rustc_span::{Ident, Span, sym}; use crate::LoweringContext; - -#[derive(Clone, Copy)] -pub(super) enum DelegationGenericsKind { - /// User-specified args are present: `reuse foo::;`. - UserSpecified, - /// The default case when no user-specified args are present: `reuse Trait::foo;`. - Default, - /// In free-to-trait reuse, when user specified args for trait `reuse Trait::::foo;` - /// in this case we need to both generate `Self` and process user args. - SelfAndUserSpecified, - /// In delegations from trait impl to other entities like free functions or trait functions, - /// we want to generate a function whose generics matches generics of signature function - /// in trait. - TraitImpl(bool /* Has user-specified args */), -} +use crate::diagnostics::DelegationInfersMismatch; #[derive(Debug, Clone, Copy)] pub(super) enum GenericsPosition { @@ -31,30 +18,30 @@ pub(super) enum GenericsPosition { Child, } +#[derive(Debug)] +pub(super) enum GenericArgSlot { + UserSpecified, + Generate(T, Option /* Infer arg index from AST */), +} + pub(super) struct DelegationGenerics { - generics: T, - kind: DelegationGenericsKind, + data: T, pos: GenericsPosition, + trait_impl: bool, } -impl<'hir> DelegationGenerics<&'hir [ty::GenericParamDef]> { - fn default(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self { - DelegationGenerics { generics, pos, kind: DelegationGenericsKind::Default } - } - - fn user_specified(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self { - DelegationGenerics { generics, pos, kind: DelegationGenericsKind::UserSpecified } - } +type TyGenerics<'hir> = Vec>; - fn trait_impl( - generics: &'hir [ty::GenericParamDef], - user_specified: bool, +impl<'hir> DelegationGenerics> { + fn generate_all( + params: &'hir [ty::GenericParamDef], pos: GenericsPosition, + trait_impl: bool, ) -> Self { DelegationGenerics { - generics, + data: params.iter().map(|p| GenericArgSlot::Generate(p, None)).collect(), pos, - kind: DelegationGenericsKind::TraitImpl(user_specified), + trait_impl, } } } @@ -70,103 +57,176 @@ impl<'hir> DelegationGenerics<&'hir [ty::GenericParamDef]> { /// (i.e., method call scenarios), in such a case this approach helps /// a lot as if `into_hir_generics` will not be called then uplifting will not happen. pub(super) enum HirOrTyGenerics<'hir> { - Ty(DelegationGenerics<&'hir [ty::GenericParamDef]>), + Ty(DelegationGenerics>), Hir(DelegationGenerics<&'hir hir::Generics<'hir>>), } pub(super) struct GenericsGenerationResult<'hir> { pub(super) generics: HirOrTyGenerics<'hir>, - pub(super) args_segment_id: Option, + pub(super) args_segment_id: HirId, + pub(super) use_for_sig_inheritance: bool, +} + +impl GenericsGenerationResult<'_> { + pub(super) fn segment_id_for_sig(&self) -> Option { + self.use_for_sig_inheritance.then(|| self.args_segment_id) + } } pub(super) struct GenericsGenerationResults<'hir> { pub(super) parent: GenericsGenerationResult<'hir>, pub(super) child: GenericsGenerationResult<'hir>, - pub(super) self_ty_id: Option, - pub(super) propagate_self_ty: bool, + pub(super) self_ty_propagation_kind: Option, } -pub(super) struct GenericArgsPropagationDetails { - pub(super) should_propagate: bool, - pub(super) use_args_in_sig_inheritance: bool, +pub(super) struct DelegationGenericArgsIterator<'hir> { + index: usize = Default::default(), + params: &'hir [hir::GenericParam<'hir>], } -impl DelegationGenericsKind { - fn args_propagation_details(self) -> GenericArgsPropagationDetails { - match self { - DelegationGenericsKind::UserSpecified - | DelegationGenericsKind::SelfAndUserSpecified => GenericArgsPropagationDetails { - should_propagate: false, - use_args_in_sig_inheritance: true, - }, - DelegationGenericsKind::TraitImpl(user_specified) => GenericArgsPropagationDetails { - should_propagate: !user_specified, - use_args_in_sig_inheritance: false, - }, - DelegationGenericsKind::Default => GenericArgsPropagationDetails { - should_propagate: true, - use_args_in_sig_inheritance: false, - }, +/// During generic args propagation we need to create generic args +/// (and their `HirId`s) on demand, as some of generic args can not be used +/// and in this case an assert of an unseen `HirId` will be triggered. Moreover, +/// when replacing infers with generated generic params we should reuse existing +/// `HirId` of replaced infer, thus this iterator abstracts the way `HirId`s are +/// created for new generic args. +impl<'hir> DelegationGenericArgsIterator<'hir> { + pub(super) fn next( + &mut self, + ctx: &mut LoweringContext<'_, 'hir>, + hir_id_factory: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> HirId, + ) -> Option> { + let p = loop { + if self.index >= self.params.len() { + return None; + } + + let p = self.params[self.index]; + self.index += 1; + + // Skip self generic arg, we do not need to propagate it. + if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() { + continue; + } + + break p; + }; + + let hir_id = hir_id_factory(ctx); + + Some(match p.kind { + hir::GenericParamKind::Lifetime { .. } => { + hir::GenericArg::Lifetime(ctx.arena.alloc(hir::Lifetime { + hir_id, + ident: p.name.ident(), + kind: hir::LifetimeKind::Param(p.def_id), + source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full }, + syntax: hir::LifetimeSyntax::ExplicitBound, + })) + } + hir::GenericParamKind::Type { .. } => hir::GenericArg::Type(ctx.arena.alloc(hir::Ty { + hir_id, + span: p.span, + kind: hir::TyKind::Path(ctx.create_generic_arg_path(&p)), + })), + hir::GenericParamKind::Const { .. } => { + hir::GenericArg::Const(ctx.arena.alloc(hir::ConstArg { + hir_id, + kind: hir::ConstArgKind::Path(ctx.create_generic_arg_path(&p)), + span: p.span, + })) + } + }) + } + + pub(super) fn consume_all( + mut self, + ctx: &mut LoweringContext<'_, 'hir>, + ) -> Vec> { + let mut args = vec![]; + while let Some(arg) = self.next(ctx, |ctx| ctx.next_id()) { + args.push(arg); } + + args } } impl<'hir> HirOrTyGenerics<'hir> { - pub(super) fn into_hir_generics( - &mut self, - ctx: &mut LoweringContext<'_, 'hir>, - span: Span, - ) -> &mut HirOrTyGenerics<'hir> { + pub(super) fn into_hir_generics(&mut self, ctx: &mut LoweringContext<'_, 'hir>, span: Span) { if let HirOrTyGenerics::Ty(ty) = self { let rename_self = matches!(ty.pos, GenericsPosition::Child); - let params = ctx.uplift_delegation_generic_params(span, ty.generics, rename_self); + let params = ctx.uplift_delegation_generic_params(span, &ty.data, rename_self); *self = HirOrTyGenerics::Hir(DelegationGenerics { - generics: params, - kind: ty.kind, + data: params, pos: ty.pos, + trait_impl: ty.trait_impl, }); } - - self } fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> { match self { HirOrTyGenerics::Ty(_) => hir::Generics::empty(), - HirOrTyGenerics::Hir(hir) => hir.generics, + HirOrTyGenerics::Hir(hir) => hir.data, } } - pub(super) fn into_generic_args( - &self, - ctx: &mut LoweringContext<'_, 'hir>, - span: Span, - ) -> &'hir hir::GenericArgs<'hir> { + pub(super) fn create_args_iterator(&self) -> DelegationGenericArgsIterator<'hir> { match self { HirOrTyGenerics::Ty(_) => { - bug!("Attempting to get generic args before uplifting to HIR") + bug!("attempting to get generic args before uplifting to HIR") } HirOrTyGenerics::Hir(hir) => { - let add_lifetimes = matches!(hir.pos, GenericsPosition::Parent); - ctx.create_generics_args_from_params(hir.generics.params, add_lifetimes, span) + DelegationGenericArgsIterator { params: hir.data.params, .. } } } } - pub(super) fn args_propagation_details(&self) -> GenericArgsPropagationDetails { + pub(super) fn infer_indices(&self) -> FxHashSet { match self { - HirOrTyGenerics::Ty(ty) => ty.kind.args_propagation_details(), - HirOrTyGenerics::Hir(hir) => hir.kind.args_propagation_details(), + HirOrTyGenerics::Ty(ty) => ty + .data + .iter() + .flat_map(|slot| match slot { + GenericArgSlot::Generate(_, Some(idx)) => Some(*idx), + _ => None, + }) + .collect(), + HirOrTyGenerics::Hir(_) => bug!("accessed infer indices on uplifted generics"), + } + } + + pub(super) fn is_trait_impl(&self) -> bool { + match self { + HirOrTyGenerics::Ty(ty) => ty.trait_impl, + HirOrTyGenerics::Hir(hir) => hir.trait_impl, + } + } + + pub(super) fn find_self_param(&self) -> &'hir hir::GenericParam<'hir> { + match self { + HirOrTyGenerics::Ty(_) => { + bug!("accessed ty-level generics while searching for uplifted `Self` param") + } + HirOrTyGenerics::Hir(hir) => hir + .data + .params + .iter() + .find(|p| p.name.ident().name == kw::SelfUpper) + .expect("`Self` generic param is not found while expected"), } } } impl<'hir> GenericsGenerationResult<'hir> { - fn new( - generics: DelegationGenerics<&'hir [ty::GenericParamDef]>, - ) -> GenericsGenerationResult<'hir> { - GenericsGenerationResult { generics: HirOrTyGenerics::Ty(generics), args_segment_id: None } + fn new(generics: DelegationGenerics>) -> GenericsGenerationResult<'hir> { + GenericsGenerationResult { + generics: HirOrTyGenerics::Ty(generics), + args_segment_id: HirId::INVALID, + use_for_sig_inheritance: false, + } } } @@ -208,13 +268,30 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, delegation: &Delegation, sig_id: DefId, - is_method: bool, ) -> GenericsGenerationResults<'hir> { let delegation_parent_kind = self.tcx.def_kind(self.tcx.local_parent(self.owner.def_id)); let segments = &delegation.path.segments; let len = segments.len(); - let child_user_specified = segments[len - 1].args.is_some(); + + let get_user_args = |idx: usize| -> Option<&AngleBracketedArgs> { + let segment = &segments[idx]; + + let Some(args) = segment.args.as_ref() else { return None }; + let GenericArgs::AngleBracketed(args) = args else { + self.tcx.dcx().span_delayed_bug( + segment.span(), + "expected angle-bracketed generic args in delegation segment", + ); + + return None; + }; + + // Treat empty args `reuse foo::<> as bar` as `reuse foo as bar`, + // the same logic applied when we call function `fn f(t: T)` + // like that `f::<>(())`, in HIR no `<>` will be generated. + (!args.args.is_empty()).then(|| args) + }; let sig_params = &self.tcx.generics_of(sig_id).own_params[..]; @@ -223,23 +300,15 @@ impl<'hir> LoweringContext<'_, 'hir> { if matches!(delegation_parent_kind, DefKind::Impl { of_trait: true }) { // Considering parent generics, during signature inheritance // we will take those args that are in trait impl header trait ref. - let parent = DelegationGenerics::trait_impl(&[], true, GenericsPosition::Parent); - let parent = GenericsGenerationResult::new(parent); + let parent = + DelegationGenerics { data: vec![], pos: GenericsPosition::Child, trait_impl: true }; - let child = DelegationGenerics::trait_impl( - sig_params, - child_user_specified, - GenericsPosition::Child, - ); + let parent = GenericsGenerationResult::new(parent); + let child = DelegationGenerics::generate_all(sig_params, GenericsPosition::Child, true); let child = GenericsGenerationResult::new(child); - return GenericsGenerationResults { - parent, - child, - self_ty_id: None, - propagate_self_ty: false, - }; + return GenericsGenerationResults { parent, child, self_ty_propagation_kind: None }; } let delegation_in_free_ctx = @@ -248,7 +317,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let sig_parent = self.tcx.parent(sig_id); let sig_in_trait = matches!(self.tcx.def_kind(sig_parent), DefKind::Trait); let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait; - let generate_self = free_to_trait_delegation && is_method && delegation.qself.is_none(); + + let qself_is_infer = + delegation.qself.as_ref().is_some_and(|qself| qself.ty.is_maybe_parenthesised_infer()); + + let qself_is_none = delegation.qself.is_none(); + + let generate_self = free_to_trait_delegation && (qself_is_none || qself_is_infer); let can_add_generics_to_parent = len >= 2 && self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| { @@ -256,57 +331,137 @@ impl<'hir> LoweringContext<'_, 'hir> { }); let parent_generics = if can_add_generics_to_parent { - let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params[..]; - - if segments[len - 2].args.is_some() { - if generate_self { - // Take only first Self parameter, it is trait so Self must be present. - DelegationGenerics { - kind: DelegationGenericsKind::SelfAndUserSpecified, - generics: &sig_parent_params[..1], - pos: GenericsPosition::Parent, - } - } else { - DelegationGenerics::user_specified(&[], GenericsPosition::Parent) + let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params; + + if let Some(args) = get_user_args(len - 2) { + DelegationGenerics { + data: self.create_slots_from_args( + args, + &sig_parent_params[usize::from(!generate_self)..], + generate_self, + ), + pos: GenericsPosition::Parent, + trait_impl: false, } } else { - let skip_self = usize::from(!generate_self); - DelegationGenerics::default( - &sig_parent_params[skip_self..], + DelegationGenerics::generate_all( + &sig_parent_params[usize::from(!generate_self)..], GenericsPosition::Parent, + false, ) } } else { - DelegationGenerics::default(&[], GenericsPosition::Parent) + DelegationGenerics { data: vec![], pos: GenericsPosition::Parent, trait_impl: false } }; - let child_generics = if child_user_specified { + let child_generics = if let Some(args) = get_user_args(len - 1) { let synth_params_index = sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len()); - DelegationGenerics::user_specified( - &sig_params[synth_params_index..], - GenericsPosition::Child, - ) + let mut slots = + self.create_slots_from_args(args, &sig_params[..synth_params_index], false); + + for synth_param in &sig_params[synth_params_index..] { + slots.push(GenericArgSlot::Generate(synth_param, None)); + } + + DelegationGenerics { data: slots, pos: GenericsPosition::Child, trait_impl: false } } else { - DelegationGenerics::default(sig_params, GenericsPosition::Child) + DelegationGenerics::generate_all(sig_params, GenericsPosition::Child, false) }; GenericsGenerationResults { parent: GenericsGenerationResult::new(parent_generics), child: GenericsGenerationResult::new(child_generics), - self_ty_id: None, - propagate_self_ty: free_to_trait_delegation && !generate_self, + self_ty_propagation_kind: match free_to_trait_delegation { + true => Some(match qself_is_none { + true => hir::DelegationSelfTyPropagationKind::SelfParam, + false => match qself_is_infer { + true => hir::DelegationSelfTyPropagationKind::SelfParam, + // HirId is filled during generic args propagation. + false => hir::DelegationSelfTyPropagationKind::SelfTy(HirId::INVALID), + }, + }), + false => None, + }, + } + } + + /// Generates generic argument slots for user-specified `args` and + /// generic `params` of the signature function. This function checks whether + /// there are infers (`kw::UnderscoreLifetime` or `kw::Underscore`) in + /// user-specified args, and if so we add `Generate` slot meaning we have to + /// generate generic param for delegation and propagate it instead of this infer. + /// We zip over user-specified args and signature generic params, so if there are more + /// infers than generic params then we will not process all infers thus not generating + /// more generic params then needed (anyway it is an error). + fn create_slots_from_args( + &self, + args: &AngleBracketedArgs, + params: &'hir [ty::GenericParamDef], + add_first_self: bool, + ) -> TyGenerics<'hir> { + let mut slots = vec![]; + if add_first_self { + slots.push(GenericArgSlot::Generate(¶ms[0], None)); + } + + let params = ¶ms[usize::from(add_first_self)..]; + for (idx, (arg, param)) in args.args.iter().zip(params).enumerate() { + let AngleBracketedArg::Arg(arg) = arg else { continue }; + + let is_infer = match arg { + GenericArg::Lifetime(lt) => lt.ident.name == kw::UnderscoreLifetime, + GenericArg::Type(ty) => ty.is_maybe_parenthesised_infer(), + GenericArg::Const(_) => false, + }; + + // If `'_` is used instead of `_` (or vice versa) we emit a meaningful + // error instead of processing this infer or leaving it as is for signature + // inheritance. + if is_infer + && matches!( + (arg, ¶m.kind), + ( + GenericArg::Lifetime(_), + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } + ) | ( + GenericArg::Type(_) | GenericArg::Const(_), + GenericParamDefKind::Lifetime { .. } + ) + ) + { + let (actual, expected) = if matches!(arg, GenericArg::Lifetime(..)) { + (kw::UnderscoreLifetime, kw::Underscore) + } else { + (kw::Underscore, kw::UnderscoreLifetime) + }; + + self.tcx.dcx().emit_err(DelegationInfersMismatch { + span: arg.span(), + actual, + expected, + }); + } + + slots.push(match is_infer { + true => GenericArgSlot::Generate(param, Some(idx)), + false => GenericArgSlot::UserSpecified, + }); } + + slots } fn uplift_delegation_generic_params( &mut self, span: Span, - params: &'hir [ty::GenericParamDef], + params: &[GenericArgSlot<&ty::GenericParamDef>], rename_self: bool, ) -> &'hir hir::Generics<'hir> { - let params = self.arena.alloc_from_iter(params.iter().map(|p| { + let params = self.arena.alloc_from_iter(params.iter().flat_map(|p| { + let GenericArgSlot::Generate(p, _) = p else { return None }; + let def_kind = match p.kind { GenericParamDefKind::Lifetime => DefKind::LifetimeParam, GenericParamDefKind::Type { .. } => DefKind::TyParam, @@ -354,7 +509,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `lower_node_id` routine so param's id is added to `self.children`. let hir_id = self.lower_node_id(node_id); - hir::GenericParam { + Some(hir::GenericParam { hir_id, colon_span: Some(span), def_id, @@ -363,7 +518,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pure_wrt_drop: p.pure_wrt_drop, source: hir::GenericParamSource::Generics, span, - } + }) })); // HACK: for now we generate predicates such that all lifetimes are early bound, @@ -413,77 +568,32 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn create_generics_args_from_params( + pub(super) fn create_generic_arg_path( &mut self, - params: &[hir::GenericParam<'hir>], - add_lifetimes: bool, - span: Span, - ) -> &'hir hir::GenericArgs<'hir> { - self.arena.alloc(hir::GenericArgs { - args: self.arena.alloc_from_iter(params.iter().filter_map(|p| { - // Skip self generic arg, we do not need to propagate it. - if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() { - return None; - } - - let create_path = |this: &mut Self| { - let res = Res::Def( - match p.kind { - hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam, - hir::GenericParamKind::Type { .. } => DefKind::TyParam, - hir::GenericParamKind::Const { .. } => DefKind::ConstParam, - }, - p.def_id.to_def_id(), - ); - - hir::QPath::Resolved( - None, - self.arena.alloc(hir::Path { - segments: this.arena.alloc_slice(&[hir::PathSegment { - args: None, - hir_id: this.next_id(), - ident: p.name.ident(), - infer_args: false, - res, - }]), - res, - span: p.span, - }), - ) - }; - - match p.kind { - hir::GenericParamKind::Lifetime { .. } => match add_lifetimes { - true => Some(hir::GenericArg::Lifetime(self.arena.alloc(hir::Lifetime { - hir_id: self.next_id(), - ident: p.name.ident(), - kind: hir::LifetimeKind::Param(p.def_id), - source: hir::LifetimeSource::Path { - angle_brackets: hir::AngleBrackets::Full, - }, - syntax: hir::LifetimeSyntax::ExplicitBound, - }))), - false => None, - }, - hir::GenericParamKind::Type { .. } => { - Some(hir::GenericArg::Type(self.arena.alloc(hir::Ty { - hir_id: self.next_id(), - span: p.span, - kind: hir::TyKind::Path(create_path(self)), - }))) - } - hir::GenericParamKind::Const { .. } => { - Some(hir::GenericArg::Const(self.arena.alloc(hir::ConstArg { - hir_id: self.next_id(), - kind: hir::ConstArgKind::Path(create_path(self)), - span: p.span, - }))) - } - } - })), - constraints: &[], - parenthesized: hir::GenericArgsParentheses::No, - span_ext: span, - }) + p: &hir::GenericParam<'hir>, + ) -> hir::QPath<'hir> { + let res = Res::Def( + match p.kind { + hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam, + hir::GenericParamKind::Type { .. } => DefKind::TyParam, + hir::GenericParamKind::Const { .. } => DefKind::ConstParam, + }, + p.def_id.to_def_id(), + ); + + hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + segments: self.arena.alloc_slice(&[hir::PathSegment { + args: None, + hir_id: self.next_id(), + ident: p.name.ident(), + infer_args: false, + res, + }]), + res, + span: p.span, + }), + ) } } diff --git a/compiler/rustc_ast_lowering/src/diagnostics.rs b/compiler/rustc_ast_lowering/src/diagnostics.rs index 31f094209a946..238a16d9b859d 100644 --- a/compiler/rustc_ast_lowering/src/diagnostics.rs +++ b/compiler/rustc_ast_lowering/src/diagnostics.rs @@ -560,3 +560,12 @@ pub(crate) struct DelegationAttemptedBlockWithDefsDeletion { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag("wrong infer used: expected {$expected}, found: {$actual}")] +pub(crate) struct DelegationInfersMismatch { + #[primary_span] + pub span: Span, + pub expected: Symbol, + pub actual: Symbol, +} diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b8d708d42ff10..06e83a7486100 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -31,6 +31,9 @@ //! in the HIR, especially for multiple identifiers. // tidy-alphabetical-start +#![feature(const_default)] +#![feature(const_trait_impl)] +#![feature(default_field_values)] #![feature(deref_patterns)] #![recursion_limit = "256"] // tidy-alphabetical-end diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 3e10e5e70b2c2..119b67b353cb8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -11,7 +11,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser { type Item = (Symbol, Span); const CONVERT: ConvertFn = |items, span| AttributeKind::AllowInternalUnstable(items, span); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::MacroDef), Allow(Target::Fn), Warn(Target::Field), @@ -36,7 +36,7 @@ impl CombineAttributeParser for UnstableFeatureBoundParser { type Item = (Symbol, Span); const CONVERT: ConvertFn = |items, _| AttributeKind::UnstableFeatureBound(items); const STABILITY: AttributeStability = unstable!(staged_api); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Impl { of_trait: true }), Allow(Target::Trait), @@ -59,7 +59,7 @@ impl CombineAttributeParser for RustcAllowConstFnUnstableParser { type Item = Symbol; const CONVERT: ConvertFn = |items, first_span| AttributeKind::RustcAllowConstFnUnstable(items, first_span); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), diff --git a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs index 890cb33d08720..78ed4ff46d997 100644 --- a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs +++ b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs @@ -19,7 +19,7 @@ pub(crate) struct RustcAutodiffParser; impl SingleAttributeParser for RustcAutodiffParser { const PATH: &[Symbol] = &[sym::rustc_autodiff]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), diff --git a/compiler/rustc_attr_parsing/src/attributes/body.rs b/compiler/rustc_attr_parsing/src/attributes/body.rs index b817d9346dafc..f3a4f04e02ae8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/body.rs +++ b/compiler/rustc_attr_parsing/src/attributes/body.rs @@ -8,7 +8,8 @@ pub(crate) struct CoroutineParser; impl NoArgsAttributeParser for CoroutineParser { const PATH: &[Symbol] = &[sym::coroutine]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::Closure)]); const STABILITY: AttributeStability = unstable!(coroutines); const CREATE: fn(rustc_span::Span) -> AttributeKind = |_| AttributeKind::Coroutine; } diff --git a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs index 2e7644fc70551..8a9102a78e25b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs @@ -4,7 +4,7 @@ use super::prelude::*; pub(crate) struct CfiEncodingParser; impl SingleAttributeParser for CfiEncodingParser { const PATH: &[Symbol] = &[sym::cfi_encoding]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Struct), Allow(Target::ForeignTy), Allow(Target::Enum), diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 155df43c813e8..7beee7e341b90 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -18,7 +18,7 @@ pub(crate) struct OptimizeParser; impl SingleAttributeParser for OptimizeParser { const PATH: &[Symbol] = &[sym::optimize]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Closure), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -51,7 +51,7 @@ pub(crate) struct ColdParser; impl NoArgsAttributeParser for ColdParser { const PATH: &[Symbol] = &[sym::cold]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), @@ -67,7 +67,7 @@ pub(crate) struct CoverageParser; impl SingleAttributeParser for CoverageParser { const PATH: &[Symbol] = &[sym::coverage]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Closure), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -114,7 +114,7 @@ impl SingleAttributeParser for ExportNameParser { note: "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them", unsafe_since: Some(Edition2024), }; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Static), Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -151,7 +151,7 @@ pub(crate) struct RustcObjcClassParser; impl SingleAttributeParser for RustcObjcClassParser { const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_class]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "ClassName"); const STABILITY: AttributeStability = unstable!(rustc_attrs); @@ -179,7 +179,7 @@ pub(crate) struct RustcObjcSelectorParser; impl SingleAttributeParser for RustcObjcSelectorParser { const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_selector]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "methodName"); const STABILITY: AttributeStability = unstable!(rustc_attrs); @@ -226,7 +226,7 @@ impl AttributeParser for NakedParser { note: "the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code).", unsafe_since: None, }; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -334,7 +334,7 @@ pub(crate) struct TrackCallerParser; impl NoArgsAttributeParser for TrackCallerParser { const PATH: &[Symbol] = &[sym::track_caller]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -359,7 +359,7 @@ impl NoArgsAttributeParser for NoMangleParser { note: "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them", unsafe_since: Some(Edition2024), }; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Static), Allow(Target::Method(MethodKind::Inherent)), @@ -462,7 +462,7 @@ impl AttributeParser for UsedParser { } }, )]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Static), Warn(Target::MacroCall)]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { @@ -533,7 +533,7 @@ impl CombineAttributeParser for TargetFeatureParser { parse_tf_attribute(cx, args) } - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -561,7 +561,7 @@ impl CombineAttributeParser for ForceTargetFeatureParser { was_forced: true, }; const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -581,7 +581,7 @@ pub(crate) struct InstrumentFnParser; impl SingleAttributeParser for InstrumentFnParser { const PATH: &[Symbol] = &[sym::instrument_fn]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -619,7 +619,7 @@ pub(crate) struct SanitizeParser; impl SingleAttributeParser for SanitizeParser { const PATH: &[Symbol] = &[sym::sanitize]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Closure), Allow(Target::Method(MethodKind::Inherent)), @@ -751,7 +751,7 @@ pub(crate) struct ThreadLocalParser; impl NoArgsAttributeParser for ThreadLocalParser { const PATH: &[Symbol] = &[sym::thread_local]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]); const STABILITY: AttributeStability = unstable!(thread_local); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ThreadLocal; @@ -761,7 +761,7 @@ pub(crate) struct RustcPassIndirectlyInNonRusticAbisParser; impl NoArgsAttributeParser for RustcPassIndirectlyInNonRusticAbisParser { const PATH: &[Symbol] = &[sym::rustc_pass_indirectly_in_non_rustic_abis]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassIndirectlyInNonRusticAbis; } @@ -770,7 +770,7 @@ pub(crate) struct RustcEiiForeignItemParser; impl NoArgsAttributeParser for RustcEiiForeignItemParser { const PATH: &[Symbol] = &[sym::rustc_eii_foreign_item]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]); const STABILITY: AttributeStability = unstable!(eii_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEiiForeignItem; @@ -780,7 +780,7 @@ pub(crate) struct PatchableFunctionEntryParser; impl SingleAttributeParser for PatchableFunctionEntryParser { const PATH: &[Symbol] = &[sym::patchable_function_entry]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!(List: &["prefix_nops = m, entry_nops = n"]); const STABILITY: AttributeStability = unstable!(patchable_function_entry); diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index 3b2115eeb01e2..091566012d158 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -32,7 +32,7 @@ impl AttributeParser for ConfusablesParser { this.first_span.get_or_insert(cx.attr_span); }, )]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index eb78bc0775f6b..03012941cb1c9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -2,7 +2,7 @@ use rustc_feature::AttributeStability; use rustc_hir::attrs::{CrateType, WindowsSubsystemKind}; use rustc_session::lint::builtin::UNKNOWN_CRATE_TYPES; use rustc_span::Symbol; -use rustc_span::edit_distance::find_best_match_for_name; +use rustc_span::edit_distance::find_best_match_for_name_with_substrings; use super::prelude::*; use crate::diagnostics::{UnknownCrateTypes, UnknownCrateTypesSuggestion}; @@ -13,7 +13,7 @@ impl SingleAttributeParser for CrateNameParser { const PATH: &[Symbol] = &[sym::crate_name]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -32,7 +32,7 @@ impl CombineAttributeParser for CrateTypeParser { const PATH: &[Symbol] = &[sym::crate_type]; type Item = CrateType; const CONVERT: ConvertFn = |items, _| AttributeKind::CrateType(items); - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html"); @@ -49,10 +49,10 @@ impl CombineAttributeParser for CrateTypeParser { let Ok(crate_type) = crate_type.try_into() else { // We don't error on invalid `#![crate_type]` when not applied to a crate if cx.shared.target == Target::Crate { - let candidate = find_best_match_for_name( + let candidate = find_best_match_for_name_with_substrings( &CrateType::all_stable().iter().map(|(name, _)| *name).collect::>(), crate_type, - None, + Some(5), ); let span = n.value_span; cx.emit_lint( @@ -76,7 +76,7 @@ impl SingleAttributeParser for RecursionLimitParser { const PATH: &[Symbol] = &[sym::recursion_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"); - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -92,7 +92,7 @@ pub(crate) struct MoveSizeLimitParser; impl SingleAttributeParser for MoveSizeLimitParser { const PATH: &[Symbol] = &[sym::move_size_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(large_assignments); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -108,7 +108,7 @@ impl SingleAttributeParser for TypeLengthLimitParser { const PATH: &[Symbol] = &[sym::type_length_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -124,7 +124,7 @@ pub(crate) struct PatternComplexityLimitParser; impl SingleAttributeParser for PatternComplexityLimitParser { const PATH: &[Symbol] = &[sym::pattern_complexity_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!( rustc_attrs, "the `#[pattern_complexity_limit]` attribute is used for rustc unit tests" @@ -141,7 +141,7 @@ pub(crate) struct NoCoreParser; impl NoArgsAttributeParser for NoCoreParser { const PATH: &[Symbol] = &[sym::no_core]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(no_core); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoCore; } @@ -151,7 +151,7 @@ pub(crate) struct NoStdParser; impl NoArgsAttributeParser for NoStdParser { const PATH: &[Symbol] = &[sym::no_std]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoStd; @@ -162,7 +162,7 @@ pub(crate) struct NoMainParser; impl NoArgsAttributeParser for NoMainParser { const PATH: &[Symbol] = &[sym::no_main]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain; @@ -172,7 +172,7 @@ pub(crate) struct RustcCoherenceIsCoreParser; impl NoArgsAttributeParser for RustcCoherenceIsCoreParser { const PATH: &[Symbol] = &[sym::rustc_coherence_is_core]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoherenceIsCore; } @@ -182,7 +182,7 @@ pub(crate) struct WindowsSubsystemParser; impl SingleAttributeParser for WindowsSubsystemParser { const PATH: &[Symbol] = &[sym::windows_subsystem]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -210,7 +210,7 @@ pub(crate) struct PanicRuntimeParser; impl NoArgsAttributeParser for PanicRuntimeParser { const PATH: &[Symbol] = &[sym::panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime; } @@ -219,7 +219,7 @@ pub(crate) struct NeedsPanicRuntimeParser; impl NoArgsAttributeParser for NeedsPanicRuntimeParser { const PATH: &[Symbol] = &[sym::needs_panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(needs_panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; } @@ -228,7 +228,7 @@ pub(crate) struct ProfilerRuntimeParser; impl NoArgsAttributeParser for ProfilerRuntimeParser { const PATH: &[Symbol] = &[sym::profiler_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(profiler_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; } @@ -238,7 +238,7 @@ pub(crate) struct NoBuiltinsParser; impl NoArgsAttributeParser for NoBuiltinsParser { const PATH: &[Symbol] = &[sym::no_builtins]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; @@ -248,7 +248,7 @@ pub(crate) struct RustcPreserveUbChecksParser; impl NoArgsAttributeParser for RustcPreserveUbChecksParser { const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; } @@ -257,7 +257,7 @@ pub(crate) struct RustcNoImplicitBoundsParser; impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; } @@ -266,7 +266,7 @@ pub(crate) struct DefaultLibAllocatorParser; impl NoArgsAttributeParser for DefaultLibAllocatorParser { const PATH: &[Symbol] = &[sym::default_lib_allocator]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator; } @@ -277,7 +277,7 @@ impl CombineAttributeParser for FeatureParser { const PATH: &[Symbol] = &[sym::feature]; type Item = Ident; const CONVERT: ConvertFn = AttributeKind::Feature; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["feature1, feature2, ..."]); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -323,7 +323,7 @@ impl CombineAttributeParser for RegisterToolParser { const PATH: &[Symbol] = &[sym::register_tool]; type Item = Ident; const CONVERT: ConvertFn = |tools, _span| AttributeKind::RegisterTool(tools); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]); const STABILITY: AttributeStability = unstable!(register_tool); diff --git a/compiler/rustc_attr_parsing/src/attributes/debugger.rs b/compiler/rustc_attr_parsing/src/attributes/debugger.rs index 8d2cff35905ed..b514235a48eca 100644 --- a/compiler/rustc_attr_parsing/src/attributes/debugger.rs +++ b/compiler/rustc_attr_parsing/src/attributes/debugger.rs @@ -7,7 +7,7 @@ pub(crate) struct DebuggerVisualizerParser; impl CombineAttributeParser for DebuggerVisualizerParser { const PATH: &[Symbol] = &[sym::debugger_visualizer]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!( List: &[r#"natvis_file = "...", gdb_script_file = "...""#], diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index ee3734bf19541..d401aafed7bec 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -32,7 +32,7 @@ fn get( pub(crate) struct DeprecatedParser; impl SingleAttributeParser for DeprecatedParser { const PATH: &[Symbol] = &[sym::deprecated]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Mod), Allow(Target::Struct), diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs index 85708273a409b..250326db42bb7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs @@ -16,7 +16,7 @@ impl SingleAttributeParser for DoNotRecommendParser { const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; // "Allowed" on any target, noop on all but trait impls - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Impl { of_trait: true })]); const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */); const STABILITY: AttributeStability = AttributeStability::Stable; diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs index dc8260ae944ef..a7b71b9080dca 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs @@ -37,7 +37,7 @@ impl AttributeParser for OnConstParser { // "Allowed" on all targets; noop on anything but non-const trait impls; // this linted on in parser. - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ // FIXME(mejrs) no constness field on `Target`, // so non-constness is still checked in check_attr.rs Allow(Target::Impl { of_trait: true }), diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs index ec77ede4127f5..1c8b3418fa746 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs @@ -43,7 +43,7 @@ impl AttributeParser for OnMoveParser { }, )]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Enum), Allow(Target::Struct), Allow(Target::Union), diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs index d5636b23a09b1..89cae4b7c55f1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs @@ -42,7 +42,7 @@ impl AttributeParser for OnTypeErrorParser { }, )]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Enum), Allow(Target::Struct), Allow(Target::Union), diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs index 86a96f7093587..057d243c6d123 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs @@ -45,7 +45,7 @@ impl AttributeParser for OnUnimplementedParser { }, ), ]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Trait)]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs index fc05ae9150d15..bfa26d993b17e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs @@ -40,7 +40,7 @@ impl AttributeParser for OnUnknownParser { }, )]; // "Allowed" for all targets, but noop for all but use statements. - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Use), Allow(Target::Mod), Allow(Target::Crate), diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs index 44975cd49c93f..18f980bfebbe8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs @@ -33,7 +33,7 @@ impl AttributeParser for OnUnmatchedArgsParser { }, )]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::MacroDef)]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index e91ab584bcf47..988df2b200f86 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -706,8 +706,8 @@ impl AttributeParser for DocParser { }, )]; // FIXME: Currently emitted from 2 different places, generating duplicated warnings. - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); - // const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(ALL_TARGETS); + // const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ // Allow(Target::ExternCrate), // Allow(Target::Use), // Allow(Target::Static), diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs index d436c7f232ec7..83984d48919b7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs +++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs @@ -12,7 +12,7 @@ pub(crate) struct RustcDummyParser; impl SingleAttributeParser for RustcDummyParser { const PATH: &[Symbol] = &[sym::rustc_dummy]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::ManuallyChecked; + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::ManuallyChecked; const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really const STABILITY: AttributeStability = unstable!(rustc_attrs, "the `#[rustc_dummy]` attribute is used for rustc unit tests"); diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index 84b880202a9e6..80328e1c8ef96 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -13,7 +13,7 @@ pub(crate) struct InlineParser; impl SingleAttributeParser for InlineParser { const PATH: &[Symbol] = &[sym::inline]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -66,7 +66,7 @@ pub(crate) struct RustcForceInlineParser; impl SingleAttributeParser for RustcForceInlineParser { const PATH: &[Symbol] = &[sym::rustc_force_inline]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), ]); diff --git a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs index 612d5d33d94e0..3a4bb926f759c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs +++ b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs @@ -8,7 +8,7 @@ pub(crate) struct InstructionSetParser; impl SingleAttributeParser for InstructionSetParser { const PATH: &[Symbol] = &[sym::instruction_set]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Closure), Allow(Target::Method(MethodKind::Inherent)), diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index f260863840080..2357d6846935c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -26,7 +26,7 @@ pub(crate) struct LinkNameParser; impl SingleAttributeParser for LinkNameParser { const PATH: &[Symbol] = &[sym::link_name]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::ForeignFn), Allow(Target::ForeignStatic), ]); @@ -70,7 +70,7 @@ impl CombineAttributeParser for LinkParser { r#"name = "...", import_name_type = "decorated|noprefix|undecorated""#, r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#, ], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute"); - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::ForeignMod)]); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -494,7 +494,7 @@ impl SingleAttributeParser for LinkSectionParser { unsafe_since: Some(Edition2024), }; const STABILITY: AttributeStability = AttributeStability::Stable; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Static), Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -535,7 +535,7 @@ impl SingleAttributeParser for LinkSectionParser { pub(crate) struct ExportStableParser; impl NoArgsAttributeParser for ExportStableParser { const PATH: &[Symbol] = &[sym::export_stable]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Struct), @@ -558,7 +558,8 @@ impl NoArgsAttributeParser for FfiConstParser { note: "`#[ffi_const]` functions shall have no effects except for its return value, which can only depend on the values of the function parameters, and is not affected by changes to the observable state of the program.", unsafe_since: None, }; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const STABILITY: AttributeStability = unstable!(ffi_const); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::FfiConst; } @@ -570,7 +571,8 @@ impl NoArgsAttributeParser for FfiPureParser { note: "`#[ffi_pure]` functions shall have no effects except for its return value, which shall not change across two consecutive function calls with the same parameters.", unsafe_since: None, }; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const STABILITY: AttributeStability = unstable!(ffi_pure); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; } @@ -578,7 +580,7 @@ impl NoArgsAttributeParser for FfiPureParser { pub(crate) struct RustcStdInternalSymbolParser; impl NoArgsAttributeParser for RustcStdInternalSymbolParser { const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::ForeignFn), Allow(Target::Static), @@ -592,7 +594,7 @@ pub(crate) struct LinkOrdinalParser; impl SingleAttributeParser for LinkOrdinalParser { const PATH: &[Symbol] = &[sym::link_ordinal]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::ForeignFn), Allow(Target::ForeignStatic), Warn(Target::MacroCall), @@ -632,7 +634,7 @@ pub(crate) struct LinkageParser; impl SingleAttributeParser for LinkageParser { const PATH: &[Symbol] = &[sym::linkage]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -708,7 +710,7 @@ pub(crate) struct NeedsAllocatorParser; impl NoArgsAttributeParser for NeedsAllocatorParser { const PATH: &[Symbol] = &[sym::needs_allocator]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; } @@ -717,7 +719,7 @@ pub(crate) struct CompilerBuiltinsParser; impl NoArgsAttributeParser for CompilerBuiltinsParser { const PATH: &[Symbol] = &[sym::compiler_builtins]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(compiler_builtins); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CompilerBuiltins; } diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 75a07e868129e..38afeea07794a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -5,7 +5,7 @@ use super::prelude::*; pub(crate) struct RustcAsPtrParser; impl NoArgsAttributeParser for RustcAsPtrParser { const PATH: &[Symbol] = &[sym::rustc_as_ptr]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -19,7 +19,7 @@ impl NoArgsAttributeParser for RustcAsPtrParser { pub(crate) struct RustcPubTransparentParser; impl NoArgsAttributeParser for RustcPubTransparentParser { const PATH: &[Symbol] = &[sym::rustc_pub_transparent]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), Allow(Target::Union), @@ -31,7 +31,7 @@ impl NoArgsAttributeParser for RustcPubTransparentParser { pub(crate) struct RustcPassByValueParser; impl NoArgsAttributeParser for RustcPassByValueParser { const PATH: &[Symbol] = &[sym::rustc_pass_by_value]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), Allow(Target::TyAlias), @@ -43,7 +43,7 @@ impl NoArgsAttributeParser for RustcPassByValueParser { pub(crate) struct RustcShouldNotBeCalledOnConstItemsParser; impl NoArgsAttributeParser for RustcShouldNotBeCalledOnConstItemsParser { const PATH: &[Symbol] = &[sym::rustc_should_not_be_called_on_const_items]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::TraitImpl)), ]); @@ -55,7 +55,7 @@ pub(crate) struct AutomaticallyDerivedParser; impl NoArgsAttributeParser for AutomaticallyDerivedParser { const PATH: &[Symbol] = &[sym::automatically_derived]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Impl { of_trait: true }), Error(Target::Crate), Error(Target::WherePredicate), diff --git a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs index 06c3cd286a06e..e46d2edaa49ba 100644 --- a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs +++ b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs @@ -5,7 +5,7 @@ use super::prelude::*; pub(crate) struct LoopMatchParser; impl NoArgsAttributeParser for LoopMatchParser { const PATH: &[Symbol] = &[sym::loop_match]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Loop)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Loop)]); const STABILITY: AttributeStability = unstable!(loop_match); const CREATE: fn(Span) -> AttributeKind = AttributeKind::LoopMatch; } @@ -13,7 +13,7 @@ impl NoArgsAttributeParser for LoopMatchParser { pub(crate) struct ConstContinueParser; impl NoArgsAttributeParser for ConstContinueParser { const PATH: &[Symbol] = &[sym::const_continue]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Break)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Break)]); const STABILITY: AttributeStability = unstable!(loop_match); const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstContinue; } diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 8ad202bad3d84..f49a7e674d560 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -8,7 +8,7 @@ pub(crate) struct MacroEscapeParser; impl NoArgsAttributeParser for MacroEscapeParser { const PATH: &[Symbol] = &[sym::macro_escape]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = MACRO_USE_ALLOWED_TARGETS; const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::MacroEscape; } @@ -32,7 +32,7 @@ const MACRO_USE_TEMPLATE: AttributeTemplate = template!( Word, List: &["name1, name2, ..."], "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute" ); -const MACRO_USE_ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ +const MACRO_USE_ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Mod), Allow(Target::ExternCrate), Error(Target::WherePredicate), @@ -106,7 +106,7 @@ impl AttributeParser for MacroUseParser { } }, )]; - const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = MACRO_USE_ALLOWED_TARGETS; fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state }) @@ -118,7 +118,7 @@ pub(crate) struct AllowInternalUnsafeParser; impl NoArgsAttributeParser for AllowInternalUnsafeParser { const PATH: &[Symbol] = &[sym::allow_internal_unsafe]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::MacroDef), Warn(Target::Field), @@ -134,7 +134,7 @@ impl SingleAttributeParser for MacroExportParser { const PATH: &[Symbol] = &[sym::macro_export]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; const TEMPLATE: AttributeTemplate = template!(Word, List: &["local_inner_macros"]); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::MacroDef), Error(Target::WherePredicate), Error(Target::Crate), @@ -174,7 +174,8 @@ impl SingleAttributeParser for CollapseDebugInfoParser { List: &["no", "external", "yes"], "https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute" ); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); const STABILITY: AttributeStability = AttributeStability::Stable; fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -204,7 +205,7 @@ pub(crate) struct RustcProcMacroDeclsParser; impl NoArgsAttributeParser for RustcProcMacroDeclsParser { const PATH: &[Symbol] = &[sym::rustc_proc_macro_decls]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Static)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcProcMacroDecls; } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 5c64e9f2eaed6..17aaa6ddf9333 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -105,7 +105,7 @@ pub(crate) trait AttributeParser: Default + 'static { /// /// If an attribute has this symbol, the `accept` function will be called on it. const ATTRIBUTES: AcceptMapping; - const ALLOWED_TARGETS: AllowedTargets; + const ALLOWED_TARGETS: AllowedTargets<'_>; const SAFETY: AttributeSafety = AttributeSafety::Normal; /// The parser has gotten a chance to accept the attributes on an item, @@ -140,7 +140,7 @@ pub(crate) trait SingleAttributeParser: 'static { const SAFETY: AttributeSafety = AttributeSafety::Normal; const STABILITY: AttributeStability; - const ALLOWED_TARGETS: AllowedTargets; + const ALLOWED_TARGETS: AllowedTargets<'_>; /// The template this attribute parser should implement. Used for diagnostics. const TEMPLATE: AttributeTemplate; @@ -174,7 +174,7 @@ impl AttributeParser for Single { } }, )]; - const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = T::ALLOWED_TARGETS; const SAFETY: AttributeSafety = T::SAFETY; fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { @@ -252,7 +252,7 @@ pub enum AttributeSafety { pub(crate) trait NoArgsAttributeParser: 'static { const PATH: &[Symbol]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets; + const ALLOWED_TARGETS: AllowedTargets<'_>; const SAFETY: AttributeSafety = AttributeSafety::Normal; const STABILITY: AttributeStability; @@ -273,7 +273,7 @@ impl SingleAttributeParser for WithoutArgs { const ON_DUPLICATE: OnDuplicate = T::ON_DUPLICATE; const SAFETY: AttributeSafety = T::SAFETY; const STABILITY: AttributeStability = T::STABILITY; - const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = T::ALLOWED_TARGETS; const TEMPLATE: AttributeTemplate = template!(Word); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -303,7 +303,7 @@ pub(crate) trait CombineAttributeParser: 'static { const SAFETY: AttributeSafety = AttributeSafety::Normal; const STABILITY: AttributeStability; - const ALLOWED_TARGETS: AllowedTargets; + const ALLOWED_TARGETS: AllowedTargets<'_>; /// The template this attribute parser should implement. Used for diagnostics. const TEMPLATE: AttributeTemplate; @@ -342,7 +342,7 @@ impl AttributeParser for Combine { group.first_span.get_or_insert(cx.attr_span); group.items.extend(T::extend(cx, args)) })]; - const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = T::ALLOWED_TARGETS; const SAFETY: AttributeSafety = T::SAFETY; fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { diff --git a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs index 25fdd5fb3e086..c7c302dd9ee2d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs @@ -6,7 +6,7 @@ pub(crate) struct MustNotSuspendParser; impl SingleAttributeParser for MustNotSuspendParser { const PATH: &[rustc_span::Symbol] = &[sym::must_not_suspend]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), Allow(Target::Union), diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs index ae41efd769ed0..62e75a2e7afd9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs @@ -7,7 +7,7 @@ pub(crate) struct MustUseParser; impl SingleAttributeParser for MustUseParser { const PATH: &[Symbol] = &[sym::must_use]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Enum), Allow(Target::Struct), diff --git a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs index ce172bc41beee..34ceca9092036 100644 --- a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs +++ b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs @@ -7,7 +7,7 @@ pub(crate) struct NoImplicitPreludeParser; impl NoArgsAttributeParser for NoImplicitPreludeParser { const PATH: &[rustc_span::Symbol] = &[sym::no_implicit_prelude]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoImplicitPrelude; diff --git a/compiler/rustc_attr_parsing/src/attributes/no_link.rs b/compiler/rustc_attr_parsing/src/attributes/no_link.rs index d067db5df81e6..772ebb6b34f69 100644 --- a/compiler/rustc_attr_parsing/src/attributes/no_link.rs +++ b/compiler/rustc_attr_parsing/src/attributes/no_link.rs @@ -6,7 +6,7 @@ pub(crate) struct NoLinkParser; impl NoArgsAttributeParser for NoLinkParser { const PATH: &[Symbol] = &[sym::no_link]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::ExternCrate), Warn(Target::Field), Warn(Target::Arm), diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs index c4cc47e593a6a..cbbaad445f70f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs +++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs @@ -12,7 +12,7 @@ pub(crate) struct NonExhaustiveParser; impl NoArgsAttributeParser for NonExhaustiveParser { const PATH: &[Symbol] = &[sym::non_exhaustive]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Enum), Allow(Target::Struct), Allow(Target::Variant), diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs index 57114d850dba8..ad4641c4be7f2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/path.rs +++ b/compiler/rustc_attr_parsing/src/attributes/path.rs @@ -7,7 +7,7 @@ pub(crate) struct PathParser; impl SingleAttributeParser for PathParser { const PATH: &[Symbol] = &[sym::path]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Error(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!( NameValueStr: "file", diff --git a/compiler/rustc_attr_parsing/src/attributes/pin_v2.rs b/compiler/rustc_attr_parsing/src/attributes/pin_v2.rs index ba84b6f8e98c4..59c35690d3c93 100644 --- a/compiler/rustc_attr_parsing/src/attributes/pin_v2.rs +++ b/compiler/rustc_attr_parsing/src/attributes/pin_v2.rs @@ -12,7 +12,7 @@ pub(crate) struct PinV2Parser; impl NoArgsAttributeParser for PinV2Parser { const PATH: &[Symbol] = &[sym::pin_v2]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Enum), Allow(Target::Struct), Allow(Target::Union), diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs index 887eb668d65ab..8b2720d2a9ca5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -3,13 +3,13 @@ use rustc_session::lint::builtin::AMBIGUOUS_DERIVE_HELPERS; use super::prelude::*; -const PROC_MACRO_ALLOWED_TARGETS: AllowedTargets = +const PROC_MACRO_ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate), Warn(Target::MacroCall)]); pub(crate) struct ProcMacroParser; impl NoArgsAttributeParser for ProcMacroParser { const PATH: &[Symbol] = &[sym::proc_macro]; - const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = PROC_MACRO_ALLOWED_TARGETS; const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProcMacro; } @@ -17,7 +17,7 @@ impl NoArgsAttributeParser for ProcMacroParser { pub(crate) struct ProcMacroAttributeParser; impl NoArgsAttributeParser for ProcMacroAttributeParser { const PATH: &[Symbol] = &[sym::proc_macro_attribute]; - const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = PROC_MACRO_ALLOWED_TARGETS; const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProcMacroAttribute; } @@ -25,7 +25,7 @@ impl NoArgsAttributeParser for ProcMacroAttributeParser { pub(crate) struct ProcMacroDeriveParser; impl SingleAttributeParser for ProcMacroDeriveParser { const PATH: &[Symbol] = &[sym::proc_macro_derive]; - const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = PROC_MACRO_ALLOWED_TARGETS; const TEMPLATE: AttributeTemplate = template!( List: &["TraitName", "TraitName, attributes(name1, name2, ...)"], "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros" @@ -44,7 +44,8 @@ impl SingleAttributeParser for ProcMacroDeriveParser { pub(crate) struct RustcBuiltinMacroParser; impl SingleAttributeParser for RustcBuiltinMacroParser { const PATH: &[Symbol] = &[sym::rustc_builtin_macro]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); const TEMPLATE: AttributeTemplate = template!(List: &["TraitName", "TraitName, attributes(name1, name2, ...)"]); const STABILITY: AttributeStability = unstable!(rustc_attrs); diff --git a/compiler/rustc_attr_parsing/src/attributes/prototype.rs b/compiler/rustc_attr_parsing/src/attributes/prototype.rs index ddc40e62a7e8e..a41010395e7c1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prototype.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prototype.rs @@ -18,7 +18,7 @@ impl SingleAttributeParser for CustomMirParser { const PATH: &[rustc_span::Symbol] = &[sym::custom_mir]; const STABILITY: AttributeStability = unstable!(custom_mir); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!(List: &[r#"dialect = "...", phase = "...""#]); diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index b6e63de1a2095..bf03d87942651 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -63,7 +63,7 @@ impl CombineAttributeParser for ReprParser { reprs } - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::ManuallyChecked; + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::ManuallyChecked; const STABILITY: AttributeStability = AttributeStability::Stable; } @@ -306,7 +306,7 @@ impl RustcAlignParser { impl AttributeParser for RustcAlignParser { const ATTRIBUTES: AcceptMapping = &[(Self::PATH, Self::TEMPLATE, unstable!(fn_align), Self::parse)]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -336,7 +336,7 @@ impl RustcAlignStaticParser { impl AttributeParser for RustcAlignStaticParser { const ATTRIBUTES: AcceptMapping = &[(Self::PATH, Self::TEMPLATE, unstable!(static_align), Self::parse)]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs index cacf98bef6e93..467289d78da9b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs @@ -6,7 +6,7 @@ pub(crate) struct RustcAllocatorParser; impl NoArgsAttributeParser for RustcAllocatorParser { const PATH: &[Symbol] = &[sym::rustc_allocator]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocator; @@ -16,7 +16,7 @@ pub(crate) struct RustcAllocatorZeroedParser; impl NoArgsAttributeParser for RustcAllocatorZeroedParser { const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocatorZeroed; @@ -26,7 +26,7 @@ pub(crate) struct RustcAllocatorZeroedVariantParser; impl SingleAttributeParser for RustcAllocatorZeroedVariantParser { const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed_variant]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "function"); const STABILITY: AttributeStability = unstable!(rustc_attrs); @@ -42,7 +42,7 @@ pub(crate) struct RustcDeallocatorParser; impl NoArgsAttributeParser for RustcDeallocatorParser { const PATH: &[Symbol] = &[sym::rustc_deallocator]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDeallocator; @@ -52,7 +52,7 @@ pub(crate) struct RustcReallocatorParser; impl NoArgsAttributeParser for RustcReallocatorParser { const PATH: &[Symbol] = &[sym::rustc_reallocator]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcReallocator; diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index acd5b465a80fe..0fd3d5d65e3a5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -10,7 +10,7 @@ pub(crate) struct RustcDumpUserArgsParser; impl NoArgsAttributeParser for RustcDumpUserArgsParser { const PATH: &[Symbol] = &[sym::rustc_dump_user_args]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpUserArgs; } @@ -19,7 +19,7 @@ pub(crate) struct RustcDumpDefParentsParser; impl NoArgsAttributeParser for RustcDumpDefParentsParser { const PATH: &[Symbol] = &[sym::rustc_dump_def_parents]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents; } @@ -28,7 +28,7 @@ pub(crate) struct RustcDumpDefPathParser; impl SingleAttributeParser for RustcDumpDefPathParser { const PATH: &[Symbol] = &[sym::rustc_dump_def_path]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::TraitImpl)), Allow(Target::Method(MethodKind::Inherent)), @@ -49,7 +49,7 @@ pub(crate) struct RustcDumpGenericsParser; impl NoArgsAttributeParser for RustcDumpGenericsParser { const PATH: &[Symbol] = &[sym::rustc_dump_generics]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), Allow(Target::Union), @@ -78,7 +78,7 @@ pub(crate) struct RustcDumpHiddenTypeOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpHiddenTypeOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_hidden_type_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpHiddenTypeOfOpaques; } @@ -87,7 +87,7 @@ pub(crate) struct RustcDumpInferredOutlivesParser; impl NoArgsAttributeParser for RustcDumpInferredOutlivesParser { const PATH: &[Symbol] = &[sym::rustc_dump_inferred_outlives]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), Allow(Target::Union), @@ -101,7 +101,8 @@ pub(crate) struct RustcDumpItemBoundsParser; impl NoArgsAttributeParser for RustcDumpItemBoundsParser { const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocTy)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::AssocTy)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds; } @@ -115,7 +116,7 @@ impl CombineAttributeParser for RustcDumpLayoutParser { const CONVERT: ConvertFn = |items, _| AttributeKind::RustcDumpLayout(items); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::Enum), Allow(Target::Union), @@ -174,7 +175,7 @@ pub(crate) struct RustcDumpObjectLifetimeDefaultsParser; impl NoArgsAttributeParser for RustcDumpObjectLifetimeDefaultsParser { const PATH: &[Symbol] = &[sym::rustc_dump_object_lifetime_defaults]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::AssocConst), Allow(Target::AssocTy), Allow(Target::Const), @@ -201,7 +202,7 @@ pub(crate) struct RustcDumpPredicatesParser; impl NoArgsAttributeParser for RustcDumpPredicatesParser { const PATH: &[Symbol] = &[sym::rustc_dump_predicates]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::AssocConst), Allow(Target::AssocTy), Allow(Target::Const), @@ -229,7 +230,7 @@ pub(crate) struct RustcDumpSymbolNameParser; impl SingleAttributeParser for RustcDumpSymbolNameParser { const PATH: &[Symbol] = &[sym::rustc_dump_symbol_name]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::TraitImpl)), Allow(Target::Method(MethodKind::Inherent)), @@ -250,7 +251,7 @@ pub(crate) struct RustcDumpVariancesParser; impl NoArgsAttributeParser for RustcDumpVariancesParser { const PATH: &[Symbol] = &[sym::rustc_dump_variances]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Enum), Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), @@ -271,7 +272,7 @@ pub(crate) struct RustcDumpVariancesOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpVariancesOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques; } @@ -280,7 +281,7 @@ pub(crate) struct RustcDumpVtableParser; impl NoArgsAttributeParser for RustcDumpVtableParser { const PATH: &[Symbol] = &[sym::rustc_dump_vtable]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Impl { of_trait: true }), Allow(Target::TyAlias), ]); diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 6552c9de7c5a5..d4e15b8964ff7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -12,6 +12,7 @@ use rustc_span::Symbol; use super::prelude::*; use super::util::parse_single_integer; use crate::diagnostics; +use crate::diagnostics::UnknownExternLangItem; use crate::session_diagnostics::{ AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, UnknownLangItem, }; @@ -20,7 +21,7 @@ pub(crate) struct RustcMainParser; impl NoArgsAttributeParser for RustcMainParser { const PATH: &[Symbol] = &[sym::rustc_main]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const STABILITY: AttributeStability = unstable!( rustc_attrs, "the `#[rustc_main]` attribute is used internally to specify test entry point function" @@ -32,7 +33,7 @@ pub(crate) struct RustcMustImplementOneOfParser; impl SingleAttributeParser for RustcMustImplementOneOfParser { const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!( rustc_attrs, "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait. Its syntax and semantics are highly experimental and will be subject to change before stabilization" @@ -78,7 +79,7 @@ pub(crate) struct RustcNeverReturnsNullPtrParser; impl NoArgsAttributeParser for RustcNeverReturnsNullPtrParser { const PATH: &[Symbol] = &[sym::rustc_never_returns_null_ptr]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -93,7 +94,7 @@ pub(crate) struct RustcNoImplicitAutorefsParser; impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser { const PATH: &[Symbol] = &[sym::rustc_no_implicit_autorefs]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -109,7 +110,7 @@ pub(crate) struct RustcLegacyConstGenericsParser; impl SingleAttributeParser for RustcLegacyConstGenericsParser { const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!(List: &["N"]); const STABILITY: AttributeStability = unstable!(rustc_attrs); @@ -149,7 +150,7 @@ pub(crate) struct RustcInheritOverflowChecksParser; impl NoArgsAttributeParser for RustcInheritOverflowChecksParser { const PATH: &[Symbol] = &[sym::rustc_inherit_overflow_checks]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::TraitImpl)), @@ -163,7 +164,7 @@ pub(crate) struct RustcLintOptDenyFieldAccessParser; impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser { const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Field)]); const TEMPLATE: AttributeTemplate = template!(Word); const STABILITY: AttributeStability = unstable!(rustc_attrs); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -178,7 +179,7 @@ pub(crate) struct RustcLintOptTyParser; impl NoArgsAttributeParser for RustcLintOptTyParser { const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy; } @@ -305,7 +306,7 @@ impl AttributeParser for RustcCguTestAttributeParser { ), ]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { @@ -317,7 +318,7 @@ pub(crate) struct RustcDeprecatedSafe2024Parser; impl SingleAttributeParser for RustcDeprecatedSafe2024Parser { const PATH: &[Symbol] = &[sym::rustc_deprecated_safe_2024]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -347,7 +348,7 @@ pub(crate) struct RustcConversionSuggestionParser; impl NoArgsAttributeParser for RustcConversionSuggestionParser { const PATH: &[Symbol] = &[sym::rustc_conversion_suggestion]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -362,7 +363,8 @@ pub(crate) struct RustcCaptureAnalysisParser; impl NoArgsAttributeParser for RustcCaptureAnalysisParser { const PATH: &[Symbol] = &[sym::rustc_capture_analysis]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::Closure)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis; } @@ -371,7 +373,7 @@ pub(crate) struct RustcNeverTypeOptionsParser; impl SingleAttributeParser for RustcNeverTypeOptionsParser { const PATH: &[Symbol] = &[sym::rustc_never_type_options]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[ r#"fallback = "unit", "never", "no""#, r#"diverging_block_default = "unit", "never""#, @@ -444,7 +446,7 @@ pub(crate) struct RustcTrivialFieldReadsParser; impl NoArgsAttributeParser for RustcTrivialFieldReadsParser { const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads; } @@ -453,7 +455,7 @@ pub(crate) struct RustcNoMirInlineParser; impl NoArgsAttributeParser for RustcNoMirInlineParser { const PATH: &[Symbol] = &[sym::rustc_no_mir_inline]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -469,7 +471,7 @@ pub(crate) struct RustcNoWritableParser; impl NoArgsAttributeParser for RustcNoWritableParser { const PATH: &[Symbol] = &[sym::rustc_no_writable]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Closure), Allow(Target::Method(MethodKind::Inherent)), @@ -484,7 +486,7 @@ pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { const PATH: &[Symbol] = &[sym::rustc_lint_query_instability]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -499,7 +501,7 @@ pub(crate) struct RustcRegionsParser; impl NoArgsAttributeParser for RustcRegionsParser { const PATH: &[Symbol] = &[sym::rustc_regions]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -514,7 +516,7 @@ pub(crate) struct RustcLintUntrackedQueryInformationParser; impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser { const PATH: &[Symbol] = &[sym::rustc_lint_untracked_query_information]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: false })), @@ -529,7 +531,7 @@ pub(crate) struct RustcSimdMonomorphizeLaneLimitParser; impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser { const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); const STABILITY: AttributeStability = unstable!(rustc_attrs); @@ -543,7 +545,7 @@ pub(crate) struct RustcScalableVectorParser; impl SingleAttributeParser for RustcScalableVectorParser { const PATH: &[Symbol] = &[sym::rustc_scalable_vector]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]); const STABILITY: AttributeStability = unstable!(rustc_attrs); @@ -565,7 +567,7 @@ pub(crate) struct LangParser; impl SingleAttributeParser for LangParser { const PATH: &[Symbol] = &[sym::lang]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes` + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::ManuallyChecked; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); const STABILITY: AttributeStability = unstable!(lang_items); @@ -576,6 +578,24 @@ impl SingleAttributeParser for LangParser { cx.emit_err(UnknownLangItem { span: cx.attr_span, name }); return None; }; + + // Only weak lang items may be applied to foreign items + if [Target::ForeignFn, Target::ForeignStatic, Target::ForeignTy, Target::ForeignMod] + .contains(&cx.target) + && !lang_item.is_weak() + { + cx.emit_err(UnknownExternLangItem { span: cx.attr_span, lang_item: lang_item.name() }); + return None; + } + + // Check the target + let allowed_targets: &[_] = if lang_item == LangItem::PanicImpl { + &[Allow(Target::Fn), Allow(Target::ForeignFn)] + } else { + &[Allow(lang_item.target())] + }; + cx.check_target(&format!(" = \"{name}\""), &AllowedTargets::AllowList(allowed_targets)); + Some(AttributeKind::Lang(lang_item)) } } @@ -584,7 +604,7 @@ pub(crate) struct RustcHasIncoherentInherentImplsParser; impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParser { const PATH: &[Symbol] = &[sym::rustc_has_incoherent_inherent_impls]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Trait), Allow(Target::Struct), Allow(Target::Enum), @@ -599,7 +619,7 @@ pub(crate) struct PanicHandlerParser; impl NoArgsAttributeParser for PanicHandlerParser { const PATH: &[Symbol] = &[sym::panic_handler]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes` + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Lang(LangItem::PanicImpl); } @@ -608,7 +628,7 @@ pub(crate) struct RustcNounwindParser; impl NoArgsAttributeParser for RustcNounwindParser { const PATH: &[Symbol] = &[sym::rustc_nounwind]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::ForeignFn), Allow(Target::Method(MethodKind::Inherent)), @@ -623,7 +643,7 @@ pub(crate) struct RustcOffloadKernelParser; impl NoArgsAttributeParser for RustcOffloadKernelParser { const PATH: &[Symbol] = &[sym::rustc_offload_kernel]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel; } @@ -636,7 +656,7 @@ impl CombineAttributeParser for RustcMirParser { type Item = RustcMirKind; const CONVERT: ConvertFn = |items, _| AttributeKind::RustcMir(items); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::TraitImpl)), @@ -712,7 +732,7 @@ pub(crate) struct RustcNonConstTraitMethodParser; impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::Trait { body: false })), ]); @@ -731,7 +751,7 @@ impl CombineAttributeParser for RustcCleanParser { type Item = RustcCleanAttribute; const CONVERT: ConvertFn = |items, _| AttributeKind::RustcClean(items); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ // tidy-alphabetical-start Allow(Target::AssocConst), Allow(Target::AssocTy), @@ -824,7 +844,7 @@ pub(crate) struct RustcIfThisChangedParser; impl SingleAttributeParser for RustcIfThisChangedParser { const PATH: &[Symbol] = &[sym::rustc_if_this_changed]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ // tidy-alphabetical-start Allow(Target::AssocConst), Allow(Target::AssocTy), @@ -882,7 +902,7 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { const CONVERT: ConvertFn = |items, _span| AttributeKind::RustcThenThisWouldNeed(items); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ // tidy-alphabetical-start Allow(Target::AssocConst), Allow(Target::AssocTy), @@ -929,7 +949,7 @@ pub(crate) struct RustcInsignificantDtorParser; impl NoArgsAttributeParser for RustcInsignificantDtorParser { const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Enum), Allow(Target::Struct), Allow(Target::ForeignTy), @@ -942,7 +962,7 @@ pub(crate) struct RustcEffectiveVisibilityParser; impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { const PATH: &[Symbol] = &[sym::rustc_effective_visibility]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Use), Allow(Target::Static), Allow(Target::Const), @@ -981,7 +1001,7 @@ pub(crate) struct RustcDiagnosticItemParser; impl SingleAttributeParser for RustcDiagnosticItemParser { const PATH: &[Symbol] = &[sym::rustc_diagnostic_item]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Trait), Allow(Target::Struct), Allow(Target::Enum), @@ -1016,7 +1036,7 @@ pub(crate) struct RustcDoNotConstCheckParser; impl NoArgsAttributeParser for RustcDoNotConstCheckParser { const PATH: &[Symbol] = &[sym::rustc_do_not_const_check]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::TraitImpl)), @@ -1034,7 +1054,7 @@ pub(crate) struct RustcNonnullOptimizationGuaranteedParser; impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser { const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const STABILITY: AttributeStability = unstable!( rustc_attrs, "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in the standard library", @@ -1047,7 +1067,7 @@ pub(crate) struct RustcStrictCoherenceParser; impl NoArgsAttributeParser for RustcStrictCoherenceParser { const PATH: &[Symbol] = &[sym::rustc_strict_coherence]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Trait), Allow(Target::Struct), Allow(Target::Enum), @@ -1062,7 +1082,7 @@ pub(crate) struct RustcReservationImplParser; impl SingleAttributeParser for RustcReservationImplParser { const PATH: &[Symbol] = &[sym::rustc_reservation_impl]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "reservation message"); const STABILITY: AttributeStability = unstable!(rustc_attrs); @@ -1079,7 +1099,7 @@ pub(crate) struct PreludeImportParser; impl NoArgsAttributeParser for PreludeImportParser { const PATH: &[Symbol] = &[sym::prelude_import]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Use)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Use)]); const STABILITY: AttributeStability = unstable!(prelude_import); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport; } @@ -1088,7 +1108,7 @@ pub(crate) struct RustcDocPrimitiveParser; impl SingleAttributeParser for RustcDocPrimitiveParser { const PATH: &[Symbol] = &[sym::rustc_doc_primitive]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Mod)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name"); const STABILITY: AttributeStability = unstable!( rustc_attrs, @@ -1107,7 +1127,7 @@ pub(crate) struct RustcIntrinsicParser; impl NoArgsAttributeParser for RustcIntrinsicParser { const PATH: &[Symbol] = &[sym::rustc_intrinsic]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const STABILITY: AttributeStability = unstable!(intrinsics); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic; } @@ -1116,7 +1136,7 @@ pub(crate) struct RustcIntrinsicConstStableIndirectParser; impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser { const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect; } @@ -1125,7 +1145,7 @@ pub(crate) struct RustcExhaustiveParser; impl NoArgsAttributeParser for RustcExhaustiveParser { const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Enum)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Enum)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively; } diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs index 07c07eb6681df..74b2cc2ffd5a1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -5,7 +5,7 @@ use super::prelude::*; pub(crate) struct MayDangleParser; impl NoArgsAttributeParser for MayDangleParser { const PATH: &[Symbol] = &[sym::may_dangle]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` const STABILITY: AttributeStability = unstable!(dropck_eyepatch); const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle; } @@ -14,7 +14,7 @@ pub(crate) struct ComptimeParser; impl NoArgsAttributeParser for ComptimeParser { const PATH: &[Symbol] = &[sym::rustc_comptime]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Fn), ]); diff --git a/compiler/rustc_attr_parsing/src/attributes/splat.rs b/compiler/rustc_attr_parsing/src/attributes/splat.rs index 65fc9fb8123f4..ab34021ad7cdf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/splat.rs +++ b/compiler/rustc_attr_parsing/src/attributes/splat.rs @@ -9,7 +9,7 @@ pub(crate) struct SplatParser; impl NoArgsAttributeParser for SplatParser { const PATH: &[Symbol] = &[sym::splat]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Param)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Param)]); const STABILITY: AttributeStability = unstable!(splat, "the `#[splat]` attribute is experimental"); const CREATE: fn(Span) -> AttributeKind = AttributeKind::Splat; diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index b38bb6d535770..d8dbe167ed175 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -13,7 +13,7 @@ use super::prelude::*; use super::util::parse_version; use crate::session_diagnostics; -const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ +const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Struct), Allow(Target::Enum), @@ -102,7 +102,7 @@ impl AttributeParser for StabilityParser { }, ), ]; - const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = ALLOWED_TARGETS; fn finalize(mut self, cx: &FinalizeContext<'_, '_>) -> Option { if let Some(atum) = self.allowed_through_unstable_modules { @@ -158,7 +158,7 @@ impl AttributeParser for BodyStabilityParser { } }, )]; - const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets<'_> = ALLOWED_TARGETS; fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { let (stability, span) = self.stability?; @@ -171,7 +171,7 @@ pub(crate) struct RustcConstStableIndirectParser; impl NoArgsAttributeParser for RustcConstStableIndirectParser { const PATH: &[Symbol] = &[sym::rustc_const_stable_indirect]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), ]); @@ -233,7 +233,7 @@ impl AttributeParser for ConstStabilityParser { this.promotable = true; }), ]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::TraitImpl)), @@ -460,7 +460,7 @@ pub(crate) struct UnstableRemovedParser; impl CombineAttributeParser for UnstableRemovedParser { type Item = UnstableRemovedFeature; const PATH: &[Symbol] = &[sym::unstable_removed]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[r#"feature = "name", reason = "...", link = "...", since = "version""#]); const STABILITY: AttributeStability = unstable!(staged_api); diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 00e113f171715..8905591bdba5a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -9,7 +9,7 @@ pub(crate) struct IgnoreParser; impl SingleAttributeParser for IgnoreParser { const PATH: &[Symbol] = &[sym::ignore]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]); const TEMPLATE: AttributeTemplate = template!( Word, NameValueStr: "reason", @@ -51,7 +51,7 @@ pub(crate) struct ShouldPanicParser; impl SingleAttributeParser for ShouldPanicParser { const PATH: &[Symbol] = &[sym::should_panic]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]); const TEMPLATE: AttributeTemplate = template!( Word, List: &[r#"expected = "reason""#], NameValueStr: "reason", @@ -83,7 +83,7 @@ pub(crate) struct ReexportTestHarnessMainParser; impl SingleAttributeParser for ReexportTestHarnessMainParser { const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); @@ -105,7 +105,7 @@ pub(crate) struct RustcAbiParser; impl SingleAttributeParser for RustcAbiParser { const PATH: &[Symbol] = &[sym::rustc_abi]; const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::debug, sym::assert_eq]); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::TyAlias), Allow(Target::Fn), Allow(Target::ForeignFn), @@ -150,7 +150,7 @@ pub(crate) struct RustcDelayedBugFromInsideQueryParser; impl NoArgsAttributeParser for RustcDelayedBugFromInsideQueryParser { const PATH: &[Symbol] = &[sym::rustc_delayed_bug_from_inside_query]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDelayedBugFromInsideQuery; } @@ -159,7 +159,7 @@ pub(crate) struct RustcEvaluateWhereClausesParser; impl NoArgsAttributeParser for RustcEvaluateWhereClausesParser { const PATH: &[Symbol] = &[sym::rustc_evaluate_where_clauses]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), @@ -174,7 +174,7 @@ pub(crate) struct TestRunnerParser; impl SingleAttributeParser for TestRunnerParser { const PATH: &[Symbol] = &[sym::test_runner]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["path"]); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); @@ -194,7 +194,7 @@ pub(crate) struct RustcTestMarkerParser; impl SingleAttributeParser for RustcTestMarkerParser { const PATH: &[Symbol] = &[sym::rustc_test_marker]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Const), Allow(Target::Fn), Allow(Target::Static), diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index 505cdea2477bf..a2348eef975cf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -12,7 +12,7 @@ use crate::target_checking::Policy::{Allow, Warn}; pub(crate) struct RustcSkipDuringMethodDispatchParser; impl SingleAttributeParser for RustcSkipDuringMethodDispatchParser { const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const TEMPLATE: AttributeTemplate = template!(List: &["array, boxed_slice"]); const STABILITY: AttributeStability = unstable!(rustc_attrs); @@ -52,7 +52,7 @@ impl SingleAttributeParser for RustcSkipDuringMethodDispatchParser { pub(crate) struct RustcParenSugarParser; impl NoArgsAttributeParser for RustcParenSugarParser { const PATH: &[Symbol] = &[sym::rustc_paren_sugar]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcParenSugar; } @@ -62,7 +62,7 @@ impl NoArgsAttributeParser for RustcParenSugarParser { pub(crate) struct MarkerParser; impl NoArgsAttributeParser for MarkerParser { const PATH: &[Symbol] = &[sym::marker]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Trait), Warn(Target::Field), Warn(Target::Arm), @@ -75,7 +75,7 @@ impl NoArgsAttributeParser for MarkerParser { pub(crate) struct RustcDenyExplicitImplParser; impl NoArgsAttributeParser for RustcDenyExplicitImplParser { const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDenyExplicitImpl; } @@ -83,7 +83,7 @@ impl NoArgsAttributeParser for RustcDenyExplicitImplParser { pub(crate) struct RustcDynIncompatibleTraitParser; impl NoArgsAttributeParser for RustcDynIncompatibleTraitParser { const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDynIncompatibleTrait; } @@ -93,7 +93,7 @@ impl NoArgsAttributeParser for RustcDynIncompatibleTraitParser { pub(crate) struct RustcSpecializationTraitParser; impl NoArgsAttributeParser for RustcSpecializationTraitParser { const PATH: &[Symbol] = &[sym::rustc_specialization_trait]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcSpecializationTrait; } @@ -101,7 +101,7 @@ impl NoArgsAttributeParser for RustcSpecializationTraitParser { pub(crate) struct RustcUnsafeSpecializationMarkerParser; impl NoArgsAttributeParser for RustcUnsafeSpecializationMarkerParser { const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcUnsafeSpecializationMarker; } @@ -111,7 +111,7 @@ impl NoArgsAttributeParser for RustcUnsafeSpecializationMarkerParser { pub(crate) struct RustcCoinductiveParser; impl NoArgsAttributeParser for RustcCoinductiveParser { const PATH: &[Symbol] = &[sym::rustc_coinductive]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoinductive; } @@ -119,7 +119,7 @@ impl NoArgsAttributeParser for RustcCoinductiveParser { pub(crate) struct RustcAllowIncoherentImplParser; impl NoArgsAttributeParser for RustcAllowIncoherentImplParser { const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAllowIncoherentImpl; @@ -128,7 +128,7 @@ impl NoArgsAttributeParser for RustcAllowIncoherentImplParser { pub(crate) struct FundamentalParser; impl NoArgsAttributeParser for FundamentalParser { const PATH: &[Symbol] = &[sym::fundamental]; - const ALLOWED_TARGETS: AllowedTargets = + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(fundamental); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental; diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index ad40f30ef418a..7f5cceb501acd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -11,7 +11,8 @@ impl SingleAttributeParser for RustcMacroTransparencyParser { cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes"); }); const STABILITY: AttributeStability = unstable!(rustc_attrs); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["transparent", "semiopaque", "opaque"]); diff --git a/compiler/rustc_attr_parsing/src/attributes/unroll.rs b/compiler/rustc_attr_parsing/src/attributes/unroll.rs index b10ddcf9dc4fc..50c73ca041cdd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/unroll.rs +++ b/compiler/rustc_attr_parsing/src/attributes/unroll.rs @@ -7,7 +7,7 @@ use super::prelude::*; pub(crate) struct UnrollParser; impl SingleAttributeParser for UnrollParser { const PATH: &[Symbol] = &[sym::unroll]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Loop), Allow(Target::ForLoop), Allow(Target::While), diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 14e443c922711..1595d2f80ddc7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -85,7 +85,7 @@ pub(super) struct GroupTypeInner { pub(super) struct GroupTypeInnerAccept { pub(super) template: AttributeTemplate, pub(super) accept_fn: AcceptFn, - pub(super) allowed_targets: AllowedTargets, + pub(super) allowed_targets: AllowedTargets<'static>, pub(super) safety: AttributeSafety, pub(super) stability: AttributeStability, pub(super) finalizer: FinalizeFn, diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index b22fe88a4de3d..d8b7144aa01ba 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1,4 +1,4 @@ -use rustc_errors::{Applicability, DiagArgValue, E0232, MultiSpan}; +use rustc_errors::{Applicability, DiagArgValue, E0232, E0264, MultiSpan}; use rustc_hir::AttrPath; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; @@ -801,3 +801,11 @@ pub(crate) struct UnsafeAttribute { pub attr_path: AttrPath, pub note: &'static str, } + +#[derive(Diagnostic)] +#[diag("unknown external lang item: `{$lang_item}`", code = E0264)] +pub(crate) struct UnknownExternLangItem { + #[primary_span] + pub span: Span, + pub lang_item: Symbol, +} diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 494824a8393b3..fef6f7d9e5503 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -337,7 +337,7 @@ pub(crate) struct InvalidTarget { pub target: &'static str, pub applied: DiagArgValue, pub only: &'static str, - pub attribute_args: &'static str, + pub attribute_args: String, #[subdiagnostic] pub help: Option, #[warning( diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 9903c6aa68d01..96737be04f5b2 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -16,9 +16,9 @@ use crate::target_checking::Policy::Allow; use crate::{AttributeParser, ShouldEmit}; #[derive(Debug)] -pub(crate) enum AllowedTargets { - AllowList(&'static [Policy]), - AllowListWarnRest(&'static [Policy]), +pub(crate) enum AllowedTargets<'a> { + AllowList(&'a [Policy]), + AllowListWarnRest(&'a [Policy]), /// This is useful for argument-dependent target checking. /// If debug assertions are enabled, /// this emits a delayed bug if the `cx.check_target(...)` method is not called during attribute parsing. @@ -31,7 +31,7 @@ pub(crate) enum AllowedResult { Error, } -impl AllowedTargets { +impl AllowedTargets<'_> { pub(crate) fn is_allowed(&self, target: Target) -> AllowedResult { match self { AllowedTargets::AllowList(list) => { @@ -94,8 +94,8 @@ pub(crate) enum Policy { impl<'sess> AttributeParser<'sess> { pub(crate) fn check_target( - allowed_targets: &AllowedTargets, - attribute_args: &'static str, + allowed_targets: &AllowedTargets<'_>, + attribute_args: &str, cx: &mut AcceptContext<'_, 'sess>, ) { if matches!(cx.should_emit, ShouldEmit::Nothing) { @@ -137,7 +137,7 @@ impl<'sess> AttributeParser<'sess> { target: cx.target.plural_name(), only: if only { "only " } else { "" }, applied: DiagArgValue::StrListSepByAnd(applied.into_iter().map(Cow::Owned).collect()), - attribute_args, + attribute_args: attribute_args.to_string(), help: Self::target_checking_help(attribute_args, cx), previously_accepted: matches!(result, AllowedResult::Warn) && !is_diagnostic_attr, on_macro_call: matches!(cx.target, Target::MacroCall), @@ -173,7 +173,7 @@ impl<'sess> AttributeParser<'sess> { } fn target_checking_help( - attribute_args: &'static str, + attribute_args: &str, cx: &AcceptContext<'_, '_>, ) -> Option { match &*cx.attr_path.segments { @@ -443,8 +443,8 @@ fn filter_targets( impl<'f, 'sess> AcceptContext<'f, 'sess> { pub(crate) fn check_target( &mut self, - attribute_args: &'static str, - allowed_targets: &AllowedTargets, + attribute_args: &str, + allowed_targets: &AllowedTargets<'_>, ) { self.ignore_target_checks(); AttributeParser::check_target(allowed_targets, attribute_args, self); diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 007251ff3df05..89ea581d34d60 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -607,6 +607,8 @@ fn make_format_args( // If there's a lot of unused arguments, // let's check if this format arguments looks like another syntax (printf / shell). let detect_foreign_fmt = unused.len() > args.explicit_args().len() / 2; + let foreign_fmt_str = + if append_newline { fmt_str.strip_suffix('\n').unwrap_or(fmt_str) } else { fmt_str }; report_missing_placeholders( ecx, unused, @@ -616,7 +618,7 @@ fn make_format_args( &invalid_refs, detect_foreign_fmt, str_style, - fmt_str, + foreign_fmt_str, uncooked_fmt_str.1.as_str(), fmt_span, ); diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 0eb493036ce51..8f965a5ef7b12 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -16,9 +16,9 @@ use rustc_abi::{CanonAbi, ExternAbi, X86Call}; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::{ShimKind, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Spanned; use rustc_target::callconv::{FnAbi, PassMode}; @@ -467,7 +467,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } // We don't need AsyncDropGlueCtorShim here because it is not `noop func`, // it is `func returning noop future` - InstanceKind::DropGlue(_, None) => { + InstanceKind::Shim(ShimKind::DropGlue(_, None)) => { // empty drop glue - a nop. let dest = target.expect("Non terminating drop_in_place_real???"); let ret_block = fx.get_block(dest); @@ -725,7 +725,7 @@ pub(crate) fn codegen_drop<'tcx>( let ret_block = fx.get_block(target); // AsyncDropGlueCtorShim can't be here - if let ty::InstanceKind::DropGlue(_, None) = drop_instance.def { + if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) = drop_instance.def { // we don't actually need to drop anything fx.bcx.ins().jump(ret_block, &[]); } else { diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index c986666f9c46e..829e7d0dfb59c 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -53,7 +53,7 @@ pub(crate) fn codegen_tls_ref<'tcx>( ) -> CValue<'tcx> { let tls_ptr = if !def_id.is_local() && fx.tcx.needs_thread_local_shim(def_id) { let instance = ty::Instance { - def: ty::InstanceKind::ThreadLocalShim(def_id), + def: ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(def_id)), args: ty::GenericArgs::empty(), }; let func_ref = fx.get_function_ref(instance); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 014fd5cf3a0e5..dfc8c8be5c03f 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -11,7 +11,9 @@ use rustc_middle::middle::exported_symbols::{ ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, }; use rustc_middle::query::LocalCrate; -use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt}; +use rustc_middle::ty::{ + self, GenericArgKind, GenericArgsRef, Instance, ShimKind, SymbolName, Ty, TyCtxt, +}; use rustc_middle::util::Providers; use rustc_session::config::CrateType; use rustc_span::Span; @@ -332,7 +334,10 @@ fn exported_generic_symbols_provider_local<'tcx>( )); } } - MonoItem::Fn(Instance { def: InstanceKind::DropGlue(_, Some(ty)), args }) => { + MonoItem::Fn(Instance { + def: InstanceKind::Shim(ShimKind::DropGlue(_, Some(ty))), + args, + }) => { // A little sanity-check assert_eq!(args.non_erasable_generics().next(), Some(GenericArgKind::Type(ty))); @@ -356,7 +361,7 @@ fn exported_generic_symbols_provider_local<'tcx>( } } MonoItem::Fn(Instance { - def: InstanceKind::AsyncDropGlueCtorShim(_, ty), + def: InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(_, ty)), args, }) => { // A little sanity-check @@ -371,7 +376,10 @@ fn exported_generic_symbols_provider_local<'tcx>( }, )); } - MonoItem::Fn(Instance { def: InstanceKind::AsyncDropGlue(def, ty), args: _ }) => { + MonoItem::Fn(Instance { + def: InstanceKind::Shim(ShimKind::AsyncDropGlue(def, ty)), + args: _, + }) => { symbols.push(( ExportedSymbol::AsyncDropGlue(def, ty), SymbolExportInfo { @@ -578,7 +586,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>( rustc_symbol_mangling::symbol_name_for_instance_in_crate( tcx, ty::Instance { - def: ty::InstanceKind::ThreadLocalShim(def_id), + def: ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(def_id)), args: ty::GenericArgs::empty(), }, instantiating_crate, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index d4932adeda1f9..b31f785c22234 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -618,7 +618,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ty = self.monomorphize(ty); let drop_fn = Instance::resolve_drop_glue(bx.tcx(), ty); - if let ty::InstanceKind::DropGlue(_, None) = drop_fn.def { + if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) = drop_fn.def { // we don't actually need to drop anything. return helper.funclet_br(self, bx, target, mergeable_succ, &[]); } @@ -934,7 +934,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match instance.def { // We don't need AsyncDropGlueCtorShim here because it is not `noop func`, // it is `func returning noop future` - ty::InstanceKind::DropGlue(_, None) => { + ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) => { // Empty drop glue; a no-op. let target = target.unwrap(); return helper.funclet_br(self, bx, target, mergeable_succ, &[]); @@ -1317,7 +1317,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } LocalRef::Operand(arg) => { let Ref(place_value) = arg.val else { - bug!("only `Ref` should use `PassMode::Indirect`"); + bug!( + "only `Ref` should use `PassMode::Indirect`, but got {:?}", + arg.val + ); }; bx.typed_place_copy(place_value, tmp.val, fn_abi.args[i].layout); op.val = arg.val; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index deb8ca12b059d..5dc4617717c11 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -665,7 +665,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id) { let instance = ty::Instance { - def: ty::InstanceKind::ThreadLocalShim(def_id), + def: ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(def_id)), args: ty::GenericArgs::empty(), }; let fn_ptr = bx.get_fn_addr(instance); diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 85da687d8af37..44420b7148478 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -428,7 +428,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Determine whether this is a non-capturing closure. That's relevant as their first // argument can be skipped (and that's the only kind of argument skipping we allow). let is_non_capturing_closure = - (matches!(instance.def, ty::InstanceKind::ClosureOnceShim { .. }) + (matches!(instance.def, ty::InstanceKind::Shim(ty::ShimKind::ClosureOnce { .. })) || self.tcx.is_closure_like(def_id)) && { let arg = &callee_fn_abi.args[0]; @@ -652,18 +652,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(()) } } - ty::InstanceKind::VTableShim(..) - | ty::InstanceKind::ReifyShim(..) - | ty::InstanceKind::ClosureOnceShim { .. } - | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::FnPtrShim(..) - | ty::InstanceKind::DropGlue(..) - | ty::InstanceKind::CloneShim(..) - | ty::InstanceKind::FnPtrAddrShim(..) - | ty::InstanceKind::ThreadLocalShim(..) - | ty::InstanceKind::AsyncDropGlueCtorShim(..) - | ty::InstanceKind::AsyncDropGlue(..) - | ty::InstanceKind::FutureDropPollShim(..) + ty::InstanceKind::Shim(ty::ShimKind::VTable(..)) + | ty::InstanceKind::Shim(ty::ShimKind::Reify(..)) + | ty::InstanceKind::Shim(ty::ShimKind::ClosureOnce { .. }) + | ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure { .. }) + | ty::InstanceKind::Shim(ty::ShimKind::FnPtr(..)) + | ty::InstanceKind::Shim(ty::ShimKind::DropGlue(..)) + | ty::InstanceKind::Shim(ty::ShimKind::Clone(..)) + | ty::InstanceKind::Shim(ty::ShimKind::FnPtrAddr(..)) + | ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(..)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(..)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(..)) + | ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(..)) | ty::InstanceKind::Item(_) => { // We need MIR for this fn. // Note that this can be an intrinsic, if we are executing its fallback body. diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index b865cafa38647..1aeaaee3a251c 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -607,7 +607,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { enter_trace_span!(M, resolve::resolve_drop_glue, ty = ?place.layout.ty); Instance::resolve_drop_glue(*self.tcx, place.layout.ty) }; - if let ty::InstanceKind::DropGlue(_, None) = instance.def { + if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) = instance.def { // This is the branch we enter if and only if the dropped type has no drop glue // whatsoever. This can happen as a result of monomorphizing a drop of a // generic. In order to make sure that generic and non-generic code behaves diff --git a/compiler/rustc_error_codes/src/error_codes/E0718.md b/compiler/rustc_error_codes/src/error_codes/E0718.md index 1fe62ecf1f4e0..2ecf3081d2ed6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0718.md +++ b/compiler/rustc_error_codes/src/error_codes/E0718.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + A `#[lang = ".."]` attribute was placed on the wrong item type. Erroneous code example: -```compile_fail,E0718 +```compile_fail #![feature(lang_items)] #[lang = "owned_box"] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2a10245d3d2e8..f429d14e3a51c 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3852,14 +3852,34 @@ pub enum OpaqueTyOrigin { }, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, StableHash)] +pub enum DelegationSelfTyPropagationKind { + /// Used when self type is explicitly specified in free-to-trait reuse + /// `reuse <() as Trait>::foo;`. + SelfTy(HirId /* Self ty id */), + /// Used when infer instead of a self type is specified or self type + /// is not specified at all: `reuse Trait::foo; reuse <_ as Trait>::foo;`. + SelfParam, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, StableHash)] pub struct DelegationInfo { pub call_expr_id: HirId, pub call_path_res: Option, - pub parent_args_segment_id: Option, - pub child_args_segment_id: Option, - pub self_ty_id: Option, - pub propagate_self_ty: bool, + + /// Id of the child segment in delegation: `reuse Trait::foo`, + /// `child_seg_id` points to `foo`. + pub child_seg_id: HirId, + + /// Ids of parent and child segments, `Some` when we need to take + /// generic args of those segments for signature/predicates inheritance. + /// `None` in trait impl case or when error delegation is generated, meaning + /// we should not access those segments for generic args lowering. + /// When `child_seg_id_for_sig` is Some it always equals `child_seg_id`. + pub parent_seg_id_for_sig: Option, + pub child_seg_id_for_sig: Option, + + pub self_ty_propagation_kind: Option, pub group_id: Option<(LocalExpnId, bool /* unused_target_expr */)>, } diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 7f3edd7f09231..de2315edb7e8f 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -5,16 +5,15 @@ use std::debug_assert_matches; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::PathSegment; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment}; use rustc_middle::ty::{ self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use rustc_span::{ErrorGuaranteed, Span, kw}; use crate::collect::ItemCtxt; -use crate::diagnostics::DelegationSelfTypeNotSpecified; use crate::hir_ty_lowering::HirTyLowerer; type RemapTable = FxHashMap; @@ -65,8 +64,9 @@ impl<'tcx> TypeFolder> for ParamIndexRemapper<'tcx> { } } +#[derive(Debug)] enum SelfPositionKind { - AfterLifetimes(bool /* Should propagate self ty */), + AfterLifetimes(Option), Zero, None, } @@ -83,8 +83,8 @@ fn create_self_position_kind( | (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero, (FnKind::Free, FnKind::AssocTrait) => { - let propagate_self_ty = tcx.hir_delegation_info(delegation_id).propagate_self_ty; - SelfPositionKind::AfterLifetimes(propagate_self_ty) + let kind = tcx.hir_delegation_info(delegation_id).self_ty_propagation_kind; + SelfPositionKind::AfterLifetimes(kind) } _ => SelfPositionKind::None, @@ -268,28 +268,6 @@ fn get_parent_and_inheritance_kind<'tcx>( } } -fn get_delegation_self_ty_or_err(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> Ty<'_> { - tcx.hir_delegation_info(delegation_id) - .self_ty_id - .map(|id| { - let ctx = ItemCtxt::new(tcx, delegation_id); - ctx.lower_ty(tcx.hir_node(id).expect_ty()) - }) - .unwrap_or_else(|| { - // It is possible to attempt to get self type when it is used in signature - // (i.e., `fn default() -> Self`), so emit error here in addition to possible - // `mismatched types` error (see #156388). - let err = DelegationSelfTypeNotSpecified { span: tcx.def_span(delegation_id) }; - tcx.dcx().emit_err(err); - - Ty::new_error_with_message( - tcx, - tcx.def_span(delegation_id), - "the self type must be specified", - ) - }) -} - fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) -> Option> { let sig_id = tcx.hir_opt_delegation_sig_id(delegation_id).expect("Delegation must have sig_id"); let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)); @@ -302,14 +280,24 @@ fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) -> | (FnKind::AssocTrait, FnKind::AssocTrait) => { match create_self_position_kind(tcx, delegation_id, sig_id) { SelfPositionKind::None => None, - SelfPositionKind::AfterLifetimes(propagate_self_ty) => { - if propagate_self_ty { - Some(get_delegation_self_ty_or_err(tcx, delegation_id)) - } else { - // Both sig parent and child lifetimes are in included in this count. - let index = tcx.generics_of(delegation_id).own_counts().lifetimes; - Some(Ty::new_param(tcx, index as u32, kw::SelfUpper)) - } + SelfPositionKind::AfterLifetimes(propagation_kind) => { + Some(match propagation_kind { + Some(kind) => match kind { + DelegationSelfTyPropagationKind::SelfTy(self_ty_id) => { + let ctx = ItemCtxt::new(tcx, delegation_id); + ctx.lower_ty(tcx.hir_node(self_ty_id).expect_ty()) + } + DelegationSelfTyPropagationKind::SelfParam => { + let index = tcx.generics_of(delegation_id).own_counts().lifetimes; + Ty::new_param(tcx, index as u32, kw::SelfUpper) + } + }, + None => Ty::new_error_with_message( + tcx, + tcx.def_span(delegation_id), + "self propagation kind must be specified for `AfterLifetimes` variant", + ), + }) } SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)), } @@ -348,137 +336,69 @@ fn create_generic_args<'tcx>( sig_id: DefId, delegation_id: LocalDefId, mut parent_args: &[ty::GenericArg<'tcx>], - child_args: &[ty::GenericArg<'tcx>], + mut child_args: &[ty::GenericArg<'tcx>], ) -> Vec> { - let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)); - + let delegation_generics = tcx.generics_of(delegation_id); let delegation_args = ty::GenericArgs::identity_for_item(tcx, delegation_id); - let deleg_parent_args_without_self_count = - get_delegation_parent_args_count_without_self(tcx, delegation_id, sig_id); - - let delegation_generics = tcx.generics_of(delegation_id); let real_args_count = delegation_args.len() - delegation_generics.own_synthetic_params_count(); let synth_args = &delegation_args[real_args_count..]; - let delegation_args = &delegation_args[..real_args_count]; - - let args = match (caller_kind, callee_kind) { - (FnKind::Free, FnKind::Free) - | (FnKind::Free, FnKind::AssocTrait) - | (FnKind::AssocInherentImpl, FnKind::Free) - | (FnKind::AssocTrait, FnKind::Free) - | (FnKind::AssocTrait, FnKind::AssocTrait) => delegation_args, - (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { - // Special case, as user specifies Trait args in trait impl header, we want to treat - // them as parent args. We always generate a function whose generics match - // child generics in trait. - let parent = tcx.local_parent(delegation_id); - parent_args = - tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args; - - assert!(child_args.is_empty(), "Child args can not be used in trait impl case"); - - tcx.mk_args(&delegation_args[delegation_generics.parent_count..]) - } - - (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { - let self_ty = - tcx.type_of(tcx.local_parent(delegation_id)).instantiate_identity().skip_norm_wip(); + let mut delegation_parent_args = + &delegation_args[delegation_generics.has_self as usize..delegation_generics.parent_count]; - tcx.mk_args_from_iter( - std::iter::once(ty::GenericArg::from(self_ty)) - .chain(delegation_args.iter().copied()), - ) - } + let delegation_args = &delegation_args[delegation_generics.parent_count..]; - // For trait impl's `sig_id` is always equal to the corresponding trait method. - // For inherent methods delegation is not yet supported. - (FnKind::AssocTraitImpl, _) - | (_, FnKind::AssocTraitImpl) - | (_, FnKind::AssocInherentImpl) => unreachable!(), - }; + let kinds = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)); + if matches!(kinds, (FnKind::AssocTraitImpl, FnKind::AssocTrait)) { + // Special case, as user specifies Trait args in trait impl header, we want to treat + // them as parent args. We always generate a function whose generics match + // child generics in trait. + let parent = tcx.local_parent(delegation_id); - let mut new_args = vec![]; + parent_args = + tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args; - let self_pos_kind = create_self_position_kind(tcx, delegation_id, sig_id); - let mut lifetimes_end_pos; + child_args = + &delegation_args[delegation_args.len() - delegation_generics.own_params.len()..]; - if !parent_args.is_empty() { - let parent_args_lifetimes_count = - parent_args.iter().filter(|a| a.as_region().is_some()).count(); - - match self_pos_kind { - SelfPositionKind::AfterLifetimes { .. } => { - new_args.extend(&parent_args[1..1 + parent_args_lifetimes_count]); + delegation_parent_args = &[]; + } - lifetimes_end_pos = parent_args_lifetimes_count; + let self_type = get_delegation_self_ty(tcx, delegation_id).map(|t| t.into()); - new_args.push(parent_args[0]); + // Remove `Self` from parent args (it is always at the `0th` index) as it is + // added manually. + if self_type.is_some() && !parent_args.is_empty() { + parent_args = &parent_args[1..]; + } - new_args.extend(&parent_args[1 + parent_args_lifetimes_count..]); + let (zero_self, after_lifetimes_self) = + match create_self_position_kind(tcx, delegation_id, sig_id) { + SelfPositionKind::AfterLifetimes(_) => { + assert!(self_type.is_some()); + (None, self_type) } SelfPositionKind::Zero => { - lifetimes_end_pos = 1 /* Self */ + parent_args_lifetimes_count; - new_args.extend_from_slice(parent_args); - - for i in 0..deleg_parent_args_without_self_count { - new_args.insert(1 + i, args[1 + i]); - } - - lifetimes_end_pos += deleg_parent_args_without_self_count; + assert!(self_type.is_some()); + (self_type, None) } - // If we have parent args then we obtained them from trait, then self must be somewhere - SelfPositionKind::None => unreachable!(), + SelfPositionKind::None => (None, None), }; - } else { - let self_impact = matches!(self_pos_kind, SelfPositionKind::Zero) as usize; - - lifetimes_end_pos = self_impact - + deleg_parent_args_without_self_count - + &args[self_impact + deleg_parent_args_without_self_count..] - .iter() - .filter(|a| a.as_region().is_some()) - .count(); - - new_args.extend_from_slice(args); - - // Parent args are empty, then if we should propagate self ty (meaning Self generic - // param was not generated) then we should insert it, as it won't be in `args`. - if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true)) { - new_args.insert( - lifetimes_end_pos, - ty::GenericArg::from(get_delegation_self_ty_or_err(tcx, delegation_id)), - ); - } - } - - if !child_args.is_empty() { - let child_lifetimes_count = child_args.iter().filter(|a| a.as_region().is_some()).count(); - - for i in 0..child_lifetimes_count { - new_args.insert(lifetimes_end_pos + i, child_args[i]); - } - new_args.extend_from_slice(&child_args[child_lifetimes_count..]); - } else if !parent_args.is_empty() { - let child_args = &delegation_args[delegation_generics.parent_count..]; - - let child_lifetimes_count = - child_args.iter().take_while(|a| a.as_region().is_some()).count(); - - for i in 0..child_lifetimes_count { - new_args.insert(lifetimes_end_pos + i, child_args[i]); - } - - // If self_ty is propagated it means that Self generic param was not generated. - let skip_self = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(false)); - new_args.extend(&child_args[child_lifetimes_count + skip_self as usize..]); - } - - new_args.extend(synth_args); - - new_args + let zero_self = zero_self.as_ref().into_iter(); + let after_lifetimes_self = after_lifetimes_self.as_ref().into_iter(); + + zero_self + .chain(delegation_parent_args) + .chain(parent_args.iter().filter(|a| a.as_region().is_some())) + .chain(child_args.iter().filter(|a| a.as_region().is_some())) + .chain(after_lifetimes_self) + .chain(parent_args.iter().filter(|a| a.as_region().is_none())) + .chain(child_args.iter().filter(|a| a.as_region().is_none())) + .chain(synth_args) + .copied() + .collect::>() } pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( @@ -541,7 +461,10 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id); let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args); let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id); - let filter_self_preds = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true)); + let filter_self_preds = matches!( + self_pos_kind, + SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..))) + ); let collector = PredicatesCollector { tcx, preds: vec![], args, folder, filter_self_preds }; let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id); @@ -640,18 +563,21 @@ pub(crate) fn delegation_user_specified_args<'tcx>( let ctx = ItemCtxt::new_for_delegation(tcx, delegation_id); let lowerer = ctx.lowerer(); + let parent_args = info + .parent_seg_id_for_sig + .and_then(get_segment) + .filter(|(_, def_id)| matches!(tcx.def_kind(*def_id), DefKind::Trait)) + .map(|(segment, def_id)| { + let self_ty = get_delegation_self_ty(tcx, delegation_id); - let parent_args = info.parent_args_segment_id.and_then(get_segment).map(|(segment, def_id)| { - let self_ty = get_delegation_self_ty(tcx, delegation_id); - - lowerer - .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty) - .0 - .as_slice() - }); + lowerer + .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty) + .0 + .as_slice() + }); let child_args = info - .child_args_segment_id + .child_seg_id_for_sig .and_then(get_segment) .filter(|(_, def_id)| matches!(tcx.def_kind(*def_id), DefKind::Fn | DefKind::AssocFn)) .map(|(segment, def_id)| { diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index 5997f16b42917..1bfc495071284 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -1582,14 +1582,6 @@ pub(crate) struct UnsupportedDelegation<'a> { pub callee_span: Span, } -#[derive(Diagnostic)] -#[diag("delegation self type is not specified")] -#[help("consider explicitly specifying self type: `reuse ::function`")] -pub(crate) struct DelegationSelfTypeNotSpecified { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("inferred lifetimes are not allowed in delegations as we need to inherit signature")] pub(crate) struct ElidedLifetimesAreNotAllowedInDelegations { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index a26d84291e42d..0187a22d564cb 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -6,7 +6,7 @@ use rustc_errors::{ }; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, GenericArg}; +use rustc_hir::{self as hir, DelegationInfo, GenericArg}; use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, }; @@ -430,8 +430,17 @@ pub(crate) fn check_generic_arg_count( prohibit_assoc_item_constraint(cx, c, None); } - let explicit_late_bound = - prohibit_explicit_late_bound_lifetimes(cx, gen_params, gen_args, gen_pos); + let tcx = cx.tcx(); + let parent_def = tcx.hir_get_parent_item(seg.hir_id).def_id; + + // Suppress this warning for delegations as it is compiler generated and lifetimes are + // propagated while late-bound lifetimes may be present. + let explicit_late_bound = match tcx.hir_opt_delegation_info(parent_def) { + Some(DelegationInfo { child_seg_id, .. }) if seg.hir_id == *child_seg_id => { + ExplicitLateBound::No + } + _ => prohibit_explicit_late_bound_lifetimes(cx, gen_params, gen_args, gen_pos), + }; let mut invalid_args = vec![]; @@ -458,7 +467,7 @@ pub(crate) fn check_generic_arg_count( }; let reported = cx.dcx().emit_err(WrongNumberOfGenericArgs::new( - cx.tcx(), + tcx, gen_args_info, seg, gen_params, @@ -536,20 +545,19 @@ pub(crate) fn check_generic_arg_count( .map(|param| param.name) .collect(); if constraint_names == param_names { - let has_assoc_ty_with_same_name = - if let DefKind::Trait = cx.tcx().def_kind(def_id) { - gen_args.constraints.iter().any(|constraint| { - traits::supertrait_def_ids(cx.tcx(), def_id).any(|trait_did| { - cx.probe_trait_that_defines_assoc_item( - trait_did, - ty::AssocTag::Type, - constraint.ident, - ) - }) + let has_assoc_ty_with_same_name = if let DefKind::Trait = tcx.def_kind(def_id) { + gen_args.constraints.iter().any(|constraint| { + traits::supertrait_def_ids(tcx, def_id).any(|trait_did| { + cx.probe_trait_that_defines_assoc_item( + trait_did, + ty::AssocTag::Type, + constraint.ident, + ) }) - } else { - false - }; + }) + } else { + false + }; // We set this to true and delay emitting `WrongNumberOfGenericArgs` // to provide a succinct error for cases like issue #113073, // but only if when we don't have any assoc type with the same name with a @@ -573,7 +581,7 @@ pub(crate) fn check_generic_arg_count( let reported = gen_args.has_err().unwrap_or_else(|| { cx.dcx() .create_err(WrongNumberOfGenericArgs::new( - cx.tcx(), + tcx, gen_args_info, seg, gen_params, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 87f88a16b2c42..6b00d58bb1e26 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2522,15 +2522,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Const<'tcx> { let tcx = self.tcx(); + let found_tuple = || { + tcx.sess + .source_map() + .span_to_snippet(span) + .map(|snippet| format!("`{snippet}`")) + .unwrap_or_else(|_| "const tuple".to_string()) + }; + let tys = match ty.kind() { ty::Tuple(tys) => tys, ty::Error(e) => return Const::new_error(tcx, *e), _ => { - let e = tcx.dcx().span_err(span, format!("expected `{}`, found const tuple", ty)); + let e = + tcx.dcx().span_err(span, format!("expected `{}`, found {}", ty, found_tuple())); return Const::new_error(tcx, e); } }; + if exprs.len() != tys.len() { + let e = tcx.dcx().span_err(span, format!("expected `{}`, found {}", ty, found_tuple())); + return Const::new_error(tcx, e); + } + let exprs = exprs .iter() .zip(tys.iter()) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index c8680be6de718..f4a30f84a3d7a 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -739,9 +739,21 @@ impl<'a, 'tcx> CastCheck<'tcx> { ); } + fn expr_span_for_type_resolution(&self, fcx: &FnCtxt<'a, 'tcx>) -> Span { + if let hir::ExprKind::Index(_, idx, _) = self.expr.kind + && fcx.resolve_vars_if_possible(self.expr_ty).is_ty_var() + && fcx.resolve_vars_if_possible(fcx.node_ty(idx.hir_id)).is_ty_var() + { + index_operand_ambiguity_span(idx) + } else { + self.expr_span + } + } + #[instrument(skip(fcx), level = "debug")] pub(crate) fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) { - self.expr_ty = fcx.structurally_resolve_type(self.expr_span, self.expr_ty); + let expr_span = self.expr_span_for_type_resolution(fcx); + self.expr_ty = fcx.structurally_resolve_type(expr_span, self.expr_ty); self.cast_ty = fcx.structurally_resolve_type(self.cast_span, self.cast_ty); debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty); @@ -1169,3 +1181,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { } } } + +fn index_operand_ambiguity_span(expr: &hir::Expr<'_>) -> Span { + match expr.kind { + hir::ExprKind::MethodCall(segment, ..) => segment.ident.span, + _ => expr.span, + } +} diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 5fe1f4191c93f..1780430567a80 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -90,7 +90,7 @@ pub(super) fn check_fn<'a, 'tcx>( } // Check that argument is Sized. - if !params_can_be_unsized { + if !params_can_be_unsized || fn_sig.abi() == rustc_abi::ExternAbi::RustTail { fcx.require_type_is_sized( param_ty, param.ty_span, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 825aa37065e15..2d436ec82b20e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -4,8 +4,11 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_infer::traits::ObligationCauseCode; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, +}; use rustc_span::{Span, kw}; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits; use crate::FnCtxt; @@ -37,6 +40,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, error: &mut traits::FulfillmentError<'tcx>, ) -> bool { + if self.adjust_binop_index_operand(error) { + return true; + } + let (def_id, hir_id, idx, flavor) = match *error.obligation.cause.code().peel_derives() { ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) => { (def_id, hir_id, idx, ClauseFlavor::Where) @@ -165,6 +172,119 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn adjust_binop_index_operand(&self, error: &mut traits::FulfillmentError<'tcx>) -> bool { + let ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. } = + *error.obligation.cause.code().peel_derives() + else { + return false; + }; + if !matches!(error.code, traits::FulfillmentErrorCode::Ambiguity { .. }) + || !error.obligation.predicate.has_infer() + { + return false; + } + + let hir::Node::Expr(lhs_expr) = self.tcx.hir_node(lhs_hir_id) else { + return false; + }; + let hir::Node::Expr(rhs_expr) = self.tcx.hir_node(rhs_hir_id) else { + return false; + }; + let Some(binop) = self.binop_for_operands(lhs_hir_id, rhs_hir_id) else { + return false; + }; + let hir::ExprKind::Index(indexed_expr, idx, _) = rhs_expr.kind else { + return false; + }; + if !self.resolve_vars_if_possible(self.node_ty(idx.hir_id)).is_ty_var() { + return false; + } + let lhs_ty = self.resolve_vars_if_possible(self.node_ty(lhs_expr.hir_id)); + let indexed_ty = self.resolve_vars_if_possible(self.node_ty(indexed_expr.hir_id)); + let rhs_ty = match *indexed_ty.kind() { + ty::Array(element_ty, _) | ty::Slice(element_ty) => element_ty, + ty::Ref(_, pointee_ty, _) => match *pointee_ty.kind() { + ty::Array(element_ty, _) | ty::Slice(element_ty) => element_ty, + _ => self.resolve_vars_if_possible(self.node_ty(rhs_expr.hir_id)), + }, + _ => self.resolve_vars_if_possible(self.node_ty(rhs_expr.hir_id)), + }; + if !self.binop_accepts_types(binop.node, lhs_ty, rhs_ty) { + return false; + } + + error.obligation.cause.span = match idx.kind { + hir::ExprKind::MethodCall(segment, ..) => segment.ident.span, + _ => idx.span, + }; + true + } + + fn binop_for_operands( + &self, + lhs_hir_id: hir::HirId, + rhs_hir_id: hir::HirId, + ) -> Option { + let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(rhs_hir_id) else { + return None; + }; + let hir::ExprKind::Binary(binop, lhs_expr, rhs_expr) = parent_expr.kind else { + return None; + }; + (lhs_expr.hir_id == lhs_hir_id && rhs_expr.hir_id == rhs_hir_id).then_some(binop) + } + + fn binop_accepts_types( + &self, + binop: hir::BinOpKind, + lhs_ty: Ty<'tcx>, + rhs_ty: Ty<'tcx>, + ) -> bool { + let lhs_ty = self.deref_ty_if_possible(lhs_ty); + let rhs_ty = self.deref_ty_if_possible(rhs_ty); + if lhs_ty.references_error() || rhs_ty.references_error() { + return true; + } + + match binop { + hir::BinOpKind::Shl | hir::BinOpKind::Shr => { + lhs_ty.is_integral() && rhs_ty.is_integral() + } + hir::BinOpKind::Add + | hir::BinOpKind::Sub + | hir::BinOpKind::Mul + | hir::BinOpKind::Div + | hir::BinOpKind::Rem => { + self.can_eq(self.param_env, lhs_ty, rhs_ty) + && (lhs_ty.is_integral() || lhs_ty.is_floating_point()) + && (rhs_ty.is_integral() || rhs_ty.is_floating_point()) + } + hir::BinOpKind::BitXor | hir::BinOpKind::BitAnd | hir::BinOpKind::BitOr => { + self.can_eq(self.param_env, lhs_ty, rhs_ty) + && ((lhs_ty.is_integral() && rhs_ty.is_integral()) + || (lhs_ty.is_bool() && rhs_ty.is_bool())) + } + hir::BinOpKind::Eq + | hir::BinOpKind::Ne + | hir::BinOpKind::Lt + | hir::BinOpKind::Le + | hir::BinOpKind::Ge + | hir::BinOpKind::Gt => { + self.can_eq(self.param_env, lhs_ty, rhs_ty) + && lhs_ty.is_scalar() + && rhs_ty.is_scalar() + } + hir::BinOpKind::And | hir::BinOpKind::Or => lhs_ty.is_bool() && rhs_ty.is_bool(), + } + } + + fn deref_ty_if_possible(&self, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.kind() { + ty::Ref(_, ty, hir::Mutability::Not) => *ty, + _ => ty, + } + } + fn point_at_expr_if_possible( &self, error: &mut traits::FulfillmentError<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index ad35dc3f7a04b..fd52c7f4b4d26 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -313,6 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); + method.sig.output() } // error types are considered "builtin" diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index ba5b55b43049f..58139a5e3480a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -348,7 +348,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) { intravisit::walk_ty(self, hir_ty); // If there are type checking errors, Type privacy pass will stop, - // so we may not get the type from hid_id, see #104513 + // so we may not get the type from hir_id, see #104513 if let Some(ty) = self.fcx.node_ty_opt(hir_ty.hir_id) { let ty = self.resolve(ty, &hir_ty.span); self.write_ty_to_typeck_results(hir_ty.hir_id, ty); diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 9b78c31871fd7..713c6597c1966 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -8,7 +8,7 @@ use rustc_span::Symbol; use rustc_target::spec::SanitizerSet; use crate::mono::Visibility; -use crate::ty::{InstanceKind, TyCtxt}; +use crate::ty::{InstanceKind, ShimKind, TyCtxt}; impl<'tcx> TyCtxt<'tcx> { pub fn codegen_instance_attrs( @@ -33,7 +33,7 @@ impl<'tcx> TyCtxt<'tcx> { // // A `ClosureOnceShim` with the track_caller attribute does not have a symbol, // and therefore can be skipped here. - if let InstanceKind::ReifyShim(_, _) = instance_kind + if let InstanceKind::Shim(ShimKind::Reify(_, _)) = instance_kind && attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) { if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { @@ -54,8 +54,11 @@ impl<'tcx> TyCtxt<'tcx> { } // Ensure closure shims have the optimization properties of their closure applied to them. - if let InstanceKind::ClosureOnceShim { call_once: _, closure, track_caller: _ } = - instance_kind + if let InstanceKind::Shim(ShimKind::ClosureOnce { + call_once: _, + closure, + track_caller: _, + }) = instance_kind { let closure_attrs = self.codegen_fn_attrs(closure); attrs.to_mut().optimize = closure_attrs.optimize; diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index fb770076f0a26..e23ad3c832ef7 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -75,7 +75,7 @@ impl<'tcx> ExportedSymbol<'tcx> { tcx.symbol_name(ty::Instance::resolve_async_drop_in_place_poll(tcx, def_id, ty)) } ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance { - def: ty::InstanceKind::ThreadLocalShim(def_id), + def: ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(def_id)), args: ty::GenericArgs::empty(), }), ExportedSymbol::NoDefId(symbol_name) => symbol_name, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index c12e72d1dce0f..3facba24d3fd7 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -32,8 +32,8 @@ use crate::mir::interpret::{AllocRange, Scalar}; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths}; use crate::ty::{ - self, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypeVisitableExt, - TypingEnv, UserTypeAnnotationIndex, + self, GenericArg, GenericArgsRef, Instance, InstanceKind, List, ShimKind, Ty, TyCtxt, + TypeVisitableExt, TypingEnv, UserTypeAnnotationIndex, }; mod basic_blocks; @@ -127,8 +127,8 @@ impl<'tcx> MirSource<'tcx> { MirSource { instance: InstanceKind::Item(def_id), promoted: None } } - pub fn from_instance(instance: InstanceKind<'tcx>) -> Self { - MirSource { instance, promoted: None } + pub fn from_shim(shim: ShimKind<'tcx>) -> Self { + MirSource { instance: InstanceKind::Shim(shim), promoted: None } } #[inline] diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 942c36f343343..beab1b1a08e1a 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -218,7 +218,7 @@ impl<'a, 'tcx> MirDumper<'a, 'tcx> { // All drop shims have the same DefId, so we have to add the type // to get unique file names. let shim_disambiguator = match source.instance { - ty::InstanceKind::DropGlue(_, Some(ty)) => { + ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, Some(ty))) => { // Unfortunately, pretty-printed types are not very filename-friendly. // We do some filtering. let mut s = ".".to_owned(); @@ -229,7 +229,7 @@ impl<'a, 'tcx> MirDumper<'a, 'tcx> { })); s } - ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => { + ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_, ty)) => { let mut s = ".".to_owned(); s.extend(ty.to_string().chars().filter_map(|c| match c { ' ' => None, @@ -238,7 +238,7 @@ impl<'a, 'tcx> MirDumper<'a, 'tcx> { })); s } - ty::InstanceKind::AsyncDropGlue(_, ty) => { + ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_, ty)) => { let ty::Coroutine(_, args) = ty.kind() else { bug!(); }; @@ -251,7 +251,7 @@ impl<'a, 'tcx> MirDumper<'a, 'tcx> { })); s } - ty::InstanceKind::FutureDropPollShim(_, proxy_cor, impl_cor) => { + ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(_, proxy_cor, impl_cor)) => { let mut s = ".".to_owned(); s.extend(proxy_cor.to_string().chars().filter_map(|c| match c { ' ' => None, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index fb89e9ac884a0..921c54b2828c2 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -347,27 +347,27 @@ macro_rules! make_mir_visitor { ty::InstanceKind::Item(_def_id) => {} ty::InstanceKind::Intrinsic(_def_id) - | ty::InstanceKind::VTableShim(_def_id) - | ty::InstanceKind::ReifyShim(_def_id, _) + | ty::InstanceKind::Shim(ty::ShimKind::VTable(_def_id)) + | ty::InstanceKind::Shim(ty::ShimKind::Reify(_def_id, _)) | ty::InstanceKind::Virtual(_def_id, _) - | ty::InstanceKind::ThreadLocalShim(_def_id) - | ty::InstanceKind::ClosureOnceShim { call_once: _def_id, closure: _, track_caller: _ } - | ty::InstanceKind::ConstructCoroutineInClosureShim { + | ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(_def_id)) + | ty::InstanceKind::Shim(ty::ShimKind::ClosureOnce { call_once: _def_id, closure: _, track_caller: _ }) + | ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure { coroutine_closure_def_id: _def_id, receiver_by_ref: _, - } - | ty::InstanceKind::DropGlue(_def_id, None) => {} - - ty::InstanceKind::FnPtrShim(_def_id, ty) - | ty::InstanceKind::DropGlue(_def_id, Some(ty)) - | ty::InstanceKind::CloneShim(_def_id, ty) - | ty::InstanceKind::FnPtrAddrShim(_def_id, ty) - | ty::InstanceKind::AsyncDropGlue(_def_id, ty) - | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, ty) => { + }) + | ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_def_id, None)) => {} + + ty::InstanceKind::Shim(ty::ShimKind::FnPtr(_def_id, ty)) + | ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_def_id, Some(ty))) + | ty::InstanceKind::Shim(ty::ShimKind::Clone(_def_id, ty)) + | ty::InstanceKind::Shim(ty::ShimKind::FnPtrAddr(_def_id, ty)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_def_id, ty)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_def_id, ty)) => { // FIXME(eddyb) use a better `TyContext` here. self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } - ty::InstanceKind::FutureDropPollShim(_def_id, proxy_ty, impl_ty) => { + ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(_def_id, proxy_ty, impl_ty)) => { self.visit_ty($(& $mutability)? *proxy_ty, TyContext::Location(location)); self.visit_ty($(& $mutability)? *impl_ty, TyContext::Location(location)); } diff --git a/compiler/rustc_middle/src/mono.rs b/compiler/rustc_middle/src/mono.rs index 2c1a9d1ed7bfb..6df67257a2ea7 100644 --- a/compiler/rustc_middle/src/mono.rs +++ b/compiler/rustc_middle/src/mono.rs @@ -22,7 +22,7 @@ use tracing::debug; use crate::dep_graph::dep_node::{make_compile_codegen_unit, make_compile_mono_item}; use crate::dep_graph::{DepNode, WorkProduct, WorkProductId}; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use crate::ty::{self, GenericArgs, Instance, InstanceKind, SymbolName, Ty, TyCtxt}; +use crate::ty::{self, GenericArgs, Instance, InstanceKind, ShimKind, SymbolName, Ty, TyCtxt}; /// Describes how a monomorphization will be instantiated in object files. #[derive(PartialEq)] @@ -173,7 +173,7 @@ impl<'tcx> MonoItem<'tcx> { // incrementality (which wants small CGUs with as many things GloballyShared as possible). // The heuristics implemented here do better than a completely naive approach in the // compiler benchmark suite, but there is no reason to believe they are optimal. - if let InstanceKind::DropGlue(_, Some(ty)) = instance.def { + if let InstanceKind::Shim(ShimKind::DropGlue(_, Some(ty))) = instance.def { if tcx.sess.opts.optimize == OptLevel::No { return InstantiationMode::GloballyShared { may_conflict: false }; } @@ -523,20 +523,20 @@ impl<'tcx> CodegenUnit<'tcx> { match item { MonoItem::Fn(ref instance) => match instance.def { InstanceKind::Item(def) => def.as_local().map(|_| def), - InstanceKind::VTableShim(..) - | InstanceKind::ReifyShim(..) - | InstanceKind::Intrinsic(..) - | InstanceKind::FnPtrShim(..) + InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..) - | InstanceKind::ClosureOnceShim { .. } - | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::DropGlue(..) - | InstanceKind::CloneShim(..) - | InstanceKind::ThreadLocalShim(..) - | InstanceKind::FnPtrAddrShim(..) - | InstanceKind::AsyncDropGlue(..) - | InstanceKind::FutureDropPollShim(..) - | InstanceKind::AsyncDropGlueCtorShim(..) => None, + | InstanceKind::Shim(ShimKind::VTable(..)) + | InstanceKind::Shim(ShimKind::Reify(..)) + | InstanceKind::Shim(ShimKind::FnPtr(..)) + | InstanceKind::Shim(ShimKind::ClosureOnce { .. }) + | InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure { .. }) + | InstanceKind::Shim(ShimKind::DropGlue(..)) + | InstanceKind::Shim(ShimKind::Clone(..)) + | InstanceKind::Shim(ShimKind::ThreadLocal(..)) + | InstanceKind::Shim(ShimKind::FnPtrAddr(..)) + | InstanceKind::Shim(ShimKind::AsyncDropGlue(..)) + | InstanceKind::Shim(ShimKind::FutureDropPoll(..)) + | InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(..)) => None, }, MonoItem::Static(def_id) => def_id.as_local().map(|_| def_id), MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id.to_def_id()), diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index d4817888468fa..9370890c399ec 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -1400,10 +1400,10 @@ rustc_queries! { } /// Generates a MIR body for the shim. - query mir_shims(key: ty::InstanceKind<'tcx>) -> &'tcx mir::Body<'tcx> { + query mir_shims(key: ty::ShimKind<'tcx>) -> &'tcx mir::Body<'tcx> { arena_cache desc { - "generating MIR shim for `{}`, instance={:?}", + "generating MIR shim for `{}`, kind={:?}", tcx.def_path_str(key.def_id()), key } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index c290ba62a3930..757ff1ab0c4b1 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -63,6 +63,12 @@ impl QueryKey for () { } } +impl<'tcx> QueryKey for ty::ShimKind<'tcx> { + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + tcx.def_span(self.def_id()) + } +} + impl<'tcx> QueryKey for ty::InstanceKind<'tcx> { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id()) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 8734d2cde8152..30c299aa82b1a 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -75,12 +75,28 @@ pub enum InstanceKind<'tcx> { /// caller. Intrinsic(DefId), + /// Dynamic dispatch to `::fn`. + /// + /// This `InstanceKind` may have a callable MIR as the default implementation. + /// Calls to `Virtual` instances must be codegen'd as virtual calls through the vtable. + /// *This means we might not know exactly what is being called.* + /// + /// If this is reified to a `fn` pointer, a `ReifyShim` is used (see `ReifyShim` above for more + /// details on that). + Virtual(DefId, usize), + + Shim(ShimKind<'tcx>), +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(TyEncodable, TyDecodable, StableHash, TypeFoldable, TypeVisitable, Lift)] +pub enum ShimKind<'tcx> { /// `::method` where `method` receives unsizeable `self: Self` (part of the /// `unsized_fn_params` feature). /// /// The generated shim will take `Self` via `*mut Self` - conceptually this is `&owned Self` - /// and dereference the argument to call the original function. - VTableShim(DefId), + VTable(DefId), /// `fn()` pointer where the function itself cannot be turned into a pointer. /// @@ -99,22 +115,12 @@ pub enum InstanceKind<'tcx> { /// /// This field will only be populated if we are compiling in a mode that needs these shims /// to be separable, currently only when KCFI is enabled. - ReifyShim(DefId, Option), + Reify(DefId, Option), /// `::call_*` (generated `FnTrait` implementation for `fn()` pointers). /// /// `DefId` is `FnTrait::call_*`. - FnPtrShim(DefId, Ty<'tcx>), - - /// Dynamic dispatch to `::fn`. - /// - /// This `InstanceKind` may have a callable MIR as the default implementation. - /// Calls to `Virtual` instances must be codegen'd as virtual calls through the vtable. - /// *This means we might not know exactly what is being called.* - /// - /// If this is reified to a `fn` pointer, a `ReifyShim` is used (see `ReifyShim` above for more - /// details on that). - Virtual(DefId, usize), + FnPtr(DefId, Ty<'tcx>), /// `<[FnMut/Fn closure] as FnOnce>::call_once`. /// @@ -122,14 +128,14 @@ pub enum InstanceKind<'tcx> { /// /// This generates a body that will just borrow the (owned) self type, /// and dispatch to the `FnMut::call_mut` instance for the closure. - ClosureOnceShim { call_once: DefId, closure: DefId, track_caller: bool }, + ClosureOnce { call_once: DefId, closure: DefId, track_caller: bool }, /// `<[FnMut/Fn coroutine-closure] as FnOnce>::call_once` /// /// The body generated here differs significantly from the `ClosureOnceShim`, /// since we need to generate a distinct coroutine type that will move the /// closure's upvars *out* of the closure. - ConstructCoroutineInClosureShim { + ConstructCoroutineInClosure { coroutine_closure_def_id: DefId, // Whether the generated MIR body takes the coroutine by-ref. This is // because the signature of `<{async fn} as FnMut>::call_mut` is: @@ -142,10 +148,10 @@ pub enum InstanceKind<'tcx> { /// Compiler-generated accessor for thread locals which returns a reference to the thread local /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking /// native support. - ThreadLocalShim(DefId), + ThreadLocal(DefId), /// Proxy shim for async drop of future (def_id, proxy_cor_ty, impl_cor_ty) - FutureDropPollShim(DefId, Ty<'tcx>, Ty<'tcx>), + FutureDropPoll(DefId, Ty<'tcx>, Ty<'tcx>), /// `core::ptr::drop_glue::`. /// @@ -162,20 +168,20 @@ pub enum InstanceKind<'tcx> { /// Additionally, arrays, tuples, and closures get a `Clone` shim even if they aren't `Copy`. /// /// The `DefId` is for `Clone::clone`, the `Ty` is the type `T` with the builtin `Clone` impl. - CloneShim(DefId, Ty<'tcx>), + Clone(DefId, Ty<'tcx>), /// Compiler-generated `::addr` implementation. /// /// Automatically generated for all potentially higher-ranked `fn(I) -> R` types. /// /// The `DefId` is for `FnPtr::addr`, the `Ty` is the type `T`. - FnPtrAddrShim(DefId, Ty<'tcx>), + FnPtrAddr(DefId, Ty<'tcx>), /// `core::future::async_drop::async_drop_in_place::<'_, T>`. /// /// The `DefId` is for `core::future::async_drop::async_drop_in_place`, the `Ty` /// is the type `T`. - AsyncDropGlueCtorShim(DefId, Ty<'tcx>), + AsyncDropGlueCtor(DefId, Ty<'tcx>), /// `core::future::async_drop::async_drop_in_place::<'_, T>::{closure}`. /// @@ -228,10 +234,12 @@ impl<'tcx> Instance<'tcx> { InstanceKind::Item(def) => tcx .upstream_monomorphizations_for(def) .and_then(|monos| monos.get(&self.args).cloned()), - InstanceKind::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args), - InstanceKind::AsyncDropGlue(_, _) => None, - InstanceKind::FutureDropPollShim(_, _, _) => None, - InstanceKind::AsyncDropGlueCtorShim(_, _) => { + InstanceKind::Shim(ShimKind::DropGlue(_, Some(_))) => { + tcx.upstream_drop_glue_for(self.args) + } + InstanceKind::Shim(ShimKind::AsyncDropGlue(_, _)) => None, + InstanceKind::Shim(ShimKind::FutureDropPoll(_, _, _)) => None, + InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(_, _)) => { tcx.upstream_async_drop_glue_for(self.args) } _ => None, @@ -244,45 +252,18 @@ impl<'tcx> InstanceKind<'tcx> { pub fn def_id(self) -> DefId { match self { InstanceKind::Item(def_id) - | InstanceKind::VTableShim(def_id) - | InstanceKind::ReifyShim(def_id, _) - | InstanceKind::FnPtrShim(def_id, _) | InstanceKind::Virtual(def_id, _) - | InstanceKind::Intrinsic(def_id) - | InstanceKind::ThreadLocalShim(def_id) - | InstanceKind::ClosureOnceShim { call_once: def_id, closure: _, track_caller: _ } - | ty::InstanceKind::ConstructCoroutineInClosureShim { - coroutine_closure_def_id: def_id, - receiver_by_ref: _, - } - | InstanceKind::DropGlue(def_id, _) - | InstanceKind::CloneShim(def_id, _) - | InstanceKind::FnPtrAddrShim(def_id, _) - | InstanceKind::FutureDropPollShim(def_id, _, _) - | InstanceKind::AsyncDropGlue(def_id, _) - | InstanceKind::AsyncDropGlueCtorShim(def_id, _) => def_id, + | InstanceKind::Intrinsic(def_id) => def_id, + InstanceKind::Shim(shim) => shim.def_id(), } } /// Returns the `DefId` of instances which might not require codegen locally. pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option { match self { - ty::InstanceKind::Item(def) => Some(def), - ty::InstanceKind::DropGlue(def_id, Some(_)) - | InstanceKind::AsyncDropGlueCtorShim(def_id, _) - | InstanceKind::AsyncDropGlue(def_id, _) - | InstanceKind::FutureDropPollShim(def_id, ..) - | InstanceKind::ThreadLocalShim(def_id) => Some(def_id), - InstanceKind::VTableShim(..) - | InstanceKind::ReifyShim(..) - | InstanceKind::FnPtrShim(..) - | InstanceKind::Virtual(..) - | InstanceKind::Intrinsic(..) - | InstanceKind::ClosureOnceShim { .. } - | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::DropGlue(..) - | InstanceKind::CloneShim(..) - | InstanceKind::FnPtrAddrShim(..) => None, + InstanceKind::Item(def) => Some(def), + InstanceKind::Virtual(..) | InstanceKind::Intrinsic(..) => None, + InstanceKind::Shim(shim) => shim.def_id_if_not_guaranteed_local_codegen(), } } @@ -293,31 +274,28 @@ impl<'tcx> InstanceKind<'tcx> { /// `generates_cgu_internal_copy` for more information. pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool { use rustc_hir::definitions::DefPathData; - let def_id = match *self { - ty::InstanceKind::Item(def) => def, - ty::InstanceKind::DropGlue(_, Some(ty)) => return ty.is_array(), - ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => return ty.is_coroutine(), - ty::InstanceKind::FutureDropPollShim(_, _, _) => return false, - ty::InstanceKind::AsyncDropGlue(_, _) => return false, - ty::InstanceKind::ThreadLocalShim(_) => return false, - _ => return true, - }; - matches!( - tcx.def_key(def_id).disambiguated_data.data, - DefPathData::Ctor | DefPathData::Closure - ) + match *self { + InstanceKind::Item(def_id) => matches!( + tcx.def_key(def_id).disambiguated_data.data, + DefPathData::Ctor | DefPathData::Closure + ), + InstanceKind::Shim(shim) => shim.requires_inline(), + InstanceKind::Virtual(..) | InstanceKind::Intrinsic(..) => true, + } } pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { match *self { InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) - | InstanceKind::VTableShim(def_id) => { + | InstanceKind::Shim(ShimKind::VTable(def_id)) => { tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } - InstanceKind::ClosureOnceShim { call_once: _, closure: _, track_caller } => { - track_caller - } + InstanceKind::Shim(ShimKind::ClosureOnce { + call_once: _, + closure: _, + track_caller, + }) => track_caller, _ => false, } } @@ -330,22 +308,79 @@ impl<'tcx> InstanceKind<'tcx> { /// body should perform necessary instantiations. pub fn has_polymorphic_mir_body(&self) -> bool { match *self { - InstanceKind::CloneShim(..) - | InstanceKind::ThreadLocalShim(..) - | InstanceKind::FnPtrAddrShim(..) - | InstanceKind::FnPtrShim(..) - | InstanceKind::DropGlue(_, Some(_)) - | InstanceKind::FutureDropPollShim(..) - | InstanceKind::AsyncDropGlue(_, _) => false, - InstanceKind::AsyncDropGlueCtorShim(_, _) => false, - InstanceKind::ClosureOnceShim { .. } - | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::DropGlue(..) - | InstanceKind::Item(_) - | InstanceKind::Intrinsic(..) - | InstanceKind::ReifyShim(..) - | InstanceKind::Virtual(..) - | InstanceKind::VTableShim(..) => true, + InstanceKind::Item(_) | InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..) => true, + InstanceKind::Shim(shim) => shim.has_polymorphic_mir_body(), + } + } +} + +impl<'tcx> ShimKind<'tcx> { + #[inline] + pub fn def_id(self) -> DefId { + match self { + ShimKind::VTable(def_id) + | ShimKind::Reify(def_id, _) + | ShimKind::FnPtr(def_id, _) + | ShimKind::ThreadLocal(def_id) + | ShimKind::ClosureOnce { call_once: def_id, closure: _, track_caller: _ } + | ShimKind::ConstructCoroutineInClosure { + coroutine_closure_def_id: def_id, + receiver_by_ref: _, + } + | ShimKind::DropGlue(def_id, _) + | ShimKind::Clone(def_id, _) + | ShimKind::FnPtrAddr(def_id, _) + | ShimKind::FutureDropPoll(def_id, _, _) + | ShimKind::AsyncDropGlue(def_id, _) + | ShimKind::AsyncDropGlueCtor(def_id, _) => def_id, + } + } + + /// Returns the `DefId` of instances which might not require codegen locally. + pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option { + match self { + ShimKind::DropGlue(def_id, Some(_)) + | ShimKind::AsyncDropGlueCtor(def_id, _) + | ShimKind::AsyncDropGlue(def_id, _) + | ShimKind::FutureDropPoll(def_id, ..) + | ShimKind::ThreadLocal(def_id) => Some(def_id), + ShimKind::VTable(..) + | ShimKind::Reify(..) + | ShimKind::FnPtr(..) + | ShimKind::ClosureOnce { .. } + | ShimKind::ConstructCoroutineInClosure { .. } + | ShimKind::DropGlue(..) + | ShimKind::Clone(..) + | ShimKind::FnPtrAddr(..) => None, + } + } + + pub fn requires_inline(&self) -> bool { + match self { + ShimKind::DropGlue(_, Some(ty)) => ty.is_array(), + ShimKind::AsyncDropGlueCtor(_, ty) => ty.is_coroutine(), + ShimKind::FutureDropPoll(_, _, _) => false, + ShimKind::AsyncDropGlue(_, _) => false, + ShimKind::ThreadLocal(_) => false, + _ => true, + } + } + + pub fn has_polymorphic_mir_body(&self) -> bool { + match *self { + ShimKind::Clone(..) + | ShimKind::ThreadLocal(..) + | ShimKind::FnPtrAddr(..) + | ShimKind::FnPtr(..) + | ShimKind::DropGlue(_, Some(_)) + | ShimKind::FutureDropPoll(..) + | ShimKind::AsyncDropGlue(_, _) => false, + ShimKind::AsyncDropGlueCtor(_, _) => false, + ShimKind::ClosureOnce { .. } + | ShimKind::ConstructCoroutineInClosure { .. } + | ShimKind::DropGlue(..) + | ShimKind::Reify(..) + | ShimKind::VTable(..) => true, } } } @@ -416,7 +451,11 @@ fn resolve_async_drop_poll<'tcx>(mut cor_ty: Ty<'tcx>) -> Instance<'tcx> { continue; } else { return Instance { - def: ty::InstanceKind::FutureDropPollShim(poll_def_id, first_cor, cor_ty), + def: ty::InstanceKind::Shim(ShimKind::FutureDropPoll( + poll_def_id, + first_cor, + cor_ty, + )), args: proxy_args, }; } @@ -426,12 +465,16 @@ fn resolve_async_drop_poll<'tcx>(mut cor_ty: Ty<'tcx>) -> Instance<'tcx> { }; if first_cor != cor_ty { return Instance { - def: ty::InstanceKind::FutureDropPollShim(poll_def_id, first_cor, cor_ty), + def: ty::InstanceKind::Shim(ShimKind::FutureDropPoll( + poll_def_id, + first_cor, + cor_ty, + )), args: proxy_args, }; } else { return Instance { - def: ty::InstanceKind::AsyncDropGlue(poll_def_id, cor_ty), + def: ty::InstanceKind::Shim(ShimKind::AsyncDropGlue(poll_def_id, cor_ty)), args: child_args, }; } @@ -599,11 +642,11 @@ impl<'tcx> Instance<'tcx> { match resolved.def { InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => { debug!(" => fn pointer created for function with #[track_caller]"); - resolved.def = InstanceKind::ReifyShim(def, reason); + resolved.def = InstanceKind::Shim(ShimKind::Reify(def, reason)); } InstanceKind::Virtual(def_id, _) => { debug!(" => fn pointer created for virtual call"); - resolved.def = InstanceKind::ReifyShim(def_id, reason); + resolved.def = InstanceKind::Shim(ShimKind::Reify(def_id, reason)); } _ if tcx.sess.is_sanitizer_kcfi_enabled() => { // Reify `::call`-like method implementations @@ -611,7 +654,10 @@ impl<'tcx> Instance<'tcx> { // Reroute through a reify via the *unresolved* instance. The resolved one can't // be directly reified because it's closure-like. The reify can handle the // unresolved instance. - resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args } + resolved = Instance { + def: InstanceKind::Shim(ShimKind::Reify(def_id, reason)), + args, + } // Reify `Trait::method` implementations if the trait is dyn-compatible. } else if let Some(assoc) = tcx.opt_associated_item(def_id) && let AssocContainer::Trait | AssocContainer::TraitImpl(Ok(_)) = @@ -620,7 +666,8 @@ impl<'tcx> Instance<'tcx> { { // If this function could also go in a vtable, we need to `ReifyShim` it with // KCFI because it can only attach one type per function. - resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason) + resolved.def = + InstanceKind::Shim(ShimKind::Reify(resolved.def_id(), reason)) } } _ => {} @@ -645,7 +692,7 @@ impl<'tcx> Instance<'tcx> { if is_vtable_shim { debug!(" => associated item with unsizeable self: Self"); - return Instance { def: InstanceKind::VTableShim(def_id), args }; + return Instance { def: InstanceKind::Shim(ShimKind::VTable(def_id)), args }; } let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span); @@ -688,19 +735,22 @@ impl<'tcx> Instance<'tcx> { // Create a shim for the `FnOnce/FnMut/Fn` method we are calling // - unlike functions, invoking a closure always goes through a // trait. - resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }; + resolved = Instance { + def: InstanceKind::Shim(ShimKind::Reify(def_id, reason)), + args, + }; } else { debug!( " => vtable fn pointer created for function with #[track_caller]: {:?}", def ); - resolved.def = InstanceKind::ReifyShim(def, reason); + resolved.def = InstanceKind::Shim(ShimKind::Reify(def, reason)); } } } InstanceKind::Virtual(def_id, _) => { debug!(" => vtable fn pointer created for virtual call"); - resolved.def = InstanceKind::ReifyShim(def_id, reason) + resolved.def = InstanceKind::Shim(ShimKind::Reify(def_id, reason)) } _ => {} } @@ -770,8 +820,11 @@ impl<'tcx> Instance<'tcx> { .def_id; let track_caller = tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER); - let def = - ty::InstanceKind::ClosureOnceShim { call_once, closure: closure_did, track_caller }; + let def = ty::InstanceKind::Shim(ShimKind::ClosureOnce { + call_once, + closure: closure_did, + track_caller, + }); let self_ty = Ty::new_closure(tcx, closure_did, args); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 980f464cea17f..ab046b5ba0e36 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -85,7 +85,7 @@ pub use self::context::{ CtxtInterners, CurrentGcx, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, }; pub use self::fold::*; -pub use self::instance::{Instance, InstanceKind, ReifyReason}; +pub use self::instance::{Instance, InstanceKind, ReifyReason, ShimKind}; pub(crate) use self::list::RawList; pub use self::list::{List, ListWithCachedTypeInfo}; pub use self::opaque_types::OpaqueTypeKey; @@ -1803,20 +1803,9 @@ impl<'tcx> TyCtxt<'tcx> { _ => self.optimized_mir(def), } } - ty::InstanceKind::VTableShim(..) - | ty::InstanceKind::ReifyShim(..) - | ty::InstanceKind::Intrinsic(..) - | ty::InstanceKind::FnPtrShim(..) - | ty::InstanceKind::Virtual(..) - | ty::InstanceKind::ClosureOnceShim { .. } - | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::FutureDropPollShim(..) - | ty::InstanceKind::DropGlue(..) - | ty::InstanceKind::CloneShim(..) - | ty::InstanceKind::ThreadLocalShim(..) - | ty::InstanceKind::FnPtrAddrShim(..) - | ty::InstanceKind::AsyncDropGlueCtorShim(..) - | ty::InstanceKind::AsyncDropGlue(..) => self.mir_shims(instance), + ty::InstanceKind::Intrinsic(..) => bug!("intrinsics have no instance MIR"), + ty::InstanceKind::Virtual(..) => bug!("virtual dispatches have no instance MIR"), + ty::InstanceKind::Shim(shim) => self.mir_shims(shim), }; assert!( @@ -1942,7 +1931,7 @@ impl<'tcx> TyCtxt<'tcx> { if args[0].has_placeholders() || args[0].has_non_region_param() { return Err(self.layout_error(LayoutError::TooGeneric(ty()))); } - let instance = InstanceKind::AsyncDropGlue(def_id, Ty::new_coroutine(self, def_id, args)); + let instance = ShimKind::AsyncDropGlue(def_id, Ty::new_coroutine(self, def_id, args)); self.mir_shims(instance) .coroutine_layout_raw() .ok_or_else(|| self.layout_error(LayoutError::Unknown(ty()))) diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 29875a3530c15..bec1ffc642769 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -367,35 +367,42 @@ impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print

for ty::Instance<'tcx> { cx.print_def_path(self.def_id(), self.args)?; match self.def { ty::InstanceKind::Item(_) => {} - ty::InstanceKind::VTableShim(_) => cx.write_str(" - shim(vtable)")?, - ty::InstanceKind::ReifyShim(_, None) => cx.write_str(" - shim(reify)")?, - ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::FnPtr)) => { - cx.write_str(" - shim(reify-fnptr)")? - } - ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::Vtable)) => { - cx.write_str(" - shim(reify-vtable)")? - } - ty::InstanceKind::ThreadLocalShim(_) => cx.write_str(" - shim(tls)")?, ty::InstanceKind::Intrinsic(_) => cx.write_str(" - intrinsic")?, ty::InstanceKind::Virtual(_, num) => cx.write_str(&format!(" - virtual#{num}"))?, - ty::InstanceKind::FnPtrShim(_, ty) => cx.write_str(&format!(" - shim({ty})"))?, - ty::InstanceKind::ClosureOnceShim { .. } => cx.write_str(" - shim")?, - ty::InstanceKind::ConstructCoroutineInClosureShim { .. } => cx.write_str(" - shim")?, - ty::InstanceKind::DropGlue(_, None) => cx.write_str(" - shim(None)")?, - ty::InstanceKind::DropGlue(_, Some(ty)) => { - cx.write_str(&format!(" - shim(Some({ty}))"))? + ty::InstanceKind::Shim(shim) => { + cx.write_str(" - ")?; + shim.print(cx)?; + } + } + Ok(()) + } +} + +impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print

for ty::ShimKind<'tcx> { + fn print(&self, cx: &mut P) -> Result<(), PrintError> { + match self { + ty::ShimKind::VTable(_) => cx.write_str("shim(vtable)"), + ty::ShimKind::Reify(_, None) => cx.write_str("shim(reify)"), + ty::ShimKind::Reify(_, Some(ty::ReifyReason::FnPtr)) => { + cx.write_str("shim(reify-fnptr)") } - ty::InstanceKind::CloneShim(_, ty) => cx.write_str(&format!(" - shim({ty})"))?, - ty::InstanceKind::FnPtrAddrShim(_, ty) => cx.write_str(&format!(" - shim({ty})"))?, - ty::InstanceKind::FutureDropPollShim(_, proxy_ty, impl_ty) => { - cx.write_str(&format!(" - dropshim({proxy_ty}-{impl_ty})"))? + ty::ShimKind::Reify(_, Some(ty::ReifyReason::Vtable)) => { + cx.write_str("shim(reify-vtable)") } - ty::InstanceKind::AsyncDropGlue(_, ty) => cx.write_str(&format!(" - shim({ty})"))?, - ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => { - cx.write_str(&format!(" - shim(Some({ty}))"))? + ty::ShimKind::ThreadLocal(_) => cx.write_str("shim(tls)"), + ty::ShimKind::FnPtr(_, ty) => cx.write_str(&format!("shim({ty})")), + ty::ShimKind::ClosureOnce { .. } => cx.write_str("shim"), + ty::ShimKind::ConstructCoroutineInClosure { .. } => cx.write_str("shim"), + ty::ShimKind::DropGlue(_, None) => cx.write_str("shim(None)"), + ty::ShimKind::DropGlue(_, Some(ty)) => cx.write_str(&format!("shim(Some({ty}))")), + ty::ShimKind::Clone(_, ty) => cx.write_str(&format!("shim({ty})")), + ty::ShimKind::FnPtrAddr(_, ty) => cx.write_str(&format!("shim({ty})")), + ty::ShimKind::FutureDropPoll(_, proxy_ty, impl_ty) => { + cx.write_str(&format!("dropshim({proxy_ty}-{impl_ty})")) } - }; - Ok(()) + ty::ShimKind::AsyncDropGlue(_, ty) => cx.write_str(&format!("shim({ty})")), + ty::ShimKind::AsyncDropGlueCtor(_, ty) => cx.write_str(&format!("shim(Some({ty}))")), + } } } diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index 8052ee26df841..ac9f6e384cf04 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -147,7 +147,9 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { // ``` // we should think what is the expected behavior here. // (we should probably just accept this by revealing opaques?) - if caller_sig.inputs_and_output != callee_sig.inputs_and_output { + if caller_sig.inputs_and_output != callee_sig.inputs_and_output + && !matches!(callee_sig.abi(), ExternAbi::RustTail) + { let caller_ty = self.tcx.type_of(self.caller_def_id).skip_binder(); self.report_signature_mismatch( @@ -189,6 +191,12 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { if callee_sig.c_variadic() { self.report_c_variadic_callee(expr.span); } + + for &arg_ty in callee_sig.inputs() { + if !arg_ty.is_sized(self.tcx, self.typing_env) { + self.report_unsized_argument(expr.span, arg_ty); + } + } } /// Returns true if the caller function needs a location argument @@ -417,6 +425,17 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { self.found_errors = Err(err); } + + fn report_unsized_argument(&mut self, sp: Span, arg_ty: Ty<'tcx>) { + let err = self + .tcx + .dcx() + .struct_span_err(sp, format!("unsized arguments cannot be used in a tail call")) + .with_note(format!("unsized argument of type `{arg_ty}`")) + .emit(); + + self.found_errors = Err(err); + } } impl<'a, 'tcx> Visitor<'a, 'tcx> for TailCallCkVisitor<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 411f090e34921..5933892ecd886 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -223,8 +223,10 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( None, &mut PerParentDisambiguatorState::new(parent_def_id), ); - by_move_body.source = - mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); + by_move_body.source = mir::MirSource { + instance: InstanceKind::Item(body_def.def_id().to_def_id()), + promoted: None, + }; if let Some(dumper) = MirDumper::new(tcx, "built", &by_move_body) { dumper.set_disambiguator(&"after").dump_mir(&by_move_body); diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 5be6887e937a1..41b973476af94 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -206,7 +206,7 @@ pub(super) fn create_coroutine_drop_shim<'tcx>( // Update the body's def to become the drop glue. let coroutine_instance = body.source.instance; let drop_glue = tcx.require_lang_item(LangItem::DropGlue, body.span); - let drop_instance = InstanceKind::DropGlue(drop_glue, Some(coroutine_ty)); + let drop_instance = InstanceKind::Shim(ShimKind::DropGlue(drop_glue, Some(coroutine_ty))); // Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible // filename. diff --git a/compiler/rustc_mir_transform/src/coroutine/mod.rs b/compiler/rustc_mir_transform/src/coroutine/mod.rs index bb57ca1cd90a7..53283680c0966 100644 --- a/compiler/rustc_mir_transform/src/coroutine/mod.rs +++ b/compiler/rustc_mir_transform/src/coroutine/mod.rs @@ -71,7 +71,7 @@ use rustc_index::{Idx, IndexVec, indexvec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{ - self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, + self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, ShimKind, Ty, TyCtxt, }; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::always_storage_live_locals; diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index df71cd48a77fe..e4ce2fb1ad3d2 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -15,7 +15,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{ - self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt, Unnormalized, + self, Instance, InstanceKind, ShimKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt, Unnormalized, }; use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::Spanned; @@ -739,18 +739,21 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>( // the correct param-env for types being dropped. Stall resolving // the MIR for this instance until all of its const params are // substituted. - InstanceKind::DropGlue(_, Some(ty)) if ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => { + InstanceKind::Shim(ShimKind::DropGlue(_, Some(ty))) + if ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => + { debug!("still needs substitution"); return Err("implementation limitation -- HACK for dropping polymorphic type"); } - InstanceKind::AsyncDropGlue(_, ty) | InstanceKind::AsyncDropGlueCtorShim(_, ty) => { + InstanceKind::Shim(ShimKind::AsyncDropGlue(_, ty)) + | InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(_, ty)) => { return if ty.still_further_specializable() { Err("still needs substitution") } else { Ok(()) }; } - InstanceKind::FutureDropPollShim(_, ty, ty2) => { + InstanceKind::Shim(ShimKind::FutureDropPoll(_, ty, ty2)) => { return if ty.still_further_specializable() || ty2.still_further_specializable() { Err("still needs substitution") } else { @@ -762,15 +765,15 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>( // not get any optimizations run on it. Any subsequent inlining may cause cycles, but we // do not need to catch this here, we can wait until the inliner decides to continue // inlining a second time. - InstanceKind::VTableShim(_) - | InstanceKind::ReifyShim(..) - | InstanceKind::FnPtrShim(..) - | InstanceKind::ClosureOnceShim { .. } - | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::DropGlue(..) - | InstanceKind::CloneShim(..) - | InstanceKind::ThreadLocalShim(..) - | InstanceKind::FnPtrAddrShim(..) => return Ok(()), + InstanceKind::Shim(ShimKind::VTable(_)) + | InstanceKind::Shim(ShimKind::Reify(..)) + | InstanceKind::Shim(ShimKind::FnPtr(..)) + | InstanceKind::Shim(ShimKind::ClosureOnce { .. }) + | InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure { .. }) + | InstanceKind::Shim(ShimKind::DropGlue(..)) + | InstanceKind::Shim(ShimKind::Clone(..)) + | InstanceKind::Shim(ShimKind::ThreadLocal(..)) + | InstanceKind::Shim(ShimKind::FnPtrAddr(..)) => return Ok(()), } if inliner.tcx().is_constructor(callee_def_id) { @@ -1370,8 +1373,8 @@ fn try_instance_mir<'tcx>( tcx: TyCtxt<'tcx>, instance: InstanceKind<'tcx>, ) -> Result<&'tcx Body<'tcx>, &'static str> { - if let ty::InstanceKind::DropGlue(_, Some(ty)) | ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) = - instance + if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, Some(ty))) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_, ty)) = instance && let ty::Adt(def, args) = ty.kind() { let fields = def.all_fields(); diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 9d031b6548021..ee63dd966baf6 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -4,7 +4,7 @@ use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::limit::Limit; use rustc_middle::mir::TerminatorKind; -use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, ShimKind, TyCtxt, TypeVisitableExt}; use rustc_span::sym; use tracing::{instrument, trace}; @@ -26,24 +26,24 @@ fn should_recurse<'tcx>(tcx: TyCtxt<'tcx>, callee: ty::Instance<'tcx>) -> bool { // These have MIR and if that MIR is inlined, instantiated and then inlining is run // again, a function item can end up getting inlined. Thus we'll be able to cause // a cycle that way - InstanceKind::VTableShim(_) - | InstanceKind::ReifyShim(..) - | InstanceKind::FnPtrShim(..) - | InstanceKind::ClosureOnceShim { .. } - | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::ThreadLocalShim { .. } - | InstanceKind::CloneShim(..) => {} + InstanceKind::Shim(ShimKind::VTable(_)) + | InstanceKind::Shim(ShimKind::Reify(..)) + | InstanceKind::Shim(ShimKind::FnPtr(..)) + | InstanceKind::Shim(ShimKind::ClosureOnce { .. }) + | InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure { .. }) + | InstanceKind::Shim(ShimKind::ThreadLocal { .. }) + | InstanceKind::Shim(ShimKind::Clone(..)) => {} // This shim does not call any other functions, thus there can be no recursion. - InstanceKind::FnPtrAddrShim(..) => return false, + InstanceKind::Shim(ShimKind::FnPtrAddr(..)) => return false, // FIXME: A not fully instantiated drop shim can cause ICEs if one attempts to // have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this // needs some more analysis. - InstanceKind::DropGlue(..) - | InstanceKind::FutureDropPollShim(..) - | InstanceKind::AsyncDropGlue(..) - | InstanceKind::AsyncDropGlueCtorShim(..) => { + InstanceKind::Shim(ShimKind::DropGlue(..)) + | InstanceKind::Shim(ShimKind::FutureDropPoll(..)) + | InstanceKind::Shim(ShimKind::AsyncDropGlue(..)) + | InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(..)) => { if callee.has_param() { return false; } diff --git a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs b/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs index 81e98585995fd..b359077753fd6 100644 --- a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs +++ b/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs @@ -93,8 +93,8 @@ fn find_unreachable_code_from<'tcx>( bb: BasicBlock, body: &Body<'tcx>, ) -> Option<(SourceInfo, &'static str)> { - let bb = &body.basic_blocks[bb]; - for stmt in &bb.statements { + let bbdata = &body.basic_blocks[bb]; + for stmt in &bbdata.statements { match &stmt.kind { // Ignore the implicit `()` return place assignment for unit functions/blocks StatementKind::Assign((_, Rvalue::Use(Operand::Constant(const_), _))) @@ -108,7 +108,10 @@ fn find_unreachable_code_from<'tcx>( StatementKind::Assign((place, _)) if place.as_local() == Some(RETURN_PLACE) => { continue; } - StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => { + // Ignore statements inserted by MIR building that do not correspond to user code. + StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) + | StatementKind::BackwardIncompatibleDropHint { .. } => { continue; } StatementKind::FakeRead(..) => return Some((stmt.source_info, "definition")), @@ -116,10 +119,18 @@ fn find_unreachable_code_from<'tcx>( } } - let term = bb.terminator(); + let term = bbdata.terminator(); match term.kind { - // No user code in this bb, and our goto target may be reachable via other paths - TerminatorKind::Goto { .. } | TerminatorKind::Return => None, + // The user does not care for `goto` and compiler-generated drops. If the target block is + // only reachable through those terminators, continue searching there. + TerminatorKind::Goto { target } | TerminatorKind::Drop { target, .. } => { + if &body.basic_blocks.predecessors()[target][..] == &[bb] { + find_unreachable_code_from(target, body) + } else { + None + } + } + TerminatorKind::Return => None, _ => Some((term.source_info, "expression")), } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 6d9b8feea05f4..436b99811ae60 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -31,16 +31,15 @@ pub(super) fn provide(providers: &mut Providers) { providers.mir_shims = make_shim; } -fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<'tcx> { - debug!("make_shim({:?})", instance); +fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, shim: ty::ShimKind<'tcx>) -> Body<'tcx> { + debug!("make_shim({:?})", shim); - let mut result = match instance { - ty::InstanceKind::Item(..) => bug!("item {:?} passed to make_shim", instance), - ty::InstanceKind::VTableShim(def_id) => { + let mut result = match shim { + ty::ShimKind::VTable(def_id) => { let adjustment = Adjustment::Deref { source: DerefSource::MutPtr }; - build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id)) + build_call_shim(tcx, shim, Some(adjustment), CallKind::Direct(def_id)) } - ty::InstanceKind::FnPtrShim(def_id, ty) => { + ty::ShimKind::FnPtr(def_id, ty) => { let trait_ = tcx.parent(def_id); // Supports `Fn` or `async Fn` traits. let adjustment = match tcx @@ -53,17 +52,17 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< None => bug!("fn pointer {:?} is not an fn", ty), }; - build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect(ty)) + build_call_shim(tcx, shim, Some(adjustment), CallKind::Indirect(ty)) } // We are generating a call back to our def-id, which the // codegen backend knows to turn to an actual call, be it // a virtual call, or a direct call to a function for which // indirect calls must be codegen'd differently than direct ones // (such as `#[track_caller]`). - ty::InstanceKind::ReifyShim(def_id, _) => { - build_call_shim(tcx, instance, None, CallKind::Direct(def_id)) + ty::ShimKind::Reify(def_id, _) => { + build_call_shim(tcx, shim, None, CallKind::Direct(def_id)) } - ty::InstanceKind::ClosureOnceShim { call_once: _, closure: _, track_caller: _ } => { + ty::ShimKind::ClosureOnce { call_once: _, closure: _, track_caller: _ } => { let fn_mut = tcx.require_lang_item(LangItem::FnMut, DUMMY_SP); let call_mut = tcx .associated_items(fn_mut) @@ -72,15 +71,14 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< .unwrap() .def_id; - build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut)) + build_call_shim(tcx, shim, Some(Adjustment::RefMut), CallKind::Direct(call_mut)) } - ty::InstanceKind::ConstructCoroutineInClosureShim { - coroutine_closure_def_id, - receiver_by_ref, - } => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref), + ty::ShimKind::ConstructCoroutineInClosure { coroutine_closure_def_id, receiver_by_ref } => { + build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref) + } - ty::InstanceKind::DropGlue(def_id, ty) => { + ty::ShimKind::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? if let Some(&ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { @@ -110,7 +108,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args).skip_norm_wip(); - debug!("make_shim({:?}) = {:?}", instance, body); + debug!("make_shim({:?}) = {:?}", shim, body); pm::run_passes( tcx, @@ -129,10 +127,10 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< build_drop_shim(tcx, def_id, ty, ty::TypingEnv::post_analysis(tcx, def_id)) } - ty::InstanceKind::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance), - ty::InstanceKind::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty), - ty::InstanceKind::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty), - ty::InstanceKind::FutureDropPollShim(def_id, proxy_ty, impl_ty) => { + ty::ShimKind::ThreadLocal(..) => build_thread_local_shim(tcx, shim), + ty::ShimKind::Clone(def_id, ty) => build_clone_shim(tcx, def_id, ty), + ty::ShimKind::FnPtrAddr(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty), + ty::ShimKind::FutureDropPoll(def_id, proxy_ty, impl_ty) => { let mut body = async_destructor_ctor::build_future_drop_poll_shim(tcx, def_id, proxy_ty, impl_ty); @@ -148,10 +146,10 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< pm::Optimizations::Allowed, ); run_optimization_passes(tcx, &mut body); - debug!("make_shim({:?}) = {:?}", instance, body); + debug!("make_shim({:?}) = {:?}", shim, body); return body; } - ty::InstanceKind::AsyncDropGlue(def_id, ty) => { + ty::ShimKind::AsyncDropGlue(def_id, ty) => { let mut body = async_destructor_ctor::build_async_drop_shim(tcx, def_id, ty); // Main pass required here is StateTransform to convert sync drop ladder @@ -170,23 +168,17 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< Some(MirPhase::Runtime(RuntimePhase::PostCleanup)), ); run_optimization_passes(tcx, &mut body); - debug!("make_shim({:?}) = {:?}", instance, body); + debug!("make_shim({:?}) = {:?}", shim, body); return body; } - ty::InstanceKind::AsyncDropGlueCtorShim(def_id, ty) => { + ty::ShimKind::AsyncDropGlueCtor(def_id, ty) => { let body = async_destructor_ctor::build_async_destructor_ctor_shim(tcx, def_id, ty); - debug!("make_shim({:?}) = {:?}", instance, body); + debug!("make_shim({:?}) = {:?}", shim, body); return body; } - ty::InstanceKind::Virtual(..) => { - bug!("InstanceKind::Virtual ({:?}) is for direct calls only", instance) - } - ty::InstanceKind::Intrinsic(_) => { - bug!("creating shims from intrinsics ({:?}) is unsupported", instance) - } }; - debug!("make_shim({:?}) = untransformed {:?}", instance, result); + debug!("make_shim({:?}) = untransformed {:?}", shim, result); deref_finder(tcx, &mut result, false); @@ -211,7 +203,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); - debug!("make_shim({:?}) = {:?}", instance, result); + debug!("make_shim({:?}) = {:?}", shim, result); result } @@ -300,7 +292,7 @@ pub fn build_drop_shim<'tcx>( } block(&mut blocks, TerminatorKind::Return); - let source = MirSource::from_instance(ty::InstanceKind::DropGlue(def_id, ty)); + let source = MirSource::from_shim(ty::ShimKind::DropGlue(def_id, ty)); let mut body = new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); @@ -480,11 +472,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { } } -fn build_thread_local_shim<'tcx>( - tcx: TyCtxt<'tcx>, - instance: ty::InstanceKind<'tcx>, -) -> Body<'tcx> { - let def_id = instance.def_id(); +fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, shim: ty::ShimKind<'tcx>) -> Body<'tcx> { + let def_id = shim.def_id(); let span = tcx.def_span(def_id); let source_info = SourceInfo::outermost(span); @@ -502,7 +491,7 @@ fn build_thread_local_shim<'tcx>( )]); new_body( - MirSource::from_instance(instance), + MirSource::from_shim(shim), blocks, IndexVec::from_raw(vec![LocalDecl::new(tcx.thread_local_ptr_ty(def_id), span)]), 0, @@ -565,10 +554,8 @@ impl<'tcx> CloneShimBuilder<'tcx> { } fn into_mir(self) -> Body<'tcx> { - let source = MirSource::from_instance(ty::InstanceKind::CloneShim( - self.def_id, - self.sig.inputs_and_output[0], - )); + let source = + MirSource::from_shim(ty::ShimKind::Clone(self.def_id, self.sig.inputs_and_output[0])); new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span) } @@ -776,14 +763,14 @@ impl<'tcx> CloneShimBuilder<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] fn build_call_shim<'tcx>( tcx: TyCtxt<'tcx>, - instance: ty::InstanceKind<'tcx>, + shim: ty::ShimKind<'tcx>, rcvr_adjustment: Option, call_kind: CallKind<'tcx>, ) -> Body<'tcx> { // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used // to instantiate into the signature of the shim. It is not necessary for users of this // MIR body to perform further instantiations (see `InstanceKind::has_polymorphic_mir_body`). - let (sig_args, untuple_args) = if let ty::InstanceKind::FnPtrShim(_, ty) = instance { + let (sig_args, untuple_args) = if let ty::ShimKind::FnPtr(_, ty) = shim { let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx)); let untuple_args = sig.inputs(); @@ -796,12 +783,12 @@ fn build_call_shim<'tcx>( (None, None) }; - let def_id = instance.def_id(); + let def_id = shim.def_id(); let sig = tcx.fn_sig(def_id); let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig)); - assert_eq!(sig_args.is_some(), !instance.has_polymorphic_mir_body()); + assert_eq!(sig_args.is_some(), !shim.has_polymorphic_mir_body()); let mut sig = if let Some(sig_args) = sig_args { sig.instantiate(tcx, &sig_args).skip_norm_wip() } else { @@ -830,14 +817,14 @@ fn build_call_shim<'tcx>( DerefSource::MutRef => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fnty), DerefSource::MutPtr => Ty::new_mut_ptr(tcx, fnty), }, - Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {instance:?}"), + Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {shim:?}"), }; sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); } // FIXME: Avoid having to adjust the signature both here and in // `fn_sig_for_fn_abi`. - if let ty::InstanceKind::VTableShim(..) = instance { + if let ty::ShimKind::VTable(..) = shim { // Modify fn(self, ...) to fn(self: *mut Self, ...) let mut inputs_and_output = sig.inputs_and_output.to_vec(); let self_arg = &mut inputs_and_output[0]; @@ -995,7 +982,7 @@ fn build_call_shim<'tcx>( } let mut body = - new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span); + new_body(MirSource::from_shim(shim), blocks, local_decls, sig.inputs().len(), span); if let ExternAbi::RustCall = sig.abi() { body.spread_arg = Some(Local::new(sig.inputs().len())); @@ -1119,7 +1106,7 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }), false, ); - let source = MirSource::from_instance(ty::InstanceKind::FnPtrAddrShim(def_id, self_ty)); + let source = MirSource::from_shim(ty::ShimKind::FnPtrAddr(def_id, self_ty)); new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span) } @@ -1218,7 +1205,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>( false, ); - let source = MirSource::from_instance(ty::InstanceKind::ConstructCoroutineInClosureShim { + let source = MirSource::from_shim(ty::ShimKind::ConstructCoroutineInClosure { coroutine_closure_def_id, receiver_by_ref, }); diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index da88247800372..f6217f1234bfc 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -106,7 +106,7 @@ pub(super) fn build_async_drop_shim<'tcx>( ); block(&mut blocks, TerminatorKind::Return); - let source = MirSource::from_instance(ty::InstanceKind::AsyncDropGlue(def_id, ty)); + let source = MirSource::from_shim(ty::ShimKind::AsyncDropGlue(def_id, ty)); let mut body = new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); @@ -175,17 +175,17 @@ pub(super) fn build_future_drop_poll_shim<'tcx>( proxy_ty: Ty<'tcx>, impl_ty: Ty<'tcx>, ) -> Body<'tcx> { - let instance = ty::InstanceKind::FutureDropPollShim(def_id, proxy_ty, impl_ty); + let shim = ty::ShimKind::FutureDropPoll(def_id, proxy_ty, impl_ty); let ty::Coroutine(coroutine_def_id, _) = impl_ty.kind() else { - bug!("build_future_drop_poll_shim not for coroutine impl type: ({:?})", instance); + bug!("build_future_drop_poll_shim not for coroutine impl type: ({:?})", shim); }; let span = tcx.def_span(def_id); if tcx.is_async_drop_in_place_coroutine(*coroutine_def_id) { - build_adrop_for_adrop_shim(tcx, proxy_ty, impl_ty, span, instance) + build_adrop_for_adrop_shim(tcx, proxy_ty, impl_ty, span, shim) } else { - build_adrop_for_coroutine_shim(tcx, proxy_ty, impl_ty, span, instance) + build_adrop_for_coroutine_shim(tcx, proxy_ty, impl_ty, span, shim) } } @@ -198,16 +198,16 @@ fn build_adrop_for_coroutine_shim<'tcx>( proxy_ty: Ty<'tcx>, impl_ty: Ty<'tcx>, span: Span, - instance: ty::InstanceKind<'tcx>, + shim: ty::ShimKind<'tcx>, ) -> Body<'tcx> { let ty::Coroutine(coroutine_def_id, impl_args) = impl_ty.kind() else { - bug!("build_adrop_for_coroutine_shim not for coroutine impl type: ({:?})", instance); + bug!("build_adrop_for_coroutine_shim not for coroutine impl type: ({:?})", shim); }; let source_info = SourceInfo::outermost(span); let body = tcx.optimized_mir(*coroutine_def_id).future_drop_poll().unwrap(); let mut body: Body<'tcx> = EarlyBinder::bind(body.clone()).instantiate(tcx, impl_args).skip_norm_wip(); - body.source.instance = instance; + body.source.instance = ty::InstanceKind::Shim(shim); body.phase = MirPhase::Runtime(RuntimePhase::Initial); body.var_debug_info.clear(); @@ -291,7 +291,7 @@ fn build_adrop_for_adrop_shim<'tcx>( proxy_ty: Ty<'tcx>, impl_ty: Ty<'tcx>, span: Span, - instance: ty::InstanceKind<'tcx>, + shim: ty::ShimKind<'tcx>, ) -> Body<'tcx> { let source_info = SourceInfo::outermost(span); let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty); @@ -413,7 +413,7 @@ fn build_adrop_for_adrop_shim<'tcx>( false, )); - let source = MirSource::from_instance(instance); + let source = MirSource::from_shim(shim); let mut body = new_body(source, blocks, locals, sig.inputs().len(), span); body.phase = MirPhase::Runtime(RuntimePhase::Initial); return body; diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 0421edc543151..20aaeba4c8c65 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -226,8 +226,8 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion}; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ - self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable, - TypeVisitable, TypeVisitableExt, TypeVisitor, Unnormalized, VtblEntry, + self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, ShimKind, Ty, TyCtxt, + TypeFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, Unnormalized, VtblEntry, }; use rustc_middle::util::Providers; use rustc_middle::{bug, span_bug}; @@ -447,7 +447,7 @@ fn collect_items_rec<'tcx>( used_items.push(respan( starting_item.span, MonoItem::Fn(Instance { - def: InstanceKind::ThreadLocalShim(def_id), + def: InstanceKind::Shim(ShimKind::ThreadLocal(def_id)), args: GenericArgs::empty(), }), )); @@ -1013,10 +1013,10 @@ fn visit_instance_use<'tcx>( bug!("{:?} being reified", instance); } } - ty::InstanceKind::ThreadLocalShim(..) => { + ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(..)) => { bug!("{:?} being reified", instance); } - ty::InstanceKind::DropGlue(_, None) => { + ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) => { // Don't need to emit noop drop glue if we are calling directly. // // Note that we also optimize away the call to visit_instance_use in vtable construction @@ -1025,18 +1025,18 @@ fn visit_instance_use<'tcx>( output.push(create_fn_mono_item(tcx, instance, source)); } } - ty::InstanceKind::DropGlue(_, Some(_)) - | ty::InstanceKind::FutureDropPollShim(..) - | ty::InstanceKind::AsyncDropGlue(_, _) - | ty::InstanceKind::AsyncDropGlueCtorShim(_, _) - | ty::InstanceKind::VTableShim(..) - | ty::InstanceKind::ReifyShim(..) - | ty::InstanceKind::ClosureOnceShim { .. } - | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::Item(..) - | ty::InstanceKind::FnPtrShim(..) - | ty::InstanceKind::CloneShim(..) - | ty::InstanceKind::FnPtrAddrShim(..) => { + ty::InstanceKind::Item(..) + | ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, Some(_))) + | ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(..)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_, _)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_, _)) + | ty::InstanceKind::Shim(ty::ShimKind::VTable(..)) + | ty::InstanceKind::Shim(ty::ShimKind::Reify(..)) + | ty::InstanceKind::Shim(ty::ShimKind::ClosureOnce { .. }) + | ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure { .. }) + | ty::InstanceKind::Shim(ty::ShimKind::FnPtr(..)) + | ty::InstanceKind::Shim(ty::ShimKind::Clone(..)) + | ty::InstanceKind::Shim(ty::ShimKind::FnPtrAddr(..)) => { output.push(create_fn_mono_item(tcx, instance, source)); } } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index aee7153419883..bf4a2bdd15107 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -115,7 +115,7 @@ use rustc_middle::mono::{ MonoItemPartitions, Visibility, }; use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths}; -use rustc_middle::ty::{self, InstanceKind, TyCtxt}; +use rustc_middle::ty::{self, InstanceKind, ShimKind, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::CodegenUnits; use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath}; @@ -630,20 +630,20 @@ fn characteristic_def_id_of_mono_item<'tcx>( MonoItem::Fn(instance) => { let def_id = match instance.def { ty::InstanceKind::Item(def) => def, - ty::InstanceKind::VTableShim(..) - | ty::InstanceKind::ReifyShim(..) - | ty::InstanceKind::FnPtrShim(..) - | ty::InstanceKind::ClosureOnceShim { .. } - | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::Intrinsic(..) - | ty::InstanceKind::DropGlue(..) + ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::Virtual(..) - | ty::InstanceKind::CloneShim(..) - | ty::InstanceKind::ThreadLocalShim(..) - | ty::InstanceKind::FnPtrAddrShim(..) - | ty::InstanceKind::FutureDropPollShim(..) - | ty::InstanceKind::AsyncDropGlue(..) - | ty::InstanceKind::AsyncDropGlueCtorShim(..) => return None, + | ty::InstanceKind::Shim(ty::ShimKind::VTable(..)) + | ty::InstanceKind::Shim(ty::ShimKind::Reify(..)) + | ty::InstanceKind::Shim(ty::ShimKind::FnPtr(..)) + | ty::InstanceKind::Shim(ty::ShimKind::ClosureOnce { .. }) + | ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure { .. }) + | ty::InstanceKind::Shim(ty::ShimKind::DropGlue(..)) + | ty::InstanceKind::Shim(ty::ShimKind::Clone(..)) + | ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(..)) + | ty::InstanceKind::Shim(ty::ShimKind::FnPtrAddr(..)) + | ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(..)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(..)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(..)) => return None, }; // If this is a method, we want to put it into the same module as @@ -794,27 +794,27 @@ fn mono_item_visibility<'tcx>( let def_id = match instance.def { InstanceKind::Item(def_id) - | InstanceKind::DropGlue(def_id, Some(_)) - | InstanceKind::FutureDropPollShim(def_id, _, _) - | InstanceKind::AsyncDropGlue(def_id, _) - | InstanceKind::AsyncDropGlueCtorShim(def_id, _) => def_id, + | InstanceKind::Shim(ShimKind::DropGlue(def_id, Some(_))) + | InstanceKind::Shim(ShimKind::FutureDropPoll(def_id, _, _)) + | InstanceKind::Shim(ShimKind::AsyncDropGlue(def_id, _)) + | InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(def_id, _)) => def_id, // We match the visibility of statics here - InstanceKind::ThreadLocalShim(def_id) => { + InstanceKind::Shim(ShimKind::ThreadLocal(def_id)) => { return static_visibility(tcx, can_be_internalized, def_id); } // These are all compiler glue and such, never exported, always hidden. - InstanceKind::VTableShim(..) - | InstanceKind::ReifyShim(..) - | InstanceKind::FnPtrShim(..) + InstanceKind::Shim(ShimKind::VTable(..)) + | InstanceKind::Shim(ShimKind::Reify(..)) + | InstanceKind::Shim(ShimKind::FnPtr(..)) | InstanceKind::Virtual(..) | InstanceKind::Intrinsic(..) - | InstanceKind::ClosureOnceShim { .. } - | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::DropGlue(..) - | InstanceKind::CloneShim(..) - | InstanceKind::FnPtrAddrShim(..) => return Visibility::Hidden, + | InstanceKind::Shim(ShimKind::ClosureOnce { .. }) + | InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure { .. }) + | InstanceKind::Shim(ShimKind::DropGlue(..)) + | InstanceKind::Shim(ShimKind::Clone(..)) + | InstanceKind::Shim(ShimKind::FnPtrAddr(..)) => return Visibility::Hidden, }; // Both the `start_fn` lang item and `main` itself should not be exported, @@ -1331,8 +1331,8 @@ pub(crate) fn provide(providers: &mut Providers) { // "Normal" functions size estimate: the number of // statements, plus one for the terminator. InstanceKind::Item(..) - | InstanceKind::DropGlue(..) - | InstanceKind::AsyncDropGlueCtorShim(..) => { + | InstanceKind::Shim(ShimKind::DropGlue(..)) + | InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(..)) => { let mir = tcx.instance_mir(instance.def); mir.basic_blocks .iter() diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index 3bf2f64cf8887..675c8be873f0d 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -121,24 +121,21 @@ where alias_term: AliasTerm, has_escaping: HasEscapingBoundVars, ) -> Result, NoSolution> { - let current_universe = self.infcx.universe(); - self.infcx.create_next_universe(); - let (normalized, ambig_goal) = (self.normalize)(alias_term)?; // Return ambiguous higher ranked alias as is, if // - it contains escaping vars, and - // - the normalized term contains infer vars newly created - // in the normalization above. - // The problem is that they may be resolved to types - // referencing the temporary placeholders. + // - the normalized term contains infer vars which may mention + // temporary placeholders after we've already mapped them back + // to bound vars. // - // We can normalize the ambiguous alias again after the binder is instantiated. + // We can normalize the ambiguous alias again after the binder is instantiated + // or once we've made further inference progress. if ambig_goal.is_some() && has_escaping == HasEscapingBoundVars::Yes { let mut visitor = MaxUniverse::new(self.infcx); normalized.visit_with(&mut visitor); let max_universe = visitor.max_universe(); - if current_universe.cannot_name(max_universe) { + if max_universe.can_name(self.universes.first().unwrap().unwrap()) { return Ok(None); } } diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index 22ec84231af49..768a9546cccd4 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -rustc-literal-escaper = "0.0.7" +rustc-literal-escaper = "0.0.8" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index 10b41a39c3bf2..e6922a5f2c919 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -rustc-literal-escaper = "0.0.7" +rustc-literal-escaper = "0.0.8" rustc_lexer = { path = "../rustc_lexer" } # tidy-alphabetical-end diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index f6c4b0cf77d12..a4ba014d2f6aa 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -5,7 +5,6 @@ use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, MultiSpan, msg, }; -use rustc_hir::Target; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{MainDefinition, Ty}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol}; @@ -326,14 +325,6 @@ pub(crate) struct DeprecatedAnnotationHasNoEffect { pub span: Span, } -#[derive(Diagnostic)] -#[diag("unknown external lang item: `{$lang_item}`", code = E0264)] -pub(crate) struct UnknownExternLangItem { - #[primary_span] - pub span: Span, - pub lang_item: Symbol, -} - #[derive(Diagnostic)] #[diag("`#[panic_handler]` function required, but not found")] pub(crate) struct MissingPanicHandler; @@ -398,17 +389,6 @@ pub(crate) struct LangItemWithTargetFeature { pub sig_span: Span, } -#[derive(Diagnostic)] -#[diag("`{$name}` lang item must be applied to a {$expected_target}", code = E0718)] -pub(crate) struct LangItemOnIncorrectTarget { - #[primary_span] - #[label("attribute should be applied to a {$expected_target}, not a {$actual_target}")] - pub span: Span, - pub name: Symbol, - pub expected_target: Target, - pub actual_target: Target, -} - #[derive(Diagnostic)] #[diag("duplicate diagnostic item in crate `{$crate_name}`: `{$name}`")] pub(crate) struct DuplicateDiagnosticItemInCrate { diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 53fb6888ddcd8..1686b4d595933 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -18,9 +18,7 @@ use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::cstore::ExternCrate; use rustc_span::{Span, Symbol, sym}; -use crate::diagnostics::{ - DuplicateLangItem, IncorrectCrateType, IncorrectTarget, LangItemOnIncorrectTarget, -}; +use crate::diagnostics::{DuplicateLangItem, IncorrectCrateType, IncorrectTarget}; use crate::weak_lang_items; pub(crate) enum Duplicate { @@ -63,8 +61,14 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { ) { if let Some((name, attr_span)) = extract_ast(attrs) { match LangItem::from_name(name) { - // Known lang item with attribute on correct target. - Some(lang_item) if actual_target == lang_item.target() => { + // Known lang item + Some(lang_item) => { + if actual_target != lang_item.target() { + self.tcx + .dcx() + .delayed_bug("lang item target is checked in attribute parser"); + return; + } self.collect_item_extended( lang_item, def_id, @@ -74,15 +78,6 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { actual_target, ); } - // Known lang item with attribute on incorrect target. - Some(lang_item) => { - self.tcx.dcx().emit_err(LangItemOnIncorrectTarget { - span: attr_span, - name, - expected_target: lang_item.target(), - actual_target, - }); - } // Unknown lang item. _ => { self.tcx.dcx().delayed_bug("unknown lang item"); diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index b42b27ec74184..50730b852455c 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -9,9 +9,7 @@ use rustc_middle::middle::lang_items::required; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; -use crate::diagnostics::{ - MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd, UnknownExternLangItem, -}; +use crate::diagnostics::{MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd}; use crate::lang_items::extract_ast; /// Checks the crate for usage of weak lang items, returning a vector of all the @@ -28,27 +26,23 @@ pub(crate) fn check_crate( items.missing.push(LangItem::EhPersonality); } - visit::Visitor::visit_crate(&mut WeakLangItemVisitor { tcx, items }, krate); + visit::Visitor::visit_crate(&mut WeakLangItemVisitor { items }, krate); verify(tcx, items); } -struct WeakLangItemVisitor<'a, 'tcx> { - tcx: TyCtxt<'tcx>, +struct WeakLangItemVisitor<'a> { items: &'a mut lang_items::LanguageItems, } -impl<'ast> visit::Visitor<'ast> for WeakLangItemVisitor<'_, '_> { +impl<'ast> visit::Visitor<'ast> for WeakLangItemVisitor<'_> { fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) { - if let Some((lang_item, _)) = extract_ast(&i.attrs) { - if let Some(item) = LangItem::from_name(lang_item) - && item.is_weak() - { - if self.items.get(item).is_none() { - self.items.missing.push(item); - } - } else { - self.tcx.dcx().emit_err(UnknownExternLangItem { span: i.span, lang_item }); + if let Some((lang_item, _)) = extract_ast(&i.attrs) + && let Some(item) = LangItem::from_name(lang_item) + && item.is_weak() + { + if self.items.get(item).is_none() { + self.items.missing.push(item); } } } diff --git a/compiler/rustc_proc_macro/Cargo.toml b/compiler/rustc_proc_macro/Cargo.toml index 54c765075113e..e31bb4efe363d 100644 --- a/compiler/rustc_proc_macro/Cargo.toml +++ b/compiler/rustc_proc_macro/Cargo.toml @@ -16,7 +16,7 @@ doctest = false [dependencies] # tidy-alphabetical-start -rustc-literal-escaper = "0.0.7" +rustc-literal-escaper = "0.0.8" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index f9ee9f4ee779e..8d57dd7f03033 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -994,18 +994,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { ty::InstanceKind::Virtual(_def_id, idx) => { crate::mir::mono::InstanceKind::Virtual { idx } } - ty::InstanceKind::VTableShim(..) - | ty::InstanceKind::ReifyShim(..) - | ty::InstanceKind::FnPtrAddrShim(..) - | ty::InstanceKind::ClosureOnceShim { .. } - | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::ThreadLocalShim(..) - | ty::InstanceKind::DropGlue(..) - | ty::InstanceKind::CloneShim(..) - | ty::InstanceKind::FnPtrShim(..) - | ty::InstanceKind::FutureDropPollShim(..) - | ty::InstanceKind::AsyncDropGlue(..) - | ty::InstanceKind::AsyncDropGlueCtorShim(..) => crate::mir::mono::InstanceKind::Shim, + ty::InstanceKind::Shim(..) => crate::mir::mono::InstanceKind::Shim, }; crate::mir::mono::Instance { def, kind } } diff --git a/compiler/rustc_public_bridge/src/context/impls.rs b/compiler/rustc_public_bridge/src/context/impls.rs index c309df59e9eca..87a8661edeb65 100644 --- a/compiler/rustc_public_bridge/src/context/impls.rs +++ b/compiler/rustc_public_bridge/src/context/impls.rs @@ -645,7 +645,7 @@ impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> { /// Check if this is an empty DropGlue shim. pub fn is_empty_drop_shim(&self, instance: ty::Instance<'tcx>) -> bool { - matches!(instance.def, ty::InstanceKind::DropGlue(_, None)) + matches!(instance.def, ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None))) } /// Convert a non-generic crate item into an instance. diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 911c6142e4b22..bb9bf8976f672 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -548,7 +548,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { root_id, vis, vis_span: item.vis.span, - on_unknown_attr: OnUnknownData::from_attrs(self.r.tcx, &item.attrs), + on_unknown_attr: OnUnknownData::from_attrs(self.r, &item.attrs), }); self.r.indeterminate_imports.push(import); @@ -863,7 +863,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { || ast::attr::contains_name(&item.attrs, sym::no_implicit_prelude), ); self.parent_scope.module = module.to_module(); - if let Some(directive) = OnUnknownData::from_attrs(self.r.tcx, &item.attrs) { + if let Some(directive) = OnUnknownData::from_attrs(self.r, &item.attrs) { self.r.on_unknown_data.insert(local_def_id, directive); } } @@ -1040,7 +1040,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { module_path: Vec::new(), vis, vis_span: item.vis.span, - on_unknown_attr: OnUnknownData::from_attrs(self.r.tcx, &item.attrs), + on_unknown_attr: OnUnknownData::from_attrs(self.r, &item.attrs), }); if used { self.r.import_use_map.insert(import, Used::Other); @@ -1172,7 +1172,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { module_path: Vec::new(), vis: Visibility::Restricted(CRATE_DEF_ID), vis_span: item.vis.span, - on_unknown_attr: OnUnknownData::from_attrs(this.r.tcx, &item.attrs), + on_unknown_attr: OnUnknownData::from_attrs(this.r, &item.attrs), }) }; @@ -1353,7 +1353,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { module_path: Vec::new(), vis, vis_span: item.vis.span, - on_unknown_attr: OnUnknownData::from_attrs(self.r.tcx, &item.attrs), + on_unknown_attr: OnUnknownData::from_attrs(self.r, &item.attrs), }); self.r.import_use_map.insert(import, Used::Other); let import_decl = self.r.new_import_decl(decl, import); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index cdc2df5bf2945..a5049339382f7 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -186,7 +186,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { // Does that prevents errors from happening? maybe let mut parser = AttributeParser::new( &self.r.tcx.sess, - self.r.tcx.features(), + self.r.features, self.r.tcx().registered_tools(()), ShouldEmit::Nothing, ); @@ -433,7 +433,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { // `MgcaDisambiguation::Direct` is set even when MGCA is disabled, so // to avoid affecting stable we have to feature gate the not creating // anon consts - if !self.r.tcx.features().min_generic_const_args() { + if !self.r.features.min_generic_const_args() { let parent = self .create_def(constant.id, None, DefKind::AnonConst, constant.value.span) .def_id(); diff --git a/compiler/rustc_resolve/src/error_helper.rs b/compiler/rustc_resolve/src/error_helper.rs index 81c1b6fa8d675..1b7d799cadd35 100644 --- a/compiler/rustc_resolve/src/error_helper.rs +++ b/compiler/rustc_resolve/src/error_helper.rs @@ -1628,7 +1628,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { in_module.for_each_child(self, |this, ident, orig_ident_span, ns, name_binding| { // Avoid non-importable candidates. if name_binding.is_assoc_item() - && !this.tcx.features().import_trait_associated_functions() + && !this.features.import_trait_associated_functions() { return; } @@ -1809,10 +1809,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }) => { if span.allows_unstable(feature) { true - } else if self.tcx.features().enabled(feature) { + } else if self.features.enabled(feature) { true } else if let Some(implied_by) = implied_by - && self.tcx.features().enabled(implied_by) + && self.features.enabled(implied_by) { true } else { @@ -4144,13 +4144,17 @@ pub(crate) struct OnUnknownData { } impl OnUnknownData { - pub(crate) fn from_attrs<'tcx>( - tcx: TyCtxt<'tcx>, + pub(crate) fn from_attrs( + r: &Resolver<'_, '_>, attrs: &[ast::Attribute], ) -> Option { - if tcx.features().diagnostic_on_unknown() + if r.features.diagnostic_on_unknown() && let Some(Attribute::Parsed(AttributeKind::OnUnknown { directive, .. })) = - AttributeParser::parse_limited(tcx.sess, attrs, &[sym::diagnostic, sym::on_unknown]) + AttributeParser::parse_limited( + r.tcx.sess, + attrs, + &[sym::diagnostic, sym::on_unknown], + ) { Some(Self { directive: directive? }) } else { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 2e69405811db4..9d08e8b98cb31 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -23,9 +23,9 @@ use crate::late::{ use crate::macros::{MacroRulesScope, sub_namespace_match}; use crate::{ AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind, - Determinacy, Finalize, IdentKey, ImportKind, ImportSummary, LateDecl, LocalModule, Module, - ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, - Resolver, Scope, ScopeSet, Segment, Stage, Symbol, Used, diagnostics, + Determinacy, ExternModule, Finalize, IdentKey, ImportKind, ImportSummary, LateDecl, + LocalModule, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, + Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, Stage, Symbol, Used, diagnostics, }; #[derive(Copy, Clone)] @@ -608,21 +608,36 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize.map(|f| Finalize { used: Used::Scope, ..f }), ) }; - let decl = self.reborrow().resolve_ident_in_module_non_globs_unadjusted( - module, - ident, - orig_ident_span, - ns, - adjusted_parent_scope, - if matches!(scope_set, ScopeSet::Module(..)) { - Shadowing::Unrestricted - } else { - Shadowing::Restricted - }, - adjusted_finalize, - ignore_decl, - ignore_import, - ); + let shadowing = if matches!(scope_set, ScopeSet::Module(..)) { + Shadowing::Unrestricted + } else { + Shadowing::Restricted + }; + let decl = if module.is_local() { + self.reborrow().resolve_ident_in_local_module_non_globs_unadjusted( + module.expect_local(), + ident, + orig_ident_span, + ns, + adjusted_parent_scope, + shadowing, + adjusted_finalize, + ignore_decl, + ignore_import, + ) + } else { + self.reborrow().resolve_ident_in_extern_module_non_globs_unadjusted( + module.expect_extern(), + ident, + orig_ident_span, + ns, + adjusted_parent_scope, + shadowing, + adjusted_finalize, + ignore_decl, + ) + }; + match decl { Ok(decl) => { if let Some(lint_id) = derive_fallback_lint_id { @@ -746,7 +761,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::BuiltinTypes => match self.builtin_type_decls.get(&ident.name) { Some(decl) => { if matches!(ident.name, sym::f16) - && !self.tcx.features().f16() + && !self.features.f16() && !orig_ident_span.allows_unstable(sym::f16) && finalize.is_some() { @@ -759,7 +774,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .emit(); } if matches!(ident.name, sym::f128) - && !self.tcx.features().f128() + && !self.features.f128() && !orig_ident_span.allows_unstable(sym::f128) && finalize.is_some() { @@ -1078,10 +1093,49 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - /// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in `module`. - fn resolve_ident_in_module_non_globs_unadjusted<'r>( + /// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in an external `module`. + fn resolve_ident_in_extern_module_non_globs_unadjusted<'r>( mut self: CmResolver<'r, 'ra, 'tcx>, - module: Module<'ra>, + module: ExternModule<'ra>, + ident: IdentKey, + orig_ident_span: Span, + ns: Namespace, + parent_scope: &ParentScope<'ra>, + shadowing: Shadowing, + finalize: Option, + // This binding should be ignored during in-module resolution, so that we don't get + // "self-confirming" import resolutions during import validation and checking. + ignore_decl: Option>, + ) -> Result, ControlFlow> { + let key = BindingKey::new(ident, ns); + let resolution = + &*self.resolution(module.to_module(), key).ok_or(ControlFlow::Continue(Determined))?; + + let binding = resolution.non_glob_decl.filter(|b| Some(*b) != ignore_decl); + + if let Some(finalize) = finalize { + return self.get_mut().finalize_module_binding( + ident, + orig_ident_span, + binding, + parent_scope, + finalize, + shadowing, + ); + } + + // Items and single imports are not shadowable, if we have one, then it's determined. + if let Some(binding) = binding { + let accessible = self.is_accessible_from(binding.vis(), parent_scope.module); + return if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) }; + } + Err(ControlFlow::Continue(Determined)) + } + + /// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in a local `module`. + fn resolve_ident_in_local_module_non_globs_unadjusted<'r>( + mut self: CmResolver<'r, 'ra, 'tcx>, + module: LocalModule<'ra>, ident: IdentKey, orig_ident_span: Span, ns: Namespace, @@ -1098,7 +1152,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // doesn't need to be mutable. It will fail when there is a cycle of imports, and without // the exclusive access infinite recursion will crash the compiler with stack overflow. let resolution = &*self - .resolution_or_default(module, key, orig_ident_span) + .resolution_or_default(module.to_module(), key, orig_ident_span) .try_borrow_mut_unchecked() .map_err(|_| ControlFlow::Continue(Determined))?; @@ -1121,11 +1175,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) }; } - // In extern modules everything is determined from the start. - if !module.is_local() { - return Err(ControlFlow::Continue(Determined)); - }; - // Check if one of single imports can still define the name, block if it can. if self.reborrow().single_import_can_define_name( &resolution, @@ -1535,7 +1584,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } RibKind::ConstParamTy => { - if !self.tcx.features().generic_const_parameter_types() { + if !self.features.generic_const_parameter_types() { if let Some(span) = finalize { self.report_error( span, @@ -1564,7 +1613,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.tcx.features().generic_const_args(), + is_gca: self.features.generic_const_args(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Type, } @@ -1629,7 +1678,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { | RibKind::ForwardGenericParamBan(_) => continue, RibKind::ConstParamTy => { - if !self.tcx.features().generic_const_parameter_types() { + if !self.features.generic_const_parameter_types() { if let Some(span) = finalize { self.report_error( span, @@ -1656,7 +1705,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.tcx.features().generic_const_args(), + is_gca: self.features.generic_const_args(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Const { name: rib_ident.name, @@ -2019,7 +2068,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module, || { let import_inherent_item_error_flag = - self.tcx.features().import_trait_associated_functions() + self.features.import_trait_associated_functions() && matches!( res, Res::Def( diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index d823da9756c81..a3cb526e60a87 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -779,7 +779,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match import_decls[ns] { PendingDecl::Ready(Some(import_decl)) => { if import_decl.is_assoc_item() - && !this.tcx.features().import_trait_associated_functions() + && !this.features.import_trait_associated_functions() { feature_err( this.tcx.sess, @@ -822,8 +822,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { continue; }; - if module.is_trait() && !self.tcx.features().import_trait_associated_functions() - { + if module.is_trait() && !self.features.import_trait_associated_functions() { feature_err( self.tcx.sess, sym::import_trait_associated_functions, @@ -1487,7 +1486,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // If importing of trait asscoiated items is enabled, an also find an // `Enum`, then note that inherent associated items cannot be imported. - let note = if self.tcx.features().import_trait_associated_functions() + let note = if self.features.import_trait_associated_functions() && let PathResult::Module(ModuleOrUniformRoot::Module(m)) = path_res && let Some(Res::Def(DefKind::Enum, _)) = m.res() { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index bf53b891a08f1..479af1582fd6f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1664,7 +1664,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }; // We'll ban these with a `ConstParamTy` rib, so just clear these ribs for better // diagnostics, so we don't mention anything about const param tys having generics at all. - if !self.r.tcx.features().generic_const_parameter_types() { + if !self.r.features.generic_const_parameter_types() { forward_ty_ban_rib_const_param_ty.bindings.clear(); forward_const_ban_rib_const_param_ty.bindings.clear(); } @@ -1701,7 +1701,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.ribs[TypeNS].push(forward_ty_ban_rib_const_param_ty); this.ribs[ValueNS].push(forward_const_ban_rib_const_param_ty); - if this.r.tcx.features().generic_const_parameter_types() { + if this.r.features.generic_const_parameter_types() { this.visit_ty(ty) } else { this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy)); @@ -1812,8 +1812,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } LifetimeRibKind::ImplTrait => { - if self.r.tcx.features().anonymous_lifetime_in_impl_trait() - { + if self.r.features.anonymous_lifetime_in_impl_trait() { None } else { Some(LifetimeUseSet::Many) @@ -2991,7 +2990,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.with_generic_param_rib( &generics.params, RibKind::Item( - if self.r.tcx.features().generic_const_items() { + if self.r.features.generic_const_items() { HasGenericParams::Yes(generics.span) } else { HasGenericParams::No @@ -3008,7 +3007,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { LifetimeRibKind::Elided(LifetimeRes::Static), |this| { if rhs_kind.is_type_const() - && !this.r.tcx.features().generic_const_parameter_types() + && !this.r.features.generic_const_parameter_types() { this.with_rib(TypeNS, RibKind::ConstParamTy, |this| { this.with_rib(ValueNS, RibKind::ConstParamTy, |this| { @@ -3255,7 +3254,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { RibKind::Normal => { // FIXME(non_lifetime_binders): Stop special-casing // const params to error out here. - if self.r.tcx.features().non_lifetime_binders() + if self.r.features.non_lifetime_binders() && matches!(param.kind, GenericParamKind::Type { .. }) { Res::Def(def_kind, def_id.to_def_id()) @@ -3409,7 +3408,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |this| { this.visit_generics(generics); if rhs_kind.is_type_const() - && !this.r.tcx.features().generic_const_parameter_types() + && !this.r.features.generic_const_parameter_types() { this.with_rib(TypeNS, RibKind::ConstParamTy, |this| { this.with_rib(ValueNS, RibKind::ConstParamTy, |this| { @@ -5038,10 +5037,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let tcx = self.r.tcx(); let gate_err_sym_msg = match prim { - PrimTy::Float(FloatTy::F16) if !tcx.features().f16() => { + PrimTy::Float(FloatTy::F16) if !self.r.features.f16() => { Some((sym::f16, "the type `f16` is unstable")) } - PrimTy::Float(FloatTy::F128) if !tcx.features().f128() => { + PrimTy::Float(FloatTy::F128) if !self.r.features.f128() => { Some((sym::f128, "the type `f128` is unstable")) } _ => None, @@ -5196,8 +5195,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes, AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::ConstArg(_) => { - if self.r.tcx.features().generic_const_exprs() - || self.r.tcx.features().min_generic_const_args() + if self.r.features.generic_const_exprs() + || self.r.features.min_generic_const_args() || is_trivial_const_arg { ConstantHasGenerics::Yes diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 95fdf8124a225..045e0ff523c7d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1775,8 +1775,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the // benefits of including them here outweighs the small number of false positives. Some(Res::Def(DefKind::Struct | DefKind::Enum, _)) - if self.r.tcx.features().adt_const_params() - || self.r.tcx.features().min_adt_const_params() => + if self.r.features.adt_const_params() || self.r.features.min_adt_const_params() => { Applicability::MaybeIncorrect } @@ -3977,7 +3976,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { }) .emit(), NoConstantGenericsReason::NonTrivialConstArg => { - assert!(!self.r.tcx.features().generic_const_exprs()); + assert!(!self.r.features.generic_const_exprs()); self.r .dcx() .create_err(diagnostics::ParamInNonTrivialAnonConst { @@ -3985,8 +3984,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { name: lifetime_ref.ident.name, param_kind: diagnostics::ParamKindInNonTrivialAnonConst::Lifetime, help: self.r.tcx.sess.is_nightly_build(), - is_gca: self.r.tcx.features().generic_const_args(), - help_gca: self.r.tcx.features().generic_const_args(), + is_gca: self.r.features.generic_const_args(), + help_gca: self.r.features.generic_const_args(), }) .emit() } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 061471ccc97e0..1f1884ea0cbe2 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -50,7 +50,7 @@ use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard}; use rustc_data_structures::unord::{UnordItems, UnordMap, UnordSet}; use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed, LintBuffer}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; -use rustc_feature::BUILTIN_ATTRIBUTES; +use rustc_feature::{BUILTIN_ATTRIBUTES, Features}; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{ @@ -1550,7 +1550,8 @@ pub struct Resolver<'ra, 'tcx> { impl_trait_names: FxHashMap = default::fx_hash_map(), /// Stores `#[diagnostic::on_unknown]` attributes placed on module declarations. - on_unknown_data: FxHashMap, + on_unknown_data: FxHashMap = default::fx_hash_map(), + features: &'tcx Features, } /// This provides memory for the rest of the crate. The `'ra` lifetime that is @@ -1808,11 +1809,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let registered_tools = tcx.registered_tools(()); let edition = tcx.sess.edition(); - let mut on_unknown_data = default::fx_hash_map(); - if let Some(directive) = OnUnknownData::from_attrs(tcx, attrs) { - on_unknown_data.insert(CRATE_DEF_ID, directive); - } - let mut resolver = Resolver { tcx, @@ -1880,10 +1876,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { current_crate_outer_attr_insert_span, disambiguators: Default::default(), delegation_infos: Default::default(), - on_unknown_data, + features: tcx.features(), .. }; + if let Some(directive) = OnUnknownData::from_attrs(&resolver, attrs) { + resolver.on_unknown_data.insert(CRATE_DEF_ID, directive); + } + let root_parent_scope = ParentScope::module(graph_root, resolver.arenas); resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope); resolver.feed_visibility(crate_feed, Visibility::Public); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index fade23f9cf308..595c2fdf011dd 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -699,7 +699,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // We are trying to avoid reporting this error if other related errors were reported. - if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes() { + if res != Res::Err && inner_attr && !self.features.custom_inner_attributes() { let is_macro = match res { Res::Def(..) => true, Res::NonMacroAttr(..) => false, @@ -727,8 +727,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && let [namespace, attribute, ..] = &*path.segments && namespace.ident.name == sym::diagnostic && !DIAGNOSTIC_ATTRIBUTES.iter().any(|(attr, feature)| { - attribute.ident.name == *attr - && feature.is_none_or(|f| self.tcx.features().enabled(f)) + attribute.ident.name == *attr && feature.is_none_or(|f| self.features.enabled(f)) }) { let name = attribute.ident.name; @@ -750,7 +749,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let candidates = DIAGNOSTIC_ATTRIBUTES .iter() .filter_map(|(attr, feature)| { - feature.is_none_or(|f| self.tcx.features().enabled(f)).then_some(*attr) + feature.is_none_or(|f| self.features.enabled(f)).then_some(*attr) }) .collect::>(); @@ -1112,7 +1111,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let feature = stability.feature; let is_allowed = - |feature| self.tcx.features().enabled(feature) || span.allows_unstable(feature); + |feature| self.features.enabled(feature) || span.allows_unstable(feature); let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature)); if !is_allowed(feature) && !allowed_by_implication { stability::report_unstable( @@ -1242,7 +1241,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> SyntaxExtension { let mut ext = compile_declarative_macro( self.tcx.sess, - self.tcx.features(), + self.features, macro_def, ident, attrs, diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 0810e327b63e3..e901e1cf98e7e 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -310,7 +310,7 @@ pub(crate) fn transform_instance<'tcx>( // FIXME: account for async-drop-glue if (matches!(instance.def, ty::InstanceKind::Virtual(..)) && tcx.is_lang_item(instance.def_id(), LangItem::DropGlue)) - || matches!(instance.def, ty::InstanceKind::DropGlue(..)) + || matches!(instance.def, ty::InstanceKind::Shim(ty::ShimKind::DropGlue(..))) { // Adjust the type ids of DropGlues // @@ -364,7 +364,7 @@ pub(crate) fn transform_instance<'tcx>( tcx.types.unit }; instance.args = tcx.mk_args_trait(self_ty, instance.args.into_iter().skip(1)); - } else if let ty::InstanceKind::VTableShim(def_id) = instance.def + } else if let ty::InstanceKind::Shim(ty::ShimKind::VTable(def_id)) = instance.def && let Some(trait_id) = tcx.trait_of_assoc(def_id) { // Adjust the type ids of VTableShims to the type id expected in the call sites for the @@ -461,7 +461,7 @@ pub(crate) fn transform_instance<'tcx>( fn default_or_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Option { match instance.def { - ty::InstanceKind::Item(def_id) | ty::InstanceKind::FnPtrShim(def_id, _) => { + ty::InstanceKind::Item(def_id) | ty::InstanceKind::Shim(ty::ShimKind::FnPtr(def_id, _)) => { tcx.opt_associated_item(def_id).map(|item| item.def_id) } _ => None, diff --git a/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs b/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs index 3243e23fcf981..23aa088c68ffa 100644 --- a/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs +++ b/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs @@ -6,7 +6,7 @@ use std::hash::Hasher; -use rustc_middle::ty::{Instance, InstanceKind, ReifyReason, Ty, TyCtxt}; +use rustc_middle::ty::{Instance, InstanceKind, ReifyReason, ShimKind, Ty, TyCtxt}; use rustc_target::callconv::FnAbi; use twox_hash::XxHash64; @@ -46,7 +46,7 @@ pub fn typeid_for_instance<'tcx>( // // This was implemented for KCFI support in #123106 and #123052 (which introduced the // ReifyReason). The tracking issue for KCFI support for Rust is #123479. - if matches!(instance.def, InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr))) { + if matches!(instance.def, InstanceKind::Shim(ShimKind::Reify(_, Some(ReifyReason::FnPtr)))) { options.insert(TypeIdOptions::USE_CONCRETE_SELF); } // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index c13300a735c3c..2513e7f958a21 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -62,13 +62,13 @@ pub(super) fn mangle<'tcx>( let mut p = LegacySymbolMangler { tcx, path: SymbolPath::new(), keep_within_component: false }; p.print_def_path( def_id, - if let ty::InstanceKind::DropGlue(_, _) - | ty::InstanceKind::AsyncDropGlueCtorShim(_, _) - | ty::InstanceKind::FutureDropPollShim(_, _, _) = instance.def + if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, _)) + | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_, _)) + | ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(_, _, _)) = instance.def { // Add the name of the dropped type to the symbol name &*instance.args - } else if let ty::InstanceKind::AsyncDropGlue(_, ty) = instance.def { + } else if let ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_, ty)) = instance.def { let ty::Coroutine(_, cor_args) = ty.kind() else { bug!(); }; @@ -81,13 +81,13 @@ pub(super) fn mangle<'tcx>( .unwrap(); match instance.def { - ty::InstanceKind::ThreadLocalShim(..) => { + ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(..)) => { p.write_str("{{tls-shim}}").unwrap(); } - ty::InstanceKind::VTableShim(..) => { + ty::InstanceKind::Shim(ty::ShimKind::VTable(..)) => { p.write_str("{{vtable-shim}}").unwrap(); } - ty::InstanceKind::ReifyShim(_, reason) => { + ty::InstanceKind::Shim(ty::ShimKind::Reify(_, reason)) => { p.write_str("{{reify-shim").unwrap(); match reason { Some(ReifyReason::FnPtr) => p.write_str("-fnptr").unwrap(), @@ -98,14 +98,17 @@ pub(super) fn mangle<'tcx>( } // FIXME(async_closures): This shouldn't be needed when we fix // `Instance::ty`/`Instance::def_id`. - ty::InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref, .. } => { + ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure { + receiver_by_ref, + .. + }) => { p.write_str(if receiver_by_ref { "{{by-move-shim}}" } else { "{{by-ref-shim}}" }) .unwrap(); } _ => {} } - if let ty::InstanceKind::FutureDropPollShim(..) = instance.def { + if let ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(..)) = instance.def { let _ = p.write_str("{{drop-shim}}"); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c6624a7820559..b259774468c91 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -49,25 +49,31 @@ pub(super) fn mangle<'tcx>( // Append `::{shim:...#0}` to shims that can coexist with a non-shim instance. let shim_kind = match instance.def { - ty::InstanceKind::ThreadLocalShim(_) => Some("tls"), - ty::InstanceKind::VTableShim(_) => Some("vtable"), - ty::InstanceKind::ReifyShim(_, None) => Some("reify"), - ty::InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => Some("reify_fnptr"), - ty::InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => Some("reify_vtable"), + ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(_)) => Some("tls"), + ty::InstanceKind::Shim(ty::ShimKind::VTable(_)) => Some("vtable"), + ty::InstanceKind::Shim(ty::ShimKind::Reify(_, None)) => Some("reify"), + ty::InstanceKind::Shim(ty::ShimKind::Reify(_, Some(ReifyReason::FnPtr))) => { + Some("reify_fnptr") + } + ty::InstanceKind::Shim(ty::ShimKind::Reify(_, Some(ReifyReason::Vtable))) => { + Some("reify_vtable") + } // FIXME(async_closures): This shouldn't be needed when we fix // `Instance::ty`/`Instance::def_id`. - ty::InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref: true, .. } => { - Some("by_move") - } - ty::InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref: false, .. } => { - Some("by_ref") - } - ty::InstanceKind::FutureDropPollShim(_, _, _) => Some("drop"), + ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure { + receiver_by_ref: true, + .. + }) => Some("by_move"), + ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure { + receiver_by_ref: false, + .. + }) => Some("by_ref"), + ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(_, _, _)) => Some("drop"), _ => None, }; - if let ty::InstanceKind::AsyncDropGlue(_, ty) = instance.def { + if let ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_, ty)) = instance.def { let ty::Coroutine(_, cor_args) = ty.kind() else { bug!(); }; diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 7e1eafa10097f..30d16b5c7b1c9 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -827,6 +827,9 @@ impl<'a, Ty> FnAbi<'a, Ty> { ArgAttribute::default() }; arg.cast_to_with_attrs(Reg { kind: RegKind::Integer, size }, attr.into()); + } else if self.conv == CanonAbi::RustTail { + assert!(arg.layout.is_sized(), "extern \"tail\" arguments must be sized"); + arg.pass_by_stack_offset(None); } } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index e782557d126bf..51db1b8efde2f 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -10,7 +10,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind, }; -use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, Unnormalized}; +use rustc_middle::ty::{self, InstanceKind, ShimKind, Ty, TyCtxt, Unnormalized}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; use rustc_target::callconv::{ @@ -38,7 +38,7 @@ fn fn_sig_for_fn_abi<'tcx>( instance: ty::Instance<'tcx>, typing_env: ty::TypingEnv<'tcx>, ) -> ty::FnSig<'tcx> { - if let InstanceKind::ThreadLocalShim(..) = instance.def { + if let InstanceKind::Shim(ShimKind::ThreadLocal(..)) = instance.def { return tcx.mk_fn_sig_safe_rust_abi([], tcx.thread_local_ptr_ty(instance.def_id())); } @@ -50,7 +50,7 @@ fn fn_sig_for_fn_abi<'tcx>( ); // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. - if let ty::InstanceKind::VTableShim(..) = instance.def { + if let ty::InstanceKind::Shim(ty::ShimKind::VTable(..)) = instance.def { let mut inputs_and_output = sig.inputs_and_output.to_vec(); inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]); sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); @@ -82,22 +82,23 @@ fn fn_sig_for_fn_abi<'tcx>( // a separate def-id for these bodies. let mut coroutine_kind = args.as_coroutine_closure().kind(); - let env_ty = - if let InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref, .. } = - instance.def - { - coroutine_kind = ty::ClosureKind::FnOnce; - - // Implementations of `FnMut` and `Fn` for coroutine-closures - // still take their receiver by ref. - if receiver_by_ref { - Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty) - } else { - coroutine_ty - } + let env_ty = if let InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure { + receiver_by_ref, + .. + }) = instance.def + { + coroutine_kind = ty::ClosureKind::FnOnce; + + // Implementations of `FnMut` and `Fn` for coroutine-closures + // still take their receiver by ref. + if receiver_by_ref { + Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty) } else { - tcx.closure_env_ty(coroutine_ty, coroutine_kind, tcx.lifetimes.re_erased) - }; + coroutine_ty + } + } else { + tcx.closure_env_ty(coroutine_ty, coroutine_kind, tcx.lifetimes.re_erased) + }; let sig = tcx.instantiate_bound_regions_with_erased(sig); @@ -264,7 +265,8 @@ impl<'tcx> FnAbiDesc<'tcx> { ) -> Self { let ty::PseudoCanonicalInput { typing_env, value: (instance, extra_args) } = query; let is_virtual_call = matches!(instance.def, ty::InstanceKind::Virtual(..)); - let is_tls_shim_call = matches!(instance.def, ty::InstanceKind::ThreadLocalShim(_)); + let is_tls_shim_call = + matches!(instance.def, ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(_))); Self { layout_cx: LayoutCx::new(tcx, typing_env), sig: tcx.normalize_erasing_regions( @@ -458,8 +460,10 @@ fn fn_abi_sanity_check<'tcx>( // omitted entirely in the calling convention. assert!(arg.is_ignore()); } - if let PassMode::Indirect { on_stack, .. } = arg.mode { - assert!(!on_stack, "rust abi shouldn't use on_stack"); + if let PassMode::Indirect { on_stack, .. } = arg.mode + && spec_abi != ExternAbi::RustTail + { + assert!(!on_stack, "rustic abi {spec_abi:?} shouldn't use on_stack"); } } else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { assert_matches!( diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 7386afbe53771..34a3a96f89c40 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -38,16 +38,16 @@ fn resolve_instance_raw<'tcx>( } else if tcx.is_lang_item(def_id, LangItem::DropGlue) { let ty = args.type_at(0); - if ty.needs_drop(tcx, typing_env) { + let shim = if ty.needs_drop(tcx, typing_env) { debug!(" => nontrivial drop glue"); match *ty.kind() { ty::Coroutine(coroutine_def_id, ..) => { // FIXME: sync drop of coroutine with async drop (generate both versions?) // Currently just ignored if tcx.optimized_mir(coroutine_def_id).coroutine_drop_async().is_some() { - ty::InstanceKind::DropGlue(def_id, None) + ty::ShimKind::DropGlue(def_id, None) } else { - ty::InstanceKind::DropGlue(def_id, Some(ty)) + ty::ShimKind::DropGlue(def_id, Some(ty)) } } ty::Closure(..) @@ -57,14 +57,15 @@ fn resolve_instance_raw<'tcx>( | ty::Dynamic(..) | ty::Array(..) | ty::Slice(..) - | ty::UnsafeBinder(..) => ty::InstanceKind::DropGlue(def_id, Some(ty)), + | ty::UnsafeBinder(..) => ty::ShimKind::DropGlue(def_id, Some(ty)), // Drop shims can only be built from ADTs. _ => return Ok(None), } } else { debug!(" => trivial drop glue"); - ty::InstanceKind::DropGlue(def_id, None) - } + ty::ShimKind::DropGlue(def_id, None) + }; + ty::InstanceKind::Shim(shim) } else if tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace) { let ty = args.type_at(0); @@ -82,14 +83,14 @@ fn resolve_instance_raw<'tcx>( _ => return Ok(None), } debug!(" => nontrivial async drop glue ctor"); - ty::InstanceKind::AsyncDropGlueCtorShim(def_id, ty) + ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(def_id, ty)) } else { debug!(" => trivial async drop glue ctor"); - ty::InstanceKind::AsyncDropGlueCtorShim(def_id, ty) + ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(def_id, ty)) } } else if tcx.is_async_drop_in_place_coroutine(def_id) { let ty = args.type_at(0); - ty::InstanceKind::AsyncDropGlue(def_id, ty) + ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(def_id, ty)) } else { debug!(" => free item"); ty::InstanceKind::Item(def_id) @@ -279,7 +280,7 @@ fn resolve_associated_item<'tcx>( }; Some(Instance { - def: ty::InstanceKind::CloneShim(trait_item_id, self_ty), + def: ty::InstanceKind::Shim(ty::ShimKind::Clone(trait_item_id, self_ty)), args: rcvr_args, }) } else { @@ -296,7 +297,10 @@ fn resolve_associated_item<'tcx>( return Ok(None); } Some(Instance { - def: ty::InstanceKind::FnPtrAddrShim(trait_item_id, self_ty), + def: ty::InstanceKind::Shim(ty::ShimKind::FnPtrAddr( + trait_item_id, + self_ty, + )), args: rcvr_args, }) } else { @@ -326,7 +330,10 @@ fn resolve_associated_item<'tcx>( Some(Instance::resolve_closure(tcx, closure_def_id, args, target_kind)) } ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { - def: ty::InstanceKind::FnPtrShim(trait_item_id, rcvr_args.type_at(0)), + def: ty::InstanceKind::Shim(ty::ShimKind::FnPtr( + trait_item_id, + rcvr_args.type_at(0), + )), args: rcvr_args, }), ty::CoroutineClosure(coroutine_closure_def_id, args) => { @@ -339,10 +346,12 @@ fn resolve_associated_item<'tcx>( Some(Instance::new_raw(coroutine_closure_def_id, args)) } else { Some(Instance { - def: ty::InstanceKind::ConstructCoroutineInClosureShim { - coroutine_closure_def_id, - receiver_by_ref: target_kind != ty::ClosureKind::FnOnce, - }, + def: ty::InstanceKind::Shim( + ty::ShimKind::ConstructCoroutineInClosure { + coroutine_closure_def_id, + receiver_by_ref: target_kind != ty::ClosureKind::FnOnce, + }, + ), args, }) } @@ -362,10 +371,12 @@ fn resolve_associated_item<'tcx>( // If we're computing `AsyncFnOnce` for a by-ref closure then // construct a new body that has the right return types. Some(Instance { - def: ty::InstanceKind::ConstructCoroutineInClosureShim { - coroutine_closure_def_id, - receiver_by_ref: false, - }, + def: ty::InstanceKind::Shim( + ty::ShimKind::ConstructCoroutineInClosure { + coroutine_closure_def_id, + receiver_by_ref: false, + }, + ), args, }) } else { @@ -376,7 +387,10 @@ fn resolve_associated_item<'tcx>( Some(Instance::resolve_closure(tcx, closure_def_id, args, target_kind)) } ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { - def: ty::InstanceKind::FnPtrShim(trait_item_id, rcvr_args.type_at(0)), + def: ty::InstanceKind::Shim(ty::ShimKind::FnPtr( + trait_item_id, + rcvr_args.type_at(0), + )), args: rcvr_args, }), _ => bug!( diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 4b23bfd0f7765..908df3ce1ea9a 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -840,7 +840,15 @@ fn rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling< escaping_outlives, I::BoundVarKinds::from_vars(infcx.cx(), bound_vars), ); - candidates.push(RegionConstraint::AliasTyOutlivesViaEnv(bound_outlives)); + let candidate = RegionConstraint::AliasTyOutlivesViaEnv(bound_outlives); + if max_universe(infcx, candidate.clone()) < u { + candidates.push(candidate); + } else { + // `PlaceholderReplacer` only folds regions. A non-lifetime binder can leave + // a placeholder type in `u`, so this type-outlives constraint cannot be + // handled by the region-outlives-only eager placeholder machinery. + candidates.push(Ambiguity); + } } let assumptions = match assumptions { @@ -885,12 +893,17 @@ fn rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling< // while we did skip the binder, bound vars aren't in any universe so // this can't be an escaping bound var - candidates.extend( - regions_outliving(escaping_r, assumptions, infcx.cx()) - .filter(|r2| max_universe(infcx, *r2) < u) - .map(|r2| AliasTyOutlivesViaEnv(bound_alias.map_bound(|alias| (alias, r2)))) - .collect::>(), - ); + for r2 in regions_outliving(escaping_r, assumptions, infcx.cx()) + .filter(|r2| max_universe(infcx, *r2) < u) + { + let candidate = + AliasTyOutlivesViaEnv(bound_alias.map_bound(|alias| (alias, r2))); + if max_universe(infcx, candidate.clone()) < u { + candidates.push(candidate); + } else { + candidates.push(Ambiguity); + } + } } // I'm not convinced our handling here is *complete* so for now @@ -978,11 +991,14 @@ pub fn regions_outlived_by_placeholder( } /// The largest universe a variable or placeholder was from in `t` -pub fn max_universe, I: Interner, T: TypeVisitable>( +pub fn max_universe, I: Interner, T: TypeFoldable>( infcx: &Infcx, t: T, ) -> UniverseIndex { let mut visitor = MaxUniverse::new(infcx); + // `max_universe` is also used while rewriting constraints to lower universes, + // so do not rely on callers having already resolved non-region infer vars. + let t = infcx.resolve_vars_if_possible(t); t.visit_with(&mut visitor); visitor.max_universe() } @@ -1036,11 +1052,17 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> TypeVisitor fn visit_region(&mut self, r: I::Region) { match r.kind() { RegionKind::RePlaceholder(p) => self.max_universe = self.max_universe.max(p.universe), - RegionKind::ReVar(var) => { - let u = self.infcx.universe_of_lt(var).unwrap(); - debug!("var {var:?} in universe {u:?}"); - self.max_universe = self.max_universe.max(u); - } + RegionKind::ReVar(var) => match self.infcx.opportunistic_resolve_lt_var(var).kind() { + RegionKind::RePlaceholder(p) => { + self.max_universe = self.max_universe.max(p.universe) + } + RegionKind::ReVar(var) => { + let u = self.infcx.universe_of_lt(var).unwrap(); + debug!("var {var:?} in universe {u:?}"); + self.max_universe = self.max_universe.max(u); + } + _ => (), + }, _ => (), } } diff --git a/library/Cargo.lock b/library/Cargo.lock index 99e9765171c4a..c30ed6dc30c55 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -283,9 +283,9 @@ dependencies = [ [[package]] name = "rustc-literal-escaper" -version = "0.0.7" +version = "0.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be87abb9e40db7466e0681dc8ecd9dcfd40360cb10b4c8fe24a7c4c3669b198" +checksum = "bfe6f213fb658c8fb95baabd5420393438cf5a98d707f5dd701d9197c705f71e" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 229514803bf6a..eb00db4568b63 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2239,15 +2239,33 @@ impl FromUtf8Error { /// invalid sequences, and [`String::from_utf8_lossy_owned`] for the /// `String` function which corresponds to this function. /// + /// This is useful in conjunction with [`String::from_utf8`] when you need + /// to branch on whether the bytes are valid UTF-8, but still want to + /// recover a lossily converted `String` in the error case. Use + /// [`String::from_utf8_lossy_owned`] if you always need a lossily converted + /// `String`. + /// + /// Since the original [`String::from_utf8`] error records where validation + /// stopped, this method does not need to re-check the already valid prefix + /// of the byte sequence. + /// /// # Examples /// /// ``` /// #![feature(string_from_utf8_lossy_owned)] /// // some invalid bytes /// let input: Vec = b"Hello \xF0\x90\x80World".into(); - /// let output = String::from_utf8(input).unwrap_or_else(|e| e.into_utf8_lossy()); + /// + /// let (output, had_invalid_utf8) = match String::from_utf8(input) { + /// Ok(output) => (output, false), + /// Err(error) => { + /// // The bytes were not valid UTF-8, but we can still recover a string. + /// (error.into_utf8_lossy(), true) + /// } + /// }; /// /// assert_eq!(String::from("Hello �World"), output); + /// assert!(had_invalid_utf8); /// ``` #[must_use] #[cfg(not(no_global_oom_handling))] diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 8c5f9d472bfa8..8517df4da2afc 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -495,7 +495,7 @@ impl char { || args.escape_grapheme_extender && self.is_grapheme_extender() || self.is_default_ignorable() || self.is_format_control() - || self.is_unassigned() => + || !self.is_assigned() => { EscapeDebug::unicode(self) } @@ -1139,8 +1139,9 @@ impl char { /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt /// #[must_use] + #[unstable(feature = "char_unassigned_private_use", issue = "158322")] #[inline] - const fn is_private_use(self) -> bool { + pub const fn is_private_use(self) -> bool { // According to // https://www.unicode.org/policies/stability_policy.html#Property_Value, // the set of codepoints in `Co` will never change. @@ -1176,54 +1177,56 @@ impl char { self > '\u{AC}' && unicode::Cf(self) } - /// Returns `true` if this `char` has not yet been assigned a meaning by Unicode, as of + /// Returns `true` if this `char` has been assigned a meaning by Unicode, as of /// [`UNICODE_VERSION`]. /// /// [`UNICODE_VERSION`]: Self::UNICODE_VERSION /// - /// These characters may have a meaning assigned in the future, - /// except for the 66 [noncharacters] which will never be assigned a meaning. - /// - /// [noncharacters]: https://www.unicode.org/faq/private_use#noncharacters - /// /// Many of Unicode's [stability policies] apply only to assigned characters. /// /// [stability policies]: https://www.unicode.org/policies/stability_policy.html /// - /// Unassigned characters (code points with the general category of `Cn`) are [described] in Chapter 4 - /// (Character Properties) of the Unicode Standard, and [specified] in the Unicode Character Database - /// by their exclusion from [`UnicodeData.txt`]. + /// Currently unassigned characters (characters for which this method returns `false`) + /// may have a meaning assigned in a future version of Unicode, + /// except for the 66 [noncharacters] which will never be assigned a meaning. + /// + /// [noncharacters]: https://www.unicode.org/faq/private_use.html#noncharacters + /// + /// A character is considered assigned if it is present in [`UnicodeData.txt`]. + /// Unassigned characters have general category `Cn`, as [described] in Chapter 4 + /// (Character Properties) of the Unicode Standard. /// - /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153 - /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153 /// /// # Examples /// /// Basic usage: /// - /// ```ignore(private) - /// assert!('\u{FFFE}'.is_unassigned()); // noncharacter, will never be assigned - /// - /// //assert!('\u{7AAAA}'.is_unassigned()); // not currently assigned, but may be in the future, - /// // so we shouldn't rely on the current status + /// ``` + /// #![feature(char_unassigned_private_use)] + /// assert!('γ'.is_assigned()); // once a character is assigned, it stays assigned forever + /// assert!(!'\u{FFFE}'.is_assigned()); // noncharacter, will never be assigned /// - /// assert!(!'γ'.is_unassigned()); // once a character is assigned, it stays assigned forever + /// // Not currently assigned, but may be in the future, + /// // so we shouldn't rely on the current status + /// /* assert!(!'\u{7AAAA}'.is_assigned()); */ /// ``` #[must_use] + #[unstable(feature = "char_unassigned_private_use", issue = "158322")] #[inline] - fn is_unassigned(self) -> bool { + pub fn is_assigned(self) -> bool { match self { - '\0'..='\u{377}' => false, - '\u{378}'..='\u{3FFFD}' => unicode::Cn_planes_0_3(self), + '\0'..='\u{377}' => true, + '\u{378}'..='\u{3FFFD}' => !unicode::Cn_planes_0_3(self), // Assigned character ranges in planes 4 and above. // `src/tools/unicode-table-generator/src/main.rs` asserts that this is correct '\u{E0001}' | '\u{E0020}'..='\u{E007F}' | '\u{E0100}'..='\u{E01EF}' | '\u{F0000}'..='\u{FFFFD}' - | '\u{100000}'..='\u{10FFFD}' => false, - _ => true, + | '\u{100000}'..='\u{10FFFD}' => true, + _ => false, } } diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index c21191dbc19be..932a2fc0bad92 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -40,7 +40,7 @@ macro_rules! panic { #[rustc_diagnostic_item = "assert_eq_macro"] #[allow_internal_unstable(panic_internals)] macro_rules! assert_eq { - ($left:expr, $right:expr $(,)?) => { + ($left:expr, $right:expr $(,)?) => {{ match (&$left, &$right) { (left_val, right_val) => { if !(*left_val == *right_val) { @@ -52,8 +52,8 @@ macro_rules! assert_eq { } } } - }; - ($left:expr, $right:expr, $($arg:tt)+) => { + }}; + ($left:expr, $right:expr, $($arg:tt)+) => {{ match (&$left, &$right) { (left_val, right_val) => { if !(*left_val == *right_val) { @@ -65,7 +65,7 @@ macro_rules! assert_eq { } } } - }; + }}; } /// Asserts that two expressions are not equal to each other (using [`PartialEq`]). @@ -96,7 +96,7 @@ macro_rules! assert_eq { #[rustc_diagnostic_item = "assert_ne_macro"] #[allow_internal_unstable(panic_internals)] macro_rules! assert_ne { - ($left:expr, $right:expr $(,)?) => { + ($left:expr, $right:expr $(,)?) => {{ match (&$left, &$right) { (left_val, right_val) => { if *left_val == *right_val { @@ -108,8 +108,8 @@ macro_rules! assert_ne { } } } - }; - ($left:expr, $right:expr, $($arg:tt)+) => { + }}; + ($left:expr, $right:expr, $($arg:tt)+) => {{ match (&($left), &($right)) { (left_val, right_val) => { if *left_val == *right_val { @@ -121,7 +121,7 @@ macro_rules! assert_ne { } } } - }; + }}; } /// Asserts that an expression matches the provided pattern. diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs index 3aab24a90d817..a6473735dd455 100644 --- a/library/core/src/net/parser.rs +++ b/library/core/src/net/parser.rs @@ -63,11 +63,6 @@ impl<'a> Parser<'a> { if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(kind)) } - /// Peek the next character from the input - fn peek_char(&self) -> Option { - self.state.first().map(|&b| char::from(b)) - } - /// Reads the next character from the input fn read_char(&mut self) -> Option { self.state.split_first().map(|(&b, tail)| { @@ -100,60 +95,56 @@ impl<'a> Parser<'a> { }) } - // Read a number off the front of the input in the given radix, stopping - // at the first non-digit character or eof. Fails if the number has more - // digits than max_digits or if there is no number. - // - // INVARIANT: `max_digits` must be less than the number of digits that `u32` - // can represent. - fn read_number>( + /// Reads a number off the front of the input in the given radix, stopping at the first + /// non-digit character or eof. Fails if the number has more digits than `max_digits`, if there + /// is no number, if the number overflows `T`, or if there are leading zeros but + /// `allow_zero_prefix` is false. + /// + /// `max_digits` must be in 1..=6. + fn read_radix_max_digits>( &mut self, radix: u32, - max_digits: Option, + max_digits: u32, allow_zero_prefix: bool, ) -> Option { - self.read_atomically(move |p| { - let mut digit_count = 0; - let has_leading_zero = p.peek_char() == Some('0'); - - // If max_digits.is_some(), then we are parsing a `u8` or `u16` and - // don't need to use checked arithmetic since it fits within a `u32`. - let result = if let Some(max_digits) = max_digits { - // u32::MAX = 4_294_967_295u32, which is 10 digits long. - // `max_digits` must be less than 10 to not overflow a `u32`. - debug_assert!(max_digits < 10); - - let mut result = 0_u32; - while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { - result *= radix; - result += digit; - digit_count += 1; - - if digit_count > max_digits { - return None; - } - } - - result.try_into().ok() - } else { - let mut result = T::ZERO; + debug_assert!(1 <= max_digits); + debug_assert!(max_digits <= 6); // Works for any radix in u32 + self.read_atomically(|p| { + let first = p.read_char()?.to_digit(radix)?; + let mut result = first; + let mut digit_count = 1; - while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { - result = result.checked_mul(radix)?; - result = result.checked_add(digit)?; - digit_count += 1; + while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { + if digit_count >= max_digits { + return None; } + result *= radix; + result += digit; + digit_count += 1; + } - Some(result) - }; - - if digit_count == 0 { - None - } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { + if !allow_zero_prefix && first == 0 && digit_count > 1 { None } else { - result + result.try_into().ok() + } + }) + } + + /// Reads a decimal number off the front of the input, stopping at the first non-digit character + /// or eof. Fails if there is no number, or if the number overflows `T`. Allows an arbitrary + /// amount of leading zeros. + fn read_decimal(&mut self) -> Option { + self.read_atomically(|p| { + let first = p.read_char()?.to_digit(10)?; + let mut result = T::ZERO.checked_add(first)?; + + while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(10)) { + result = result.checked_mul(10)?; + result = result.checked_add(digit)?; } + + Some(result) }) } @@ -166,7 +157,7 @@ impl<'a> Parser<'a> { *slot = p.read_separator('.', i, |p| { // Disallow octal number in IP string. // https://tools.ietf.org/html/rfc6943#section-3.1.1 - p.read_number(10, Some(3), false) + p.read_radix_max_digits(10, 3, false) })?; } @@ -198,7 +189,7 @@ impl<'a> Parser<'a> { } } - let group = p.read_separator(':', i, |p| p.read_number(16, Some(4), true)); + let group = p.read_separator(':', i, |p| p.read_radix_max_digits(16, 4, true)); match group { Some(g) => *slot = g, @@ -250,7 +241,7 @@ impl<'a> Parser<'a> { fn read_port(&mut self) -> Option { self.read_atomically(|p| { p.read_given_char(':')?; - p.read_number(10, None, true) + p.read_decimal() }) } @@ -258,7 +249,7 @@ impl<'a> Parser<'a> { fn read_scope_id(&mut self) -> Option { self.read_atomically(|p| { p.read_given_char('%')?; - p.read_number(10, None, true) + p.read_decimal() }) } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 34f16184e4ec3..f5508b1a4463d 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1181,7 +1181,7 @@ macro_rules! int_impl { ( lhs: $SelfT = self, rhs: $SelfT = rhs, - ) => rhs > 0 && lhs % rhs == 0 && (lhs != <$SelfT>::MIN || rhs != -1), + ) => rhs != 0 && lhs % rhs == 0 && (lhs != <$SelfT>::MIN || rhs != -1), ); // SAFETY: Same precondition unsafe { intrinsics::exact_div(self, rhs) } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 9b077f1f9c1bd..7ab476e785d16 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2530,6 +2530,7 @@ impl [T] { F: FnMut(&T) -> bool, { let index = self.iter().position(pred)?; + // Slice bounds checks optimized are away (as of June 2026) Some((&self[..index], &self[index + 1..])) } @@ -2558,6 +2559,7 @@ impl [T] { F: FnMut(&T) -> bool, { let index = self.iter().rposition(pred)?; + // Slice bounds checks optimized are away (as of June 2026) Some((&self[..index], &self[index + 1..])) } diff --git a/library/coretests/benches/net/addr_parser.rs b/library/coretests/benches/net/addr_parser.rs index bbf2ea3eb9796..d44ea98bfcbec 100644 --- a/library/coretests/benches/net/addr_parser.rs +++ b/library/coretests/benches/net/addr_parser.rs @@ -3,76 +3,210 @@ use core::str::FromStr; use test::{Bencher, black_box}; -const IPV4_STR: &str = "192.168.0.1"; -const IPV4_STR_PORT: &str = "192.168.0.1:8080"; - -const IPV6_STR_FULL: &str = "2001:db8:0:0:0:0:c0a8:1"; -const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1"; -const IPV6_STR_V4: &str = "2001:db8::192.168.0.1"; -const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080"; -const IPV6_STR_PORT_SCOPE_ID: &str = "[2001:db8::c0a8:1%1337]:8080"; +const IPV4: &[&str] = &[ + "192.168.0.1", + "8.8.8.8", + "127.0.0.1", + "255.255.255.255", + "0.0.0.0", + "10.0.0.1", + "203.0.113.42", + "172.16.254.1", + "100.64.0.1", + "1.2.3.4", +]; + +const IPV4_PORT: &[&str] = &[ + "192.168.0.1:8080", + "8.8.8.8:53", + "127.0.0.1:65535", + "255.255.255.255:1", + "0.0.0.0:80", + "10.0.0.1:443", + "203.0.113.42:22", + "172.16.254.1:3306", + "100.64.0.1:8443", + "1.2.3.4:0", +]; + +const IPV6_FULL: &[&str] = &[ + "2001:db8:0:0:0:0:c0a8:1", + "2001:db8:85a3:8d3:1319:8a2e:370:7348", + "fe80:0:0:0:0:0:0:1", + "ff02:0:0:0:0:0:0:101", + "2001:4860:4860:0:0:0:0:8888", + "2606:4700:4700:0:0:0:0:1111", + "fd00:0:0:0:0:0:0:1", + "fec0:0:0:0:0:0:0:abcd", + "1:2:3:4:5:6:7:8", + "abcd:ef01:2345:6789:abcd:ef01:2345:6789", +]; + +const IPV6_COMPRESS: &[&str] = &[ + "2001:db8::c0a8:1", + "::1", + "fe80::1", + "2001:db8::", + "ff02::1:2", + "64:ff9b::", + "::", + "2001:4860:4860::8888", + "2606:4700:4700::1111", + "fe80::1ff:fe23:4567:890a", +]; + +const IPV6_V4: &[&str] = &[ + "2001:db8::192.168.0.1", + "::ffff:192.168.0.1", + "64:ff9b::192.0.2.33", + "::ffff:8.8.8.8", + "::192.168.0.1", + "::ffff:255.255.255.255", + "2001:db8:0:0:0:0:192.168.0.1", + "64:ff9b::10.0.0.1", + "::ffff:1.2.3.4", + "::ffff:127.0.0.1", +]; + +const IPV6_PORT: &[&str] = &[ + "[2001:db8::c0a8:1]:8080", + "[::1]:443", + "[fe80::1]:53", + "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:22", + "[::]:80", + "[2001:4860:4860::8888]:443", + "[2606:4700:4700::1111]:53", + "[fe80::1ff:fe23:4567:890a]:8080", + "[64:ff9b::192.0.2.33]:443", + "[::ffff:8.8.8.8]:53", +]; + +const IPV6_PORT_SCOPE_ID: &[&str] = &[ + "[2001:db8::c0a8:1%1337]:8080", + "[fe80::1%1]:53", + "[fe80::1%999999]:443", + "[fe80::1%0]:80", + "[fe80::1ff:fe23:4567:890a%2]:8080", + "[::1%1]:443", + "[fe80::abcd%15]:22", + "[ff02::1%42]:5353", + "[fe80::1%4294967295]:443", + "[2001:db8::1%100]:8080", +]; #[bench] fn bench_parse_ipv4(b: &mut Bencher) { - b.iter(|| Ipv4Addr::from_str(black_box(IPV4_STR))); + b.iter(|| { + for s in IPV4 { + let _ = black_box(Ipv4Addr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_ipv6_full(b: &mut Bencher) { - b.iter(|| Ipv6Addr::from_str(black_box(IPV6_STR_FULL))); + b.iter(|| { + for s in IPV6_FULL { + let _ = black_box(Ipv6Addr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_ipv6_compress(b: &mut Bencher) { - b.iter(|| Ipv6Addr::from_str(black_box(IPV6_STR_COMPRESS))); + b.iter(|| { + for s in IPV6_COMPRESS { + let _ = black_box(Ipv6Addr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_ipv6_v4(b: &mut Bencher) { - b.iter(|| Ipv6Addr::from_str(black_box(IPV6_STR_V4))); + b.iter(|| { + for s in IPV6_V4 { + let _ = black_box(Ipv6Addr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_ipaddr_v4(b: &mut Bencher) { - b.iter(|| IpAddr::from_str(black_box(IPV4_STR))); + b.iter(|| { + for s in IPV4 { + let _ = black_box(IpAddr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_ipaddr_v6_full(b: &mut Bencher) { - b.iter(|| IpAddr::from_str(black_box(IPV6_STR_FULL))); + b.iter(|| { + for s in IPV6_FULL { + let _ = black_box(IpAddr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_ipaddr_v6_compress(b: &mut Bencher) { - b.iter(|| IpAddr::from_str(black_box(IPV6_STR_COMPRESS))); + b.iter(|| { + for s in IPV6_COMPRESS { + let _ = black_box(IpAddr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_ipaddr_v6_v4(b: &mut Bencher) { - b.iter(|| IpAddr::from_str(black_box(IPV6_STR_V4))); + b.iter(|| { + for s in IPV6_V4 { + let _ = black_box(IpAddr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_socket_v4(b: &mut Bencher) { - b.iter(|| SocketAddrV4::from_str(black_box(IPV4_STR_PORT))); + b.iter(|| { + for s in IPV4_PORT { + let _ = black_box(SocketAddrV4::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_socket_v6(b: &mut Bencher) { - b.iter(|| SocketAddrV6::from_str(black_box(IPV6_STR_PORT))); + b.iter(|| { + for s in IPV6_PORT { + let _ = black_box(SocketAddrV6::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_socket_v6_scope_id(b: &mut Bencher) { - b.iter(|| SocketAddrV6::from_str(black_box(IPV6_STR_PORT_SCOPE_ID))); + b.iter(|| { + for s in IPV6_PORT_SCOPE_ID { + let _ = black_box(SocketAddrV6::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_socketaddr_v4(b: &mut Bencher) { - b.iter(|| SocketAddr::from_str(black_box(IPV4_STR_PORT))); + b.iter(|| { + for s in IPV4_PORT { + let _ = black_box(SocketAddr::from_str(black_box(s))); + } + }); } #[bench] fn bench_parse_socketaddr_v6(b: &mut Bencher) { - b.iter(|| SocketAddr::from_str(black_box(IPV6_STR_PORT))); + b.iter(|| { + for s in IPV6_PORT { + let _ = black_box(SocketAddr::from_str(black_box(s))); + } + }); } diff --git a/library/coretests/tests/macros.rs b/library/coretests/tests/macros.rs index 9f73ebd253c3b..86419bb41e527 100644 --- a/library/coretests/tests/macros.rs +++ b/library/coretests/tests/macros.rs @@ -241,7 +241,19 @@ fn temporary_scope_introduction() { (assert_matches!(*MutRefWithDrop(&mut val).0, 0), std::mem::take(&mut val)); (assert_matches!(*MutRefWithDrop(&mut val).0, 0, "msg"), std::mem::take(&mut val)); - (debug_assert_matches!(*MutRefWithDrop(&mut val).0, 0), std::mem::take(&mut val)); (debug_assert_matches!(*MutRefWithDrop(&mut val).0, 0, "msg"), std::mem::take(&mut val)); + + (assert_eq!(*MutRefWithDrop(&mut val).0, 0), std::mem::take(&mut val)); + (assert_eq!(*MutRefWithDrop(&mut val).0, 0, "msg"), std::mem::take(&mut val)); + (debug_assert_eq!(*MutRefWithDrop(&mut val).0, 0), std::mem::take(&mut val)); + (debug_assert_eq!(*MutRefWithDrop(&mut val).0, 0, "msg"), std::mem::take(&mut val)); + + (assert_ne!(*MutRefWithDrop(&mut val).0, 1), std::mem::take(&mut val)); + (assert_ne!(*MutRefWithDrop(&mut val).0, 1, "msg"), std::mem::take(&mut val)); + (debug_assert_ne!(*MutRefWithDrop(&mut val).0, 1), std::mem::take(&mut val)); + (debug_assert_ne!(*MutRefWithDrop(&mut val).0, 1, "msg"), std::mem::take(&mut val)); + + (assert!(*MutRefWithDrop(&mut val).0 == 0), std::mem::take(&mut val)); + (assert!(*MutRefWithDrop(&mut val).0 == 0, "msg"), std::mem::take(&mut val)); } diff --git a/library/proc_macro/Cargo.toml b/library/proc_macro/Cargo.toml index 1e5046ca61c39..286080e1bea2e 100644 --- a/library/proc_macro/Cargo.toml +++ b/library/proc_macro/Cargo.toml @@ -9,7 +9,7 @@ std = { path = "../std" } # `core` when resolving doc links. Without this line a different `core` will be # loaded from sysroot causing duplicate lang items and other similar errors. core = { path = "../core" } -rustc-literal-escaper = { version = "0.0.7", features = ["rustc-dep-of-std"] } +rustc-literal-escaper = { version = "0.0.8", features = ["rustc-dep-of-std"] } [features] default = ["rustc-dep-of-std"] diff --git a/library/proc_macro/src/bridge/buffer.rs b/library/proc_macro/src/bridge/buffer.rs index 3760749d83a54..3176b9ea35c8c 100644 --- a/library/proc_macro/src/bridge/buffer.rs +++ b/library/proc_macro/src/bridge/buffer.rs @@ -1,8 +1,7 @@ //! Buffer management for same-process client<->server communication. -use std::io::{self, Write}; use std::mem::{self, ManuallyDrop}; -use std::ops::{Deref, DerefMut}; +use std::ops::Deref; use std::slice; #[repr(C)] @@ -32,13 +31,6 @@ impl Deref for Buffer { } } -impl DerefMut for Buffer { - #[inline] - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.data, self.len) } - } -} - impl Buffer { #[inline] pub(super) fn new() -> Self { @@ -99,25 +91,6 @@ impl Buffer { } } -impl Write for Buffer { - #[inline] - fn write(&mut self, xs: &[u8]) -> io::Result { - self.extend_from_slice(xs); - Ok(xs.len()) - } - - #[inline] - fn write_all(&mut self, xs: &[u8]) -> io::Result<()> { - self.extend_from_slice(xs); - Ok(()) - } - - #[inline] - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - impl Drop for Buffer { #[inline] fn drop(&mut self) { @@ -128,8 +101,7 @@ impl Drop for Buffer { impl From> for Buffer { fn from(v: Vec) -> Self { - let mut v = ManuallyDrop::new(v); - let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity()); + let (data, len, capacity) = v.into_raw_parts(); // This utility function is nested in here because it can *only* // be safely called on `Buffer`s created by *this* `proc_macro`. diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index a5966f767596e..48e6245ecf98b 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -282,7 +282,7 @@ impl Client { pub const fn expand1(f: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy) -> Self { Client { run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| { - run_client(bridge, |input| f(input)) + run_client(bridge, f) }), } } diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 3459426b5cd3f..2c72497ad2723 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -1,6 +1,5 @@ //! Serialization for client-server communication. -use std::io::Write; use std::num::NonZero; use super::buffer::Buffer; @@ -209,7 +208,7 @@ impl Encode for &str { fn encode(self, w: &mut Buffer, s: &mut S) { let bytes = self.as_bytes(); bytes.len().encode(w, s); - w.write_all(bytes).unwrap(); + w.extend_from_slice(bytes); } } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 98b00c600f5ef..2cba4b52fc276 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -37,7 +37,7 @@ #![warn(unreachable_pub)] #![deny(unsafe_op_in_unsafe_fn)] -#[unstable(feature = "proc_macro_internals", issue = "27812")] +#[unstable(feature = "proc_macro_internals", issue = "none")] #[doc(hidden)] pub mod bridge; @@ -296,7 +296,7 @@ impl TokenStream { /// Checks if this `TokenStream` is empty. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn is_empty(&self) -> bool { - self.0.as_ref().map(|h| BridgeMethods::ts_is_empty(h)).unwrap_or(true) + self.0.as_ref().map(BridgeMethods::ts_is_empty).unwrap_or(true) } /// Parses this `TokenStream` as an expression and attempts to expand any @@ -575,9 +575,7 @@ pub mod token_stream { type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { - IntoIter( - self.0.map(|v| BridgeMethods::ts_into_trees(v)).unwrap_or_default().into_iter(), - ) + IntoIter(self.0.map(BridgeMethods::ts_into_trees).unwrap_or_default().into_iter()) } } } @@ -595,7 +593,7 @@ pub macro quote($($t:tt)*) { /* compiler built-in */ } -#[unstable(feature = "proc_macro_internals", issue = "27812")] +#[unstable(feature = "proc_macro_internals", issue = "none")] #[doc(hidden)] mod quote; @@ -755,14 +753,14 @@ impl Span { // Used by the implementation of `Span::quote` #[doc(hidden)] - #[unstable(feature = "proc_macro_internals", issue = "27812")] + #[unstable(feature = "proc_macro_internals", issue = "none")] pub fn save_span(&self) -> usize { BridgeMethods::span_save_span(self.0) } // Used by the implementation of `Span::quote` #[doc(hidden)] - #[unstable(feature = "proc_macro_internals", issue = "27812")] + #[unstable(feature = "proc_macro_internals", issue = "none")] pub fn recover_proc_macro_span(id: usize) -> Span { Span(BridgeMethods::span_recover_proc_macro_span(id)) } @@ -1296,7 +1294,7 @@ macro_rules! unsuffixed_int_literals { /// specified on this token, meaning that invocations like /// `Literal::i8_unsuffixed(1)` are equivalent to /// `Literal::u32_unsuffixed(1)`. - /// Literals created from negative numbers might not survive rountrips through + /// Literals created from negative numbers might not survive roundtrips through /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). /// /// Literals created through this method have the `Span::call_site()` @@ -1416,7 +1414,7 @@ impl Literal { /// This constructor is similar to those like `Literal::i8_unsuffixed` where /// the float's value is emitted directly into the token but no suffix is /// used, so it may be inferred to be a `f64` later in the compiler. - /// Literals created from negative numbers might not survive rountrips through + /// Literals created from negative numbers might not survive roundtrips through /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). /// /// # Panics @@ -1441,7 +1439,7 @@ impl Literal { /// specified is the preceding part of the token and `f32` is the suffix of /// the token. This token will always be inferred to be an `f32` in the /// compiler. - /// Literals created from negative numbers might not survive rountrips through + /// Literals created from negative numbers might not survive roundtrips through /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). /// /// # Panics @@ -1461,7 +1459,7 @@ impl Literal { /// This constructor is similar to those like `Literal::i8_unsuffixed` where /// the float's value is emitted directly into the token but no suffix is /// used, so it may be inferred to be a `f64` later in the compiler. - /// Literals created from negative numbers might not survive rountrips through + /// Literals created from negative numbers might not survive roundtrips through /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). /// /// # Panics @@ -1486,7 +1484,7 @@ impl Literal { /// specified is the preceding part of the token and `f64` is the suffix of /// the token. This token will always be inferred to be an `f64` in the /// compiler. - /// Literals created from negative numbers might not survive rountrips through + /// Literals created from negative numbers might not survive roundtrips through /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). /// /// # Panics diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 76374402be4b3..44ddb55c920f4 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -6,121 +6,83 @@ pub mod raw; -// The code below could be written clearer using `cfg_if!`. However, the items below are -// publicly exported by `std` and external tools can have trouble analysing them because of the use -// of a macro that is not vendored by Rust and included in the toolchain. -// See https://github.com/rust-analyzer/rust-analyzer/issues/6038. +// # Important platforms -// On certain platforms right now the "main modules" modules that are -// documented don't compile (missing things in `libc` which is empty), -// so just omit them with an empty module and add the "unstable" attribute. - -// darwin, unix, linux, wasi and windows are handled a bit differently. -#[cfg(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -))] -#[unstable(issue = "none", feature = "std_internals")] -pub mod darwin {} -#[cfg(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -))] -#[unstable(issue = "none", feature = "std_internals")] -pub mod unix {} -#[cfg(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -))] -#[unstable(issue = "none", feature = "std_internals")] -pub mod linux {} -#[cfg(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -))] -#[unstable(issue = "none", feature = "std_internals")] -pub mod wasi {} -#[cfg(all( - doc, +// We always want to show documentation for the most important platforms, +// so these are handled specially here. +// +// FIXME: On certain platforms compilation errors (due to empty `libc`), +// prevent this, so we substitute an unstable empty module. +#[cfg(doc)] +cfg_select! { any( all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") - ) -))] -#[unstable(issue = "none", feature = "std_internals")] -pub mod windows {} + ) => { + #[unstable(issue = "none", feature = "std_internals")] + pub mod darwin {} -// darwin -#[cfg(not(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -)))] -#[cfg(any(target_vendor = "apple", doc))] -pub mod darwin; + #[unstable(issue = "none", feature = "std_internals")] + pub mod unix {} -// unix -#[cfg(not(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -)))] -#[cfg(all(not(target_os = "hermit"), any(unix, doc)))] -pub mod unix; + #[unstable(issue = "none", feature = "std_internals")] + pub mod linux {} -// linux -#[cfg(not(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -)))] -#[cfg(any(target_os = "linux", doc))] -pub mod linux; + #[unstable(issue = "none", feature = "std_internals")] + pub mod wasi {} -// wasi -#[cfg(not(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -)))] -#[cfg(any(target_os = "wasi", any(target_env = "p1", target_env = "p2"), doc))] -pub mod wasi; + #[unstable(issue = "none", feature = "std_internals")] + pub mod windows {} + } + _ => { + // important platforms + pub mod darwin; + pub mod linux; + pub mod unix; + pub mod wasi; + pub mod wasip2; + pub mod windows; + } +} +#[cfg(not(doc))] // to prevent double module declarations +cfg_select! { + target_family = "unix" => { + pub mod unix; + #[cfg(target_vendor = "apple")] + pub mod darwin; + #[cfg(target_os = "linux")] + pub mod linux; + } + target_family = "wasm" => { + #[cfg(any(target_env = "p1", target_env = "p2"))] + pub mod wasi; + #[cfg(target_env = "p2")] + pub mod wasip2; + } + target_family = "windows" => { + pub mod windows; + } + _ => { /* handled below */ } +} -#[cfg(any(all(target_os = "wasi", target_env = "p2"), doc))] -pub mod wasip2; +// # Special modules -// windows -#[cfg(not(all( - doc, - any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - ) -)))] -#[cfg(any(windows, doc))] -pub mod windows; +#[cfg(any( + unix, + target_os = "hermit", + target_os = "trusty", + target_os = "wasi", + target_os = "motor", + doc +))] +pub mod fd; + +#[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin", doc))] +mod net; + +// # Ordinary platforms +// `cfg(doc)` not handled specially -// Others. #[cfg(target_os = "aix")] pub mod aix; #[cfg(target_os = "android")] @@ -183,16 +145,3 @@ pub mod vita; pub mod vxworks; #[cfg(target_os = "xous")] pub mod xous; - -#[cfg(any( - unix, - target_os = "hermit", - target_os = "trusty", - target_os = "wasi", - target_os = "motor", - doc -))] -pub mod fd; - -#[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin", doc))] -mod net; diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs index 9f40c01546632..ee7e5f8586700 100644 --- a/library/std/src/sync/poison.rs +++ b/library/std/src/sync/poison.rs @@ -57,9 +57,6 @@ //! //! [`Once`]: crate::sync::Once -// If we are not unwinding, `PoisonError` is uninhabited. -#![cfg_attr(not(panic = "unwind"), expect(unreachable_code))] - #[stable(feature = "rust1", since = "1.0.0")] pub use self::condvar::Condvar; #[unstable(feature = "mapped_lock_guards", issue = "117108")] diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index b0feea13b0485..114387d963a6d 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1201,11 +1201,6 @@ impl Step for Src { // not needed and contains symlinks which rustup currently // chokes on when unpacking. "library/backtrace/crates", - // these are 30MB combined and aren't necessary for building - // the standard library. - "library/stdarch/Cargo.toml", - "library/stdarch/crates/stdarch-verify", - "library/stdarch/crates/intrinsic-test", ], &dst_src, ); diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh index 17bedaa7b8266..470ef4ffea433 100755 --- a/src/ci/scripts/install-mingw.sh +++ b/src/ci/scripts/install-mingw.sh @@ -6,8 +6,8 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -MINGW_ARCHIVE_32="i686-14.1.0-release-posix-dwarf-msvcrt-rt_v12-rev0.7z" -MINGW_ARCHIVE_64="x86_64-14.1.0-release-posix-seh-msvcrt-rt_v12-rev0.7z" +MINGW_ARCHIVE_32="i686-14.2.0-release-posix-dwarf-msvcrt-rt_v12-rev2.7z" +MINGW_ARCHIVE_64="x86_64-14.2.0-release-posix-seh-msvcrt-rt_v12-rev2.7z" LLVM_MINGW_ARCHIVE_AARCH64="llvm-mingw-20251104-ucrt-aarch64.zip" LLVM_MINGW_ARCHIVE_X86_64="llvm-mingw-20251104-ucrt-x86_64.zip" diff --git a/src/doc/rustc/src/platform-support/windows-gnu.md b/src/doc/rustc/src/platform-support/windows-gnu.md index a867ebcfe2539..d7aec5af21dec 100644 --- a/src/doc/rustc/src/platform-support/windows-gnu.md +++ b/src/doc/rustc/src/platform-support/windows-gnu.md @@ -26,6 +26,18 @@ They follow Windows calling convention for `extern "C"`. Like with any other Windows target, created binaries are in PE format. +### C toolchain + +The targets are built and tested using a reasonably modern C toolchain, and it should be considered as the oldest supported version: + +* GNU Binutils 2.44 +* GCC 14.2 +* mingw-w64 12.0.0 +* MSVCRT library as the default + +Using older tools (especially Binutils) may not work properly, due to the number of issues plaguing older versions of Binutils. +The supported toolchain versions are subject to change. + ## Building Rust programs Rust does ship a pre-compiled std library for those targets. diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index 49dc5c9f10a89..a11abc8d7cc4c 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -10,7 +10,7 @@ clap = { version = "4.4", features = ["derive"] } indoc = "1.0" itertools = "0.12" opener = "0.8" -rustc-literal-escaper = "0.0.7" +rustc-literal-escaper = "0.0.8" walkdir = "2.3" [package.metadata.rust-analyzer] diff --git a/src/tools/lint-docs/Cargo.toml b/src/tools/lint-docs/Cargo.toml index ab99eb8ea3b72..2d7d6a6fc5e79 100644 --- a/src/tools/lint-docs/Cargo.toml +++ b/src/tools/lint-docs/Cargo.toml @@ -7,7 +7,7 @@ description = "A script to extract the lint documentation for the rustc book." # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rustc-literal-escaper = "0.0.7" +rustc-literal-escaper = "0.0.8" serde_json = "1.0.57" tempfile = "3.1.0" walkdir = "2.3.1" diff --git a/src/tools/miri/tests/pass/c-variadic.rs b/src/tools/miri/tests/pass/c-variadic.rs index 4179c7090830c..e17d6820c5b0b 100644 --- a/src/tools/miri/tests/pass/c-variadic.rs +++ b/src/tools/miri/tests/pass/c-variadic.rs @@ -106,6 +106,20 @@ fn various_types() { } } +fn equal_up_to_free_lifetime() { + // Types are considered equal up to free lifetimes: `*const &'static str` + // is the same as `*const &'a str`. + // Bound lifetimes (using e.g. `for<'_>`) are different. + #[expect(improper_ctypes_definitions)] + pub unsafe extern "C" fn foo(mut args: ...) -> &'static str { + unsafe { *args.next_arg::<*const &'static str>() } + } + + let data = String::from("abc"); + let x: &str = data.as_str(); + assert_eq!(unsafe { foo(&raw const x) }, "abc"); +} + fn clone() { if cfg!(force_intrinsic_fallback) { // Skip this test when we use the fallback bodies. The fallback body does @@ -170,6 +184,7 @@ fn main() { forward_by_ref(); nested(); various_types(); + equal_up_to_free_lifetime(); clone(); clone_and_advance(); } diff --git a/src/tools/rust-analyzer/.github/FUNDING.yml b/src/tools/rust-analyzer/.github/FUNDING.yml new file mode 100644 index 0000000000000..1d270e78949f8 --- /dev/null +++ b/src/tools/rust-analyzer/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: rustfoundation +custom: ["rust-lang.org/funding"] diff --git a/src/tools/rust-analyzer/.github/actions/github-release/Dockerfile b/src/tools/rust-analyzer/.github/actions/github-release/Dockerfile index 5849eac7d246a..ad296ce74152f 100644 --- a/src/tools/rust-analyzer/.github/actions/github-release/Dockerfile +++ b/src/tools/rust-analyzer/.github/actions/github-release/Dockerfile @@ -1,4 +1,4 @@ -FROM node:slim +FROM node:24.16-slim@sha256:ca520832af80fa37a57c14077ed0fcdd83b5aefccc356059fdc3a9a05b78ae1f COPY . /action WORKDIR /action diff --git a/src/tools/rust-analyzer/.gitignore b/src/tools/rust-analyzer/.gitignore index 3beabe39bc7a3..32374dac91818 100644 --- a/src/tools/rust-analyzer/.gitignore +++ b/src/tools/rust-analyzer/.gitignore @@ -7,6 +7,7 @@ vendor/ *.log *.iml .vscode/settings.json +.vim/coc-settings.json .DS_Store /out/ /dump.lsif diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 477ecfba2f752..602af6f1222d7 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1002,15 +1002,6 @@ dependencies = [ "typed-arena", ] -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "icu_collections" version = "2.2.0" @@ -3116,7 +3107,6 @@ name = "toolchain" version = "0.0.0" dependencies = [ "camino", - "home", ] [[package]] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 3094e08a53c3c..a69755baf632c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -671,6 +671,7 @@ impl<'db> ExprCollector<'db> { } pl.params() + .filter(|it| it.dotdotdot_token().is_none()) .map(|it| { let type_ref = self.lower_type_ref_opt(it.ty(), impl_trait_lower_fn); let name = match it.pat() { @@ -2403,6 +2404,10 @@ impl<'db> ExprCollector<'db> { statements: &mut Vec, mac: ast::MacroExpr, ) -> Option { + if !self.check_cfg(&ast::Expr::MacroExpr(mac.clone())) { + return None; + } + let mac_call = mac.macro_call()?; let syntax_ptr = AstPtr::new(&ast::Expr::from(mac)); let macro_ptr = AstPtr::new(&mac_call); @@ -2446,10 +2451,6 @@ impl<'db> ExprCollector<'db> { } ast::Stmt::ExprStmt(stmt) => { let expr = stmt.expr(); - match &expr { - Some(expr) if !self.check_cfg(expr) => return, - _ => (), - } let has_semi = stmt.semicolon_token().is_some(); // Note that macro could be expanded to multiple statements if let Some(ast::Expr::MacroExpr(mac)) = expr { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs index e97718ca22c32..da412a620d0a7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs @@ -688,3 +688,31 @@ fn foo() { }"#]], ); } + +#[test] +fn foo() { + pretty_print( + r#" +macro_rules! foo { + () => { + 1 + }; +} + +fn foo() -> i64 { + #[cfg(true)] + { + 5 + } + #[cfg(false)] + foo!() +} + "#, + expect![[r#" + fn foo() { + { + 5 + } + }"#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 513115684f872..33672d10fa6d5 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -141,11 +141,6 @@ pub trait ExpandDatabase: SourceDatabase { fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext; } -#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext, revisions = usize::MAX)] -pub struct SyntaxContextWrapper { - pub data: SyntaxContext, -} - fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContext { match file { HirFileId::FileId(_) => SyntaxContext::root(edition), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index d6580d3752f6b..a880ae5353b66 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -87,18 +87,24 @@ fn intern_const_ref<'db>( let valtree = match (ty.kind(), value) { (TyKind::Uint(uint), Literal::Uint(value, _)) => { let size = uint.bit_width().map(Size::from_bits).unwrap_or(data_layout.pointer_size()); - let scalar = ScalarInt::try_from_uint(*value, size).unwrap(); + let Some(scalar) = ScalarInt::try_from_uint(*value, size) else { + return Ok(Const::error(interner)); + }; ValTreeKind::Leaf(scalar) } (TyKind::Uint(uint), Literal::Int(value, _)) => { // `Literal::Int` is the default, so we also need to account for the type being uint. let size = uint.bit_width().map(Size::from_bits).unwrap_or(data_layout.pointer_size()); - let scalar = ScalarInt::try_from_uint(*value as u128, size).unwrap(); + let Some(scalar) = ScalarInt::try_from_uint(*value as u128, size) else { + return Ok(Const::error(interner)); + }; ValTreeKind::Leaf(scalar) } (TyKind::Int(int), Literal::Int(value, _)) => { let size = int.bit_width().map(Size::from_bits).unwrap_or(data_layout.pointer_size()); - let scalar = ScalarInt::try_from_int(*value, size).unwrap(); + let Some(scalar) = ScalarInt::try_from_int(*value, size) else { + return Ok(Const::error(interner)); + }; ValTreeKind::Leaf(scalar) } (TyKind::Bool, Literal::Bool(value)) => ValTreeKind::Leaf(ScalarInt::from(*value)), @@ -219,7 +225,9 @@ pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option, krate: Cr return Const::error(interner); }; let usize_ty = interner.default_types().types.usize; - let scalar = ScalarInt::try_from_uint(value, data_layout.pointer_size()).unwrap(); + let Some(scalar) = ScalarInt::try_from_uint(value, data_layout.pointer_size()) else { + return Const::error(interner); + }; Const::new_valtree(interner, usize_ty, ValTreeKind::Leaf(scalar)) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 5421b97db2386..0e51594a78d06 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -2633,6 +2633,19 @@ fn const_generic_subst_fn() { ); } +#[test] +fn const_generic_fixed_width() { + check_number( + r#" + const fn m() -> u64 { + N + } + const GOAL: u64 = m::<0>(); + "#, + 0, + ); +} + #[test] fn layout_of_type_with_associated_type_field_defined_inside_body() { check_number( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index baf8bbd56fb1e..93ae26abce88b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -6,8 +6,8 @@ use base_db::{Crate, target::TargetLoadError}; use either::Either; use hir_def::{ AdtId, BuiltinDeriveImplId, CallableDefId, ConstId, ConstParamId, EnumVariantId, - ExpressionStoreOwnerId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, - LocalFieldId, ModuleId, StaticId, TraitId, TypeAliasId, VariantId, + ExpressionStoreOwnerId, FunctionId, GenericDefId, HasModule, ImplId, LocalFieldId, ModuleId, + StaticId, TraitId, TypeAliasId, VariantId, builtin_derive::BuiltinDeriveImplMethod, db::DefDatabase, expr_store::ExpressionStore, @@ -294,19 +294,6 @@ fn hir_database_is_dyn_compatible() { fn _assert_dyn_compatible(_: &dyn HirDatabase) {} } -#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)] -#[derive(PartialOrd, Ord)] -pub struct InternedLifetimeParamId { - /// This stores the param and its index. - pub loc: (LifetimeParamId, u32), -} - -#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)] -#[derive(PartialOrd, Ord)] -pub struct InternedConstParamId { - pub loc: ConstParamId, -} - #[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)] #[derive(PartialOrd, Ord)] pub struct InternedOpaqueTyId { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs index 34f9508e763f0..d8a8cceee6583 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs @@ -1016,8 +1016,9 @@ impl<'a, 'b, 'db, D: Delegate<'db>> ExprUseVisitor<'a, 'b, 'db, D> { } } Pat::Expr(expr) => { - // Destructuring assignment. this.mutate_expr(expr)?; + // Destructuring assignment moves + this.consume_or_copy(place); } Pat::Or(_) | Pat::Box { .. } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index eb0e4c60200f2..c69febd019672 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -1935,25 +1935,37 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { Ok(Interval::new(addr, 4)) } TyKind::Int(int_ty) => { - let size = int_ty.bit_width().unwrap_or(self.ptr_size() as u64); - let value = valtree.inner().to_leaf().to_int(Size::from_bytes(size)); - let addr = self.heap_allocate(size as usize, size as usize)?; - self.write_memory(addr, &value.to_le_bytes()[..size as usize])?; - Ok(Interval::new(addr, size as usize)) + let size = int_ty + .bit_width() + .map(Size::from_bits) + .unwrap_or_else(|| Size::from_bytes(self.ptr_size() as u64)); + let bytes = size.bytes_usize(); + + let value = valtree.inner().to_leaf().to_int(size); + let addr = self.heap_allocate(bytes, bytes)?; + self.write_memory(addr, &value.to_le_bytes()[..bytes])?; + Ok(Interval::new(addr, bytes)) } TyKind::Uint(uint_ty) => { - let size = uint_ty.bit_width().unwrap_or(self.ptr_size() as u64); - let value = valtree.inner().to_leaf().to_uint(Size::from_bytes(size)); - let addr = self.heap_allocate(size as usize, size as usize)?; - self.write_memory(addr, &value.to_le_bytes()[..size as usize])?; - Ok(Interval::new(addr, size as usize)) + let size = uint_ty + .bit_width() + .map(Size::from_bits) + .unwrap_or_else(|| Size::from_bytes(self.ptr_size() as u64)); + let bytes = size.bytes_usize(); + + let value = valtree.inner().to_leaf().to_uint(size); + let addr = self.heap_allocate(bytes, bytes)?; + self.write_memory(addr, &value.to_le_bytes()[..bytes])?; + Ok(Interval::new(addr, bytes)) } TyKind::Float(float_ty) => { - let size = float_ty.bit_width(); - let value = valtree.inner().to_leaf().to_uint(Size::from_bytes(size)); - let addr = self.heap_allocate(size as usize, size as usize)?; - self.write_memory(addr, &value.to_le_bytes()[..size as usize])?; - Ok(Interval::new(addr, size as usize)) + let size = Size::from_bits(float_ty.bit_width()); + let bytes = size.bytes_usize(); + + let value = valtree.inner().to_leaf().to_uint(size); + let addr = self.heap_allocate(bytes, bytes)?; + self.write_memory(addr, &value.to_le_bytes()[..bytes])?; + Ok(Interval::new(addr, bytes)) } TyKind::RawPtr(..) => { let size = self.ptr_size(); @@ -1995,15 +2007,13 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> { _ => not_supported!("unsupported const"), }) .collect::>>()?; + let item_size = item_layout.size.bytes_usize(); let items_addr = self.heap_allocate( - items.len() * (item_layout.size.bits() as usize), - item_layout.align.bits_usize(), + items.len() * item_size, + item_layout.align.bytes() as usize, )?; for (i, item) in items.iter().enumerate() { - self.copy_from_interval( - items_addr.offset(i * (item_layout.size.bits() as usize)), - *item, - )?; + self.copy_from_interval(items_addr.offset(i * item_size), *item)?; } let ref_addr = self.heap_allocate(self.ptr_size() * 2, self.ptr_size())?; self.write_memory(ref_addr, &items_addr.to_bytes())?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs index 6b6dd549b34e0..2c2f7dbf67301 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs @@ -843,7 +843,7 @@ impl<'db> InferCtxt<'db> { GenericArgs::for_item(self.interner, def_id, |_index, kind, _| self.var_for_def(kind, span)) } - /// Like `fresh_args_for_item()`, but first uses the args from `first`. + /// Like [`Self::fresh_args_for_item`], but first uses the args from `first`. pub fn fill_rest_fresh_args( &self, span: Span, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs index b466fe0f1810b..ef626fc0c8869 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs @@ -1128,6 +1128,9 @@ impl<'db> Interner for DbInterner<'db> { SolverDefId::ConstId(def_id) => { AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) } } + SolverDefId::StaticId(def_id) => { + AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) } + } SolverDefId::AnonConstId(def_id) => { AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) } } @@ -2626,8 +2629,8 @@ macro_rules! impl_gc_visit_slice { } #[inline] - fn visit_slice(header: &[::SliceType], gc: &mut ::intern::GarbageCollector) { - header.generic_visit_with(gc); + fn visit_slice(slice: &[::SliceType], gc: &mut ::intern::GarbageCollector) { + slice.generic_visit_with(gc); } } )* diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs index 3942a7ae27afa..bf0e60cf21b80 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs @@ -617,3 +617,40 @@ fn foo(foo: &Foo) { expect!["102..126;85..88;114..117 ByRef(Immutable) *foo &' Foo"], ); } + +#[test] +fn method_call_field_access_regression() { + check_closure_captures( + r#" +//- minicore:copy, fn +struct NonCopy; + +struct Wrapper { + field: NonCopy, +} + +impl Wrapper { + fn wrapped(&self) -> NonCopy { + NonCopy + } +} + +pub struct Wrapper2 { + field1: NonCopy, + field2: NonCopy, +} + +fn fun(wrapper: Wrapper) { + pub fn update(_: impl FnOnce(&mut T)) { + todo!() + } + + update::(|this| { + this.field1 = wrapper.wrapped(); + this.field2 = wrapper.field; + }); +} + "#, + expect!["319..411;206..213;350..357,391..398 ByValue wrapper Wrapper"], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs index c77b20f4b54c1..fb00a755fa055 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs @@ -394,6 +394,26 @@ fn main() { ); } +#[test] +fn static_as_array_len_does_not_panic() { + check_no_mismatches( + r#" +static S: usize = 8; +const A: [u8; S] = [0; 8]; + "#, + ); +} + +#[test] +fn oversized_array_len_does_not_panic() { + // The array length literal does not fit in `usize`; interning it must not panic. + check_no_mismatches( + r#" +fn f(_: [u8; 18446744073709551616]) {} + "#, + ); +} + #[test] fn another_20654_case() { check_no_mismatches( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index 4c76ae901da8c..2ca9ebe070bc9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -20,7 +20,7 @@ use hir_expand::name::Name; use intern::sym; use rustc_type_ir::{ TypeVisitableExt, TypingMode, - inherent::{BoundExistentialPredicates, IntoKind}, + inherent::{BoundExistentialPredicates, IntoKind, Ty as _}, }; use crate::{ @@ -154,6 +154,9 @@ pub fn implements_trait_unique_with_infcx<'db>( let args = create_args(&infcx); let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args); + if trait_ref.self_ty().is_ty_error() { + return false; + } let obligation = Obligation::new(interner, ObligationCause::dummy(), env.param_env, trait_ref); infcx.predicate_must_hold_modulo_regions(&obligation) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs index 2755962362677..a272351e134cc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs @@ -1236,15 +1236,11 @@ fn main { fn destructure_in_sub_pattern() { check_sub_pattern_assist( r#" -#![feature(bindings_after_at)] - fn main() { let $0t = (1,2); } "#, r#" -#![feature(bindings_after_at)] - fn main() { let t @ ($0_0, _1) = (1,2); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs index 40eaed0080a0a..40c54e98820a8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs @@ -17,9 +17,10 @@ use syntax::{ ast::{ self, HasVisibility, edit::{AstNodeEdit, IndentLevel}, - make, + syntax_factory::SyntaxFactory, }, - match_ast, ted, + match_ast, + syntax_editor::{Position, SyntaxEditor}, }; use crate::{AssistContext, Assists}; @@ -121,15 +122,18 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> let (usages_to_be_processed, record_fields, use_stmts_to_be_inserted) = module.get_usages_and_record_fields(ctx, module_text_range); + let make = SyntaxFactory::without_mappings(); + builder.edit_file(ctx.vfs_file_id()); use_stmts_to_be_inserted.into_iter().for_each(|(_, use_stmt)| { builder.insert(ctx.selection_trimmed().end(), format!("\n{use_stmt}")); }); - let import_items = module.resolve_imports(curr_parent_module, ctx); - module.change_visibility(record_fields); + let import_items = module.resolve_imports(curr_parent_module, ctx, &make); + module.change_visibility(record_fields, &make); - let module_def = generate_module_def(&impl_parent, &module).indent(old_item_indent); + let module_def = + generate_module_def(&impl_parent, &module, &make).indent(old_item_indent); let mut usages_to_be_processed_for_cur_file = vec![]; for (file_id, usages) in usages_to_be_processed { @@ -185,6 +189,7 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> fn generate_module_def( parent_impl: &Option, Module { name, body_items, use_items }: &Module, + make: &SyntaxFactory, ) -> ast::Module { let items: Vec<_> = if let Some(impl_) = parent_impl.as_ref() && let Some(self_ty) = impl_.self_ty() @@ -195,11 +200,15 @@ fn generate_module_def( .filter_map(ast::AssocItem::cast) .map(|it| it.indent(IndentLevel(1))) .collect_vec(); - let assoc_item_list = make::assoc_item_list(Some(assoc_items)).clone_for_update(); - let impl_ = impl_.reset_indent(); - ted::replace(impl_.get_or_create_assoc_item_list().syntax(), assoc_item_list.syntax()); + let impl_reset = impl_.reset_indent(); + let (editor, impl_root) = SyntaxEditor::with_ast_node(&impl_reset); + let assoc_item_list = editor.make().assoc_item_list(assoc_items); + if let Some(existing_list) = impl_root.assoc_item_list() { + editor.replace(existing_list.syntax(), assoc_item_list.syntax()); + } + let impl_ = ast::Impl::cast(editor.finish().new_root().clone()).unwrap(); // Add the import for enum/struct corresponding to given impl block - let use_impl = make_use_stmt_of_node_with_super(self_ty.syntax()); + let use_impl = make_use_stmt_of_node_with_super(self_ty.syntax(), make); once(use_impl) .chain(use_items.iter().cloned()) .chain(once(ast::Item::Impl(impl_))) @@ -209,19 +218,18 @@ fn generate_module_def( }; let items = items.into_iter().map(|it| it.reset_indent().indent(IndentLevel(1))).collect_vec(); - let module_body = make::item_list(Some(items)); - - let module_name = make::name(name); - make::mod_(module_name, Some(module_body)) + let module_body = make.item_list(items); + let module_name = make.name(name); + make.mod_(module_name, Some(module_body)) } -fn make_use_stmt_of_node_with_super(node_syntax: &SyntaxNode) -> ast::Item { - let super_path = make::ext::ident_path("super"); - let node_path = make::ext::ident_path(&node_syntax.to_string()); - let use_ = make::use_( +fn make_use_stmt_of_node_with_super(node_syntax: &SyntaxNode, make: &SyntaxFactory) -> ast::Item { + let super_path = make.ident_path("super"); + let node_path = make.path_from_text(&node_syntax.to_string()); + let use_ = make.use_( + [], None, - None, - make::use_tree(make::join_paths(vec![super_path, node_path]), None, None, false), + make.use_tree(make.path_concat(super_path, node_path), None, None, false), ); ast::Item::from(use_) @@ -385,18 +393,30 @@ impl Module { if use_.syntax().parent().is_some_and(|parent| parent == covering_node) && use_stmts_set.insert(use_.syntax().text_range().start()) { - let use_ = use_stmts_to_be_inserted - .entry(use_.syntax().text_range().start()) - .or_insert_with(|| use_.clone_subtree().clone_for_update()); - for seg in use_ - .syntax() - .descendants() - .filter_map(ast::NameRef::cast) - .filter(|seg| seg.syntax().to_string() == name_ref.to_string()) - { - let new_ref = make::path_from_text(&format!("{mod_name}::{seg}")) - .clone_for_update(); - ted::replace(seg.syntax().parent()?, new_ref.syntax()); + let key = use_.syntax().text_range().start(); + let entry = + use_stmts_to_be_inserted.entry(key).or_insert_with(|| use_.clone()); + let (editor, edit_root) = SyntaxEditor::with_ast_node(&*entry); + let replacements: Vec<_> = { + let make = editor.make(); + edit_root + .syntax() + .descendants() + .filter_map(ast::NameRef::cast) + .filter(|seg| seg.syntax().to_string() == name_ref.to_string()) + .filter_map(|seg| { + Some(( + seg.syntax().parent()?, + make.path_from_text(&format!("{mod_name}::{seg}")), + )) + }) + .collect() + }; + if !replacements.is_empty() { + for (parent, new_ref) in &replacements { + editor.replace(parent, new_ref.syntax()); + } + *entry = ast::Use::cast(editor.finish().new_root().clone()).unwrap(); } } } @@ -407,18 +427,23 @@ impl Module { } } - fn change_visibility(&mut self, record_fields: Vec) { + fn change_visibility(&mut self, record_fields: Vec, make: &SyntaxFactory) { + for item in &mut self.body_items { + let (_, root) = SyntaxEditor::with_ast_node(&item.reset_indent()); + *item = root; + } + let (mut replacements, record_field_parents, impls) = - get_replacements_for_visibility_change(&mut self.body_items, false); + get_replacements_for_visibility_change(&self.body_items); - let mut impl_items = impls + let impl_items = impls .into_iter() .flat_map(|impl_| impl_.syntax().descendants()) .filter_map(ast::Item::cast) .collect_vec(); let (mut impl_item_replacements, _, _) = - get_replacements_for_visibility_change(&mut impl_items, true); + get_replacements_for_visibility_change(&impl_items); replacements.append(&mut impl_item_replacements); @@ -432,17 +457,39 @@ impl Module { } } - for (vis, syntax) in replacements { - let item = syntax.children_with_tokens().find(|node_or_token| { - match node_or_token.kind() { - // We're skipping comments, doc comments, and attribute macros that may precede the keyword - // that the visibility should be placed before. - SyntaxKind::COMMENT | SyntaxKind::ATTR | SyntaxKind::WHITESPACE => false, - _ => true, - } - }); + for body_item in &mut self.body_items { + let insert_targets: Vec<_> = replacements + .iter() + .filter(|(vis, syntax)| { + vis.is_none() + && (syntax == body_item.syntax() + || syntax.ancestors().any(|a| &a == body_item.syntax())) + }) + .filter_map(|(_, syntax)| { + syntax.children_with_tokens().find(|nt| { + !matches!( + nt.kind(), + SyntaxKind::COMMENT | SyntaxKind::ATTR | SyntaxKind::WHITESPACE + ) + }) + }) + .collect(); - add_change_vis(vis, item); + if insert_targets.is_empty() { + continue; + } + + let (editor, _) = SyntaxEditor::new(body_item.syntax().clone()); + for target in insert_targets { + editor.insert_all( + Position::before(target), + vec![ + make.visibility_pub_crate().syntax().clone().into(), + make.whitespace(" ").into(), + ], + ); + } + *body_item = ast::Item::cast(editor.finish().new_root().clone()).unwrap(); } } @@ -450,6 +497,7 @@ impl Module { &mut self, module: Option, ctx: &AssistContext<'_, '_>, + make: &SyntaxFactory, ) -> Vec { let mut imports_to_remove = vec![]; let mut node_set = FxHashSet::default(); @@ -476,7 +524,8 @@ impl Module { }) .for_each(|(node, def)| { if node_set.insert(node.to_string()) - && let Some(import) = self.process_def_in_sel(def, &node, &module, ctx) + && let Some(import) = + self.process_def_in_sel(def, &node, &module, ctx, make) { check_intersection_and_push(&mut imports_to_remove, import); } @@ -492,6 +541,7 @@ impl Module { use_node: &SyntaxNode, curr_parent_module: &Option, ctx: &AssistContext<'_, '_>, + make: &SyntaxFactory, ) -> Option { //We only need to find in the current file let selection_range = ctx.selection_trimmed(); @@ -567,7 +617,7 @@ impl Module { // mod -> ust_stmt transversal // true | false -> super import insertion // true | true -> super import insertion - let super_use_node = make_use_stmt_of_node_with_super(use_node); + let super_use_node = make_use_stmt_of_node_with_super(use_node, make); self.use_items.insert(0, super_use_node); } None => {} @@ -590,14 +640,14 @@ impl Module { if !first_path_in_use_tree_str.contains("super") && !first_path_in_use_tree_str.contains("crate") { - let super_path = make::ext::ident_path("super"); + let super_path = make.ident_path("super"); use_tree_str.push(super_path); } } use_tree_paths = Some(use_tree_str); } else if def_in_mod && def_out_sel { - let super_use_node = make_use_stmt_of_node_with_super(use_node); + let super_use_node = make_use_stmt_of_node_with_super(use_node, make); self.use_items.insert(0, super_use_node); } } @@ -609,7 +659,7 @@ impl Module { && let Some(first_path_in_use_tree) = use_tree_paths.first() && first_path_in_use_tree.to_string().contains("super") { - use_tree_paths.insert(0, make::ext::ident_path("super")); + use_tree_paths.insert(0, make.ident_path("super")); } let is_item = matches!( @@ -624,12 +674,12 @@ impl Module { | Definition::TypeAlias(_) ); - if (def_out_sel || !is_item) && use_stmt_not_in_sel { - let use_ = make::use_( - None, - None, - make::use_tree(make::join_paths(use_tree_paths), None, None, false), - ); + if (def_out_sel || !is_item) + && use_stmt_not_in_sel + && let Some(joined) = + use_tree_paths.into_iter().reduce(|acc, p| make.path_concat(acc, p)) + { + let use_ = make.use_([], None, make.use_tree(joined, None, None, false)); self.use_items.insert(0, ast::Item::from(use_)); } } @@ -741,8 +791,7 @@ fn check_def_in_mod_and_out_sel( } fn get_replacements_for_visibility_change( - items: &mut [ast::Item], - is_clone_for_updated: bool, + items: &[ast::Item], ) -> ( Vec<(Option, SyntaxNode)>, Vec<(Option, SyntaxNode)>, @@ -753,9 +802,6 @@ fn get_replacements_for_visibility_change( let mut impls = Vec::new(); for item in items { - if !is_clone_for_updated { - *item = item.clone_for_update(); - } //Use stmts are ignored macro_rules! push_to_replacement { ($it:ident) => { @@ -812,15 +858,6 @@ fn get_use_tree_paths_from_path( Some(use_tree_str) } -fn add_change_vis(vis: Option, node_or_token_opt: Option) { - if vis.is_none() - && let Some(node_or_token) = node_or_token_opt - { - let pub_crate_vis = make::visibility_pub_crate().clone_for_update(); - ted::insert(ted::Position::before(node_or_token), pub_crate_vis.syntax()); - } -} - fn indent_range_before_given_node(node: &SyntaxNode) -> Option { node.siblings_with_tokens(syntax::Direction::Prev) .find(|x| x.kind() == WHITESPACE) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index 531adf62ba3f5..7a82e8b2f3ac8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -1,19 +1,20 @@ use either::{Either, for_both}; -use hir::{PathResolution, Semantics}; +use hir::{EditionedFileId, PathResolution, Semantics}; use ide_db::{ - EditionedFileId, RootDatabase, + RootDatabase, defs::Definition, - search::{FileReference, FileReferenceNode, UsageSearchResult}, + search::{FileReference, UsageSearchResult}, }; use syntax::{ - Direction, TextRange, + Direction, T, TextRange, ast::{self, AstNode, AstToken, HasName}, - syntax_editor::{Element, SyntaxEditor}, + syntax_editor::{Element, Position, SyntaxEditor}, }; use crate::{ AssistId, assist_context::{AssistContext, Assists}, + utils::{cover_edit_range, original_range_in}, }; // Assist: inline_local_variable @@ -34,11 +35,12 @@ use crate::{ // ``` pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> Option<()> { let file_id = ctx.file_id(); + let source = ctx.source_file().syntax(); let range = ctx.selection_trimmed(); let InlineData { let_stmt, delete_let, references, target } = - if let Some(path_expr) = ctx.find_node_at_offset::() { + if let Some(path_expr) = ctx.find_node_at_offset_with_descend::() { inline_usage(&ctx.sema, path_expr, range, file_id) - } else if let Some(let_stmt) = ctx.find_node_at_offset() { + } else if let Some(let_stmt) = ctx.find_node_at_offset_with_descend() { inline_let(&ctx.sema, let_stmt, range, file_id) } else { None @@ -47,71 +49,65 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_, ' either::Either::Left(it) => it.initializer()?, either::Either::Right(it) => it.expr()?, }; - - let wrap_in_parens = references - .into_iter() - .filter_map(|FileReference { range, name, .. }| match name { - FileReferenceNode::NameRef(name) => Some((range, name)), - _ => None, - }) - .map(|(range, name_ref)| { - if range != name_ref.syntax().text_range() { - // Do not rename inside macros - // FIXME: This feels like a bad heuristic for macros - return None; + let needs_parens = |name_ref: &ast::NameRef| { + let usage_node = + name_ref.syntax().ancestors().find(|it| ast::PathExpr::can_cast(it.kind())); + let usage_parent = usage_node.as_ref().and_then(|it| it.parent()); + match (usage_node, usage_parent) { + (Some(usage), Some(parent)) => { + initializer_expr.needs_parens_in_place_of(&parent, &usage) } - let usage_node = - name_ref.syntax().ancestors().find(|it| ast::PathExpr::can_cast(it.kind())); - let usage_parent_option = usage_node.as_ref().and_then(|it| it.parent()); - let usage_parent = match usage_parent_option { - Some(u) => u, - None => return Some((name_ref, false)), - }; - let should_wrap = initializer_expr - .needs_parens_in_place_of(&usage_parent, usage_node.as_ref().unwrap()); - Some((name_ref, should_wrap)) - }) - .collect::>>()?; - - let target = match target { - ast::NameOrNameRef::Name(it) => it.syntax().clone(), - ast::NameOrNameRef::NameRef(it) => it.syntax().clone(), + _ => false, + } }; acc.add( AssistId::refactor_inline("inline_local_variable"), "Inline variable", - target.text_range(), - move |builder| { - let editor = builder.make_editor(&target); + target, + |builder| { + let editor = builder.make_editor(source); let make = editor.make(); - if delete_let { - editor.delete(let_stmt.syntax()); - + if delete_let + && let Some(original) = original_range_in(file_id, &ctx.sema, let_stmt.syntax()) + { + let place = cover_edit_range(source, original); + editor.delete_all(place.clone()); + + // Processing let-expr in let-chain + // FIXME: process let-expr in macro, but this case is very rare if let Some(bin_expr) = let_stmt.syntax().parent().and_then(ast::BinExpr::cast) && let Some(op_token) = bin_expr.op_token() { editor.delete(&op_token); remove_whitespace(op_token, Direction::Prev, &editor); - remove_whitespace(let_stmt.syntax(), Direction::Prev, &editor); + remove_whitespace(place.start(), Direction::Prev, &editor); } else { - remove_whitespace(let_stmt.syntax(), Direction::Next, &editor); + remove_whitespace(place.end(), Direction::Next, &editor); } } - for (name, should_wrap) in wrap_in_parens { - let replacement = if should_wrap { + for FileReference { range, name, .. } in references { + let Some(name) = name.as_name_ref().cloned() else { continue }; + let replacement = if needs_parens(&name) { make.expr_paren(initializer_expr.clone()).into() } else { initializer_expr.clone() }; - if let Some(record_field) = ast::RecordExprField::for_field_name(&name) { + let place = cover_edit_range(source, range); + if ast::RecordExprField::for_field_name(&name).is_some() { cov_mark::hit!(inline_field_shorthand); - let replacement = make.record_expr_field(name, Some(replacement)); - editor.replace(record_field.syntax(), replacement.syntax()); + editor.insert_all( + Position::after(place.end()), + vec![ + make.token(T![:]).into(), + make.whitespace(" ").into(), + replacement.syntax().clone().into(), + ], + ); } else { - editor.replace(name.syntax(), replacement.syntax()); + editor.replace_all(place, vec![replacement.syntax().clone().into()]); } } builder.add_file_edits(ctx.vfs_file_id(), editor); @@ -122,7 +118,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_, ' struct InlineData { let_stmt: Either, delete_let: bool, - target: ast::NameOrNameRef, + target: TextRange, references: Vec, } @@ -140,20 +136,18 @@ fn inline_let( cov_mark::hit!(test_not_inline_mut_variable); return None; } - if !bind_pat.syntax().text_range().contains_range(range) { + let target = original_range_in(file_id, sema, bind_pat.name()?.syntax())?; + if !target.contains_range(range) { cov_mark::hit!(not_applicable_outside_of_bind_pat); return None; } let local = sema.to_def(&bind_pat)?; - let UsageSearchResult { mut references } = Definition::Local(local).usages(sema).all(); - match references.remove(&file_id) { - Some(references) => Some(InlineData { - let_stmt, - delete_let: true, - target: ast::NameOrNameRef::Name(bind_pat.name()?), - references, - }), + let UsageSearchResult { references } = Definition::Local(local).usages(sema).all(); + let references = references.into_iter().flat_map(|it| it.1).collect::>(); + + match references.first() { + Some(_) => Some(InlineData { let_stmt, delete_let: true, target, references }), None => { cov_mark::hit!(test_not_applicable_if_variable_unused); None @@ -169,7 +163,8 @@ fn inline_usage( ) -> Option { let path = path_expr.path()?; let name = path.as_single_name_ref()?; - if !name.syntax().text_range().contains_range(range) { + let target = original_range_in(file_id, sema, name.syntax())?; + if !target.contains_range(range) { cov_mark::hit!(test_not_inline_selection_too_broad); return None; } @@ -193,12 +188,12 @@ fn inline_usage( let let_stmt = AstNode::cast(bind_pat.syntax().parent()?)?; - let UsageSearchResult { mut references } = Definition::Local(local).usages(sema).all(); - let mut references = references.remove(&file_id)?; + let UsageSearchResult { references } = Definition::Local(local).usages(sema).all(); + let mut references = references.into_iter().flat_map(|it| it.1).collect::>(); let delete_let = references.len() == 1; references.retain(|fref| fref.name.as_name_ref() == Some(&name)); - Some(InlineData { let_stmt, delete_let, target: ast::NameOrNameRef::NameRef(name), references }) + Some(InlineData { let_stmt, delete_let, target, references }) } fn remove_whitespace(elem: impl Element, dir: Direction, editor: &SyntaxEditor) { @@ -969,8 +964,8 @@ fn main() { } #[test] - fn not_applicable_on_local_usage_in_macro() { - check_assist_not_applicable( + fn local_usage_in_macro() { + check_assist( inline_local_variable, r#" macro_rules! m { @@ -978,11 +973,19 @@ macro_rules! m { } fn f() { let xyz = 0; - m!(xyz$0); // replacing it would break the macro + m!(xyz$0); // some macros may break, but it's best to support them +} +"#, + r#" +macro_rules! m { + ($i:ident) => { $i } +} +fn f() { + m!(0); // some macros may break, but it's best to support them } "#, ); - check_assist_not_applicable( + check_assist( inline_local_variable, r#" macro_rules! m { @@ -990,7 +993,84 @@ macro_rules! m { } fn f() { let xyz$0 = 0; - m!(xyz); // replacing it would break the macro + m!(xyz); // some macros may break, but it's best to support them +} +"#, + r#" +macro_rules! m { + ($i:ident) => { $i } +} +fn f() { + m!(0); // some macros may break, but it's best to support them +} +"#, + ); + } + + #[test] + fn local_def_in_macro() { + check_assist( + inline_local_variable, + r#" +macro_rules! i { + ($($t:tt)*) => { $($t)* } +} +fn f() { + i!(let xyz = 0;); + _ = xyz$0; +} +"#, + r#" +macro_rules! i { + ($($t:tt)*) => { $($t)* } +} +fn f() { + i!(); + _ = 0; +} +"#, + ); + check_assist( + inline_local_variable, + r#" +macro_rules! i { + ($($t:tt)*) => { $($t)* } +} +fn f() { + i!(let xyz = 0;); + _ = xyz$0; + _ = xyz; +} +"#, + r#" +macro_rules! i { + ($($t:tt)*) => { $($t)* } +} +fn f() { + i!(let xyz = 0;); + _ = 0; + _ = xyz; +} +"#, + ); + check_assist( + inline_local_variable, + r#" +macro_rules! i { + ($($t:tt)*) => { $($t)* } +} +fn f() { + i!(let $0xyz = 0;); + _ = xyz; +} +"#, + r#" +macro_rules! i { + ($($t:tt)*) => { $($t)* } +} +fn f() { + i!(); + _ = 0; } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs index 002791b88df64..f4ac75d2290dd 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs @@ -1,8 +1,11 @@ use hir::db::ExpandDatabase; use ide_db::syntax_helpers::prettify_macro_expansion; -use syntax::ast::{self, AstNode, edit::AstNodeEdit}; +use syntax::ast::{self, AstNode, edit::IndentLevel}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{ + AssistContext, AssistId, Assists, + utils::{cover_edit_range, original_range_in}, +}; // Assist: inline_macro // @@ -36,24 +39,40 @@ use crate::{AssistContext, AssistId, Assists}; // } // ``` pub(crate) fn inline_macro(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> Option<()> { - let unexpanded = ctx.find_node_at_offset::()?; - let macro_call = ctx.sema.to_def(&unexpanded)?; + let source = ctx.source_file().syntax(); + let sel = ctx.selection_trimmed(); + let (macro_call, text_range) = ctx + .sema + .find_nodes_at_offset_with_descend::(source, ctx.offset()) + .find_map(|macro_call_node| { + let macro_call = ctx.sema.to_def(¯o_call_node)?; + let original_range = + original_range_in(ctx.file_id(), &ctx.sema, macro_call_node.syntax())?; + original_range.contains_range(sel).then_some((macro_call, original_range)) + })?; let target_crate_id = ctx.sema.file_to_module_def(ctx.vfs_file_id())?.krate(ctx.db()).into(); - let text_range = unexpanded.syntax().text_range(); acc.add( AssistId::refactor_inline("inline_macro"), "Inline macro".to_owned(), text_range, |builder| { - let editor = builder.make_editor(unexpanded.syntax()); let expanded = ctx.sema.parse_or_expand(macro_call.into()); let span_map = ctx.sema.db.expansion_span_map(macro_call); // Don't call `prettify_macro_expansion()` outside the actual assist action; it does some heavy rowan tree manipulation, // which can be very costly for big macros when it is done *even without the assist being invoked*. let expanded = prettify_macro_expansion(ctx.db(), expanded, span_map, target_crate_id); - let expanded = ast::edit::indent(&expanded, unexpanded.indent_level()); - editor.replace(unexpanded.syntax(), expanded); + + // macro_call is from an expansion, use source position for indent + let indent = source + .token_at_offset(text_range.start()) + .right_biased() + .map_or_else(IndentLevel::zero, |t| IndentLevel::from_token(&t)); + let expanded = ast::edit::indent(&expanded, indent); + + let editor = builder.make_editor(source); + let place = cover_edit_range(source, text_range); + editor.replace_all(place, vec![expanded.into()]); builder.add_file_edits(ctx.vfs_file_id(), editor); }, ) @@ -103,6 +122,7 @@ macro_rules! num { "# }; } + #[test] fn inline_macro_target() { check_assist_target( @@ -376,6 +396,37 @@ fn bar() { fn bar() { a::Foo; } +"#, + ); + } + + #[test] + fn inline_macro_in_macro() { + check_assist( + inline_macro, + r#" +macro_rules! foo { () => { 2 }; } +macro_rules! m { ($($tt:tt)*) => { $($tt)* }; } +fn f() { m! { $0foo!(); } } +"#, + r#" +macro_rules! foo { () => { 2 }; } +macro_rules! m { ($($tt:tt)*) => { $($tt)* }; } +fn f() { m! { 2; } } +"#, + ); + check_assist( + inline_macro, + r#" +//- proc_macros: identity +macro_rules! foo { () => { 2 }; } +#[proc_macros::identity] +fn f() { $0foo!(); } +"#, + r#" +macro_rules! foo { () => { 2 }; } +#[proc_macros::identity] +fn f() { 2; } "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs index e4a1314f5bb29..bb76e2743c377 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs @@ -135,7 +135,20 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_, '_>) PathResolution::SelfType(imp) => { concrete_type = imp.source(ctx.db())?.value.self_ty()?; } - // FIXME: should also work in ADT definitions + PathResolution::Def(hir::ModuleDef::Adt(adt)) => { + let make = SyntaxFactory::without_mappings(); + let src = adt.source(ctx.db())?.value; + let name = src.name()?; + let generic_params = src.generic_param_list(); + let name_ref = make.name_ref(&name.text()); + let segment = match generic_params { + Some(params) => { + make.path_segment_generics(name_ref, params.to_generic_args(&make)) + } + None => make.path_segment(name_ref), + }; + concrete_type = make.ty_path_from_segments([segment], false); + } _ => return None, } @@ -996,6 +1009,68 @@ trait Tr { ); } + #[test] + fn inline_self_type_in_adt_definition() { + check_assist( + inline_type_alias, + r#" +enum Foo { + A(i32), + B(Box), +} +"#, + r#" +enum Foo { + A(i32), + B(Box), +} +"#, + ); + check_assist( + inline_type_alias, + r#" +struct Foo { + a: Box, +} +"#, + r#" +struct Foo { + a: Box, +} +"#, + ); + check_assist( + inline_type_alias, + r#" +struct Foo { + a: T, + b: Box, +} +"#, + r#" +struct Foo { + a: T, + b: Box>, +} +"#, + ); + check_assist( + inline_type_alias, + r#" +union Foo { + a: u32, + b: std::mem::ManuallyDrop>, +} +"#, + r#" +union Foo { + a: u32, + b: std::mem::ManuallyDrop>, +} +"#, + ); + } + #[test] fn inline_types_with_lifetime() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs index dc40a6a640e00..4234a6090dc3f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs @@ -1,10 +1,12 @@ -use either::Either; use ide_db::imports::{ insert_use::{ImportGranularity, InsertUseConfig}, merge_imports::{MergeBehavior, try_merge_imports, try_merge_trees}, }; use syntax::{ - AstNode, SyntaxElement, SyntaxNode, algo::neighbor, ast, match_ast, syntax_editor::Removable, + AstNode, SyntaxElement, + algo::neighbor, + ast, match_ast, + syntax_editor::{Removable, SyntaxEditor}, }; use crate::{ @@ -13,8 +15,6 @@ use crate::{ utils::next_prev, }; -use Edit::*; - // Assist: merge_imports // // Merges neighbor imports with a common prefix. @@ -28,16 +28,17 @@ use Edit::*; // use std::{fmt::Formatter, io}; // ``` pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> Option<()> { - let (target, edits) = if ctx.has_empty_selection() { + let (target, editor) = if ctx.has_empty_selection() { // Merge a neighbor cov_mark::hit!(merge_with_use_item_neighbors); let tree = ctx.find_node_at_offset::()?.top_use_tree(); let target = tree.syntax().text_range(); let use_item = tree.syntax().parent().and_then(ast::Use::cast)?; - let mut neighbor = next_prev().find_map(|dir| neighbor(&use_item, dir)).into_iter(); - let edits = use_item.try_merge_from(&mut neighbor, &ctx.config.insert_use); - (target, edits?) + let neighbor = next_prev().find_map(|dir| neighbor(&use_item, dir))?; + let (editor, _) = SyntaxEditor::new(use_item.syntax().parent()?.ancestors().last()?); + merge_uses(use_item, vec![neighbor], &ctx.config.insert_use, &editor)?; + (target, editor) } else { // Merge selected let selection_range = ctx.selection_trimmed(); @@ -50,104 +51,80 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> O }); let first_selected = selected_nodes.next()?; - let edits = match_ast! { + let (editor, _) = SyntaxEditor::new(parent_node.ancestors().last().unwrap()); + match_ast! { match first_selected { ast::Use(use_item) => { cov_mark::hit!(merge_with_selected_use_item_neighbors); - use_item.try_merge_from(&mut selected_nodes.filter_map(ast::Use::cast), &ctx.config.insert_use) + merge_uses( + use_item, + selected_nodes.filter_map(ast::Use::cast).collect(), + &ctx.config.insert_use, + &editor, + )?; }, ast::UseTree(use_tree) => { cov_mark::hit!(merge_with_selected_use_tree_neighbors); - use_tree.try_merge_from(&mut selected_nodes.filter_map(ast::UseTree::cast), &ctx.config.insert_use) + merge_use_trees( + use_tree, + selected_nodes.filter_map(ast::UseTree::cast).collect(), + &editor, + )?; }, _ => return None, } - }; - (selection_range, edits?) - }; - - let parent_node = match ctx.covering_element() { - SyntaxElement::Node(n) => n, - SyntaxElement::Token(t) => t.parent()?, + } + (selection_range, editor) }; acc.add(AssistId::refactor_rewrite("merge_imports"), "Merge imports", target, |builder| { - let editor = builder.make_editor(&parent_node); - - for edit in edits { - match edit { - Remove(it) => { - let node = it.as_ref(); - if let Some(left) = node.left() { - left.remove(&editor); - } else if let Some(right) = node.right() { - right.remove(&editor); - } - } - Replace(old, new) => { - editor.replace(old, &new); - } - } - } builder.add_file_edits(ctx.vfs_file_id(), editor); }) } -trait Merge: AstNode + Clone { - fn try_merge_from( - self, - items: &mut dyn Iterator, - cfg: &InsertUseConfig, - ) -> Option> { - let mut edits = Vec::new(); - let mut merged = self.clone(); - for item in items { - merged = merged.try_merge(&item, cfg)?; - edits.push(Edit::Remove(item.into_either())); - } - if !edits.is_empty() { - edits.push(Edit::replace(self, merged)); - Some(edits) - } else { - None - } +fn merge_uses( + first: ast::Use, + rest: Vec, + cfg: &InsertUseConfig, + editor: &SyntaxEditor, +) -> Option<()> { + if rest.is_empty() { + return None; } - fn try_merge(&self, other: &Self, cfg: &InsertUseConfig) -> Option; - fn into_either(self) -> Either; -} -impl Merge for ast::Use { - fn try_merge(&self, other: &Self, cfg: &InsertUseConfig) -> Option { - let mb = match cfg.granularity { - ImportGranularity::One => MergeBehavior::One, - _ => MergeBehavior::Crate, - }; - try_merge_imports(self, other, mb) + let mb = match cfg.granularity { + ImportGranularity::One => MergeBehavior::One, + _ => MergeBehavior::Crate, + }; + let mut merged = first.clone(); + for item in &rest { + merged = try_merge_imports(editor.make(), &merged, item, mb)?; } - fn into_either(self) -> Either { - Either::Left(self) + for item in rest { + item.remove(editor); } + editor.replace(first.syntax(), merged.syntax()); + Some(()) } -impl Merge for ast::UseTree { - fn try_merge(&self, other: &Self, _: &InsertUseConfig) -> Option { - try_merge_trees(self, other, MergeBehavior::Crate) +fn merge_use_trees( + first: ast::UseTree, + rest: Vec, + editor: &SyntaxEditor, +) -> Option<()> { + if rest.is_empty() { + return None; } - fn into_either(self) -> Either { - Either::Right(self) - } -} -#[derive(Debug)] -enum Edit { - Remove(Either), - Replace(SyntaxNode, SyntaxNode), -} - -impl Edit { - fn replace(old: impl AstNode, new: impl AstNode) -> Self { - Edit::Replace(old.syntax().clone(), new.syntax().clone()) + let mut merged = first.clone(); + for item in &rest { + merged = try_merge_trees(editor.make(), &merged, item, MergeBehavior::Crate)?; + } + for item in rest { + item.remove(editor); } + editor.replace(first.syntax(), merged.syntax()); + Some(()) } #[cfg(test)] @@ -558,6 +535,62 @@ use foo::{bar, baz}; ); } + #[test] + fn mod_indent_whitespace() { + check_assist( + merge_imports, + r" +mod tests { + use foo$0::bar; + use foo::baz; + fn feature() {} +} +", + r" +mod tests { + use foo::{bar, baz}; + fn feature() {} +} +", + ); + check_assist( + merge_imports, + r" +mod tests { + use foo$0::bar; + use foo::baz; + + fn feature() {} +} +", + r" +mod tests { + use foo::{bar, baz}; + + fn feature() {} +} +", + ); + check_assist( + merge_imports, + r" +mod tests { + use foo::bar; + use foo$0::baz; + + fn feature() {} +} +", + r" +mod tests { + use foo::{bar, baz}; + + fn feature() {} +} +", + ); + } + #[test] fn works_with_trailing_comma() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs index f97a3e583f030..906f38cba407f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs @@ -1,5 +1,5 @@ use ide_db::imports::merge_imports::try_normalize_import; -use syntax::{AstNode, ast}; +use syntax::{AstNode, ast, syntax_editor::SyntaxEditor}; use crate::{ AssistId, @@ -25,11 +25,13 @@ pub(crate) fn normalize_import(acc: &mut Assists, ctx: &AssistContext<'_, '_>) - }; let target = use_item.syntax().text_range(); + let (editor, _) = SyntaxEditor::new(use_item.syntax().ancestors().last().unwrap()); let normalized_use_item = - try_normalize_import(&use_item, ctx.config.insert_use.granularity.into())?; + try_normalize_import(editor.make(), &use_item, ctx.config.insert_use.granularity.into())?; + editor.replace(use_item.syntax(), normalized_use_item.syntax()); acc.add(AssistId::refactor_rewrite("normalize_import"), "Normalize import", target, |builder| { - builder.replace_ast(use_item, normalized_use_item); + builder.add_file_edits(ctx.vfs_file_id(), editor); }) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs index ff2d0544b2a18..5225202177111 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs @@ -17,7 +17,7 @@ use crate::{ AssistContext, AssistId, Assists, utils::{ does_pat_match_variant, does_pat_variant_nested_or_literal, unwrap_trivial_block, - wrap_paren, + wrap_paren_in_guard_chain, }, }; @@ -303,7 +303,7 @@ pub(crate) fn replace_match_with_if_let( _ => make.expr_let(if_let_pat, scrutinee).into(), }; let condition = if let Some(guard) = guard { - let guard = wrap_paren(guard, make, ast::prec::ExprPrecedence::LAnd); + let guard = wrap_paren_in_guard_chain(guard, make); make.expr_bin(condition, ast::BinaryOp::LogicOp(ast::LogicOp::And), guard).into() } else { condition @@ -712,13 +712,11 @@ impl VariantData { check_assist( replace_if_let_with_match, r#" -#![feature(if_let_guard)] fn main() { if $0let true = true && let Some(1) = None {} else { other() } } "#, r#" -#![feature(if_let_guard)] fn main() { match true { true if let Some(1) = None => {} @@ -731,7 +729,6 @@ fn main() { check_assist( replace_if_let_with_match, r#" -#![feature(if_let_guard)] fn main() { if true { $0if let ParenExpr(expr) = cond @@ -758,7 +755,6 @@ fn main() { } "#, r#" -#![feature(if_let_guard)] fn main() { if true { match cond { @@ -816,13 +812,11 @@ fn main() { check_assist( replace_if_let_with_match, r#" -#![feature(if_let_guard)] fn main() { if $0let true = true && let Some(1) = None {} } "#, r#" -#![feature(if_let_guard)] fn main() { match true { true if let Some(1) = None => {} @@ -2460,7 +2454,7 @@ fn main() { } #[test] - fn test_replace_match_with_if_let_chain() { + fn test_replace_match_with_if_let_with_simple_guard() { check_assist( replace_match_with_if_let, r#" @@ -2504,6 +2498,73 @@ fn main() { ); } + #[test] + fn test_replace_match_with_if_let_with_if_let_guard() { + check_assist( + replace_match_with_if_let, + r#" +fn main() { + match$0 Some(0) { + Some(n) if let Some(m) = n.checked_add(1) => (), + _ => code(), + } +} +"#, + r#" +fn main() { + if let Some(n) = Some(0) && let Some(m) = n.checked_add(1) { + () + } else { + code() + } +} +"#, + ); + + check_assist( + replace_match_with_if_let, + r#" +fn main() { + match$0 Some(0) { + Some(n) if let Some(m) = n.checked_add(1) && m > 5 => (), + _ => code(), + } +} + "#, + r#" +fn main() { + if let Some(n) = Some(0) && let Some(m) = n.checked_add(1) && m > 5 { + () + } else { + code() + } +} + "#, + ); + + // what if the `let` expr is not the first one in the guard? + check_assist( + replace_match_with_if_let, + r#" +fn main() { + match$0 Some(0) { + Some(n) if n > 5 && let Some(m) = n.checked_add(1) => (), + _ => code(), + } +} + "#, + r#" +fn main() { + if let Some(n) = Some(0) && n > 5 && let Some(m) = n.checked_add(1) { + () + } else { + code() + } +} + "#, + ); + } + #[test] fn test_replace_match_with_if_let_not_applicable_pat2_is_ident_pat() { check_assist_not_applicable( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index 1b6c9a579aba0..2c4fb5f405a77 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -110,6 +110,26 @@ fn needs_parens_in_call(make: &SyntaxFactory, param: &ast::Expr) -> bool { param.needs_parens_in_place_of(call.syntax(), callable.syntax()) } +pub(crate) fn wrap_paren_in_guard_chain(guard: ast::Expr, make: &SyntaxFactory) -> ast::Expr { + if needs_parens_in_guard_chain(make, &guard) { make.expr_paren(guard).into() } else { guard } +} + +fn needs_parens_in_guard_chain(make: &SyntaxFactory, guard: &ast::Expr) -> bool { + let ast::Expr::BinExpr(if_let_and_guard) = make.expr_bin_op( + make.expr_unit(), + ast::BinaryOp::LogicOp(ast::LogicOp::And), + make.expr_unit(), + ) else { + stdx::never!("`SyntaxFactory::expr_bin_op` returns a `BinExpr`"); + return false; + }; + let Some(fake_guard) = if_let_and_guard.rhs() else { + stdx::never!("invalid make call"); + return false; + }; + guard.needs_parens_in_place_of(if_let_and_guard.syntax(), fake_guard.syntax()) +} + /// This is a method with a heuristics to support test methods annotated with custom test annotations, such as /// `#[test_case(...)]`, `#[tokio::test]` and similar. /// Also a regular `#[test]` annotation is supported. @@ -1177,6 +1197,15 @@ pub fn is_body_const(sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr) -> bo is_const } +pub(crate) fn original_range_in( + file_id: hir::EditionedFileId, + sema: &Semantics<'_, RootDatabase>, + value: &SyntaxNode, +) -> Option { + let original = sema.original_range_opt(value)?; + (original.file_id == file_id).then_some(original.range) +} + // FIXME: #20460 When hir-ty can analyze the `never` statement at the end of block, remove it pub(crate) fn is_never_block( sema: &Semantics<'_, RootDatabase>, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs index ac52c816e52a9..0739084381b3b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs @@ -45,6 +45,7 @@ pub enum AutoImportExclusionType { Always, Methods, SubItems, + Variants, } #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index f7bb14391b7de..507ecaff0dca0 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -868,10 +868,22 @@ impl<'a, 'db> CompletionContext<'a, 'db> { _ => None, }) .collect::>(); + let exclude_variants = exclude_flyimport + .iter() + .flat_map(|it| match it { + (ModuleDef::Adt(hir::Adt::Enum(enum_)), AutoImportExclusionType::Variants) => { + enum_.variants(db) + } + _ => vec![], + }) + .collect::>(); exclude_flyimport .extend(exclude_traits.iter().map(|&t| (t.into(), AutoImportExclusionType::Always))); exclude_flyimport .extend(exclude_subitems.into_iter().map(|it| (it, AutoImportExclusionType::Always))); + exclude_flyimport.extend( + exclude_variants.into_iter().map(|it| (it.into(), AutoImportExclusionType::Always)), + ); // FIXME: This should be part of `CompletionAnalysis` / `expand_and_analyze` let complete_semicolon = if !config.add_semicolon_to_unit { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index e48847c983b4e..7cb1eaa061f3c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -2372,7 +2372,7 @@ impl S { } fn foo(s: S) { s.$0 } "#, - CompletionItemKind::SymbolKind(SymbolKind::Method), + SymbolKind::Method, expect![[r#" [ CompletionItem { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index e49afa66ad738..adf4dda18441f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -3041,6 +3041,76 @@ fn foo() { ); } +#[test] +fn flyimport_excluded_enum_variants_from_flyimport() { + check_with_config( + CompletionConfig { + exclude_flyimport: vec![( + "ra_test_fixture::Foo".to_owned(), + AutoImportExclusionType::Variants, + )], + ..TEST_CONFIG + }, + r#" +enum Foo { + Variant1, + Variant2, +} +fn foo() { + V$0 +} + "#, + expect![[r#" + ct CONST Unit + en Enum Enum + en Foo Foo + fn foo() fn() + fn function() fn() + ma makro!(…) macro_rules! makro + md module:: + sc STATIC Unit + st Record Record + st Tuple Tuple + st Unit Unit + un Union Union + ev TupleV(…) TupleV(u32) + bt u32 u32 + kw async + kw const + kw crate:: + kw enum + kw extern + kw false + kw fn + kw for + kw if + kw if let + kw impl + kw impl for + kw let + kw letm + kw loop + kw match + kw mod + kw return + kw self:: + kw static + kw struct + kw trait + kw true + kw type + kw union + kw unsafe + kw use + kw while + kw while let + sn macro_rules + sn pd + sn ppd + "#]], + ); +} + #[test] fn excluded_trait_method_is_excluded_from_path_completion() { check_with_config( @@ -4109,3 +4179,31 @@ fn main() { "#]], ); } + +#[test] +fn no_await_on_error_type() { + check( + r#" +//- minicore: future +fn foo(t: T) { + let _ = t.$0; +} + "#, + expect![[r#" + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn if if expr {} + sn match match expr {} + sn not !expr + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} + sn while while expr {} + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index b77a18f56ea21..7a3c466daa50c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -1,16 +1,21 @@ //! Applies changes to the IDE state transactionally. +use std::time::{Duration, Instant}; + use profile::Bytes; use salsa::Database as _; use crate::{ChangeWithProcMacros, RootDatabase}; impl RootDatabase { - pub fn apply_change(&mut self, change: ChangeWithProcMacros) { + pub fn apply_change(&mut self, change: ChangeWithProcMacros) -> Duration { let _p = tracing::info_span!("RootDatabase::apply_change").entered(); + let now = Instant::now(); self.trigger_cancellation(); + let elapsed = now.elapsed(); tracing::trace!("apply_change {:?}", change); change.apply(self); + elapsed } // Feature: Memory Usage diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs index c3949f871314f..27e3ed6bdb52e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs @@ -17,7 +17,7 @@ use crate::{ RootDatabase, imports::merge_imports::{ MergeBehavior, NormalizationStyle, common_prefix, eq_attrs, eq_visibility, - try_merge_imports, use_tree_cmp, + try_merge_imports, use_tree_cmp, wrap_in_tree_list, }, }; @@ -251,7 +251,7 @@ fn insert_use_with_alias_option_with_editor( let mut use_tree = make.use_tree(path, None, alias, false); if mb == Some(MergeBehavior::One) && use_tree.path().is_some() - && let Some(wrapped) = use_tree.wrap_in_tree_list_with_editor() + && let Some(wrapped) = wrap_in_tree_list(&use_tree, make) { use_tree = wrapped; } @@ -263,7 +263,9 @@ fn insert_use_with_alias_option_with_editor( for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast).filter(filter) { - if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) { + if let Some(merged) = + try_merge_imports(syntax_editor.make(), &existing_use, &use_item, mb) + { syntax_editor.replace(existing_use.syntax(), merged.syntax()); return; } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs index 4fa05c4603461..34ff7c8d5b426 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs @@ -1,4 +1,5 @@ use stdx::trim_indent; +use syntax::ast::syntax_factory::SyntaxFactory; use test_fixture::WithFixture; use test_utils::{CURSOR_MARKER, assert_eq_text}; @@ -1430,7 +1431,8 @@ fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior .find_map(ast::Use::cast) .unwrap(); - let result = try_merge_imports(&use0, &use1, mb); + let make = SyntaxFactory::without_mappings(); + let result = try_merge_imports(&make, &use0, &use1, mb); assert_eq!(result.map(|u| u.to_string()), None); } @@ -1495,7 +1497,8 @@ fn check_merge(ra_fixture0: &str, ra_fixture1: &str, last: &str, mb: MergeBehavi .find_map(ast::Use::cast) .unwrap(); - let result = try_merge_imports(&use0, &use1, mb); + let make = SyntaxFactory::without_mappings(); + let result = try_merge_imports(&make, &use0, &use1, mb); assert_eq!(result.map(|u| u.to_string().trim().to_owned()), Some(last.trim().to_owned())); } @@ -1525,7 +1528,8 @@ fn merge_gated_imports_with_different_values() { .find_map(ast::Use::cast) .unwrap(); - let result = try_merge_imports(&use0, &use1, MergeBehavior::Crate); + let make = SyntaxFactory::without_mappings(); + let result = try_merge_imports(&make, &use0, &use1, MergeBehavior::Crate); assert_eq!(result, None); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs index bbd351a4cc14c..9b68c27ae3443 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs @@ -4,12 +4,12 @@ use std::cmp::Ordering; use itertools::{EitherOrBoth, Itertools}; use parser::T; use syntax::{ - Direction, SyntaxElement, ToSmolStr, algo, + ToSmolStr, ast::{ - self, AstNode, HasAttrs, HasName, HasVisibility, PathSegmentKind, edit_in_place::Removable, - make, + self, AstNode, HasAttrs, HasName, HasVisibility, PathSegmentKind, + syntax_factory::SyntaxFactory, }, - ted::{self, Position}, + syntax_editor::{Position, SyntaxEditor}, }; use crate::syntax_helpers::node_ext::vis_eq; @@ -39,8 +39,8 @@ impl MergeBehavior { } /// Merge `rhs` into `lhs` keeping both intact. -/// Returned AST is mutable. pub fn try_merge_imports( + make: &SyntaxFactory, lhs: &ast::Use, rhs: &ast::Use, merge_behavior: MergeBehavior, @@ -53,39 +53,39 @@ pub fn try_merge_imports( return None; } - let lhs = lhs.clone_subtree().clone_for_update(); - let rhs = rhs.clone_subtree().clone_for_update(); let lhs_tree = lhs.use_tree()?; let rhs_tree = rhs.use_tree()?; - try_merge_trees_mut(&lhs_tree, &rhs_tree, merge_behavior)?; + let merged_tree = try_merge_trees_with_factory(lhs_tree, rhs_tree, merge_behavior, make)?; // Ignore `None` result because normalization should not affect the merge result. - try_normalize_use_tree_mut(&lhs_tree, merge_behavior.into()); + let use_tree = try_normalize_use_tree(merged_tree.clone(), merge_behavior.into(), make) + .unwrap_or(merged_tree); - Some(lhs) + make_use_with_tree(lhs, use_tree) } /// Merge `rhs` into `lhs` keeping both intact. -/// Returned AST is mutable. pub fn try_merge_trees( + make: &SyntaxFactory, lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior, ) -> Option { - let lhs = lhs.clone_subtree().clone_for_update(); - let rhs = rhs.clone_subtree().clone_for_update(); - try_merge_trees_mut(&lhs, &rhs, merge)?; + let merged = try_merge_trees_with_factory(lhs.clone(), rhs.clone(), merge, make)?; // Ignore `None` result because normalization should not affect the merge result. - try_normalize_use_tree_mut(&lhs, merge.into()); - - Some(lhs) + Some(try_normalize_use_tree(merged.clone(), merge.into(), make).unwrap_or(merged)) } -fn try_merge_trees_mut(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) -> Option<()> { +fn try_merge_trees_with_factory( + mut lhs: ast::UseTree, + mut rhs: ast::UseTree, + merge: MergeBehavior, + make: &SyntaxFactory, +) -> Option { if merge == MergeBehavior::One { - lhs.wrap_in_tree_list(); - rhs.wrap_in_tree_list(); + lhs = wrap_in_tree_list(&lhs, make).unwrap_or(lhs); + rhs = wrap_in_tree_list(&rhs, make).unwrap_or(rhs); } else { let lhs_path = lhs.path()?; let rhs_path = rhs.path()?; @@ -100,46 +100,53 @@ fn try_merge_trees_mut(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehav // and we can safely return here let lhs_name = lhs.rename().and_then(|lhs_name| lhs_name.name()); let rhs_name = rhs.rename().and_then(|rhs_name| rhs_name.name()); - if lhs_name != rhs_name { + if lhs_name.as_ref().map(|name| name.text()) + != rhs_name.as_ref().map(|name| name.text()) + { return None; } - ted::replace(lhs.syntax(), rhs.syntax()); - // we can safely return here, in this case `recursive_merge` doesn't do anything - return Some(()); + return Some(rhs); } else { - lhs.split_prefix(&lhs_prefix); - rhs.split_prefix(&rhs_prefix); + lhs = split_prefix(&lhs, &lhs_prefix, make)?; + rhs = split_prefix(&rhs, &rhs_prefix, make)?; } } - recursive_merge(lhs, rhs, merge) + recursive_merge(lhs, rhs, merge, make) } /// Recursively merges rhs to lhs #[must_use] -fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) -> Option<()> { +fn recursive_merge( + lhs: ast::UseTree, + rhs: ast::UseTree, + merge: MergeBehavior, + make: &SyntaxFactory, +) -> Option { let mut use_trees: Vec = lhs - .use_tree_list() - .into_iter() - .flat_map(|list| list.use_trees()) - // We use Option here to early return from this function(this is not the - // same as a `filter` op). + .use_tree_list()? + .use_trees() + // We use Option here to early return from this function. This is not the + // same as a `filter` op. .map(|tree| merge.is_tree_allowed(&tree).then_some(tree)) .collect::>()?; + // Sorts the use trees similar to rustfmt's algorithm for ordering imports // (see `use_tree_cmp` doc). use_trees.sort_unstable_by(use_tree_cmp); - for rhs_t in rhs.use_tree_list().into_iter().flat_map(|list| list.use_trees()) { + + for rhs_t in rhs.use_tree_list()?.use_trees() { if !merge.is_tree_allowed(&rhs_t) { return None; } match use_trees.binary_search_by(|lhs_t| use_tree_cmp_bin_search(lhs_t, &rhs_t)) { Ok(idx) => { - let lhs_t = &mut use_trees[idx]; + let mut lhs_t = use_trees[idx].clone(); let lhs_path = lhs_t.path()?; let rhs_path = rhs_t.path()?; let (lhs_prefix, rhs_prefix) = common_prefix(&lhs_path, &rhs_path)?; + if lhs_prefix == lhs_path && rhs_prefix == rhs_path { let tree_is_self = |tree: &ast::UseTree| { tree.path().as_ref().map(path_is_self).unwrap_or(false) @@ -157,20 +164,20 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) }; if lhs_t.rename().and_then(|x| x.underscore_token()).is_some() { - ted::replace(lhs_t.syntax(), rhs_t.syntax()); - *lhs_t = rhs_t; + use_trees[idx] = rhs_t; continue; } - match (tree_contains_self(lhs_t), tree_contains_self(&rhs_t)) { + match (tree_contains_self(&lhs_t), tree_contains_self(&rhs_t)) { (Some(true), None) => { - remove_subtree_if_only_self(lhs_t); + lhs_t = remove_subtree_if_only_self(lhs_t, make)?; + use_trees[idx] = lhs_t; continue; } (None, Some(true)) => { - ted::replace(lhs_t.syntax(), rhs_t.syntax()); - *lhs_t = rhs_t; - remove_subtree_if_only_self(lhs_t); + lhs_t = rhs_t; + lhs_t = remove_subtree_if_only_self(lhs_t, make)?; + use_trees[idx] = lhs_t; continue; } _ => (), @@ -180,9 +187,11 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) continue; } } - lhs_t.split_prefix(&lhs_prefix); - rhs_t.split_prefix(&rhs_prefix); - recursive_merge(lhs_t, &rhs_t, merge)?; + + lhs_t = split_prefix(&lhs_t, &lhs_prefix, make)?; + let rhs_t = split_prefix(&rhs_t, &rhs_prefix, make)?; + lhs_t = recursive_merge(lhs_t, rhs_t, merge, make)?; + use_trees[idx] = lhs_t; } Err(_) if merge == MergeBehavior::Module @@ -192,15 +201,12 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) return None; } Err(insert_idx) => { - use_trees.insert(insert_idx, rhs_t.clone()); - // We simply add the use tree to the end of tree list. Ordering of use trees - // and imports is done by the `try_normalize_*` functions. The sorted `use_trees` - // vec is only used for binary search. - lhs.get_or_create_use_tree_list().add_use_tree(rhs_t); + use_trees.insert(insert_idx, rhs_t); } } } - Some(()) + + with_use_tree_list(&lhs, use_trees, make) } /// Style to follow when normalizing a use tree. @@ -250,241 +256,216 @@ impl From for NormalizationStyle { /// - `foo::{bar::Qux, bar::{self}}` -> `{foo::bar::{self, Qux}}` /// - `foo::bar::{self}` -> `{foo::bar}` /// - `foo::bar` -> `{foo::bar}` -pub fn try_normalize_import(use_item: &ast::Use, style: NormalizationStyle) -> Option { - let use_item = use_item.clone_subtree().clone_for_update(); - try_normalize_use_tree_mut(&use_item.use_tree()?, style)?; - Some(use_item) +pub fn try_normalize_import( + make: &SyntaxFactory, + use_item: &ast::Use, + style: NormalizationStyle, +) -> Option { + let use_tree = try_normalize_use_tree(use_item.use_tree()?, style, make)?; + + make_use_with_tree(use_item, use_tree) } -fn try_normalize_use_tree_mut(use_tree: &ast::UseTree, style: NormalizationStyle) -> Option<()> { +fn try_normalize_use_tree( + use_tree: ast::UseTree, + style: NormalizationStyle, + make: &SyntaxFactory, +) -> Option { if style == NormalizationStyle::One { + let mut use_tree = use_tree; let mut modified = false; - modified |= use_tree.wrap_in_tree_list().is_some(); - modified |= recursive_normalize(use_tree, style).is_some(); - if !modified { - // Either the use tree was already normalized or its semantically empty. - return None; + if let Some(wrapped) = wrap_in_tree_list(&use_tree, make) { + use_tree = wrapped; + modified = true; } - } else { - recursive_normalize(use_tree, NormalizationStyle::Default)?; + if let Some(normalized) = recursive_normalize(use_tree.clone(), style, make) { + use_tree = normalized; + modified = true; + } + return modified.then_some(use_tree); } - Some(()) + + recursive_normalize(use_tree, NormalizationStyle::Default, make) } /// Recursively normalizes a use tree and its subtrees (if any). -fn recursive_normalize(use_tree: &ast::UseTree, style: NormalizationStyle) -> Option<()> { +fn recursive_normalize( + use_tree: ast::UseTree, + style: NormalizationStyle, + make: &SyntaxFactory, +) -> Option { let use_tree_list = use_tree.use_tree_list()?; - let merge_subtree_into_parent_tree = |single_subtree: &ast::UseTree| { - let subtree_is_only_self = single_subtree.path().as_ref().is_some_and(path_is_self); - - let merged_path = match (use_tree.path(), single_subtree.path()) { - // If the subtree is `{self}` then we cannot merge: `use - // foo::bar::{self}` is not equivalent to `use foo::bar`. See - // https://github.com/rust-lang/rust-analyzer/pull/17140#issuecomment-2079189725. - _ if subtree_is_only_self => None, - - (None, None) => None, - (Some(outer), None) => Some(outer), - (None, Some(inner)) => Some(inner), - (Some(outer), Some(inner)) => Some(make::path_concat(outer, inner).clone_for_update()), - }; - - if merged_path.is_some() - || single_subtree.use_tree_list().is_some() - || single_subtree.star_token().is_some() + let mut subtrees = use_tree_list.use_trees().collect::>(); + if subtrees.len() == 1 { + if style == NormalizationStyle::One { + let subtree = subtrees.pop()?; + let normalized = recursive_normalize(subtree, NormalizationStyle::Default, make)?; + return with_use_tree_list(&use_tree, vec![normalized], make); + } + + let merged = merge_single_subtree_into_parent_tree(use_tree, make)?; + return Some(recursive_normalize(merged.clone(), style, make).unwrap_or(merged)); + } + + let mut modified = false; + let mut new_use_tree_list = Vec::new(); + for subtree in subtrees { + if one_style_tree_list(&subtree).is_some() { + let mut elements = Vec::new(); + flatten_one_style_tree(subtree, &mut elements, &mut modified, make); + new_use_tree_list.extend(elements); + modified = true; + } else if let Some(normalized) = + recursive_normalize(subtree.clone(), NormalizationStyle::Default, make) { - ted::remove_all_iter(use_tree.syntax().children_with_tokens()); - if let Some(path) = merged_path { - ted::insert_raw(Position::first_child_of(use_tree.syntax()), path.syntax()); - if single_subtree.use_tree_list().is_some() || single_subtree.star_token().is_some() + new_use_tree_list.push(normalized); + modified = true; + } else { + new_use_tree_list.push(subtree); + } + } + + let mut use_tree = + if modified { with_use_tree_list(&use_tree, new_use_tree_list, make)? } else { use_tree }; + + let mut use_tree_list = use_tree.use_tree_list()?.use_trees().collect::>(); + let mut anchor_idx = 0; + let mut merged_any = false; + while anchor_idx < use_tree_list.len() { + let mut candidate_idx = anchor_idx + 1; + while candidate_idx < use_tree_list.len() { + if let Some(mut merged) = try_merge_trees_with_factory( + use_tree_list[anchor_idx].clone(), + use_tree_list[candidate_idx].clone(), + MergeBehavior::Crate, + make, + ) { + if let Some(normalized) = + recursive_normalize(merged.clone(), NormalizationStyle::Default, make) { - ted::insert_raw( - Position::last_child_of(use_tree.syntax()), - make::token(T![::]), - ); + merged = normalized; } + + use_tree_list[anchor_idx] = merged; + use_tree_list.remove(candidate_idx); + merged_any = true; + } else { + candidate_idx += 1; } - if let Some(inner_use_tree_list) = single_subtree.use_tree_list() { - ted::insert_raw( - Position::last_child_of(use_tree.syntax()), - inner_use_tree_list.syntax(), - ); - } else if single_subtree.star_token().is_some() { - ted::insert_raw(Position::last_child_of(use_tree.syntax()), make::token(T![*])); - } else if let Some(rename) = single_subtree.rename() { - ted::insert_raw( - Position::last_child_of(use_tree.syntax()), - make::tokens::single_space(), - ); - ted::insert_raw(Position::last_child_of(use_tree.syntax()), rename.syntax()); - } - Some(()) - } else { - // Bail on semantically empty use trees. - None } - }; - let one_style_tree_list = |subtree: &ast::UseTree| match ( - subtree.path().is_none() && subtree.star_token().is_none() && subtree.rename().is_none(), - subtree.use_tree_list(), - ) { - (true, tree_list) => tree_list, - _ => None, - }; - let add_element_to_list = |elem: SyntaxElement, elements: &mut Vec| { - if !elements.is_empty() { - elements.push(make::token(T![,]).into()); - elements.push(make::tokens::single_space().into()); + + anchor_idx += 1; + } + if merged_any { + use_tree = with_use_tree_list(&use_tree, use_tree_list, make)?; + modified = true; + } + + if style != NormalizationStyle::One { + let subtrees = use_tree.use_tree_list()?.use_trees().collect::>(); + if subtrees.len() == 1 + && let Some(merged) = merge_single_subtree_into_parent_tree(use_tree.clone(), make) + { + use_tree = merged; + modified = true; } - elements.push(elem); - }; - if let Some((single_subtree,)) = use_tree_list.use_trees().collect_tuple() { - if style == NormalizationStyle::One { - // Only normalize descendant subtrees if the normalization style is "one". - recursive_normalize(&single_subtree, NormalizationStyle::Default)?; - } else { - // Otherwise, merge the single subtree into it's parent (if possible) - // and then normalize the result. - merge_subtree_into_parent_tree(&single_subtree)?; - recursive_normalize(use_tree, style); + } + + if let Some(list) = use_tree.use_tree_list() { + let mut use_tree_list = list.use_trees().collect::>(); + if use_tree_list + .windows(2) + .any(|trees| use_tree_cmp_bin_search(&trees[0], &trees[1]).is_gt()) + { + use_tree_list.sort_unstable_by(use_tree_cmp_bin_search); + use_tree = with_use_tree_list(&use_tree, use_tree_list, make)?; + modified = true; } - } else { - // Tracks whether any changes have been made to the use tree. - let mut modified = false; + } - // Recursively un-nests (if necessary) and then normalizes each subtree in the tree list. - for subtree in use_tree_list.use_trees() { - if let Some(one_tree_list) = one_style_tree_list(&subtree) { - let mut elements = Vec::new(); - let mut one_tree_list_iter = one_tree_list.use_trees(); - let mut prev_skipped = Vec::new(); - loop { - let mut prev_skipped_iter = prev_skipped.into_iter(); - let mut curr_skipped = Vec::new(); - - while let Some(sub_sub_tree) = - one_tree_list_iter.next().or(prev_skipped_iter.next()) - { - if let Some(sub_one_tree_list) = one_style_tree_list(&sub_sub_tree) { - curr_skipped.extend(sub_one_tree_list.use_trees()); - } else { - modified |= - recursive_normalize(&sub_sub_tree, NormalizationStyle::Default) - .is_some(); - add_element_to_list( - sub_sub_tree.syntax().clone().into(), - &mut elements, - ); - } - } + modified.then_some(use_tree) +} - if curr_skipped.is_empty() { - // Un-nesting is complete. - break; - } - prev_skipped = curr_skipped; - } +fn flatten_one_style_tree( + subtree: ast::UseTree, + elements: &mut Vec, + modified: &mut bool, + make: &SyntaxFactory, +) { + let Some(one_tree_list) = one_style_tree_list(&subtree) else { return }; + let mut one_tree_list_iter = one_tree_list.use_trees(); + let mut prev_skipped = Vec::new(); + loop { + let mut prev_skipped_iter = prev_skipped.into_iter(); + let mut curr_skipped = Vec::new(); - // Either removes the subtree (if its semantically empty) or replaces it with - // the un-nested elements. - if elements.is_empty() { - subtree.remove(); - } else { - ted::replace_with_many(subtree.syntax(), elements); - } - // Silence unused assignment warning on `modified`. - let _ = modified; - modified = true; + while let Some(sub_sub_tree) = + one_tree_list_iter.next().or_else(|| prev_skipped_iter.next()) + { + if let Some(sub_one_tree_list) = one_style_tree_list(&sub_sub_tree) { + curr_skipped.extend(sub_one_tree_list.use_trees()); + } else if let Some(normalized) = + recursive_normalize(sub_sub_tree.clone(), NormalizationStyle::Default, make) + { + *modified = true; + elements.push(normalized); } else { - modified |= recursive_normalize(&subtree, NormalizationStyle::Default).is_some(); + elements.push(sub_sub_tree); } } - // Merge all merge-able subtrees. - let mut tree_list_iter = use_tree_list.use_trees(); - let mut anchor = tree_list_iter.next()?; - let mut prev_skipped = Vec::new(); - loop { - let mut has_merged = false; - let mut prev_skipped_iter = prev_skipped.into_iter(); - let mut next_anchor = None; - let mut curr_skipped = Vec::new(); - - while let Some(candidate) = tree_list_iter.next().or(prev_skipped_iter.next()) { - let result = try_merge_trees_mut(&anchor, &candidate, MergeBehavior::Crate); - if result.is_some() { - // Remove merged subtree. - candidate.remove(); - has_merged = true; - } else if next_anchor.is_none() { - next_anchor = Some(candidate); - } else { - curr_skipped.push(candidate); - } - } - - if has_merged { - // Normalize the merge result. - recursive_normalize(&anchor, NormalizationStyle::Default); - modified = true; - } + if curr_skipped.is_empty() { + break; + } + prev_skipped = curr_skipped; + } +} - let (Some(next_anchor), true) = (next_anchor, !curr_skipped.is_empty()) else { - // Merging is complete. - break; - }; +fn merge_single_subtree_into_parent_tree( + use_tree: ast::UseTree, + make: &SyntaxFactory, +) -> Option { + let single_subtree = get_single_subtree(&use_tree)?; + let subtree_is_only_self = single_subtree.path().as_ref().is_some_and(path_is_self); + + let merged_path = match (use_tree.path(), single_subtree.path()) { + _ if subtree_is_only_self => None, + (None, None) => None, + (Some(outer), None) => Some(outer), + (None, Some(inner)) => Some(inner), + (Some(outer), Some(inner)) => Some(make.path_concat(outer, inner)), + }; - // Try to merge the remaining subtrees in the next iteration. - anchor = next_anchor; - prev_skipped = curr_skipped; - } + let list = single_subtree.use_tree_list(); + let list_is_none = list.is_none(); + let star = single_subtree.star_token().is_some(); + if merged_path.is_some() || list.is_some() || star { + let rename = (!star && list_is_none).then(|| single_subtree.rename()).flatten(); + make_use_tree_from_parts(make, merged_path, list, rename, star) + } else { + None + } +} - let mut subtrees: Vec<_> = use_tree_list.use_trees().collect(); - // Merge the remaining subtree into its parent, if its only one and - // the normalization style is not "one". - if subtrees.len() == 1 && style != NormalizationStyle::One { - modified |= merge_subtree_into_parent_tree(&subtrees[0]).is_some(); - } - // Order the remaining subtrees (if necessary). - if subtrees.len() > 1 { - let mut did_sort = false; - subtrees.sort_unstable_by(|a, b| { - let order = use_tree_cmp_bin_search(a, b); - if !did_sort && order == Ordering::Less { - did_sort = true; - } - order - }); - if did_sort { - let start = use_tree_list - .l_curly_token() - .and_then(|l_curly| algo::non_trivia_sibling(l_curly.into(), Direction::Next)) - .filter(|it| it.kind() != T!['}']); - let end = use_tree_list - .r_curly_token() - .and_then(|r_curly| algo::non_trivia_sibling(r_curly.into(), Direction::Prev)) - .filter(|it| it.kind() != T!['{']); - if let Some((start, end)) = start.zip(end) { - // Attempt to insert elements while preserving preceding and trailing trivia. - let mut elements = Vec::new(); - for subtree in subtrees { - add_element_to_list(subtree.syntax().clone().into(), &mut elements); - } - ted::replace_all(start..=end, elements); - } else { - let new_use_tree_list = make::use_tree_list(subtrees).clone_for_update(); - ted::replace(use_tree_list.syntax(), new_use_tree_list.syntax()); - } - modified = true; - } - } +fn one_style_tree_list(subtree: &ast::UseTree) -> Option { + (subtree.path().is_none() && subtree.star_token().is_none() && subtree.rename().is_none()) + .then(|| subtree.use_tree_list()) + .flatten() +} - if !modified { - // Either the use tree was already normalized or its semantically empty. - return None; +fn remove_subtree_if_only_self( + use_tree: ast::UseTree, + make: &SyntaxFactory, +) -> Option { + let Some(single_subtree) = get_single_subtree(&use_tree) else { + return Some(use_tree); + }; + match (use_tree.path(), single_subtree.path()) { + (Some(path), Some(inner)) if path_is_self(&inner) => { + Some(make.use_tree(path, None, use_tree.rename(), false)) } + _ => Some(use_tree), } - Some(()) } /// Traverses both paths until they differ, returning the common prefix of both. @@ -513,10 +494,9 @@ pub fn common_prefix(lhs: &ast::Path, rhs: &ast::Path) -> Option<(ast::Path, ast fn use_tree_cmp_bin_search(lhs: &ast::UseTree, rhs: &ast::UseTree) -> Ordering { let lhs_is_simple_path = lhs.is_simple_path() && lhs.rename().is_none(); let rhs_is_simple_path = rhs.is_simple_path() && rhs.rename().is_none(); - match ( - lhs.path().as_ref().and_then(ast::Path::first_segment), - rhs.path().as_ref().and_then(ast::Path::first_segment), - ) { + let lhs_segment = lhs.path().and_then(|path| path.first_segment()); + let rhs_segment = rhs.path().and_then(|path| path.first_segment()); + match (lhs_segment, rhs_segment) { (None, None) => match (lhs_is_simple_path, rhs_is_simple_path) { (true, true) => Ordering::Equal, (true, false) => Ordering::Less, @@ -701,14 +681,164 @@ fn get_single_subtree(use_tree: &ast::UseTree) -> Option { .map(|(single_subtree,)| single_subtree) } -fn remove_subtree_if_only_self(use_tree: &ast::UseTree) { - let Some(single_subtree) = get_single_subtree(use_tree) else { return }; - match (use_tree.path(), single_subtree.path()) { - (Some(_), Some(inner)) if path_is_self(&inner) => { - ted::remove_all_iter(single_subtree.syntax().children_with_tokens()); - } - _ => (), +fn make_use_with_tree(original: &ast::Use, use_tree: ast::UseTree) -> Option { + let (editor, use_item) = SyntaxEditor::with_ast_node(original); + let original_tree = use_item.use_tree()?; + editor.replace(original_tree.syntax(), use_tree.syntax()); + let edit = editor.finish(); + ast::Use::cast(edit.new_root().clone()) +} + +fn make_use_tree_list( + make: &SyntaxFactory, + use_trees: Vec, + style_source: Option<&ast::UseTreeList>, +) -> Option { + let use_tree_list = make.use_tree_list(use_trees); + let Some(style_source) = style_source else { + return Some(use_tree_list); + }; + + let source_l_curly = style_source.l_curly_token()?; + let source_r_curly = style_source.r_curly_token()?; + + let leading_ws = source_l_curly.next_token().filter(|token| token.kind().is_trivia()); + + let trailing_ws = source_r_curly.prev_token().filter(|token| token.kind().is_trivia()); + + let source_trailing_token = trailing_ws + .as_ref() + .and_then(|token| token.prev_token()) + .or_else(|| source_r_curly.prev_token()); + + let source_has_trailing_comma = + source_trailing_token.is_some_and(|token| token.kind() == T![,]); + + let (editor, use_tree_list) = SyntaxEditor::with_ast_node(&use_tree_list); + let make = editor.make(); + + if let Some(leading_ws) = leading_ws { + editor.insert( + Position::after(use_tree_list.l_curly_token()?), + make.whitespace(leading_ws.text()), + ); + } + + let r_curly = use_tree_list.r_curly_token()?; + + let generated_has_trailing_comma = r_curly + .prev_token() + .and_then(|token| if token.kind().is_trivia() { token.prev_token() } else { Some(token) }) + .is_some_and(|token| token.kind() == T![,]); + + let mut trailing = Vec::new(); + + if source_has_trailing_comma + && !generated_has_trailing_comma + && use_tree_list.use_trees().next().is_some() + { + trailing.push(make.token(T![,]).into()); + } + + if let Some(trailing_ws) = trailing_ws { + trailing.push(make.whitespace(trailing_ws.text()).into()); + } + + if !trailing.is_empty() { + editor.insert_all(Position::before(r_curly), trailing); + } + + let edit = editor.finish(); + ast::UseTreeList::cast(edit.new_root().clone()) +} + +fn make_use_tree_from_list(make: &SyntaxFactory, list: ast::UseTreeList) -> Option { + let placeholder = make.use_tree_glob(); + let (editor, use_tree) = SyntaxEditor::with_ast_node(&placeholder); + let first_child = use_tree.syntax().first_child_or_token()?; + let last_child = use_tree.syntax().last_child_or_token()?; + editor.replace_all(first_child..=last_child, vec![list.syntax().clone().into()]); + let edit = editor.finish(); + ast::UseTree::cast(edit.new_root().clone()) +} + +fn make_use_tree_from_parts( + make: &SyntaxFactory, + path: Option, + list: Option, + rename: Option, + star: bool, +) -> Option { + match (path, list, star) { + (Some(path), list, star) => Some(make.use_tree(path, list, rename, star)), + (None, Some(list), false) if rename.is_none() => make_use_tree_from_list(make, list), + (None, None, true) if rename.is_none() => Some(make.use_tree_glob()), + (None, None, false) if rename.is_none() => None, + _ => None, + } +} + +fn with_use_tree_list( + use_tree: &ast::UseTree, + use_trees: Vec, + make: &SyntaxFactory, +) -> Option { + let list = make_use_tree_list(make, use_trees, use_tree.use_tree_list().as_ref())?; + make_use_tree_from_parts( + make, + use_tree.path(), + Some(list), + use_tree.rename(), + use_tree.star_token().is_some(), + ) +} + +pub(crate) fn wrap_in_tree_list( + use_tree: &ast::UseTree, + make: &SyntaxFactory, +) -> Option { + if use_tree.path().is_none() + && use_tree.use_tree_list().is_some() + && use_tree.rename().is_none() + && use_tree.star_token().is_none() + { + return None; } + + let list = make_use_tree_list(make, vec![use_tree.clone()], None)?; + make_use_tree_from_list(make, list) +} + +fn split_prefix( + use_tree: &ast::UseTree, + prefix: &ast::Path, + make: &SyntaxFactory, +) -> Option { + let path = use_tree.path()?; + if path == *prefix && use_tree.use_tree_list().is_some() { + return Some(use_tree.clone()); + } + + let suffix = if path == *prefix { + if use_tree.star_token().is_some() { + make.use_tree_glob() + } else { + let self_path = make.path_unqualified(make.path_segment_self()); + make.use_tree(self_path, None, use_tree.rename(), false) + } + } else { + let suffix_segments = path.segments().skip(prefix.segments().count()); + let suffix_path = make.path_from_segments(suffix_segments, false); + make.use_tree( + suffix_path, + use_tree.use_tree_list(), + use_tree.rename(), + use_tree.star_token().is_some(), + ) + }; + + let list = make_use_tree_list(make, vec![suffix], None)?; + Some(make.use_tree(prefix.clone(), Some(list), None, false)) } // Taken from rustfmt diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs index bd8fa69e28707..e1c2053289b96 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -1025,7 +1025,6 @@ fn _slice(bar: &[i32]) -> bool { check_diagnostics( r#" //- minicore: coerce_unsized, dispatch_from_dyn -#![feature(trait_upcasting)] trait Foo {} trait Bar: Foo {} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index f6293e35d0c37..d1c3d1c5df096 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -354,6 +354,30 @@ fn f() { ) } + #[test] + fn varargs_fn_pointer() { + check_diagnostics( + r#" +struct Funcs { + f: unsafe extern "C" fn(u8, u8, ...) -> i32, + g: unsafe extern "C" fn(...) -> i32, +} + +fn f(funcs: Funcs) { + unsafe { + (funcs.f)(0, 1); + (funcs.f)(0, 1, 2); + (funcs.f)(0); + //^ error: expected 2 arguments, found 1 + (funcs.g)(); + (funcs.g)(0); + (funcs.g)(0, 1); + } +} + "#, + ) + } + #[test] fn arg_count_lambda() { check_diagnostics( diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index 88cb570c6b0f3..dded01520ffbc 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -60,6 +60,7 @@ mod view_mir; mod view_syntax_tree; use std::panic::{AssertUnwindSafe, UnwindSafe}; +use std::time::Duration; use cfg::CfgOptions; use fetch_crates::CrateInfo; @@ -197,8 +198,8 @@ impl AnalysisHost { /// Applies changes to the current state of the world. If there are /// outstanding snapshots, they will be canceled. - pub fn apply_change(&mut self, change: ChangeWithProcMacros) { - self.db.apply_change(change); + pub fn apply_change(&mut self, change: ChangeWithProcMacros) -> Duration { + self.db.apply_change(change) } /// NB: this clears the database diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index b8c14dc09f9a2..24031429db88f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -50,7 +50,6 @@ pub struct NavigationTarget { pub kind: Option, pub container_name: Option, pub description: Option, - // FIXME: Use the database lifetime here. pub docs: Option>, /// In addition to a `name` field, a `NavigationTarget` may also be aliased /// In such cases we want a `NavigationTarget` to be accessible by its alias diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html index 1184739cc2589..2f2c7f251a703 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html @@ -128,9 +128,9 @@ let y = &mut x; let z = &y; - let Foo { x: z, y } = Foo { x: z, y }; + let Foo { x: z, y } = Foo { x: z, y }; - y; + y; let mut foo = Foo { x, y: x }; let foo2 = Foo { x, y: x }; @@ -143,7 +143,7 @@ copy.qux(); copy.baz(copy); - let a = |x| x; + let a = |x| x; let bar = Foo::baz; let baz = (-42,); @@ -173,13 +173,13 @@ } async fn learn_and_sing() { - let song = learn_song().await; - sing_song(song).await; + let song = learn_song().await; + sing_song(song).await; } async fn async_main() { let f1 = learn_and_sing(); - let f2 = dance(); + let f2 = dance(); futures::join!(f1, f2); } diff --git a/src/tools/rust-analyzer/crates/intern/Cargo.toml b/src/tools/rust-analyzer/crates/intern/Cargo.toml index 2ba802f05706c..adf49ca7b6c29 100644 --- a/src/tools/rust-analyzer/crates/intern/Cargo.toml +++ b/src/tools/rust-analyzer/crates/intern/Cargo.toml @@ -12,7 +12,6 @@ rust-version.workspace = true [lib] doctest = false - [dependencies] dashmap.workspace = true # We need to freeze the version of the crate, as it needs to match with dashmap diff --git a/src/tools/rust-analyzer/crates/intern/src/gc.rs b/src/tools/rust-analyzer/crates/intern/src/gc.rs index f4e8f75e7194b..596b05eb1cb13 100644 --- a/src/tools/rust-analyzer/crates/intern/src/gc.rs +++ b/src/tools/rust-analyzer/crates/intern/src/gc.rs @@ -34,9 +34,7 @@ impl Storage for InternedStorage { for item in storage { let item = item.key(); let addr = Arc::as_ptr(item).addr(); - if Arc::strong_count(item) > 1 { - // The item is referenced from the outside. - gc.alive.insert(addr); + if Arc::strong_count(item) > 1 && gc.alive.insert(addr) { item.visit_with(gc); } } @@ -60,9 +58,7 @@ impl Storage for InternedSliceStorage for item in storage { let item = item.key(); let addr = ThinArc::as_ptr(item).addr(); - if ThinArc::strong_count(item) > 1 { - // The item is referenced from the outside. - gc.alive.insert(addr); + if ThinArc::strong_count(item) > 1 && gc.alive.insert(addr) { T::visit_header(&item.header.header, gc); T::visit_slice(&item.slice, gc); } @@ -81,7 +77,7 @@ pub trait GcInternedVisit { pub trait GcInternedSliceVisit: SliceInternable { fn visit_header(header: &Self::Header, gc: &mut GarbageCollector); - fn visit_slice(header: &[Self::SliceType], gc: &mut GarbageCollector); + fn visit_slice(slice: &[Self::SliceType], gc: &mut GarbageCollector); } #[derive(Default)] @@ -103,11 +99,13 @@ impl GarbageCollector { self.storages.push(&InternedSliceStorage::(PhantomData)); } + /// Collects unreachable GC-managed interned values. + /// /// # Safety /// /// - This cannot be called if there are some not-yet-recorded type values. - /// - All relevant storages must have been added; that is, within the full graph of values, - /// the added storages must form a DAG. + /// - All storages that can contain live GC-managed values must have been added, and those + /// storages must be closed over the GC-managed values reachable from them. /// - [`GcInternedVisit`] and [`GcInternedSliceVisit`] must mark all values reachable from the node. pub unsafe fn collect(mut self) { if cfg!(feature = "prevent-gc") { @@ -136,8 +134,9 @@ impl GarbageCollector { &mut self, interned: InternedRef<'_, T>, ) -> ControlFlow<()> { + const { assert!(T::USE_GC) }; + if interned.strong_count() > 1 { - // It will be visited anyway, so short-circuit return ControlFlow::Break(()); } let addr = interned.as_raw().addr(); @@ -148,8 +147,9 @@ impl GarbageCollector { &mut self, interned: InternedSliceRef<'_, T>, ) -> ControlFlow<()> { + const { assert!(T::USE_GC) }; + if interned.strong_count() > 1 { - // It will be visited anyway, so short-circuit return ControlFlow::Break(()); } let addr = interned.as_raw().addr(); @@ -240,7 +240,7 @@ mod tests { impl GcInternedSliceVisit for StringSlice { fn visit_header(_header: &Self::Header, _gc: &mut GarbageCollector) {} - fn visit_slice(_header: &[Self::SliceType], _gc: &mut GarbageCollector) {} + fn visit_slice(_slice: &[Self::SliceType], _gc: &mut GarbageCollector) {} } let (a, d) = { @@ -276,6 +276,10 @@ mod tests { gc.add_storage::(); unsafe { gc.collect() }; + if !cfg!(feature = "prevent-gc") { + assert_eq!(::storage().get().len(), 1); + assert_eq!(::storage().get().len(), 1); + } assert_eq!(a.0, "abc"); assert_eq!(d.header.length, 2); assert_eq!(d.header.header, "abc"); @@ -288,6 +292,11 @@ mod tests { gc.add_slice_storage::(); gc.add_storage::(); unsafe { gc.collect() }; + + if !cfg!(feature = "prevent-gc") { + assert_eq!(::storage().get().len(), 0); + assert_eq!(::storage().get().len(), 0); + } } #[test] @@ -309,7 +318,7 @@ mod tests { impl GcInternedSliceVisit for StringSlice { fn visit_header(_header: &Self::Header, _gc: &mut GarbageCollector) {} - fn visit_slice(_header: &[Self::SliceType], _gc: &mut GarbageCollector) {} + fn visit_slice(_slice: &[Self::SliceType], _gc: &mut GarbageCollector) {} } let outer = { @@ -322,6 +331,10 @@ mod tests { gc.add_storage::(); unsafe { gc.collect() }; + if !cfg!(feature = "prevent-gc") { + assert_eq!(::storage().get().len(), 1); + assert_eq!(::storage().get().len(), 1); + } assert_eq!(outer.0.header.header, "abc"); assert_eq!(outer.0.slice, [123, 456, 789]); @@ -331,5 +344,10 @@ mod tests { gc.add_slice_storage::(); gc.add_storage::(); unsafe { gc.collect() }; + + if !cfg!(feature = "prevent-gc") { + assert_eq!(::storage().get().len(), 0); + assert_eq!(::storage().get().len(), 0); + } } } diff --git a/src/tools/rust-analyzer/crates/parser/src/output.rs b/src/tools/rust-analyzer/crates/parser/src/output.rs index 2f09b1121891b..ce64db8adae90 100644 --- a/src/tools/rust-analyzer/crates/parser/src/output.rs +++ b/src/tools/rust-analyzer/crates/parser/src/output.rs @@ -18,7 +18,7 @@ pub struct Output { /// /// ```text /// |16 bit kind|8 bit n_input_tokens|4 bit tag|4 bit leftover| - /// `````` + /// ``` event: Vec, error: Vec, } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index f5d40a4b9ffc2..1b86eac0129aa 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -29,7 +29,7 @@ line-index.workspace = true proc-macro-test.path = "./proc-macro-test" [features] -default = ["in-rust-tree"] +default = [] in-rust-tree = [] [lints] diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs index e44af96f36435..352f41a82636a 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs @@ -560,7 +560,7 @@ impl WorkspaceBuildScripts { // FIXME: Find a better way to know if it is a dylib. fn is_dylib(path: &Utf8Path) -> bool { - match path.extension().map(|e| e.to_owned().to_lowercase()) { + match path.extension().map(|e| e.to_ascii_lowercase()) { None => false, Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"), } diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 675533645d0db..c9bf803da347b 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -811,6 +811,7 @@ impl ProjectWorkspace { .packages() .map(|pkg| { let is_local = cargo[pkg].is_local; + let is_member = cargo[pkg].is_member; let pkg_root = cargo[pkg].manifest.parent().to_path_buf(); let mut include = vec![pkg_root.clone()]; @@ -844,9 +845,11 @@ impl ProjectWorkspace { let mut exclude = vec![pkg_root.join(".git")]; if is_local { include.extend(self.extra_includes.iter().cloned()); - exclude.push(pkg_root.join("target")); - } else { + } + if !is_member { + // For non-workspace-members, we only resolve library targets, + // so none of these need to be loaded into the VFS. exclude.push(pkg_root.join("tests")); exclude.push(pkg_root.join("examples")); exclude.push(pkg_root.join("benches")); @@ -874,6 +877,7 @@ impl ProjectWorkspace { .chain(cargo_script.iter().flat_map(|(cargo, build_scripts, _)| { cargo.packages().map(|pkg| { let is_local = cargo[pkg].is_local; + let is_member = cargo[pkg].is_member; let pkg_root = cargo[pkg].manifest.parent().to_path_buf(); let mut include = vec![pkg_root.clone()]; @@ -909,7 +913,10 @@ impl ProjectWorkspace { include.extend(self.extra_includes.iter().cloned()); exclude.push(pkg_root.join("target")); - } else { + } + if !is_member { + // For non-workspace-members, we only resolve library targets, + // so none of these need to be loaded into the VFS. exclude.push(pkg_root.join("tests")); exclude.push(pkg_root.join("examples")); exclude.push(pkg_root.join("benches")); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 49f28352b6cf6..69405b421eca5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -64,6 +64,7 @@ impl Tester { fn new() -> Result { let mut path = AbsPathBuf::assert_utf8(std::env::temp_dir()); path.push("ra-rustc-test"); + std::fs::create_dir_all(&path)?; let tmp_file = path.join("ra-rustc-test.rs"); std::fs::write(&tmp_file, "")?; let cargo_config = CargoConfig { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index bca38ed82fdd5..d3acbb934d5bb 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -237,7 +237,7 @@ impl flags::Scip { let token = si.tokens.get(id).unwrap(); let Some(definition) = token.definition else { - break; + continue; }; let file_id = definition.file_id; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 6f532e4224885..4ea447333903d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -662,9 +662,12 @@ config_data! { /// For traits the type "methods" can be used to only exclude the methods but not the trait /// itself. /// - /// For modules the type "subItems" can be used to only exclude the all items in it but not the module + /// For modules the type "sub_items" can be used to only exclude the all items in it but not the module /// itself. This does not include items defined in nested modules. /// + /// For enums the type "variants" can be used to only exclude the all variants in it but not the enum + /// itself. + /// /// This setting also inherits `#rust-analyzer.completion.excludeTraits#`. completion_autoimport_exclude: Vec = vec![ AutoImportExclusion::Verbose { path: "core::borrow::Borrow".to_owned(), r#type: AutoImportExclusionType::Methods }, @@ -1944,6 +1947,9 @@ impl Config { AutoImportExclusionType::SubItems => { ide_completion::AutoImportExclusionType::SubItems } + AutoImportExclusionType::Variants => { + ide_completion::AutoImportExclusionType::Variants + } }, ), }) @@ -3004,6 +3010,7 @@ pub enum AutoImportExclusionType { Always, Methods, SubItems, + Variants, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -4135,7 +4142,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json }, "type": { "type": "string", - "enum": ["always", "methods", "subItems"], + "enum": ["always", "methods", "sub_items", "variants"], "enumDescriptions": [ "Do not show this item or its methods (if it is a trait) in auto-import completions.", "Do not show this trait's methods in auto-import completions.", diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index afd4162de6227..f91e9532aaf02 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -330,7 +330,7 @@ impl GlobalState { this } - pub(crate) fn process_changes(&mut self) -> bool { + pub(crate) fn process_changes(&mut self) -> (bool, Option) { let _p = span!(Level::INFO, "GlobalState::process_changes").entered(); // We cannot directly resolve a change in a ratoml file to a format // that can be used by the config module because config talks @@ -343,7 +343,7 @@ impl GlobalState { let mut guard = self.vfs.write(); let changed_files = guard.0.take_changes(); if changed_files.is_empty() { - return false; + return (false, None); } let (change, modified_rust_files, workspace_structure_change) = @@ -439,7 +439,7 @@ impl GlobalState { (change, modified_rust_files, workspace_structure_change) }); - self.analysis_host.apply_change(change); + let cancellation_time = self.analysis_host.apply_change(change); if !modified_ratoml_files.is_empty() || !self.config.same_source_root_parent_map(&self.local_roots_parent_map) @@ -561,7 +561,7 @@ impl GlobalState { } } - true + (true, Some(cancellation_time)) } pub(crate) fn snapshot(&self) -> GlobalStateSnapshot { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index edf3da5e6c07a..d966e29ede0c4 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -307,15 +307,11 @@ impl GlobalState { let _p = tracing::info_span!("GlobalState::handle_event", event = %event).entered(); let event_dbg_msg = format!("{event:?}"); - tracing::debug!(?loop_start, ?event, "handle_event"); - if tracing::enabled!(tracing::Level::TRACE) { - let task_queue_len = self.task_pool.handle.len(); - if task_queue_len > 0 { - tracing::trace!("task queue len: {}", task_queue_len); - } - } + tracing::debug!(?event, "handle_event"); let was_quiescent = self.is_quiescent(); + + let mut cancellation_time = None; match event { Event::Lsp(msg) => match msg { lsp_server::Message::Request(req) => self.on_new_request(loop_start, req), @@ -326,7 +322,9 @@ impl GlobalState { let _p = tracing::info_span!("GlobalState::handle_event/queued_task").entered(); self.handle_deferred_task(task); // Coalesce multiple deferred task events into one loop turn - while let Ok(task) = self.deferred_task_queue.receiver.try_recv() { + while loop_start.elapsed() < Duration::from_millis(50) + && let Ok(task) = self.deferred_task_queue.receiver.try_recv() + { self.handle_deferred_task(task); } } @@ -334,14 +332,16 @@ impl GlobalState { let _p = tracing::info_span!("GlobalState::handle_event/task").entered(); let mut prime_caches_progress = Vec::new(); - self.handle_task(&mut prime_caches_progress, task); + cancellation_time = self.handle_task(&mut prime_caches_progress, task); // Coalesce multiple task events into one loop turn - while let Ok(task) = self.task_pool.receiver.try_recv() { + while loop_start.elapsed() < Duration::from_millis(50) + && let Ok(task) = self.task_pool.receiver.try_recv() + { self.handle_task(&mut prime_caches_progress, task); } let title = "Indexing"; - let cancel_token = Some("rustAnalyzer/cachePriming".to_owned()); + let cancel_token = || Some("rustAnalyzer/cachePriming".to_owned()); let mut last_report = None; for progress in prime_caches_progress { @@ -352,7 +352,7 @@ impl GlobalState { Progress::Begin, None, Some(0.0), - cancel_token.clone(), + cancel_token(), ); } PrimeCachesProgress::Report(report) => { @@ -387,6 +387,16 @@ impl GlobalState { if cancelled { self.prime_caches_queue .request_op("restart after cancellation".to_owned(), ()); + } else if self.config.check_on_save(None) + && self.config.flycheck_workspace(None) + && !self.fetch_build_data_queue.op_requested() + { + // Priming finished; now run the deferred initial workspace flycheck + // (kept off the critical path so `cargo check` doesn't contend with + // cache priming for CPU). + self.flycheck + .iter() + .for_each(|flycheck| flycheck.restart_workspace(None)); } if let Some((message, fraction, title)) = last_report.take() { self.report_progress( @@ -394,7 +404,7 @@ impl GlobalState { Progress::Report, message, Some(fraction), - cancel_token.clone(), + cancel_token(), ); } self.report_progress( @@ -402,7 +412,7 @@ impl GlobalState { Progress::End, None, Some(1.0), - cancel_token.clone(), + cancel_token(), ); } }; @@ -413,7 +423,7 @@ impl GlobalState { Progress::Report, message, Some(fraction), - cancel_token.clone(), + cancel_token(), ); } } @@ -422,7 +432,9 @@ impl GlobalState { let mut last_progress_report = None; self.handle_vfs_msg(message, &mut last_progress_report); // Coalesce many VFS event into a single loop turn - while let Ok(message) = self.loader.receiver.try_recv() { + while loop_start.elapsed() < Duration::from_millis(50) + && let Ok(message) = self.loader.receiver.try_recv() + { self.handle_vfs_msg(message, &mut last_progress_report); } if let Some((message, fraction)) = last_progress_report { @@ -439,7 +451,9 @@ impl GlobalState { let mut cargo_finished = false; self.handle_flycheck_msg(message, &mut cargo_finished); // Coalesce many flycheck updates into a single loop turn - while let Ok(message) = self.flycheck_receiver.try_recv() { + while loop_start.elapsed() < Duration::from_millis(50) + && let Ok(message) = self.flycheck_receiver.try_recv() + { self.handle_flycheck_msg(message, &mut cargo_finished); } if cargo_finished { @@ -453,14 +467,18 @@ impl GlobalState { let _p = tracing::info_span!("GlobalState::handle_event/test_result").entered(); self.handle_cargo_test_msg(message); // Coalesce many test result event into a single loop turn - while let Ok(message) = self.test_run_receiver.try_recv() { + while loop_start.elapsed() < Duration::from_millis(50) + && let Ok(message) = self.test_run_receiver.try_recv() + { self.handle_cargo_test_msg(message); } } Event::DiscoverProject(message) => { self.handle_discover_msg(message); // Coalesce many project discovery events into a single loop turn. - while let Ok(message) = self.discover_receiver.try_recv() { + while loop_start.elapsed() < Duration::from_millis(50) + && let Ok(message) = self.discover_receiver.try_recv() + { self.handle_discover_msg(message); } } @@ -469,26 +487,29 @@ impl GlobalState { } } let event_handling_duration = loop_start.elapsed(); - let (state_changed, memdocs_added_or_removed) = if self.vfs_done { - if let Some(cause) = self.wants_to_switch.take() { - self.switch_workspaces(cause); - } - (self.process_changes(), self.mem_docs.take_changes()) - } else { - (false, false) + let ((state_changed, changes_cancellation_time), memdocs_added_or_removed) = + if self.vfs_done { + if let Some(cause) = self.wants_to_switch.take() { + cancellation_time = match (cancellation_time, self.switch_workspaces(cause)) { + (Some(a), Some(b)) => Some(a + b), + (Some(d), None) | (None, Some(d)) => Some(d), + (None, None) => None, + }; + } + (self.process_changes(), self.mem_docs.take_changes()) + } else { + ((false, None), false) + }; + cancellation_time = match (cancellation_time, changes_cancellation_time) { + (Some(a), Some(b)) => Some(a + b), + (Some(d), None) | (None, Some(d)) => Some(d), + (None, None) => None, }; let mut gc_elapsed = None; if self.is_quiescent() { let became_quiescent = !was_quiescent; if became_quiescent { - if self.config.check_on_save(None) - && self.config.flycheck_workspace(None) - && !self.fetch_build_data_queue.op_requested() - { - // Project has loaded properly, kick off initial flycheck - self.flycheck.iter().for_each(|flycheck| flycheck.restart_workspace(None)); - } // delay initial cache priming until proc macros are loaded, or we will load up a bunch of garbage into salsa let proc_macros_loaded = self.config.prefill_caches() && (!self.config.expand_proc_macros() @@ -496,6 +517,19 @@ impl GlobalState { if proc_macros_loaded { self.prime_caches_queue.request_op("became quiescent".to_owned(), ()); } + if self.config.check_on_save(None) + && self.config.flycheck_workspace(None) + && !self.fetch_build_data_queue.op_requested() + { + if !self.config.prefill_caches() { + self.flycheck.iter().for_each(|flycheck| flycheck.restart_workspace(None)); + } else if proc_macros_loaded + && !self.prime_caches_queue.op_in_progress() + && !self.prime_caches_queue.op_requested() + { + self.flycheck.iter().for_each(|flycheck| flycheck.restart_workspace(None)); + } + } } let client_refresh = became_quiescent || state_changed; @@ -593,11 +627,13 @@ impl GlobalState { tracing::warn!( "overly long loop turn took {loop_duration:?}:\n\ (event handling took {event_handling_duration:?}): {event_dbg_msg}\n\ + (cancellation took {cancellation_time:?}) (garbage collection took {gc_elapsed:?})" ); self.poke_rust_analyzer_developer(format!( "overly long loop turn took {loop_duration:?}:\n\ (event handling took {event_handling_duration:?}): {event_dbg_msg}\n\ + (cancellation took {cancellation_time:?}) (garbage collection took {gc_elapsed:?})" )); } @@ -803,7 +839,12 @@ impl GlobalState { } } - fn handle_task(&mut self, prime_caches_progress: &mut Vec, task: Task) { + fn handle_task( + &mut self, + prime_caches_progress: &mut Vec, + task: Task, + ) -> Option { + let mut cancellation_time = None; match task { Task::Response(response) => self.respond(response), // Only retry requests that haven't been cancelled. Otherwise we do unnecessary work. @@ -906,8 +947,9 @@ impl GlobalState { ProcMacroProgress::Report(msg) => (Some(Progress::Report), Some(msg)), ProcMacroProgress::End(change) => { self.fetch_proc_macros_queue.op_completed(true); - self.analysis_host.apply_change(change); - self.finish_loading_crate_graph(); + cancellation_time = Some(self.analysis_host.apply_change(change)); + // FIXME This feels a bit off, this should go through similar machinery as build scripts? + _ = self.finish_loading_crate_graph(); (Some(Progress::End), None) } }; @@ -921,6 +963,7 @@ impl GlobalState { self.send_notification::(tests); } } + cancellation_time } fn handle_vfs_msg( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 74fd0e653398b..4940defed2ac2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -13,7 +13,7 @@ //! project is currently loading and we don't have a full project model, we //! still want to respond to various requests. // FIXME: This is a mess that needs some untangling work -use std::{iter, mem, sync::atomic::AtomicUsize}; +use std::{iter, mem, sync::atomic::AtomicUsize, time::Duration}; use hir::{ChangeWithProcMacros, ProcMacrosBuilder, db::DefDatabase}; use ide_db::{ @@ -468,25 +468,22 @@ impl GlobalState { }); } - pub(crate) fn switch_workspaces(&mut self, cause: Cause) { + pub(crate) fn switch_workspaces(&mut self, cause: Cause) -> Option { let _p = tracing::info_span!("GlobalState::switch_workspaces").entered(); tracing::info!(%cause, "will switch workspaces"); - let Some(FetchWorkspaceResponse { workspaces, force_crate_graph_reload }) = - self.fetch_workspaces_queue.last_op_result() - else { - return; - }; + let FetchWorkspaceResponse { workspaces, force_crate_graph_reload } = + self.fetch_workspaces_queue.last_op_result()?; let switching_from_empty_workspace = self.workspaces.is_empty(); info!(%cause, ?force_crate_graph_reload, %switching_from_empty_workspace); if self.fetch_workspace_error().is_err() && !switching_from_empty_workspace { if *force_crate_graph_reload { - self.recreate_crate_graph(cause, false); + return self.recreate_crate_graph(cause, false); } // It only makes sense to switch to a partially broken workspace // if we don't have any workspace at all yet. - return; + return None; } let workspaces = @@ -501,7 +498,7 @@ impl GlobalState { if same_workspaces { if switching_from_empty_workspace { // Switching from empty to empty is a no-op - return; + return None; } if let Some(FetchBuildDataResponse { workspaces, build_scripts }) = self.fetch_build_data_queue.last_op_result() @@ -524,20 +521,20 @@ impl GlobalState { } else { info!("build scripts do not match the version of the active workspace"); if *force_crate_graph_reload { - self.recreate_crate_graph(cause, switching_from_empty_workspace); + return self.recreate_crate_graph(cause, switching_from_empty_workspace); } // Current build scripts do not match the version of the active // workspace, so there's nothing for us to update. - return; + return None; } } else { if *force_crate_graph_reload { - self.recreate_crate_graph(cause, switching_from_empty_workspace); + return self.recreate_crate_graph(cause, switching_from_empty_workspace); } // No build scripts but unchanged workspaces, nothing to do here - return; + return None; } } else { info!("abandon build scripts for workspaces"); @@ -560,7 +557,7 @@ impl GlobalState { // `switch_workspaces()` will be called again when build scripts already run, which should // take a short time. If we update the workspace now we will invalidate proc macros and cfgs, // and then when build scripts complete we will invalidate them again. - return; + return None; } } } @@ -733,13 +730,15 @@ impl GlobalState { self.local_roots_parent_map = Arc::new(self.source_root_config.source_root_parent_map()); info!(?cause, "recreating the crate graph"); - self.recreate_crate_graph(cause, switching_from_empty_workspace); + let cancellation_time = self.recreate_crate_graph(cause, switching_from_empty_workspace); info!("did switch workspaces"); + cancellation_time } - fn recreate_crate_graph(&mut self, cause: String, initial_build: bool) { + fn recreate_crate_graph(&mut self, cause: String, initial_build: bool) -> Option { info!(?cause, "Building Crate Graph"); + let mut cancellation_time = None; self.report_progress( "Building CrateGraph", crate::lsp::utils::Progress::Begin, @@ -795,9 +794,8 @@ impl GlobalState { } change.set_crate_graph(crate_graph); - self.analysis_host.apply_change(change); - - self.finish_loading_crate_graph(); + cancellation_time = Some(self.analysis_host.apply_change(change)); + _ = self.finish_loading_crate_graph(); } else { change.set_crate_graph(crate_graph); self.fetch_proc_macros_queue.request_op(cause, (change, proc_macro_paths)); @@ -810,11 +808,13 @@ impl GlobalState { None, None, ); + cancellation_time } - pub(crate) fn finish_loading_crate_graph(&mut self) { - self.process_changes(); + pub(crate) fn finish_loading_crate_graph(&mut self) -> Option { + let (_, cancellation_time) = self.process_changes(); self.reload_flycheck(); + cancellation_time } pub(super) fn fetch_workspace_error(&self) -> Result<(), String> { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs index 81d9786809b72..fdcd2c98b904d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs @@ -153,6 +153,9 @@ impl CargoTargetSpec { Some(CargoTargetSpec { target_kind: TargetKind::Test, .. }) => { config.test_command } + Some(CargoTargetSpec { target_kind: TargetKind::Bench, .. }) => { + config.bench_command + } _ => "run".to_owned(), }; cargo_args.push(subcommand); @@ -225,6 +228,9 @@ impl CargoTargetSpec { Some(CargoTargetSpec { target_kind: TargetKind::Test, .. }) => { (config.test_override_command, None) } + Some(CargoTargetSpec { target_kind: TargetKind::Bench, .. }) => { + (config.bench_override_command, None) + } _ => (None, None), }, }; @@ -319,7 +325,11 @@ impl CargoTargetSpec { pub(crate) fn push_to(self, buf: &mut Vec, kind: &RunnableKind) { buf.push("--package".to_owned()); - buf.push(self.package); + if self.package.contains(":") { + buf.push(self.package_id.to_string()); + } else { + buf.push(self.package); + } // Can't mix --doc with other target flags if let RunnableKind::DocTest { .. } = kind { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/task_pool.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/task_pool.rs index 104cd3d2eae9e..2da52f7480d8a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/task_pool.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/task_pool.rs @@ -40,10 +40,6 @@ impl TaskPool { }) } - pub(crate) fn len(&self) -> usize { - self.pool.len() - } - pub(crate) fn is_empty(&self) -> bool { self.pool.is_empty() } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast.rs b/src/tools/rust-analyzer/crates/syntax/src/ast.rs index dc592a43727b4..d8c7e1583031d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast.rs @@ -1,7 +1,6 @@ //! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s pub mod edit; -pub mod edit_in_place; mod expr_ext; mod generated; pub mod make; diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs index 2e3a4016ee89f..eaa36903bf26f 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs @@ -13,7 +13,7 @@ use crate::{ SyntaxKind::{ATTR, COMMENT, WHITESPACE}, SyntaxNode, SyntaxToken, ast::{self, AstNode, HasName, make}, - syntax_editor::{Position, SyntaxEditor, SyntaxMappingBuilder}, + syntax_editor::{Position, Removable, SyntaxEditor, SyntaxMappingBuilder}, }; use super::syntax_factory::SyntaxFactory; @@ -263,6 +263,109 @@ pub fn indent(node: &SyntaxNode, level: IndentLevel) -> SyntaxNode { level.clone_increase_indent(node) } +impl ast::GenericParamList { + /// Constructs a matching [`ast::GenericArgList`] + pub fn to_generic_args(&self, make: &SyntaxFactory) -> ast::GenericArgList { + let args = self.generic_params().filter_map(|param| match param { + ast::GenericParam::LifetimeParam(it) => { + Some(ast::GenericArg::LifetimeArg(make.lifetime_arg(it.lifetime()?))) + } + ast::GenericParam::TypeParam(it) => { + Some(ast::GenericArg::TypeArg(make.type_arg(make.ty_name(it.name()?)))) + } + ast::GenericParam::ConstParam(it) => { + // Name-only const params get parsed as `TypeArg`s + Some(ast::GenericArg::TypeArg(make.type_arg(make.ty_name(it.name()?)))) + } + }); + + make::generic_arg_list(args) + } +} + +impl ast::UseTree { + /// Deletes the usetree node represented by the input. Recursively removes parents, including use nodes that become empty. + pub fn remove_recursive(self, editor: &SyntaxEditor) { + let parent = self.syntax().parent(); + + if let Some(u) = parent.clone().and_then(ast::Use::cast) { + u.remove(editor); + } else if let Some(u) = parent.and_then(ast::UseTreeList::cast) { + if u.use_trees().nth(1).is_none() + || u.use_trees().all(|use_tree| { + use_tree.syntax() == self.syntax() || editor.deleted(use_tree.syntax()) + }) + { + u.parent_use_tree().remove_recursive(editor); + return; + } + self.remove(editor); + u.remove_unnecessary_braces(editor); + } + } + + /// Splits off the given prefix, making it the path component of the use tree, + /// appending the rest of the path to all UseTreeList items. + /// + /// # Examples + /// + /// `prefix$0::suffix` -> `prefix::{suffix}` + /// + /// `prefix$0` -> `prefix::{self}` + /// + /// `prefix$0::*` -> `prefix::{*}` + pub fn split_prefix_with_editor(&self, editor: &SyntaxEditor, prefix: &ast::Path) { + debug_assert_eq!(self.path(), Some(prefix.top_path())); + + let make = editor.make(); + let path = self.path().unwrap(); + let suffix = if path == *prefix { + if self.use_tree_list().is_some() { + return; + } else if self.star_token().is_some() { + make.use_tree_glob() + } else { + let self_path = make.path_unqualified(make.path_segment_self()); + make.use_tree(self_path, None, self.rename(), false) + } + } else { + let suffix_segments = path.segments().skip(prefix.segments().count()); + let suffix_path = make.path_from_segments(suffix_segments, false); + make.use_tree( + suffix_path, + self.use_tree_list(), + self.rename(), + self.star_token().is_some(), + ) + }; + let use_tree_list = make.use_tree_list(once(suffix)); + let new_use_tree = make.use_tree(prefix.clone(), Some(use_tree_list), None, false); + + editor.replace(self.syntax(), new_use_tree.syntax()); + } +} + +impl ast::RecordExprField { + /// This will either replace the initializer, or in the case that this is a shorthand convert + /// the initializer into the name ref and insert the expr as the new initializer. + pub fn replace_expr(&self, editor: &SyntaxEditor, expr: ast::Expr) { + if self.name_ref().is_some() { + if let Some(prev) = self.expr() { + editor.replace(prev.syntax(), expr.syntax()); + } + } else if let Some(ast::Expr::PathExpr(path_expr)) = self.expr() + && let Some(path) = path_expr.path() + && let Some(name_ref) = path.as_single_name_ref() + { + // shorthand `{ x }` → expand to `{ x: expr }` + let new_field = editor + .make() + .record_expr_field(editor.make().name_ref(&name_ref.text()), Some(expr)); + editor.replace(self.syntax(), new_field.syntax()); + } + } +} + #[test] fn test_increase_indent() { let arm_list = { @@ -285,3 +388,29 @@ fn test_increase_indent() { }" ); } + +#[test] +fn split_prefix_inserts_self() { + check_split_prefix("use foo;", "foo::{self}"); +} + +#[test] +fn split_prefix_preserves_rename() { + check_split_prefix("use foo as bar;", "foo::{self as bar}"); +} + +#[test] +fn split_prefix_wraps_glob() { + check_split_prefix("use foo::*;", "foo::{*}"); +} + +#[cfg(test)] +fn check_split_prefix(before: &str, expected: &str) { + let source = crate::SourceFile::parse(before, parser::Edition::CURRENT).tree(); + let use_tree = source.syntax().descendants().find_map(ast::UseTree::cast).unwrap(); + let (editor, use_tree) = SyntaxEditor::with_ast_node(&use_tree); + let prefix = use_tree.path().unwrap(); + use_tree.split_prefix_with_editor(&editor, &prefix); + let edit = editor.finish(); + assert_eq!(edit.new_root().to_string(), expected); +} diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs deleted file mode 100644 index 4a8c9d450c45c..0000000000000 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs +++ /dev/null @@ -1,318 +0,0 @@ -//! Structural editing for ast. - -use std::iter::{empty, once, successors}; - -use parser::T; - -use crate::{ - AstNode, AstToken, Direction, - algo::{self, neighbor}, - ast::{self, make, syntax_factory::SyntaxFactory}, - syntax_editor::SyntaxEditor, - ted, -}; - -use super::HasName; - -impl ast::GenericParamList { - /// Constructs a matching [`ast::GenericArgList`] - pub fn to_generic_args(&self, make: &SyntaxFactory) -> ast::GenericArgList { - let args = self.generic_params().filter_map(|param| match param { - ast::GenericParam::LifetimeParam(it) => { - Some(ast::GenericArg::LifetimeArg(make.lifetime_arg(it.lifetime()?))) - } - ast::GenericParam::TypeParam(it) => { - Some(ast::GenericArg::TypeArg(make.type_arg(make.ty_name(it.name()?)))) - } - ast::GenericParam::ConstParam(it) => { - // Name-only const params get parsed as `TypeArg`s - Some(ast::GenericArg::TypeArg(make.type_arg(make.ty_name(it.name()?)))) - } - }); - - make::generic_arg_list(args) - } -} - -pub trait Removable: AstNode { - fn remove(&self); -} - -impl Removable for ast::UseTree { - fn remove(&self) { - for dir in [Direction::Next, Direction::Prev] { - if let Some(next_use_tree) = neighbor(self, dir) { - let separators = self - .syntax() - .siblings_with_tokens(dir) - .skip(1) - .take_while(|it| it.as_node() != Some(next_use_tree.syntax())); - ted::remove_all_iter(separators); - break; - } - } - ted::remove(self.syntax()); - } -} - -impl ast::UseTree { - /// Editor variant of UseTree remove - fn remove_with_editor(&self, editor: &SyntaxEditor) { - for dir in [Direction::Next, Direction::Prev] { - if let Some(next_use_tree) = neighbor(self, dir) { - let separators = self - .syntax() - .siblings_with_tokens(dir) - .skip(1) - .take_while(|it| it.as_node() != Some(next_use_tree.syntax())); - for separator in separators { - editor.delete(separator); - } - break; - } - } - editor.delete(self.syntax()); - } - - /// Deletes the usetree node represented by the input. Recursively removes parents, including use nodes that become empty. - pub fn remove_recursive(self, editor: &SyntaxEditor) { - let parent = self.syntax().parent(); - - if let Some(u) = parent.clone().and_then(ast::Use::cast) { - u.remove(editor); - } else if let Some(u) = parent.and_then(ast::UseTreeList::cast) { - if u.use_trees().nth(1).is_none() - || u.use_trees().all(|use_tree| { - use_tree.syntax() == self.syntax() || editor.deleted(use_tree.syntax()) - }) - { - u.parent_use_tree().remove_recursive(editor); - return; - } - self.remove_with_editor(editor); - u.remove_unnecessary_braces(editor); - } - } - - pub fn get_or_create_use_tree_list(&self) -> ast::UseTreeList { - match self.use_tree_list() { - Some(it) => it, - None => { - let position = ted::Position::last_child_of(self.syntax()); - let use_tree_list = make::use_tree_list(empty()).clone_for_update(); - let mut elements = Vec::with_capacity(2); - if self.coloncolon_token().is_none() { - elements.push(make::token(T![::]).into()); - } - elements.push(use_tree_list.syntax().clone().into()); - ted::insert_all_raw(position, elements); - use_tree_list - } - } - } - - /// Splits off the given prefix, making it the path component of the use tree, - /// appending the rest of the path to all UseTreeList items. - /// - /// # Examples - /// - /// `prefix$0::suffix` -> `prefix::{suffix}` - /// - /// `prefix$0` -> `prefix::{self}` - /// - /// `prefix$0::*` -> `prefix::{*}` - pub fn split_prefix(&self, prefix: &ast::Path) { - debug_assert_eq!(self.path(), Some(prefix.top_path())); - let path = self.path().unwrap(); - if &path == prefix && self.use_tree_list().is_none() { - if self.star_token().is_some() { - // path$0::* -> * - if let Some(a) = self.coloncolon_token() { - ted::remove(a) - } - ted::remove(prefix.syntax()); - } else { - // path$0 -> self - let self_suffix = - make::path_unqualified(make::path_segment_self()).clone_for_update(); - ted::replace(path.syntax(), self_suffix.syntax()); - } - } else if split_path_prefix(prefix).is_none() { - return; - } - // At this point, prefix path is detached; _self_ use tree has suffix path. - // Next, transform 'suffix' use tree into 'prefix::{suffix}' - let subtree = self.clone_subtree().clone_for_update(); - ted::remove_all_iter(self.syntax().children_with_tokens()); - ted::insert(ted::Position::first_child_of(self.syntax()), prefix.syntax()); - self.get_or_create_use_tree_list().add_use_tree(subtree); - - fn split_path_prefix(prefix: &ast::Path) -> Option<()> { - let parent = prefix.parent_path()?; - let segment = parent.segment()?; - if algo::has_errors(segment.syntax()) { - return None; - } - for p in successors(parent.parent_path(), |it| it.parent_path()) { - p.segment()?; - } - if let Some(a) = prefix.parent_path().and_then(|p| p.coloncolon_token()) { - ted::remove(a) - } - ted::remove(prefix.syntax()); - Some(()) - } - } - - /// Editor variant of `split_prefix` - pub fn split_prefix_with_editor(&self, editor: &SyntaxEditor, prefix: &ast::Path) { - debug_assert_eq!(self.path(), Some(prefix.top_path())); - - let make = editor.make(); - let path = self.path().unwrap(); - let suffix = if path == *prefix && self.use_tree_list().is_none() { - if self.star_token().is_some() { - make.use_tree_glob() - } else { - let self_path = make.path_unqualified(make.path_segment_self()); - make.use_tree(self_path, None, None, false) - } - } else { - let suffix_segments = path.segments().skip(prefix.segments().count()); - let suffix_path = make.path_from_segments(suffix_segments, false); - make.use_tree( - suffix_path, - self.use_tree_list(), - self.rename(), - self.star_token().is_some(), - ) - }; - let use_tree_list = make.use_tree_list(once(suffix)); - let new_use_tree = make.use_tree(prefix.clone(), Some(use_tree_list), None, false); - - editor.replace(self.syntax(), new_use_tree.syntax()); - } - - /// Wraps the use tree in use tree list with no top level path (if it isn't already). - /// - /// # Examples - /// - /// `foo::bar` -> `{foo::bar}` - /// - /// `{foo::bar}` -> `{foo::bar}` - pub fn wrap_in_tree_list(&self) -> Option<()> { - if self.use_tree_list().is_some() - && self.path().is_none() - && self.star_token().is_none() - && self.rename().is_none() - { - return None; - } - let subtree = self.clone_subtree().clone_for_update(); - ted::remove_all_iter(self.syntax().children_with_tokens()); - ted::append_child( - self.syntax(), - make::use_tree_list(once(subtree)).clone_for_update().syntax(), - ); - Some(()) - } -} - -impl ast::UseTreeList { - pub fn add_use_tree(&self, use_tree: ast::UseTree) { - let (position, elements) = match self.use_trees().last() { - Some(last_tree) => ( - ted::Position::after(last_tree.syntax()), - vec![ - make::token(T![,]).into(), - make::tokens::single_space().into(), - use_tree.syntax.into(), - ], - ), - None => { - let position = match self.l_curly_token() { - Some(l_curly) => ted::Position::after(l_curly), - None => ted::Position::last_child_of(self.syntax()), - }; - (position, vec![use_tree.syntax.into()]) - } - }; - ted::insert_all_raw(position, elements); - } -} - -impl ast::Use { - fn remove(&self, editor: &SyntaxEditor) { - let make = editor.make(); - let next_ws = self - .syntax() - .next_sibling_or_token() - .and_then(|it| it.into_token()) - .and_then(ast::Whitespace::cast); - if let Some(next_ws) = next_ws { - let ws_text = next_ws.syntax().text(); - if let Some(rest) = ws_text.strip_prefix('\n') { - let next_use_removed = next_ws - .syntax() - .next_sibling_or_token() - .and_then(|it| it.into_node()) - .and_then(ast::Use::cast) - .and_then(|use_| use_.use_tree()) - .is_some_and(|use_tree| editor.deleted(use_tree.syntax())); - if rest.is_empty() || next_use_removed { - editor.delete(next_ws.syntax()); - } else { - editor.replace(next_ws.syntax(), make.whitespace(rest)); - } - } - } - let prev_ws = self - .syntax() - .prev_sibling_or_token() - .and_then(|it| it.into_token()) - .and_then(ast::Whitespace::cast); - if let Some(prev_ws) = prev_ws { - let ws_text = prev_ws.syntax().text(); - let prev_newline = ws_text.rfind('\n').map(|x| x + 1).unwrap_or(0); - let rest = &ws_text[0..prev_newline]; - if rest.is_empty() { - editor.delete(prev_ws.syntax()); - } else { - editor.replace(prev_ws.syntax(), make.whitespace(rest)); - } - } - - editor.delete(self.syntax()); - } -} - -impl ast::Impl { - pub fn get_or_create_assoc_item_list(&self) -> ast::AssocItemList { - if self.assoc_item_list().is_none() { - let assoc_item_list = make::assoc_item_list(None).clone_for_update(); - ted::append_child(self.syntax(), assoc_item_list.syntax()); - } - self.assoc_item_list().unwrap() - } -} - -impl ast::RecordExprField { - /// This will either replace the initializer, or in the case that this is a shorthand convert - /// the initializer into the name ref and insert the expr as the new initializer. - pub fn replace_expr(&self, editor: &SyntaxEditor, expr: ast::Expr) { - if self.name_ref().is_some() { - if let Some(prev) = self.expr() { - editor.replace(prev.syntax(), expr.syntax()); - } - } else if let Some(ast::Expr::PathExpr(path_expr)) = self.expr() - && let Some(path) = path_expr.path() - && let Some(name_ref) = path.as_single_name_ref() - { - // shorthand `{ x }` → expand to `{ x: expr }` - let new_field = editor - .make() - .record_expr_field(editor.make().name_ref(&name_ref.text()), Some(expr)); - editor.replace(self.syntax(), new_field.syntax()); - } - } -} diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs index 8411275350542..2a50d233c3bfb 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs @@ -264,6 +264,14 @@ impl Expr { return false; } + // Special-case `cond && ` + if let ast::Expr::BinExpr(parent) = parent + && parent.op_kind() == Some(ast::BinaryOp::LogicOp(ast::LogicOp::And)) + && self.contains_let_expr() + { + return false; + } + let (left, right, inv) = match self.is_ordered_before_parent_in_place_of(parent, place_of) { true => (self, parent, false), false => (parent, self, true), @@ -551,4 +559,19 @@ impl Expr { ForExpr(_) | IfExpr(_) | MatchExpr(_) | WhileExpr(_) | IncludeBytesExpr(_) => true, } } + + fn contains_let_expr(&self) -> bool { + use Expr::*; + + match self { + LetExpr(_) => true, + BinExpr(e) => { + // if we find something other than a `&&`, then this can't be a let chain + e.op_kind() == Some(ast::BinaryOp::LogicOp(ast::LogicOp::And)) + && (e.lhs().is_none_or(|it| it.contains_let_expr()) + || e.rhs().is_none_or(|it| it.contains_let_expr())) + } + _ => false, + } + } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs index 2f7eab2423ce5..7f9cd1fce94eb 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -4,8 +4,8 @@ use either::Either; use crate::{ AstNode, Edition, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, ast::{ - self, HasArgList, HasAttrs, HasGenericArgs, HasGenericParams, HasLoopBody, HasName, - HasTypeBounds, HasVisibility, Lifetime, Param, RangeItem, make, + self, HasArgList, HasAttrs, HasGenericArgs, HasGenericParams, HasLoopBody, HasModuleItem, + HasName, HasTypeBounds, HasVisibility, Lifetime, Param, RangeItem, make, }, syntax_editor::SyntaxMappingBuilder, }; @@ -2015,6 +2015,35 @@ impl SyntaxFactory { make::assoc_item_list(None).clone_for_update() } + pub fn item_list(&self, items: impl IntoIterator) -> ast::ItemList { + let (items, input) = iterator_input(items); + let items_vec: Vec<_> = items.into_iter().collect(); + let ast = make::item_list(Some(items_vec)).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_children(input, ast.items().map(|item: ast::Item| item.syntax().clone())); + builder.finish(&mut mapping); + } + + ast + } + + pub fn mod_(&self, name: ast::Name, body: Option) -> ast::Module { + let ast = make::mod_(name.clone(), body.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(name.syntax().clone(), ast.name().unwrap().syntax().clone()); + if let Some(body) = body { + builder.map_node(body.syntax().clone(), ast.item_list().unwrap().syntax().clone()); + } + builder.finish(&mut mapping); + } + + ast + } + pub fn attr_outer(&self, meta: ast::Meta) -> ast::Attr { let ast = make::attr_outer(meta.clone()).clone_for_update(); diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs index cda3e69b7c625..924e72ee40397 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -39,7 +39,6 @@ pub mod ast; pub mod fuzz; pub mod hacks; pub mod syntax_editor; -pub mod ted; pub mod utils; use std::{marker::PhantomData, ops::Range}; diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs index f2b979eb9d1ae..9fab8716b412f 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs @@ -459,13 +459,35 @@ impl Removable for ast::Use { if let Some(next_ws) = next_ws { let ws_text = next_ws.syntax().text(); if let Some(rest) = ws_text.strip_prefix('\n') { - if rest.is_empty() { + let next_use_removed = next_ws + .syntax() + .next_sibling_or_token() + .and_then(|it| it.into_node()) + .and_then(ast::Use::cast) + .and_then(|use_| use_.use_tree()) + .is_some_and(|use_tree| editor.deleted(use_tree.syntax())); + if rest.is_empty() || next_use_removed { editor.delete(next_ws.syntax()); } else { editor.replace(next_ws.syntax(), make.whitespace(rest)); } } } + let prev_ws = self + .syntax() + .prev_sibling_or_token() + .and_then(|it| it.into_token()) + .and_then(ast::Whitespace::cast); + if let Some(prev_ws) = prev_ws { + let ws_text = prev_ws.syntax().text(); + let prev_newline = ws_text.rfind('\n').map(|x| x + 1).unwrap_or(0); + let rest = &ws_text[0..prev_newline]; + if rest.is_empty() { + editor.delete(prev_ws.syntax()); + } else { + editor.replace(prev_ws.syntax(), make.whitespace(rest)); + } + } editor.delete(self.syntax()); } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ted.rs b/src/tools/rust-analyzer/crates/syntax/src/ted.rs deleted file mode 100644 index 5c286479c4e3d..0000000000000 --- a/src/tools/rust-analyzer/crates/syntax/src/ted.rs +++ /dev/null @@ -1,227 +0,0 @@ -//! Primitive tree editor, ed for trees. -//! -//! The `_raw`-suffixed functions insert elements as is, unsuffixed versions fix -//! up elements around the edges. -use std::{mem, ops::RangeInclusive}; - -use parser::T; -use rowan::TextSize; - -use crate::{ - SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, - ast::{self, AstNode, edit::IndentLevel, make}, -}; - -/// Utility trait to allow calling `ted` functions with references or owned -/// nodes. Do not use outside of this module. -pub trait Element { - fn syntax_element(self) -> SyntaxElement; -} - -impl Element for &'_ E { - fn syntax_element(self) -> SyntaxElement { - self.clone().syntax_element() - } -} -impl Element for SyntaxElement { - fn syntax_element(self) -> SyntaxElement { - self - } -} -impl Element for SyntaxNode { - fn syntax_element(self) -> SyntaxElement { - self.into() - } -} -impl Element for SyntaxToken { - fn syntax_element(self) -> SyntaxElement { - self.into() - } -} - -#[derive(Debug)] -pub struct Position { - repr: PositionRepr, -} - -#[derive(Debug)] -enum PositionRepr { - FirstChild(SyntaxNode), - After(SyntaxElement), -} - -impl Position { - pub fn after(elem: impl Element) -> Position { - let repr = PositionRepr::After(elem.syntax_element()); - Position { repr } - } - pub fn before(elem: impl Element) -> Position { - let elem = elem.syntax_element(); - let repr = match elem.prev_sibling_or_token() { - Some(it) => PositionRepr::After(it), - None => PositionRepr::FirstChild(elem.parent().unwrap()), - }; - Position { repr } - } - pub fn first_child_of(node: &(impl Into + Clone)) -> Position { - let repr = PositionRepr::FirstChild(node.clone().into()); - Position { repr } - } - pub fn last_child_of(node: &(impl Into + Clone)) -> Position { - let node = node.clone().into(); - let repr = match node.last_child_or_token() { - Some(it) => PositionRepr::After(it), - None => PositionRepr::FirstChild(node), - }; - Position { repr } - } - pub fn offset(&self) -> TextSize { - match &self.repr { - PositionRepr::FirstChild(node) => node.text_range().start(), - PositionRepr::After(elem) => elem.text_range().end(), - } - } -} - -pub fn insert(position: Position, elem: impl Element) { - insert_all(position, vec![elem.syntax_element()]); -} -pub fn insert_raw(position: Position, elem: impl Element) { - insert_all_raw(position, vec![elem.syntax_element()]); -} -pub fn insert_all(position: Position, mut elements: Vec) { - if let Some(first) = elements.first() - && let Some(ws) = ws_before(&position, first) - { - elements.insert(0, ws.into()); - } - if let Some(last) = elements.last() - && let Some(ws) = ws_after(&position, last) - { - elements.push(ws.into()); - } - insert_all_raw(position, elements); -} -pub fn insert_all_raw(position: Position, elements: Vec) { - let (parent, index) = match position.repr { - PositionRepr::FirstChild(parent) => (parent, 0), - PositionRepr::After(child) => (child.parent().unwrap(), child.index() + 1), - }; - parent.splice_children(index..index, elements); -} - -pub fn remove(elem: impl Element) { - elem.syntax_element().detach(); -} -pub fn remove_all(range: RangeInclusive) { - replace_all(range, Vec::new()); -} -pub fn remove_all_iter(range: impl IntoIterator) { - let mut it = range.into_iter(); - if let Some(mut first) = it.next() { - match it.last() { - Some(mut last) => { - if first.index() > last.index() { - mem::swap(&mut first, &mut last); - } - remove_all(first..=last); - } - None => remove(first), - } - } -} - -pub fn replace(old: impl Element, new: impl Element) { - replace_with_many(old, vec![new.syntax_element()]); -} -pub fn replace_with_many(old: impl Element, new: Vec) { - let old = old.syntax_element(); - replace_all(old.clone()..=old, new); -} -pub fn replace_all(range: RangeInclusive, new: Vec) { - let start = range.start().index(); - let end = range.end().index(); - let parent = range.start().parent().unwrap(); - parent.splice_children(start..end + 1, new); -} - -pub fn append_child(node: &(impl Into + Clone), child: impl Element) { - let position = Position::last_child_of(node); - insert(position, child); -} -pub fn append_child_raw(node: &(impl Into + Clone), child: impl Element) { - let position = Position::last_child_of(node); - insert_raw(position, child); -} - -pub fn prepend_child(node: &(impl Into + Clone), child: impl Element) { - let position = Position::first_child_of(node); - insert(position, child); -} - -fn ws_before(position: &Position, new: &SyntaxElement) -> Option { - let prev = match &position.repr { - PositionRepr::FirstChild(_) => return None, - PositionRepr::After(it) => it, - }; - - if prev.kind() == T!['{'] - && new.kind() == SyntaxKind::USE - && let Some(item_list) = prev.parent().and_then(ast::ItemList::cast) - { - let mut indent = IndentLevel::from_element(&item_list.syntax().clone().into()); - indent.0 += 1; - return Some(make::tokens::whitespace(&format!("\n{indent}"))); - } - - if prev.kind() == T!['{'] - && ast::Stmt::can_cast(new.kind()) - && let Some(stmt_list) = prev.parent().and_then(ast::StmtList::cast) - { - let mut indent = IndentLevel::from_element(&stmt_list.syntax().clone().into()); - indent.0 += 1; - return Some(make::tokens::whitespace(&format!("\n{indent}"))); - } - - ws_between(prev, new) -} -fn ws_after(position: &Position, new: &SyntaxElement) -> Option { - let next = match &position.repr { - PositionRepr::FirstChild(parent) => parent.first_child_or_token()?, - PositionRepr::After(sibling) => sibling.next_sibling_or_token()?, - }; - ws_between(new, &next) -} -fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option { - if left.kind() == SyntaxKind::WHITESPACE || right.kind() == SyntaxKind::WHITESPACE { - return None; - } - if right.kind() == T![;] || right.kind() == T![,] { - return None; - } - if left.kind() == T![<] || right.kind() == T![>] { - return None; - } - if left.kind() == T![&] && right.kind() == SyntaxKind::LIFETIME { - return None; - } - if right.kind() == SyntaxKind::GENERIC_ARG_LIST { - return None; - } - - if right.kind() == SyntaxKind::USE { - let mut indent = IndentLevel::from_element(left); - if left.kind() == SyntaxKind::USE { - indent.0 = IndentLevel::from_element(right).0.max(indent.0); - } - return Some(make::tokens::whitespace(&format!("\n{indent}"))); - } - if left.kind() == SyntaxKind::ATTR { - let mut indent = IndentLevel::from_element(right); - if right.kind() == SyntaxKind::ATTR { - indent.0 = IndentLevel::from_element(left).0.max(indent.0); - } - return Some(make::tokens::whitespace(&format!("\n{indent}"))); - } - Some(make::tokens::single_space()) -} diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml index f561c1c0e2b0e..d0d5840e785a0 100644 --- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml +++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml @@ -13,7 +13,6 @@ rust-version.workspace = true doctest = false [dependencies] -home = "0.5.11" camino.workspace = true [lints] diff --git a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs index 39319886cfe4a..ea08f7aacac4e 100644 --- a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs +++ b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs @@ -119,7 +119,7 @@ fn get_cargo_home() -> Option { return Utf8PathBuf::try_from(PathBuf::from(path)).ok(); } - if let Some(mut path) = home::home_dir() { + if let Some(mut path) = env::home_dir() { path.push(".cargo"); return Utf8PathBuf::try_from(path).ok(); } diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md index 7bbb9e0258169..76b626b09fb5b 100644 --- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md +++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md @@ -446,9 +446,12 @@ verbose form `{ "path": "path::to::item", type: "always" }`. For traits the type "methods" can be used to only exclude the methods but not the trait itself. -For modules the type "subItems" can be used to only exclude the all items in it but not the module +For modules the type "sub_items" can be used to only exclude the all items in it but not the module itself. This does not include items defined in nested modules. +For enums the type "variants" can be used to only exclude the all variants in it but not the enum +itself. + This setting also inherits `#rust-analyzer.completion.excludeTraits#`. diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/README.md b/src/tools/rust-analyzer/docs/book/src/contributing/README.md index bb2b6081ad956..d3e2acd9f7307 100644 --- a/src/tools/rust-analyzer/docs/book/src/contributing/README.md +++ b/src/tools/rust-analyzer/docs/book/src/contributing/README.md @@ -206,13 +206,6 @@ To measure time for from-scratch analysis, use something like this: cargo run --release -p rust-analyzer -- analysis-stats ../chalk/ ``` -For measuring time of incremental analysis, use either of these: - -```bash -cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --highlight ../chalk/chalk-engine/src/logic.rs -cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0 -``` - Look for `fn benchmark_xxx` tests for a quick way to reproduce performance problems. ## Release Process diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 53c5a295ceede..13d32283d2290 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -214,6 +214,11 @@ "title": "Reload workspace", "category": "rust-analyzer" }, + { + "command": "rust-analyzer.newProject", + "title": "Create New Project...", + "category": "rust-analyzer" + }, { "command": "rust-analyzer.rebuildProcMacros", "title": "Rebuild proc macros and build scripts", @@ -491,6 +496,23 @@ "markdownDescription": "Do not start rust-analyzer server when the extension is activated.", "default": false, "type": "boolean" + }, + "rust-analyzer.projectCreation.openAfterCreate": { + "markdownDescription": "Control what happens after `rust-analyzer: Create New Project...` finishes creating a Cargo project.", + "default": "ask", + "enum": [ + "ask", + "open", + "openNewWindow", + "addToWorkspace" + ], + "enumDescriptions": [ + "Prompt for how to open the new project.", + "Open the new project in the current window.", + "Open the new project in a new window.", + "Add the new project to the current workspace, or open it if no workspace is open." + ], + "type": "string" } } }, @@ -1333,7 +1355,7 @@ "title": "Completion", "properties": { "rust-analyzer.completion.autoimport.exclude": { - "markdownDescription": "A list of full paths to items to exclude from auto-importing completions.\n\nTraits in this list won't have their methods suggested in completions unless the trait\nis in scope.\n\nYou can either specify a string path which defaults to type \"always\" or use the more\nverbose form `{ \"path\": \"path::to::item\", type: \"always\" }`.\n\nFor traits the type \"methods\" can be used to only exclude the methods but not the trait\nitself.\n\nFor modules the type \"subItems\" can be used to only exclude the all items in it but not the module\nitself. This does not include items defined in nested modules.\n\nThis setting also inherits `#rust-analyzer.completion.excludeTraits#`.", + "markdownDescription": "A list of full paths to items to exclude from auto-importing completions.\n\nTraits in this list won't have their methods suggested in completions unless the trait\nis in scope.\n\nYou can either specify a string path which defaults to type \"always\" or use the more\nverbose form `{ \"path\": \"path::to::item\", type: \"always\" }`.\n\nFor traits the type \"methods\" can be used to only exclude the methods but not the trait\nitself.\n\nFor modules the type \"sub_items\" can be used to only exclude the all items in it but not the module\nitself. This does not include items defined in nested modules.\n\nFor enums the type \"variants\" can be used to only exclude the all variants in it but not the enum\nitself.\n\nThis setting also inherits `#rust-analyzer.completion.excludeTraits#`.", "default": [ { "path": "core::borrow::Borrow", @@ -1361,7 +1383,8 @@ "enum": [ "always", "methods", - "subItems" + "sub_items", + "variants" ], "enumDescriptions": [ "Do not show this item or its methods (if it is a trait) in auto-import completions.", @@ -3811,6 +3834,9 @@ "command": "rust-analyzer.memoryUsage", "when": "inRustProject" }, + { + "command": "rust-analyzer.newProject" + }, { "command": "rust-analyzer.reloadWorkspace", "when": "inRustProject" @@ -3930,6 +3956,13 @@ } ] }, + "viewsWelcome": [ + { + "view": "explorer", + "contents": "Create a new Rust project.\n[Create Rust Project](command:rust-analyzer.newProject)", + "when": "workspaceFolderCount == 0" + } + ], "viewsContainers": { "activitybar": [ { @@ -3955,6 +3988,14 @@ "title": "Learn about rust-analyzer", "description": "A brief introduction to get started with rust-analyzer. Learn about key features and resources to help you get the most out of the extension.", "steps": [ + { + "id": "create-project", + "title": "Create a Rust project", + "description": "Start a new Cargo binary or library project from VS Code.\n\n[Create a Rust Project](command:rust-analyzer.newProject)", + "media": { + "markdown": "./walkthrough-create-project.md" + } + }, { "id": "setup", "title": "Useful Setup Tips", diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts index 9c8b7071b3094..5514319c698cc 100644 --- a/src/tools/rust-analyzer/editors/code/src/commands.ts +++ b/src/tools/rust-analyzer/editors/code/src/commands.ts @@ -33,6 +33,7 @@ import { log } from "./util"; import type { SyntaxElement } from "./syntax_tree_provider"; export * from "./run"; +export { newProject } from "./new_project"; export function analyzerStatus(ctx: CtxInit): Cmd { const tdcp = new (class implements vscode.TextDocumentContentProvider { diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index d65f011c754be..0f783c71b9541 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -447,6 +447,10 @@ export class Config { return this.get("initializeStopped"); } + get projectCreationOpenAfterCreate() { + return this.get("projectCreation.openAfterCreate"); + } + get askBeforeUpdateTest() { return this.get("runnables.askBeforeUpdateTest"); } diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts index 6567bcd2f170c..7136314e7ca2c 100644 --- a/src/tools/rust-analyzer/editors/code/src/main.ts +++ b/src/tools/rust-analyzer/editors/code/src/main.ts @@ -161,6 +161,12 @@ function createCommands(): Record { memoryUsage: { enabled: commands.memoryUsage }, reloadWorkspace: { enabled: commands.reloadWorkspace }, rebuildProcMacros: { enabled: commands.rebuildProcMacros }, + newProject: { + // Project creation is a pure VS Code-side workflow and should stay available even in + // empty windows before rust-analyzer has started or a Rust workspace exists. + enabled: commands.newProject, + disabled: commands.newProject, + }, matchingBrace: { enabled: commands.matchingBrace }, joinLines: { enabled: commands.joinLines }, parentModule: { enabled: commands.parentModule }, diff --git a/src/tools/rust-analyzer/editors/code/src/new_project.ts b/src/tools/rust-analyzer/editors/code/src/new_project.ts new file mode 100644 index 0000000000000..f5f6d86da04df --- /dev/null +++ b/src/tools/rust-analyzer/editors/code/src/new_project.ts @@ -0,0 +1,311 @@ +import * as vscode from "vscode"; + +import type { Ctx, Cmd } from "./ctx"; +import * as ra from "./lsp_ext"; +import { cargoPath } from "./toolchain"; +import { log, spawnAsync } from "./util"; + +type NewProjectKind = "bin" | "lib"; +type NewProjectOpenAction = "open" | "openNewWindow" | "addToWorkspace"; + +type NewProjectTemplate = { + detail: string; + id: NewProjectKind; + label: string; +}; + +type NewProjectCargo = { + cargo: string; + cargoEnv: NodeJS.ProcessEnv; +}; + +const NEW_PROJECT_TEMPLATES: readonly NewProjectTemplate[] = [ + { + id: "bin", + label: "Binary Application", + detail: "Create a Cargo binary package (`cargo new --bin`)", + }, + { + id: "lib", + label: "Library", + detail: "Create a Cargo library package (`cargo new --lib`)", + }, +] as const; + +export function newProject(ctx: Ctx): Cmd { + return async () => { + const cargo = await resolveNewProjectCargo(ctx); + + const selectedKind = await promptForNewProjectTemplate(); + if (!selectedKind) { + return; + } + + const parentFolder = await promptForNewProjectParentFolder(); + if (!parentFolder) { + return; + } + + const projectName = await promptForNewProjectName(parentFolder); + if (!projectName) { + return; + } + + if (!(await createNewProject(cargo, parentFolder, selectedKind, projectName))) { + return; + } + + const projectUri = vscode.Uri.joinPath(parentFolder, projectName); + const defaultAction = determineNewProjectOpenAction( + ctx.config.projectCreationOpenAfterCreate, + Boolean(vscode.workspace.workspaceFolders?.length), + ); + const action = + defaultAction === "ask" + ? await promptForNewProjectOpenAction( + projectName, + Boolean(vscode.workspace.workspaceFolders?.length), + ) + : defaultAction; + + if (action) { + await executeNewProjectOpenAction(ctx, action, projectUri); + } + }; +} + +async function resolveNewProjectCargo(ctx: Ctx): Promise { + // Use the same effective environment rust-analyzer uses elsewhere so project creation sees + // toolchain wrappers, PATH overrides, and CARGO_HOME changes from configuration. + const cargoEnv = { ...process.env, ...ctx.config.serverExtraEnv }; + return { cargo: await cargoPath(cargoEnv), cargoEnv }; +} + +async function promptForNewProjectTemplate(): Promise { + const selected = await vscode.window.showQuickPick(NEW_PROJECT_TEMPLATES, { + placeHolder: "Select a Rust project kind", + }); + return selected?.id; +} + +async function promptForNewProjectParentFolder(): Promise { + const selectedFolder = await vscode.window.showOpenDialog({ + title: "Select the parent folder for the new Rust project", + openLabel: "Select parent folder", + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + }); + if (!selectedFolder?.length) { + return undefined; + } + return selectedFolder[0]; +} + +const CARGO_MANIFEST_NAME_PATTERN = /^[\p{Alphabetic}\p{Number}_-]+$/u; + +// Keep local validation focused on stable checks that can be reported in the input box, then let +// `cargo new` remain the source of truth for package-name-specific identifier and keyword rules. +export function validateNewProjectName( + value: string, + existingNames: readonly string[], +): string | undefined { + const trimmedValue = value.trim(); + if (trimmedValue.length === 0) { + return "Project name cannot be empty."; + } + if (trimmedValue.includes("/") || trimmedValue.includes("\\")) { + return "Project name cannot contain '/' or '\\' characters."; + } + if (trimmedValue === "." || trimmedValue === "..") { + return "Project name cannot be '.' or '..'."; + } + if (!CARGO_MANIFEST_NAME_PATTERN.test(trimmedValue)) { + return "Project name can contain only alphanumeric characters, '-' or '_'."; + } + if (existingNames.includes(trimmedValue)) { + return "A file or folder with this name already exists."; + } + return undefined; +} + +async function promptForNewProjectName(parentFolder: vscode.Uri): Promise { + let existingNames: string[] = []; + try { + const entries = await vscode.workspace.fs.readDirectory(parentFolder); + existingNames = entries.map(([name]) => name); + } catch (error) { + log.error("Failed to read project parent folder", error); + void vscode.window.showErrorMessage("Failed to read the selected parent folder."); + return undefined; + } + + const projectName = await vscode.window.showInputBox({ + prompt: `Enter the new project name to create inside ${parentFolder.fsPath}`, + validateInput: async (value) => validateNewProjectName(value, existingNames), + }); + return projectName?.trim(); +} + +export function cargoNewArgs(kind: NewProjectKind, name: string): string[] { + return ["new", kind === "bin" ? "--bin" : "--lib", name]; +} + +async function createNewProject( + cargo: NewProjectCargo, + parentFolder: vscode.Uri, + kind: NewProjectKind, + projectName: string, +): Promise { + const args = cargoNewArgs(kind, projectName); + const createResult = await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: `Creating Rust project ${projectName}`, + }, + async () => + spawnAsync(cargo.cargo, args, { + cwd: parentFolder.fsPath, + env: cargo.cargoEnv, + }), + ); + + if (createResult.error || createResult.status !== 0) { + const details = formatProcessDetails(createResult); + await showNewProjectError("Failed to create Rust project.", details || undefined, { + cargo: cargo.cargo, + args, + cwd: parentFolder.fsPath, + error: createResult.error?.message, + status: createResult.status, + stderr: createResult.stderr || undefined, + stdout: createResult.stdout || undefined, + }); + return false; + } + + return true; +} + +function formatProcessDetails(result: { error?: Error; stderr: string; stdout: string }): string { + return [result.stderr, result.stdout, result.error?.message] + .filter((value): value is string => Boolean(value && value.trim().length > 0)) + .join("\n") + .trim(); +} + +async function showNewProjectError( + message: string, + details: string | undefined, + logContext: { + cargo: string; + args: string[]; + cwd?: string; + error?: string; + status: number | null; + stderr?: string; + stdout?: string; + }, +): Promise { + // Keep command-failure logging focused on the invocation and process output. Environment + // variables may contain secrets such as API keys, tokens, and credentials, so failure logs + // must not dump the merged env here. + const commandLine = [logContext.cargo, ...logContext.args].join(" "); + log.error(message); + log.error(`command: ${commandLine}`); + if (logContext.cwd) { + log.error(`cwd: ${logContext.cwd}`); + } + log.error(`exit status: ${String(logContext.status)}`); + if (logContext.error) { + log.error(`error: ${logContext.error}`); + } + if (logContext.stderr) { + log.error(`stderr:\n${logContext.stderr}`); + } + if (logContext.stdout) { + log.error(`stdout:\n${logContext.stdout}`); + } + const selection = await vscode.window.showErrorMessage( + details ? `${message}\n${details}` : message, + "Open Extension Logs", + ); + if (selection === "Open Extension Logs") { + log.show(); + } +} + +export function determineNewProjectOpenAction( + configuredAction: string | undefined, + hasWorkspaceFolders: boolean, +): "ask" | NewProjectOpenAction { + switch (configuredAction) { + case "open": + case "openNewWindow": + return configuredAction; + case "addToWorkspace": + // Adding to a workspace only makes sense when one is already open. Falling back to + // "open" keeps the setting usable in empty windows without adding another prompt path. + return hasWorkspaceFolders ? configuredAction : "open"; + default: + return "ask"; + } +} + +async function promptForNewProjectOpenAction( + projectName: string, + hasWorkspaceFolders: boolean, +): Promise { + let message = `Would you like to open ${projectName}?`; + const open = "Open"; + const openNewWindow = "Open in New Window"; + const choices = [open, openNewWindow]; + + const addToWorkspace = "Add to VS Code Workspace"; + if (hasWorkspaceFolders) { + message = `Would you like to open ${projectName}, or add it to the current VS Code workspace?`; + choices.push(addToWorkspace); + } + + const result = await vscode.window.showInformationMessage( + message, + { modal: true, detail: "The default action can be configured in settings." }, + ...choices, + ); + + const actionMap: Record = { + [open]: "open", + [openNewWindow]: "openNewWindow", + [addToWorkspace]: "addToWorkspace", + }; + return result ? actionMap[result] : undefined; +} + +async function executeNewProjectOpenAction( + ctx: Ctx, + action: NewProjectOpenAction, + projectUri: vscode.Uri, +): Promise { + if (action === "open") { + await vscode.commands.executeCommand("vscode.openFolder", projectUri, { + forceReuseWindow: true, + }); + return; + } + + if (action === "openNewWindow") { + await vscode.commands.executeCommand("vscode.openFolder", projectUri, { + forceNewWindow: true, + }); + return; + } + + const index = vscode.workspace.workspaceFolders?.length ?? 0; + vscode.workspace.updateWorkspaceFolders(index, 0, { uri: projectUri }); + // Reuse the existing workspace window when requested, but nudge rust-analyzer afterwards so + // the newly added Cargo project is discovered immediately instead of waiting for a later + // background refresh. + if (ctx.client?.isRunning()) { + await ctx.client.sendRequest(ra.reloadWorkspace); + } +} diff --git a/src/tools/rust-analyzer/editors/code/src/toolchain.ts b/src/tools/rust-analyzer/editors/code/src/toolchain.ts index 76946d1510162..6ae365c71c7ac 100644 --- a/src/tools/rust-analyzer/editors/code/src/toolchain.ts +++ b/src/tools/rust-analyzer/editors/code/src/toolchain.ts @@ -3,7 +3,7 @@ import * as os from "os"; import * as path from "path"; import * as readline from "readline"; import * as vscode from "vscode"; -import { Env, log, memoizeAsync, unwrapUndefinable } from "./util"; +import { Env, isWindows, log, memoizeAsync, unwrapUndefinable } from "./util"; import type { CargoRunnableArgs } from "./lsp_ext"; interface CompilationArtifact { @@ -160,9 +160,46 @@ export function cargoPath(env?: Env): Promise { if (env?.["RUSTC_TOOLCHAIN"]) { return Promise.resolve("cargo"); } + if (env) { + return getPathForExecutableWithEnv("cargo", env); + } return getPathForExecutable("cargo"); } +/** + * Resolves an executable using an explicitly supplied environment instead of the VS Code host + * process environment. + * + * Some extension call sites already construct the exact env they will use for spawning, so path + * resolution needs to honor that same `PATH`/`CARGO_HOME` view to avoid launching a different + * toolchain than the one that was resolved. + */ +async function getPathForExecutableWithEnv( + executableName: "cargo" | "rustc" | "rustup", + env: Env, +): Promise { + const envVar = getEnvVar(env, executableName.toUpperCase()); + if (envVar) { + return envVar; + } + + if (await lookupInPath(executableName, getEnvVar(env, "PATH") ?? "")) { + return executableName; + } + + const cargoHome = getCargoHomeFromPath(getEnvVar(env, "CARGO_HOME")); + if (cargoHome) { + for (const candidate of executableCandidates(executableName)) { + const standardPath = vscode.Uri.joinPath(cargoHome, "bin", candidate); + if (await isFileAtUri(standardPath)) { + return standardPath.fsPath; + } + } + } + + return executableName; +} + /** Mirrors `toolchain::get_path_for_executable()` implementation */ const getPathForExecutable = memoizeAsync( // We apply caching to decrease file-system interactions @@ -172,23 +209,22 @@ const getPathForExecutable = memoizeAsync( if (envVar) return envVar; } - if (await lookupInPath(executableName)) return executableName; + if (await lookupInPath(executableName, process.env["PATH"] ?? "")) return executableName; const cargoHome = getCargoHome(); if (cargoHome) { - const standardPath = vscode.Uri.joinPath(cargoHome, "bin", executableName); - if (await isFileAtUri(standardPath)) return standardPath.fsPath; + for (const candidate of executableCandidates(executableName)) { + const standardPath = vscode.Uri.joinPath(cargoHome, "bin", candidate); + if (await isFileAtUri(standardPath)) return standardPath.fsPath; + } } return executableName; }, ); -async function lookupInPath(exec: string): Promise { - const paths = process.env["PATH"] ?? ""; - +async function lookupInPath(exec: string, paths: string): Promise { const candidates = paths.split(path.delimiter).flatMap((dirInPath) => { - const candidate = path.join(dirInPath, exec); - return os.type() === "Windows_NT" ? [candidate, `${candidate}.exe`] : [candidate]; + return executableCandidates(exec).map((candidate) => path.join(dirInPath, candidate)); }); for await (const isFile of candidates.map(isFileAtPath)) { @@ -199,8 +235,28 @@ async function lookupInPath(exec: string): Promise { return false; } +function executableCandidates(executableName: string): string[] { + // Keep the extension-side probe aligned with `crates/toolchain::probe_for_binary()`, which + // checks both the bare executable name and the platform suffix such as `.exe` on Windows. + // That matters for both PATH lookups and `$CARGO_HOME/bin/` fallbacks. + return isWindows ? [executableName, `${executableName}.exe`] : [executableName]; +} + +function getEnvVar(env: Env, name: string): string | undefined { + if (!isWindows) { + return env[name]; + } + + const foldedName = name.toLowerCase(); + return Object.entries(env).find(([key]) => key.toLowerCase() === foldedName)?.[1]; +} + function getCargoHome(): vscode.Uri | null { const envVar = process.env["CARGO_HOME"]; + return getCargoHomeFromPath(envVar); +} + +function getCargoHomeFromPath(envVar: string | undefined): vscode.Uri | null { if (envVar) return vscode.Uri.file(envVar); try { diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts index 05b475080cbd2..ddeec814b4158 100644 --- a/src/tools/rust-analyzer/editors/code/src/util.ts +++ b/src/tools/rust-analyzer/editors/code/src/util.ts @@ -22,6 +22,10 @@ class Log { log: true, }); + show(): void { + this.output.show(true); + } + trace(...messages: [unknown, ...unknown[]]): void { this.output.trace(this.stringify(messages)); } @@ -40,7 +44,7 @@ class Log { error(...messages: [unknown, ...unknown[]]): void { this.output.error(this.stringify(messages)); - this.output.show(true); + this.show(); } private stringify(messages: unknown[]): string { diff --git a/src/tools/rust-analyzer/editors/code/tests/unit/commands.test.ts b/src/tools/rust-analyzer/editors/code/tests/unit/commands.test.ts new file mode 100644 index 0000000000000..900bb2779d565 --- /dev/null +++ b/src/tools/rust-analyzer/editors/code/tests/unit/commands.test.ts @@ -0,0 +1,80 @@ +import * as assert from "node:assert/strict"; + +import { + cargoNewArgs, + determineNewProjectOpenAction, + validateNewProjectName, +} from "../../src/new_project"; +import type { Context } from "."; + +export async function getTests(ctx: Context) { + await ctx.suite("New project command", (suite) => { + suite.addTest("rejects empty project name", async () => { + assert.equal(validateNewProjectName("", []), "Project name cannot be empty."); + assert.equal(validateNewProjectName(" ", []), "Project name cannot be empty."); + }); + + suite.addTest("rejects dot project names", async () => { + assert.equal(validateNewProjectName(".", []), "Project name cannot be '.' or '..'."); + assert.equal(validateNewProjectName("..", []), "Project name cannot be '.' or '..'."); + }); + + suite.addTest("rejects path separators", async () => { + assert.equal( + validateNewProjectName("foo/bar", []), + "Project name cannot contain '/' or '\\' characters.", + ); + assert.equal( + validateNewProjectName("foo\\bar", []), + "Project name cannot contain '/' or '\\' characters.", + ); + }); + + suite.addTest("rejects invalid Cargo package name characters", async () => { + assert.equal( + validateNewProjectName("foo.bar", []), + "Project name can contain only alphanumeric characters, '-' or '_'.", + ); + assert.equal( + validateNewProjectName("foo bar", []), + "Project name can contain only alphanumeric characters, '-' or '_'.", + ); + assert.equal( + validateNewProjectName("foo+bar", []), + "Project name can contain only alphanumeric characters, '-' or '_'.", + ); + }); + + suite.addTest("rejects existing child folder collisions", async () => { + assert.equal( + validateNewProjectName("demo", ["demo"]), + "A file or folder with this name already exists.", + ); + }); + + suite.addTest("accepts a normal project name", async () => { + assert.equal(validateNewProjectName("demo-project", []), undefined); + }); + + suite.addTest("resolves addToWorkspace fallback without workspace", async () => { + assert.equal(determineNewProjectOpenAction("addToWorkspace", false), "open"); + }); + + suite.addTest("keeps addToWorkspace when workspace exists", async () => { + assert.equal(determineNewProjectOpenAction("addToWorkspace", true), "addToWorkspace"); + }); + + suite.addTest("defaults to ask for unknown values", async () => { + assert.equal(determineNewProjectOpenAction(undefined, true), "ask"); + assert.equal(determineNewProjectOpenAction("ask", true), "ask"); + }); + + suite.addTest("builds binary cargo args", async () => { + assert.deepEqual(cargoNewArgs("bin", "demo"), ["new", "--bin", "demo"]); + }); + + suite.addTest("builds library cargo args", async () => { + assert.deepEqual(cargoNewArgs("lib", "demo"), ["new", "--lib", "demo"]); + }); + }); +} diff --git a/src/tools/rust-analyzer/editors/code/tests/unit/launch_config.test.ts b/src/tools/rust-analyzer/editors/code/tests/unit/launch_config.test.ts index eeb8608a42db5..8da62cd241655 100644 --- a/src/tools/rust-analyzer/editors/code/tests/unit/launch_config.test.ts +++ b/src/tools/rust-analyzer/editors/code/tests/unit/launch_config.test.ts @@ -1,5 +1,9 @@ import * as assert from "assert"; -import { Cargo } from "../../src/toolchain"; +import * as os from "os"; +import * as path from "path"; +import { mkdtemp, mkdir, rm, writeFile } from "fs/promises"; +import { Cargo, cargoPath } from "../../src/toolchain"; +import { isWindows, normalizeDriveLetter } from "../../src/util"; import type { Context } from "."; export async function getTests(ctx: Context) { @@ -96,4 +100,47 @@ export async function getTests(ctx: Context) { assert.notDeepStrictEqual(args.filter, undefined); }); }); + + await ctx.suite("Toolchain resolution", (suite) => { + suite.addTest("prefers explicit CARGO from provided env", async () => { + const explicitCargo = path.join(os.tmpdir(), "custom-cargo"); + assert.strictEqual(await cargoPath({ CARGO: explicitCargo }), explicitCargo); + }); + + suite.addTest("resolves cargo from provided PATH", async () => { + const tempDir = await mkdtemp(path.join(os.tmpdir(), "ra-cargo-path-")); + try { + const cargoBinary = path.join(tempDir, isWindows ? "cargo.exe" : "cargo"); + await writeFile(cargoBinary, ""); + + const pathKey = isWindows ? "Path" : "PATH"; + assert.strictEqual(await cargoPath({ [pathKey]: tempDir }), "cargo"); + } finally { + await rm(tempDir, { recursive: true, force: true }); + } + }); + + suite.addTest("resolves cargo from provided CARGO_HOME", async () => { + const cargoHome = await mkdtemp(path.join(os.tmpdir(), "ra-cargo-home-")); + try { + const binDir = path.join(cargoHome, "bin"); + await mkdir(binDir); + const cargoBinary = path.join(binDir, isWindows ? "cargo.exe" : "cargo"); + await writeFile(cargoBinary, ""); + + assert.strictEqual( + normalizeComparablePath(await cargoPath({ PATH: "", CARGO_HOME: cargoHome })), + normalizeComparablePath(cargoBinary), + ); + } finally { + await rm(cargoHome, { recursive: true, force: true }); + } + }); + }); +} + +function normalizeComparablePath(filePath: string): string { + // Windows path comparisons should ignore drive-letter casing because `fsPath` + // may normalize it differently while still pointing to the same file. + return normalizeDriveLetter(filePath, isWindows); } diff --git a/src/tools/rust-analyzer/editors/code/walkthrough-create-project.md b/src/tools/rust-analyzer/editors/code/walkthrough-create-project.md new file mode 100644 index 0000000000000..34c04cdd1db4a --- /dev/null +++ b/src/tools/rust-analyzer/editors/code/walkthrough-create-project.md @@ -0,0 +1,9 @@ +# Create a New Cargo Project + +Create a new Cargo project without leaving VS Code. + +The command lets you choose the package kind, parent folder, project name, and +how the new project should be opened afterward. + +The project is created with Cargo, so the generated files and defaults match +the normal `cargo new` experience. diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index 387bd8edd2196..5db47ca8fc59b 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -029c9e18dd1f4668e1d42bb187c1c263dfe20093 +942ac9ce4116d4ea784c9882659372b34978b1f8 diff --git a/tests/pretty/delegation-self-rename.pp b/tests/pretty/delegation-self-rename.pp index 7f7afc403607b..526021c061178 100644 --- a/tests/pretty/delegation-self-rename.pp +++ b/tests/pretty/delegation-self-rename.pp @@ -19,15 +19,18 @@ #[attr = Inline(Hint)] fn foo<'a, Self, A, const B: _, const B2: _, T, U, impl FnOnce() -> usize>(self: _, arg1: _) -> _ where - 'a:'a { Trait::<'a, A, B>::foo::(self, arg1) } + 'a:'a { >::foo::(self, arg1) } #[attr = Inline(Hint)] fn bar usize>(self: _, arg1: _) - -> _ { Trait::<'static, (), true>::foo::(self, arg1) } + -> + _ { + >::foo::(self, arg1) +} #[attr = Inline(Hint)] fn foo2<'a, This, A, const B: _, const B2: _, T, U, impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where - 'a:'a { foo::(arg0, arg1) } + 'a:'a { foo::<'a, This, A, B, B2, T, U>(arg0, arg1) } #[attr = Inline(Hint)] fn bar2 usize>(arg0: _, arg1: _) -> _ { bar::(arg0, arg1) } @@ -36,7 +39,7 @@ #[attr = Inline(Hint)] fn foo3<'a, This, A, const B: _, const B2: _, T, U, impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where - 'a:'a { foo2::(arg0, arg1) } + 'a:'a { foo2::<'a, This, A, B, B2, T, U>(arg0, arg1) } #[attr = Inline(Hint)] fn bar3 usize>(arg0: _, arg1: _) -> _ { bar2::(arg0, arg1) } @@ -47,7 +50,7 @@ #[attr = Inline(Hint)] fn foo4<'a, This, A, const B: _, const B2: _, T, U, impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where - 'a:'a { <() as Trait2>::foo3::(arg0, arg1) } + 'a:'a { <() as Trait2>::foo3::<'a, This, A, B, B2, T, U>(arg0, arg1) } #[attr = Inline(Hint)] fn bar4 usize>(arg0: _, arg1: _) -> _ { <() as Trait2>::bar3::(arg0, arg1) } diff --git a/tests/ui/array-slice-vec/eval-array-expr.rs b/tests/ui/array-slice-vec/eval-array-expr.rs new file mode 100644 index 0000000000000..1238ffe696e96 --- /dev/null +++ b/tests/ui/array-slice-vec/eval-array-expr.rs @@ -0,0 +1,12 @@ +//! Regression test for . +//! Check expr in [expr; N] is always being evaluated. +//! +//! This used to trigger an LLVM assertion during compilation +//@ run-fail +//@ error-pattern:panic evaluated +//@ needs-subprocess + +#[allow(unused_variables)] +fn main() { + let x = [panic!("panic evaluated"); 2]; +} diff --git a/tests/ui/issues/issue-23354.rs b/tests/ui/array-slice-vec/eval-empty-array-expr.rs similarity index 54% rename from tests/ui/issues/issue-23354.rs rename to tests/ui/array-slice-vec/eval-empty-array-expr.rs index eff5f3d27147a..92e1c689436ab 100644 --- a/tests/ui/issues/issue-23354.rs +++ b/tests/ui/array-slice-vec/eval-empty-array-expr.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Check expr in [expr; N] is always being evaluated. //@ run-fail //@ error-pattern:panic evaluated //@ needs-subprocess diff --git a/tests/ui/issues/issue-22036.rs b/tests/ui/associated-types/assoc-type-projection-in-default-method.rs similarity index 87% rename from tests/ui/issues/issue-22036.rs rename to tests/ui/associated-types/assoc-type-projection-in-default-method.rs index befdf7ead06d2..1886d6384b412 100644 --- a/tests/ui/issues/issue-22036.rs +++ b/tests/ui/associated-types/assoc-type-projection-in-default-method.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ run-pass trait DigitCollection: Sized { diff --git a/tests/ui/issues/issue-22356.rs b/tests/ui/associated-types/associated-type-projection-alias-in-field.rs similarity index 88% rename from tests/ui/issues/issue-22356.rs rename to tests/ui/associated-types/associated-type-projection-alias-in-field.rs index b7c5c2a59327e..de7350b108831 100644 --- a/tests/ui/issues/issue-22356.rs +++ b/tests/ui/associated-types/associated-type-projection-alias-in-field.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ check-pass #![allow(type_alias_bounds)] diff --git a/tests/ui/associated-types/associated-type-unconstrained-lifetime.rs b/tests/ui/associated-types/associated-type-unconstrained-lifetime.rs new file mode 100644 index 0000000000000..a4b278392b6d6 --- /dev/null +++ b/tests/ui/associated-types/associated-type-unconstrained-lifetime.rs @@ -0,0 +1,32 @@ +//! Regression test for . +//! Test that associated type's inner state cannot be observed past +//! borrow end via saved reference. +//! +//! This was possible as trait implementation with unconstrained lifetime +//! allowed to use any lifetime for associated type, which introduced +//! soundness holes. +//! +//! Fixed by prohibiting use of unconstrained lifetimes on associated types +//! in . +//! +//! Related . + +fn crash_please() { + let mut iter = Newtype(Some(Box::new(0))); + let saved = iter.next().unwrap(); + println!("{}", saved); + iter.0 = None; + println!("{}", saved); +} + +struct Newtype(Option>); + +impl<'a> Iterator for Newtype { //~ ERROR E0207 + type Item = &'a Box; + + fn next(&mut self) -> Option<&Box> { + self.0.as_ref() + } +} + +fn main() { } diff --git a/tests/ui/issues/issue-22886.stderr b/tests/ui/associated-types/associated-type-unconstrained-lifetime.stderr similarity index 89% rename from tests/ui/issues/issue-22886.stderr rename to tests/ui/associated-types/associated-type-unconstrained-lifetime.stderr index aebbdf8a2ec12..108465bf6f932 100644 --- a/tests/ui/issues/issue-22886.stderr +++ b/tests/ui/associated-types/associated-type-unconstrained-lifetime.stderr @@ -1,5 +1,5 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-22886.rs:13:6 + --> $DIR/associated-type-unconstrained-lifetime.rs:24:6 | LL | impl<'a> Iterator for Newtype { | ^^ unconstrained lifetime parameter diff --git a/tests/ui/associated-types/normalize-assoc-types.rs b/tests/ui/associated-types/normalize-assoc-types.rs new file mode 100644 index 0000000000000..c90fef9554af8 --- /dev/null +++ b/tests/ui/associated-types/normalize-assoc-types.rs @@ -0,0 +1,14 @@ +//! Regression test for . +//! Test transitive analysis for associated types. Collected types +//! should be normalized and new obligations generated. + +//@ run-pass +#![allow(unused_imports)] + +use std::borrow::{ToOwned, Cow}; + +fn assert_send(_: T) {} + +fn main() { + assert_send(Cow::Borrowed("foo")); +} diff --git a/tests/ui/issues/issue-22258.rs b/tests/ui/associated-types/ret-associated-type.rs similarity index 68% rename from tests/ui/issues/issue-22258.rs rename to tests/ui/associated-types/ret-associated-type.rs index a1eb8ba14ca98..0da4dfbe73c80 100644 --- a/tests/ui/issues/issue-22258.rs +++ b/tests/ui/associated-types/ret-associated-type.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ run-pass use std::ops::Add; diff --git a/tests/ui/issues/issue-22673.rs b/tests/ui/associated-types/supertrait-bound-references-own-associated-type.rs similarity index 52% rename from tests/ui/issues/issue-22673.rs rename to tests/ui/associated-types/supertrait-bound-references-own-associated-type.rs index 019c45dbadc8a..7d410fd4d6127 100644 --- a/tests/ui/issues/issue-22673.rs +++ b/tests/ui/associated-types/supertrait-bound-references-own-associated-type.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ check-pass trait Expr: PartialEq { diff --git a/tests/ui/assumptions_on_binders/non_lifetime_binder_alias_outlives.rs b/tests/ui/assumptions_on_binders/non_lifetime_binder_alias_outlives.rs new file mode 100644 index 0000000000000..8178575555383 --- /dev/null +++ b/tests/ui/assumptions_on_binders/non_lifetime_binder_alias_outlives.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Znext-solver -Zassumptions-on-binders + +// Regression test for #157778. +// +// A non-lifetime binder (`for`) introduces a placeholder *type* in universe `u`. The +// resulting alias-outlives constraint `::Assoc: 'r` stays in `u` because the +// region-only rewrite (`PlaceholderReplacer` only folds regions) cannot pull a type +// placeholder out of `u`. This used to trip an `assert!(max_universe < u)` and ICE in +// `pull_region_outlives_constraints_out_of_universe`. The assumptions-on-binders machinery +// is region-outlives-only, so we now report ambiguity instead of panicking. + +#![feature(non_lifetime_binders)] + +trait Trait { + type Assoc; + type Ref //~ ERROR cannot satisfy `::Assoc: 'static` + where + for T: Trait; +} + +fn main() {} diff --git a/tests/ui/assumptions_on_binders/non_lifetime_binder_alias_outlives.stderr b/tests/ui/assumptions_on_binders/non_lifetime_binder_alias_outlives.stderr new file mode 100644 index 0000000000000..3b8c8720c6774 --- /dev/null +++ b/tests/ui/assumptions_on_binders/non_lifetime_binder_alias_outlives.stderr @@ -0,0 +1,20 @@ +error[E0284]: type annotations needed: cannot satisfy `::Assoc: 'static` + --> $DIR/non_lifetime_binder_alias_outlives.rs:16:5 + | +LL | / type Ref +LL | | where +LL | | for T: Trait; + | |________________________________________^ cannot satisfy `::Assoc: 'static` + | +note: required by a bound in `Trait::Ref` + --> $DIR/non_lifetime_binder_alias_outlives.rs:18:32 + | +LL | type Ref + | --- required by a bound in this associated type +LL | where +LL | for T: Trait; + | ^^^^^^^ required by this bound in `Trait::Ref` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs new file mode 100644 index 0000000000000..46c9aacdd93d9 --- /dev/null +++ b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs @@ -0,0 +1,28 @@ +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally + +// Regression test for an ICE in the `MaxUniverse` region visitor. When computing +// the max universe of a region constraint, a `ReVar` term could already have been +// unified with another region. `universe_of_lt` returns `None` for such a resolved +// variable, so the visitor used to `unwrap()` `None` and panic. +// +// The missing `T` in `check` is intentional. It makes HIR ty lowering emit an +// error while still leaving behind the region constraint that used to ICE. + +#![feature(min_generic_const_args, inherent_associated_types, generic_const_items)] + +struct Parent<'a> { + a: &'a str, +} + +impl<'a> Parent<'a> { + type const CT: usize = 0; +} + +fn check() +where + [(); Parent::CT::]:, + //~^ ERROR cannot find type `T` in this scope +{ +} + +fn main() {} diff --git a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.stderr b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.stderr new file mode 100644 index 0000000000000..e77a0994fc2db --- /dev/null +++ b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find type `T` in this scope + --> $DIR/resolved-region-var-max-universe.rs:23:23 + | +LL | [(); Parent::CT::]:, + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn check() + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/attributes/invalid-crate-type.rs b/tests/ui/attributes/invalid-crate-type.rs index c233e7d5e3db8..aea75f4cfad90 100644 --- a/tests/ui/attributes/invalid-crate-type.rs +++ b/tests/ui/attributes/invalid-crate-type.rs @@ -1,5 +1,8 @@ // regression test for issue 11256 #![crate_type="foo"] //~ ERROR invalid `crate_type` value +//~| NOTE `#[deny(unknown_crate_types)]` on by default +//~| HELP did you mean +//~| SUGGESTION lib // Tests for suggestions (#53958) @@ -43,6 +46,52 @@ //~| HELP did you mean //~| SUGGESTION cdylib +// substring matching tests +#![crate_type="binary"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION bin + +#![crate_type="library"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION lib + +#![crate_type="rustlib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION rlib + +#![crate_type="dynamiclib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION dylib + +#![crate_type="dylibrary"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION dylib + +#![crate_type="cdynamiclib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION cdylib + +#![crate_type="cdylibrary"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION cdylib + +#![crate_type="staticlibrary"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION staticlib + +#![crate_type="procedural-macro"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION proc-macro + fn main() { return } diff --git a/tests/ui/attributes/invalid-crate-type.stderr b/tests/ui/attributes/invalid-crate-type.stderr index 3eae04678b4a7..2c7663b10925e 100644 --- a/tests/ui/attributes/invalid-crate-type.stderr +++ b/tests/ui/attributes/invalid-crate-type.stderr @@ -2,57 +2,111 @@ error: invalid `crate_type` value --> $DIR/invalid-crate-type.rs:2:15 | LL | #![crate_type="foo"] - | ^^^^^ + | ^^^^^ help: did you mean: `"lib"` | = note: `#[deny(unknown_crate_types)]` on by default error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:6:15 + --> $DIR/invalid-crate-type.rs:9:15 | LL | #![crate_type="statoclib"] | ^^^^^^^^^^^ help: did you mean: `"staticlib"` error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:11:15 + --> $DIR/invalid-crate-type.rs:14:15 | LL | #![crate_type="procmacro"] | ^^^^^^^^^^^ help: did you mean: `"proc-macro"` error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:16:15 + --> $DIR/invalid-crate-type.rs:19:15 | LL | #![crate_type="static-lib"] | ^^^^^^^^^^^^ help: did you mean: `"staticlib"` error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:21:15 + --> $DIR/invalid-crate-type.rs:24:15 | LL | #![crate_type="drylib"] | ^^^^^^^^ help: did you mean: `"dylib"` error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:26:15 + --> $DIR/invalid-crate-type.rs:29:15 | LL | #![crate_type="dlib"] | ^^^^^^ help: did you mean: `"lib"` error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:31:15 + --> $DIR/invalid-crate-type.rs:34:15 | LL | #![crate_type="lob"] | ^^^^^ help: did you mean: `"lib"` error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:36:15 + --> $DIR/invalid-crate-type.rs:39:15 | LL | #![crate_type="bon"] | ^^^^^ help: did you mean: `"bin"` error: invalid `crate_type` value - --> $DIR/invalid-crate-type.rs:41:15 + --> $DIR/invalid-crate-type.rs:44:15 | LL | #![crate_type="cdalib"] | ^^^^^^^^ help: did you mean: `"cdylib"` -error: aborting due to 9 previous errors +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:50:15 + | +LL | #![crate_type="binary"] + | ^^^^^^^^ help: did you mean: `"bin"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:55:15 + | +LL | #![crate_type="library"] + | ^^^^^^^^^ help: did you mean: `"lib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:60:15 + | +LL | #![crate_type="rustlib"] + | ^^^^^^^^^ help: did you mean: `"rlib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:65:15 + | +LL | #![crate_type="dynamiclib"] + | ^^^^^^^^^^^^ help: did you mean: `"dylib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:70:15 + | +LL | #![crate_type="dylibrary"] + | ^^^^^^^^^^^ help: did you mean: `"dylib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:75:15 + | +LL | #![crate_type="cdynamiclib"] + | ^^^^^^^^^^^^^ help: did you mean: `"cdylib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:80:15 + | +LL | #![crate_type="cdylibrary"] + | ^^^^^^^^^^^^ help: did you mean: `"cdylib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:85:15 + | +LL | #![crate_type="staticlibrary"] + | ^^^^^^^^^^^^^^^ help: did you mean: `"staticlib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:90:15 + | +LL | #![crate_type="procedural-macro"] + | ^^^^^^^^^^^^^^^^^^ help: did you mean: `"proc-macro"` + +error: aborting due to 18 previous errors diff --git a/tests/ui/issues/issue-21763.rs b/tests/ui/auto-traits/hashmap-send-requires-send-contents.rs similarity index 68% rename from tests/ui/issues/issue-21763.rs rename to tests/ui/auto-traits/hashmap-send-requires-send-contents.rs index 5f236a25e9944..b543929642f3f 100644 --- a/tests/ui/issues/issue-21763.rs +++ b/tests/ui/auto-traits/hashmap-send-requires-send-contents.rs @@ -1,4 +1,5 @@ -// Regression test for HashMap only impl'ing Send/Sync if its contents do +//! Regression test for . +//! Test HashMap only impl Send/Sync if its contents do //@ normalize-stderr: "(?:[A-Za-z]:[/\\]|/).*[\\/]hashbrown\S+" -> "$$HASHBROWN_SRC_LOCATION" diff --git a/tests/ui/issues/issue-21763.stderr b/tests/ui/auto-traits/hashmap-send-requires-send-contents.stderr similarity index 89% rename from tests/ui/issues/issue-21763.stderr rename to tests/ui/auto-traits/hashmap-send-requires-send-contents.stderr index 135b705eeeff2..db37db925b00a 100644 --- a/tests/ui/issues/issue-21763.stderr +++ b/tests/ui/auto-traits/hashmap-send-requires-send-contents.stderr @@ -1,5 +1,5 @@ error[E0277]: `Rc<()>` cannot be sent between threads safely - --> $DIR/issue-21763.rs:11:11 + --> $DIR/hashmap-send-requires-send-contents.rs:12:11 | LL | foo::, Rc<()>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely @@ -12,7 +12,7 @@ note: required because it appears within the type `hashbrown::map::HashMap, Rc<()>>` --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL note: required by a bound in `foo` - --> $DIR/issue-21763.rs:8:11 + --> $DIR/hashmap-send-requires-send-contents.rs:9:11 | LL | fn foo() {} | ^^^^ required by this bound in `foo` diff --git a/tests/ui/issues/issue-21922.rs b/tests/ui/binop/add-ref-operand-method-lookup.rs similarity index 56% rename from tests/ui/issues/issue-21922.rs rename to tests/ui/binop/add-ref-operand-method-lookup.rs index 6404ab8b7aa0f..b4573fc7658b6 100644 --- a/tests/ui/issues/issue-21922.rs +++ b/tests/ui/binop/add-ref-operand-method-lookup.rs @@ -1,3 +1,10 @@ +//! Regression test for . +//! +//! Ensure Add works with all value/reference operand combinations, +//! both via the + operator and ufcs. +//! +//! Originally method lookup failed only for x + &y. + //@ run-pass use std::ops::Add; fn show(z: i32) { diff --git a/tests/ui/issues/issue-21634.rs b/tests/ui/binop/infer-rhs-type.rs similarity index 85% rename from tests/ui/issues/issue-21634.rs rename to tests/ui/binop/infer-rhs-type.rs index 475a33eca58ec..41ad829141c63 100644 --- a/tests/ui/issues/issue-21634.rs +++ b/tests/ui/binop/infer-rhs-type.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ run-pass #[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] diff --git a/tests/ui/issues/issue-25497.rs b/tests/ui/box/match-box-deref-codegen.rs similarity index 60% rename from tests/ui/issues/issue-25497.rs rename to tests/ui/box/match-box-deref-codegen.rs index 58dcf416dbebb..30f07c0fd8990 100644 --- a/tests/ui/issues/issue-25497.rs +++ b/tests/ui/box/match-box-deref-codegen.rs @@ -1,4 +1,8 @@ +//! Regression test for . +//! Test box deref in match arm doesn't generate invalid LLVM IR. +//! Related . //@ run-pass + #[derive(Clone, Debug, PartialEq)] enum Expression { Dummy, diff --git a/tests/ui/issues/issue-23024.rs b/tests/ui/cast/dyn-any-to-fn-with-missing-generics.rs similarity index 79% rename from tests/ui/issues/issue-23024.rs rename to tests/ui/cast/dyn-any-to-fn-with-missing-generics.rs index 1b072dd7b69c0..504fe096c4204 100644 --- a/tests/ui/issues/issue-23024.rs +++ b/tests/ui/cast/dyn-any-to-fn-with-missing-generics.rs @@ -1,3 +1,4 @@ +//! Regression test for . use std::any::Any; fn main() diff --git a/tests/ui/issues/issue-23024.stderr b/tests/ui/cast/dyn-any-to-fn-with-missing-generics.stderr similarity index 90% rename from tests/ui/issues/issue-23024.stderr rename to tests/ui/cast/dyn-any-to-fn-with-missing-generics.stderr index 51db0414f3a39..53aa609321431 100644 --- a/tests/ui/issues/issue-23024.stderr +++ b/tests/ui/cast/dyn-any-to-fn-with-missing-generics.stderr @@ -1,5 +1,5 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change - --> $DIR/issue-23024.rs:8:39 + --> $DIR/dyn-any-to-fn-with-missing-generics.rs:9:39 | LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); | ^^ help: use parenthetical notation instead: `Fn() -> ()` @@ -9,7 +9,7 @@ LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0107]: missing generics for trait `Fn` - --> $DIR/issue-23024.rs:8:39 + --> $DIR/dyn-any-to-fn-with-missing-generics.rs:9:39 | LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); | ^^ expected 1 generic argument diff --git a/tests/ui/issues/issue-22034.rs b/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.rs similarity index 72% rename from tests/ui/issues/issue-22034.rs rename to tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.rs index 3631c2368fe82..6572140786d2e 100644 --- a/tests/ui/issues/issue-22034.rs +++ b/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.rs @@ -1,3 +1,5 @@ +//! Regression test for . + fn main() { let ptr: *mut () = core::ptr::null_mut(); let _: &mut dyn Fn() = unsafe { diff --git a/tests/ui/issues/issue-22034.stderr b/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.stderr similarity index 91% rename from tests/ui/issues/issue-22034.stderr rename to tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.stderr index 68202085e77db..d0f0bcb201425 100644 --- a/tests/ui/issues/issue-22034.stderr +++ b/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.stderr @@ -1,5 +1,5 @@ error[E0277]: expected a `Fn()` closure, found `()` - --> $DIR/issue-22034.rs:4:16 + --> $DIR/raw-ptr-to-dyn-fn-raw-ptr.rs:6:16 | LL | &mut *(ptr as *mut dyn Fn()) | ^^^ expected an `Fn()` closure, found `()` diff --git a/tests/ui/issues/issue-26468.rs b/tests/ui/codegen/match-enum-range-metadata-misopt.rs similarity index 75% rename from tests/ui/issues/issue-26468.rs rename to tests/ui/codegen/match-enum-range-metadata-misopt.rs index 2103b354977f8..a087ef8850b2c 100644 --- a/tests/ui/issues/issue-26468.rs +++ b/tests/ui/codegen/match-enum-range-metadata-misopt.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Range bug in LLVM misoptimized second `if let` inside `for _ in 0..1` away. //@ run-pass + #![allow(dead_code)] enum FooMode { diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs index 4aecd30e86bbb..70b955589d3e7 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs @@ -2,7 +2,7 @@ #![expect(incomplete_features)] struct Y { - stuff: [u8; { ([1, 2], 3, [4, 5]) }], //~ ERROR expected `usize`, found const tuple + stuff: [u8; { ([1, 2], 3, [4, 5]) }], //~ ERROR expected `usize`, found `([1, 2], 3, [4, 5])` } fn main() {} diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr index 468bf703d90d4..aa54a5ae77048 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr @@ -1,4 +1,4 @@ -error: expected `usize`, found const tuple +error: expected `usize`, found `([1, 2], 3, [4, 5])` --> $DIR/tuple_expr_arg_bad-issue-151048.rs:5:19 | LL | stuff: [u8; { ([1, 2], 3, [4, 5]) }], diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs index 95acd66074f6f..608a4af353a5e 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs @@ -2,7 +2,7 @@ #![expect(incomplete_features)] pub fn takes_nested_tuple() { - takes_nested_tuple::<{ () }> //~ ERROR expected `u32`, found const tuple + takes_nested_tuple::<{ () }> //~ ERROR expected `u32`, found `()` } fn main() {} diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr index dfbd294951fdc..d8314a6b6a57e 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr @@ -1,4 +1,4 @@ -error: expected `u32`, found const tuple +error: expected `u32`, found `()` --> $DIR/tuple_expr_arg_mismatch_type.rs:5:28 | LL | takes_nested_tuple::<{ () }> diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs new file mode 100644 index 0000000000000..f844dae5c8220 --- /dev/null +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs @@ -0,0 +1,13 @@ +#![feature(min_generic_const_args, adt_const_params)] + +// Regression test for an ICE in privacy checking while walking the `T` qself +// of `T::ASSOC` inside a tuple const argument. + +fn takes_tuple() {} + +fn generic_caller() { + takes_tuple::<{ (N, T::ASSOC) }>; + //~^ ERROR expected `()`, found `(N, T::ASSOC)` +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.stderr new file mode 100644 index 0000000000000..3af04db14b60b --- /dev/null +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.stderr @@ -0,0 +1,8 @@ +error: expected `()`, found `(N, T::ASSOC)` + --> $DIR/tuple_expr_arg_unbounded_assoc_const.rs:9:21 + | +LL | takes_tuple::<{ (N, T::ASSOC) }>; + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const-eval/c-variadic-fail.rs b/tests/ui/consts/const-eval/c-variadic-fail.rs index 063e1af88cc7c..087e649af95f9 100644 --- a/tests/ui/consts/const-eval/c-variadic-fail.rs +++ b/tests/ui/consts/const-eval/c-variadic-fail.rs @@ -119,6 +119,15 @@ unsafe fn read_cast_pointer() { //~^ ERROR requested `*const u8` is incompatible with next argument of type `usize` } +unsafe fn read_cast_lifetime() { + // The types are equal up to free lifetimes. + const { read_as::<*const &'static i32>(std::ptr::dangling::<&i32>()) }; + + // Bound lifetimes do matter. + const { read_as::<*const fn(&'static ())>(std::ptr::dangling:: fn(&'a ())>()) }; + //~^ ERROR va_arg type mismatch: requested `*const fn(&())` is incompatible with next argument of type `*const for<'a> fn(&'a ())` +} + fn use_after_free() { const unsafe extern "C" fn helper(ap: ...) -> [u8; size_of::()] { unsafe { std::mem::transmute(ap) } @@ -196,6 +205,7 @@ fn main() { read_too_many(); read_cast_numeric(); read_cast_pointer(); + read_cast_lifetime(); manual_copy_read(); manual_copy_drop(); manual_copy_forget(); diff --git a/tests/ui/consts/const-eval/c-variadic-fail.stderr b/tests/ui/consts/const-eval/c-variadic-fail.stderr index a184a3ab435e7..c1f9ed0fb398a 100644 --- a/tests/ui/consts/const-eval/c-variadic-fail.stderr +++ b/tests/ui/consts/const-eval/c-variadic-fail.stderr @@ -390,8 +390,36 @@ LL | const { read_as::<*const u8>(1usize) }; | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0080]: va_arg type mismatch: requested `*const fn(&())` is incompatible with next argument of type `*const for<'a> fn(&'a ())` + --> $DIR/c-variadic-fail.rs:127:13 + | +LL | const { read_as::<*const fn(&'static ())>(std::ptr::dangling:: fn(&'a ())>()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `read_cast_lifetime::{constant#1}` failed inside this call + | +note: inside `read_as::<*const fn(&())>` + --> $DIR/c-variadic-fail.rs:37:5 + | +LL | ap.next_arg::() + | ^^^^^^^^^^^^^^^^^^ +note: inside `VaList::<'_>::next_arg::<*const fn(&())>` + --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL + +note: erroneous constant encountered + --> $DIR/c-variadic-fail.rs:127:5 + | +LL | const { read_as::<*const fn(&'static ())>(std::ptr::dangling:: fn(&'a ())>()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/c-variadic-fail.rs:127:5 + | +LL | const { read_as::<*const fn(&'static ())>(std::ptr::dangling:: fn(&'a ())>()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0080]: memory access failed: ALLOC0 has been freed, so this pointer is dangling - --> $DIR/c-variadic-fail.rs:131:13 + --> $DIR/c-variadic-fail.rs:140:13 | LL | ap.next_arg::(); | ^^^^^^^^^^^^^^^^^^^^ evaluation of `use_after_free::{constant#0}` failed inside this call @@ -400,7 +428,7 @@ note: inside `VaList::<'_>::next_arg::` --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:127:5 + --> $DIR/c-variadic-fail.rs:136:5 | LL | / const { LL | | unsafe { @@ -411,7 +439,7 @@ LL | | }; | |_____^ note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:127:5 + --> $DIR/c-variadic-fail.rs:136:5 | LL | / const { LL | | unsafe { @@ -424,13 +452,13 @@ LL | | }; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0080]: using ALLOC1 as variable argument list pointer but it does not point to a variable argument list - --> $DIR/c-variadic-fail.rs:153:22 + --> $DIR/c-variadic-fail.rs:162:22 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^ evaluation of `manual_copy_drop::{constant#0}` failed inside this call | note: inside `manual_copy_drop::helper` - --> $DIR/c-variadic-fail.rs:150:9 + --> $DIR/c-variadic-fail.rs:159:9 | LL | drop(ap); | ^^^^^^^^ @@ -442,13 +470,13 @@ note: inside ` as Drop>::drop` --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:153:5 + --> $DIR/c-variadic-fail.rs:162:5 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:153:5 + --> $DIR/c-variadic-fail.rs:162:5 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -456,13 +484,13 @@ LL | const { unsafe { helper(1, 2, 3) } }; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0080]: using ALLOC2 as variable argument list pointer but it does not point to a variable argument list - --> $DIR/c-variadic-fail.rs:169:22 + --> $DIR/c-variadic-fail.rs:178:22 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^ evaluation of `manual_copy_forget::{constant#0}` failed inside this call | note: inside `manual_copy_forget::helper` - --> $DIR/c-variadic-fail.rs:166:9 + --> $DIR/c-variadic-fail.rs:175:9 | LL | drop(ap); | ^^^^^^^^ @@ -474,13 +502,13 @@ note: inside ` as Drop>::drop` --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:169:5 + --> $DIR/c-variadic-fail.rs:178:5 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:169:5 + --> $DIR/c-variadic-fail.rs:178:5 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -488,13 +516,13 @@ LL | const { unsafe { helper(1, 2, 3) } }; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0080]: using ALLOC3 as variable argument list pointer but it does not point to a variable argument list - --> $DIR/c-variadic-fail.rs:182:22 + --> $DIR/c-variadic-fail.rs:191:22 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^ evaluation of `manual_copy_read::{constant#0}` failed inside this call | note: inside `manual_copy_read::helper` - --> $DIR/c-variadic-fail.rs:179:17 + --> $DIR/c-variadic-fail.rs:188:17 | LL | let _ = ap.next_arg::(); | ^^^^^^^^^^^^^^^^^^^^ @@ -502,13 +530,13 @@ note: inside `VaList::<'_>::next_arg::` --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:182:5 + --> $DIR/c-variadic-fail.rs:191:5 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:182:5 + --> $DIR/c-variadic-fail.rs:191:5 | LL | const { unsafe { helper(1, 2, 3) } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -516,7 +544,7 @@ LL | const { unsafe { helper(1, 2, 3) } }; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0080]: pointer not dereferenceable: pointer must point to some allocation, but got null pointer - --> $DIR/c-variadic-fail.rs:190:5 + --> $DIR/c-variadic-fail.rs:199:5 | LL | } | ^ evaluation of `drop_of_invalid::{constant#0}` failed inside this call @@ -527,7 +555,7 @@ note: inside ` as Drop>::drop` --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:187:5 + --> $DIR/c-variadic-fail.rs:196:5 | LL | / const { LL | | let mut invalid: MaybeUninit = MaybeUninit::zeroed(); @@ -536,7 +564,7 @@ LL | | } | |_____^ note: erroneous constant encountered - --> $DIR/c-variadic-fail.rs:187:5 + --> $DIR/c-variadic-fail.rs:196:5 | LL | / const { LL | | let mut invalid: MaybeUninit = MaybeUninit::zeroed(); @@ -546,6 +574,6 @@ LL | | } | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/delegation/generics/free-fn-to-trait-infer.rs b/tests/ui/delegation/generics/free-fn-to-trait-infer.rs deleted file mode 100644 index 0a0665b752681..0000000000000 --- a/tests/ui/delegation/generics/free-fn-to-trait-infer.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ compile-flags: -Z deduplicate-diagnostics=yes - -#![feature(fn_delegation)] - -trait Trait { - fn foo(&self, _: U, _: T) {} -} - -impl Trait for u8 {} - -reuse Trait::<_>::foo:: as generic_arguments1; -//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions -reuse >::foo as generic_arguments2; -//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions -reuse <_ as Trait<_>>::foo as generic_arguments3; -//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions -//~| ERROR the placeholder `_` is not allowed within types on item signatures for functions - -fn main() {} diff --git a/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr b/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr deleted file mode 100644 index f1e9231cc4050..0000000000000 --- a/tests/ui/delegation/generics/free-fn-to-trait-infer.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/free-fn-to-trait-infer.rs:11:15 - | -LL | reuse Trait::<_>::foo:: as generic_arguments1; - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/free-fn-to-trait-infer.rs:13:20 - | -LL | reuse >::foo as generic_arguments2; - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/free-fn-to-trait-infer.rs:15:8 - | -LL | reuse <_ as Trait<_>>::foo as generic_arguments3; - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/free-fn-to-trait-infer.rs:15:19 - | -LL | reuse <_ as Trait<_>>::foo as generic_arguments3; - | ^ not allowed in type signatures - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/delegation/generics/free-to-trait-static-reuse.rs b/tests/ui/delegation/generics/free-to-trait-static-reuse.rs index e3d0bdbc7e9b0..3f52209ded317 100644 --- a/tests/ui/delegation/generics/free-to-trait-static-reuse.rs +++ b/tests/ui/delegation/generics/free-to-trait-static-reuse.rs @@ -20,17 +20,9 @@ reuse ::static_method as bar { self + 1 } reuse ::static_method::<'static, Vec, false> as bar2; reuse Trait::static_method as error { self - 123 } -//~^ ERROR: type annotations needed -//~| ERROR: delegation self type is not specified reuse Trait::<'static, i32, 123>::static_method as error2; -//~^ ERROR: type annotations needed -//~| ERROR: delegation self type is not specified reuse Trait::<'static, i32, 123>::static_method::<'static, String, false> as error3; -//~^ ERROR: type annotations needed -//~| ERROR: delegation self type is not specified reuse Trait::static_method::<'static, Vec, false> as error4 { self + 4 } -//~^ ERROR: type annotations needed -//~| ERROR: delegation self type is not specified reuse ::static_method as error5; //~^ ERROR: the trait bound `String: Trait<'a, T, X>` is not satisfied diff --git a/tests/ui/delegation/generics/free-to-trait-static-reuse.stderr b/tests/ui/delegation/generics/free-to-trait-static-reuse.stderr index 8d87b9376acd4..04f5e60044cdc 100644 --- a/tests/ui/delegation/generics/free-to-trait-static-reuse.stderr +++ b/tests/ui/delegation/generics/free-to-trait-static-reuse.stderr @@ -1,43 +1,11 @@ -error: delegation self type is not specified - --> $DIR/free-to-trait-static-reuse.rs:22:14 - | -LL | reuse Trait::static_method as error { self - 123 } - | ^^^^^^^^^^^^^ - | - = help: consider explicitly specifying self type: `reuse ::function` - -error: delegation self type is not specified - --> $DIR/free-to-trait-static-reuse.rs:25:35 - | -LL | reuse Trait::<'static, i32, 123>::static_method as error2; - | ^^^^^^^^^^^^^ - | - = help: consider explicitly specifying self type: `reuse ::function` - -error: delegation self type is not specified - --> $DIR/free-to-trait-static-reuse.rs:28:35 - | -LL | reuse Trait::<'static, i32, 123>::static_method::<'static, String, false> as error3; - | ^^^^^^^^^^^^^ - | - = help: consider explicitly specifying self type: `reuse ::function` - -error: delegation self type is not specified - --> $DIR/free-to-trait-static-reuse.rs:31:14 - | -LL | reuse Trait::static_method::<'static, Vec, false> as error4 { self + 4 } - | ^^^^^^^^^^^^^ - | - = help: consider explicitly specifying self type: `reuse ::function` - error[E0277]: the trait bound `Struct: Bound` is not satisfied - --> $DIR/free-to-trait-static-reuse.rs:39:49 + --> $DIR/free-to-trait-static-reuse.rs:31:49 | LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} | ^^^^^^ unsatisfied trait bound | help: the trait `Bound` is not implemented for `Struct` - --> $DIR/free-to-trait-static-reuse.rs:38:1 + --> $DIR/free-to-trait-static-reuse.rs:30:1 | LL | struct Struct; | ^^^^^^^^^^^^^ @@ -55,68 +23,8 @@ LL | where LL | Self: Bound, | ^^^^^^^^ required by this bound in `Trait` -error[E0283]: type annotations needed - --> $DIR/free-to-trait-static-reuse.rs:22:14 - | -LL | reuse Trait::static_method as error { self - 123 } - | ^^^^^^^^^^^^^ cannot infer type - | -note: multiple `impl`s satisfying `_: Trait<'a, T, X>` found - --> $DIR/free-to-trait-static-reuse.rs:14:1 - | -LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0283]: type annotations needed - --> $DIR/free-to-trait-static-reuse.rs:25:35 - | -LL | reuse Trait::<'static, i32, 123>::static_method as error2; - | ^^^^^^^^^^^^^ cannot infer type - | -note: multiple `impl`s satisfying `_: Trait<'static, i32, 123>` found - --> $DIR/free-to-trait-static-reuse.rs:14:1 - | -LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0283]: type annotations needed - --> $DIR/free-to-trait-static-reuse.rs:28:35 - | -LL | reuse Trait::<'static, i32, 123>::static_method::<'static, String, false> as error3; - | ^^^^^^^^^^^^^ cannot infer type - | -note: multiple `impl`s satisfying `_: Trait<'static, i32, 123>` found - --> $DIR/free-to-trait-static-reuse.rs:14:1 - | -LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0283]: type annotations needed - --> $DIR/free-to-trait-static-reuse.rs:31:14 - | -LL | reuse Trait::static_method::<'static, Vec, false> as error4 { self + 4 } - | ^^^^^^^^^^^^^ cannot infer type - | -note: multiple `impl`s satisfying `_: Trait<'a, T, X>` found - --> $DIR/free-to-trait-static-reuse.rs:14:1 - | -LL | impl<'a, T, const X: usize> Trait<'a, T, X> for usize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0277]: the trait bound `String: Trait<'a, T, X>` is not satisfied - --> $DIR/free-to-trait-static-reuse.rs:35:8 + --> $DIR/free-to-trait-static-reuse.rs:27:8 | LL | reuse ::static_method as error5; | ^^^^^^ the trait `Trait<'a, T, X>` is not implemented for `String` @@ -131,13 +39,13 @@ LL | impl<'a, T, const X: usize> Trait<'a, T, X> for Struct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Struct` error[E0277]: the trait bound `Struct: Bound` is not satisfied - --> $DIR/free-to-trait-static-reuse.rs:42:8 + --> $DIR/free-to-trait-static-reuse.rs:34:8 | LL | reuse ::static_method as error6; | ^^^^^^ unsatisfied trait bound | help: the trait `Bound` is not implemented for `Struct` - --> $DIR/free-to-trait-static-reuse.rs:38:1 + --> $DIR/free-to-trait-static-reuse.rs:30:1 | LL | struct Struct; | ^^^^^^^^^^^^^ @@ -155,7 +63,6 @@ LL | { LL | fn static_method<'c: 'c, U, const B: bool>(x: usize) {} | ------------- required by a bound in this associated function -error: aborting due to 11 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0283. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/generics-gen-args-errors.rs b/tests/ui/delegation/generics/generics-gen-args-errors.rs index 4e1ac0a5e4176..6a8d1674fe184 100644 --- a/tests/ui/delegation/generics/generics-gen-args-errors.rs +++ b/tests/ui/delegation/generics/generics-gen-args-errors.rs @@ -44,8 +44,6 @@ mod test_2 { fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} reuse foo::<> as bar1; - //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions - //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse foo:: as bar2; //~^ ERROR: function takes 3 generic arguments but 2 generic arguments were supplied @@ -54,9 +52,9 @@ mod test_2 { reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; //~^ ERROR: use of undeclared lifetime name `'asdasd` - //~| ERROR: function takes 2 lifetime arguments but 5 lifetime arguments were supplied - //~| ERROR: function takes 3 generic arguments but 2 generic arguments were supplied - //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: function takes 2 lifetime arguments but 6 lifetime arguments were supplied + //~| ERROR: function takes 3 generic arguments but 1 generic argument was supplied + //~| ERROR: wrong infer used: expected '_, found: _ reuse foo:: as bar4; //~^ ERROR: cannot find type `asdasd` in this scope @@ -131,12 +129,13 @@ mod test_3 { //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; - //~^ ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied - //~| ERROR: trait takes 2 generic arguments but 5 generic arguments were supplied + //~^ ERROR: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied + //~| ERROR: trait takes 2 generic arguments but 4 generic arguments were supplied //~| ERROR: method takes 2 generic arguments but 5 generic arguments were supplied //~| ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: wrong infer used: expected '_, found: _ } fn main() {} diff --git a/tests/ui/delegation/generics/generics-gen-args-errors.stderr b/tests/ui/delegation/generics/generics-gen-args-errors.stderr index 7aa1766dfef89..c08e23e6c016a 100644 --- a/tests/ui/delegation/generics/generics-gen-args-errors.stderr +++ b/tests/ui/delegation/generics/generics-gen-args-errors.stderr @@ -38,7 +38,7 @@ LL | reuse foo:: as xd; = note: nested items are independent from their parent item for everything except for privacy and name resolution error[E0261]: use of undeclared lifetime name `'asdasd` - --> $DIR/generics-gen-args-errors.rs:55:29 + --> $DIR/generics-gen-args-errors.rs:53:29 | LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; | ^^^^^^^ undeclared lifetime @@ -49,7 +49,7 @@ LL | reuse foo'asdasd, ::<'static, _, 'asdasd, 'static, 'static, 'static, _> | ++++++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/generics-gen-args-errors.rs:77:50 + --> $DIR/generics-gen-args-errors.rs:75:50 | LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; | ^^ undeclared lifetime @@ -103,65 +103,77 @@ LL | fn check() { | +++++ error[E0425]: cannot find type `asdasd` in this scope - --> $DIR/generics-gen-args-errors.rs:61:39 + --> $DIR/generics-gen-args-errors.rs:59:39 | LL | reuse foo:: as bar4; | ^^^^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:71:22 + --> $DIR/generics-gen-args-errors.rs:69:22 | LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:77:27 + --> $DIR/generics-gen-args-errors.rs:75:27 | LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:94:19 + --> $DIR/generics-gen-args-errors.rs:92:19 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:94:24 + --> $DIR/generics-gen-args-errors.rs:92:24 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:94:29 + --> $DIR/generics-gen-args-errors.rs:92:29 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:94:34 + --> $DIR/generics-gen-args-errors.rs:92:34 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:94:39 + --> $DIR/generics-gen-args-errors.rs:92:39 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asdasa` in this scope - --> $DIR/generics-gen-args-errors.rs:94:44 + --> $DIR/generics-gen-args-errors.rs:92:44 | LL | reuse Trait::::foo as bar1; | ^^^^^^ not found in this scope error[E0425]: cannot find type `DDDD` in this scope - --> $DIR/generics-gen-args-errors.rs:124:34 + --> $DIR/generics-gen-args-errors.rs:122:34 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^^ not found in this scope +error: wrong infer used: expected '_, found: _ + --> $DIR/generics-gen-args-errors.rs:53:26 + | +LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; + | ^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/generics-gen-args-errors.rs:131:33 + | +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ^ + error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied --> $DIR/generics-gen-args-errors.rs:33:15 | @@ -184,20 +196,8 @@ error: inferred lifetimes are not allowed in delegations as we need to inherit s LL | reuse foo:: as xd; | ^^^ -error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:46:11 - | -LL | reuse foo::<> as bar1; - | ^^^ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/generics-gen-args-errors.rs:46:11 - | -LL | reuse foo::<> as bar1; - | ^^^ not allowed in type signatures - error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:50:11 + --> $DIR/generics-gen-args-errors.rs:48:11 | LL | reuse foo:: as bar2; | ^^^ expected 2 lifetime arguments @@ -213,7 +213,7 @@ LL | reuse foo::<'a, 'b, String, String> as bar2; | +++++++ error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:50:11 + --> $DIR/generics-gen-args-errors.rs:48:11 | LL | reuse foo:: as bar2; | ^^^ ------ ------ supplied 2 generic arguments @@ -231,16 +231,16 @@ LL | reuse foo:: as bar2; | +++ error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:50:11 + --> $DIR/generics-gen-args-errors.rs:48:11 | LL | reuse foo:: as bar2; | ^^^ -error[E0107]: function takes 2 lifetime arguments but 5 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:55:11 +error[E0107]: function takes 2 lifetime arguments but 6 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:53:11 | LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; - | ^^^ --------------------------- help: remove the lifetime arguments + | ^^^------------------------------------------------- help: remove the lifetime arguments | | | expected 2 lifetime arguments | @@ -250,30 +250,24 @@ note: function defined here, with 2 lifetime parameters: `'a`, `'b` LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ -- -- -error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:55:11 +error[E0107]: function takes 3 generic arguments but 1 generic argument was supplied + --> $DIR/generics-gen-args-errors.rs:53:11 | LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; - | ^^^ expected 3 generic arguments ------- - supplied 2 generic arguments + | ^^^ expected 3 generic arguments - supplied 1 generic argument | note: function defined here, with 3 generic parameters: `T`, `U`, `N` --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ - - -------------- -help: add missing generic argument +help: add missing generic arguments | -LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _, N> as bar3; - | +++ - -error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:55:11 - | -LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; - | ^^^ +LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _, U, N> as bar3; + | ++++++ error[E0107]: function takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/generics-gen-args-errors.rs:61:11 + --> $DIR/generics-gen-args-errors.rs:59:11 | LL | reuse foo:: as bar4; | ^^^ ------ supplied 1 lifetime argument @@ -291,13 +285,13 @@ LL | reuse foo:: as bar4; | +++++++++ error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:61:11 + --> $DIR/generics-gen-args-errors.rs:59:11 | LL | reuse foo:: as bar4; | ^^^ error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:66:11 + --> $DIR/generics-gen-args-errors.rs:64:11 | LL | reuse foo::<1, 2, _, 4, 5, _> as bar5; | ^^^ expected 2 lifetime arguments @@ -313,10 +307,10 @@ LL | reuse foo::<'a, 'b, 1, 2, _, 4, 5, _> as bar5; | +++++++ error[E0107]: function takes 3 generic arguments but 6 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:66:11 + --> $DIR/generics-gen-args-errors.rs:64:11 | LL | reuse foo::<1, 2, _, 4, 5, _> as bar5; - | ^^^ --------- help: remove the unnecessary generic arguments + | ^^^------------------- help: remove the unnecessary generic arguments | | | expected 3 generic arguments | @@ -327,13 +321,13 @@ LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ - - -------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:66:11 + --> $DIR/generics-gen-args-errors.rs:64:11 | LL | reuse foo::<1, 2, _, 4, 5, _> as bar5; | ^^^ error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:71:11 + --> $DIR/generics-gen-args-errors.rs:69:11 | LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; | ^^^ expected 2 lifetime arguments @@ -349,7 +343,7 @@ LL | reuse foo::<'a, 'b, 1, 2,asd,String, { let x = 0; }> as bar6; | +++++++ error[E0107]: function takes 3 generic arguments but 5 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:71:11 + --> $DIR/generics-gen-args-errors.rs:69:11 | LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; | ^^^ ----------------------- help: remove the unnecessary generic arguments @@ -363,25 +357,25 @@ LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ - - -------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:71:11 + --> $DIR/generics-gen-args-errors.rs:69:11 | LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; | ^^^ error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:77:11 + --> $DIR/generics-gen-args-errors.rs:75:11 | LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; | ^^^ error[E0747]: constant provided when a type was expected - --> $DIR/generics-gen-args-errors.rs:77:17 + --> $DIR/generics-gen-args-errors.rs:75:17 | LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; | ^^^^^^^^ error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:83:11 + --> $DIR/generics-gen-args-errors.rs:81:11 | LL | reuse foo::<{}, {}, {}> as bar8; | ^^^ expected 2 lifetime arguments @@ -397,19 +391,19 @@ LL | reuse foo::<'a, 'b, {}, {}, {}> as bar8; | +++++++ error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:83:11 + --> $DIR/generics-gen-args-errors.rs:81:11 | LL | reuse foo::<{}, {}, {}> as bar8; | ^^^ error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:94:11 + --> $DIR/generics-gen-args-errors.rs:92:11 | LL | reuse Trait::::foo as bar1; | ^^^^^ expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -419,7 +413,7 @@ LL | reuse Trait::<'b, 'c, 'a, asd, asd, asd, asd, asd, asdasa>::foo as bar1 | +++++++++++ error[E0107]: trait takes 2 generic arguments but 6 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:94:11 + --> $DIR/generics-gen-args-errors.rs:92:11 | LL | reuse Trait::::foo as bar1; | ^^^^^ ----------------------- help: remove the unnecessary generic arguments @@ -427,19 +421,19 @@ LL | reuse Trait::::foo as bar1; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:94:11 + --> $DIR/generics-gen-args-errors.rs:92:11 | LL | reuse Trait::::foo as bar1; | ^^^^^ error[E0107]: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:105:11 + --> $DIR/generics-gen-args-errors.rs:103:11 | LL | reuse Trait::<'static, 'static>::foo as bar2; | ^^^^^ ------- ------- supplied 2 lifetime arguments @@ -447,7 +441,7 @@ LL | reuse Trait::<'static, 'static>::foo as bar2; | expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -457,25 +451,25 @@ LL | reuse Trait::<'static, 'static, 'static>::foo as bar2; | +++++++++ error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:105:11 + --> $DIR/generics-gen-args-errors.rs:103:11 | LL | reuse Trait::<'static, 'static>::foo as bar2; | ^^^^^ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/generics-gen-args-errors.rs:105:11 + --> $DIR/generics-gen-args-errors.rs:103:11 | LL | reuse Trait::<'static, 'static>::foo as bar2; | ^^^^^ not allowed in type signatures error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:109:11 + --> $DIR/generics-gen-args-errors.rs:107:11 | LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; | ^^^^^ expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -485,7 +479,7 @@ LL | reuse Trait::<'b, 'c, 'a, 1, 2, 3, 4, 5>::foo as bar3; | +++++++++++ error[E0107]: trait takes 2 generic arguments but 5 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:109:11 + --> $DIR/generics-gen-args-errors.rs:107:11 | LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; | ^^^^^ --------- help: remove the unnecessary generic arguments @@ -493,25 +487,25 @@ LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:109:11 + --> $DIR/generics-gen-args-errors.rs:107:11 | LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; | ^^^^^ error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:114:11 + --> $DIR/generics-gen-args-errors.rs:112:11 | LL | reuse Trait::<1, 2, true>::foo as bar4; | ^^^^^ expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -521,7 +515,7 @@ LL | reuse Trait::<'b, 'c, 'a, 1, 2, true>::foo as bar4; | +++++++++++ error[E0107]: trait takes 2 generic arguments but 3 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:114:11 + --> $DIR/generics-gen-args-errors.rs:112:11 | LL | reuse Trait::<1, 2, true>::foo as bar4; | ^^^^^ ------ help: remove the unnecessary generic argument @@ -529,19 +523,19 @@ LL | reuse Trait::<1, 2, true>::foo as bar4; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:114:11 + --> $DIR/generics-gen-args-errors.rs:112:11 | LL | reuse Trait::<1, 2, true>::foo as bar4; | ^^^^^ error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/generics-gen-args-errors.rs:119:11 + --> $DIR/generics-gen-args-errors.rs:117:11 | LL | reuse Trait::<'static>::foo as bar5; | ^^^^^ ------- supplied 1 lifetime argument @@ -549,7 +543,7 @@ LL | reuse Trait::<'static>::foo as bar5; | expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -559,19 +553,19 @@ LL | reuse Trait::<'static, 'static, 'static>::foo as bar5; | ++++++++++++++++++ error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:119:11 + --> $DIR/generics-gen-args-errors.rs:117:11 | LL | reuse Trait::<'static>::foo as bar5; | ^^^^^ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/generics-gen-args-errors.rs:119:11 + --> $DIR/generics-gen-args-errors.rs:117:11 | LL | reuse Trait::<'static>::foo as bar5; | ^^^^^ not allowed in type signatures error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/generics-gen-args-errors.rs:124:11 + --> $DIR/generics-gen-args-errors.rs:122:11 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^^^ - supplied 1 lifetime argument @@ -579,7 +573,7 @@ LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -589,7 +583,7 @@ LL | reuse Trait::<1, 'static, 'static, 2, 'static, DDDD>::foo::<1, 2, 3, 4, | ++++++++++++++++++ error[E0107]: trait takes 2 generic arguments but 3 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:124:11 + --> $DIR/generics-gen-args-errors.rs:122:11 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^^^ --------------- help: remove the unnecessary generic argument @@ -597,25 +591,25 @@ LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:124:11 + --> $DIR/generics-gen-args-errors.rs:122:11 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^^^ error[E0107]: method takes 1 lifetime argument but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:124:41 + --> $DIR/generics-gen-args-errors.rs:122:41 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^ expected 1 lifetime argument | note: method defined here, with 1 lifetime parameter: `'d` - --> $DIR/generics-gen-args-errors.rs:91:12 + --> $DIR/generics-gen-args-errors.rs:89:12 | LL | fn foo<'d: 'd, U, const M: bool>(self) {} | ^^^ -- @@ -625,7 +619,7 @@ LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<'d, 1, 2, 3, 4, 5, 6> as bar6 | +++ error[E0107]: method takes 2 generic arguments but 6 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:124:41 + --> $DIR/generics-gen-args-errors.rs:122:41 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^ ------------ help: remove the unnecessary generic arguments @@ -633,73 +627,73 @@ LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | expected 2 generic arguments | note: method defined here, with 2 generic parameters: `U`, `M` - --> $DIR/generics-gen-args-errors.rs:91:12 + --> $DIR/generics-gen-args-errors.rs:89:12 | LL | fn foo<'d: 'd, U, const M: bool>(self) {} | ^^^ - ------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:124:41 + --> $DIR/generics-gen-args-errors.rs:122:41 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^ -error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/generics-gen-args-errors.rs:133:11 +error[E0107]: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:131:11 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; - | ^^^^^ ----- supplied 1 lifetime argument + | ^^^^^ ----- ----- supplied 2 lifetime arguments | | | expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- -help: add missing lifetime arguments +help: add missing lifetime argument | -LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; - | ++++++++++++++++++ +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ++++ -error[E0107]: trait takes 2 generic arguments but 5 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:133:11 +error[E0107]: trait takes 2 generic arguments but 4 generic arguments were supplied + --> $DIR/generics-gen-args-errors.rs:131:11 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; - | ^^^^^ --- help: remove the unnecessary generic argument + | ^^^^^ ------------------------- help: remove the unnecessary generic arguments | | | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:90:11 + --> $DIR/generics-gen-args-errors.rs:88:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:133:11 + --> $DIR/generics-gen-args-errors.rs:131:11 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; | ^^^^^ error[E0107]: method takes 1 lifetime argument but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:133:59 + --> $DIR/generics-gen-args-errors.rs:131:59 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; | ^^^ expected 1 lifetime argument | note: method defined here, with 1 lifetime parameter: `'d` - --> $DIR/generics-gen-args-errors.rs:91:12 + --> $DIR/generics-gen-args-errors.rs:89:12 | LL | fn foo<'d: 'd, U, const M: bool>(self) {} | ^^^ -- help: add missing lifetime argument | -LL | reuse Trait::::foo::<'d, 1, 2, 3, _, 6> as bar7; +LL | reuse Trait::::foo::<'a, 1, 2, 3, _, 6> as bar7; | +++ error[E0107]: method takes 2 generic arguments but 5 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:133:59 + --> $DIR/generics-gen-args-errors.rs:131:59 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; | ^^^ --------- help: remove the unnecessary generic arguments @@ -707,13 +701,13 @@ LL | reuse Trait::::foo::<1, 2, 3, _, | expected 2 generic arguments | note: method defined here, with 2 generic parameters: `U`, `M` - --> $DIR/generics-gen-args-errors.rs:91:12 + --> $DIR/generics-gen-args-errors.rs:89:12 | LL | fn foo<'d: 'd, U, const M: bool>(self) {} | ^^^ - ------------- error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/generics-gen-args-errors.rs:133:59 + --> $DIR/generics-gen-args-errors.rs:131:59 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; | ^^^ @@ -789,12 +783,12 @@ LL | reuse foo:: as xd; | + + error[E0747]: constant provided when a type was expected - --> $DIR/generics-gen-args-errors.rs:83:17 + --> $DIR/generics-gen-args-errors.rs:81:17 | LL | reuse foo::<{}, {}, {}> as bar8; | ^^ -error: aborting due to 75 previous errors +error: aborting due to 74 previous errors Some errors have detailed explanations: E0107, E0121, E0261, E0401, E0423, E0425, E0747. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/delegation/generics/infers.rs b/tests/ui/delegation/generics/infers.rs new file mode 100644 index 0000000000000..d9205f510a7b4 --- /dev/null +++ b/tests/ui/delegation/generics/infers.rs @@ -0,0 +1,356 @@ +//@ compile-flags: -Z deduplicate-diagnostics=yes + +#![feature(fn_delegation)] + +// Some interesting cases: +mod selected_tests { + mod different_infers { + fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + + // Should differentiate between lifetime and types/consts infers. + reuse foo::<_, '_, '_, '_> as bar; + //~^ ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + } + + mod self_type { + trait Trait<'a, X> { + fn method<'b: 'b, const M: usize>(&self) {} + fn r#static<'b, Y, const B: bool>() {} + } + + impl<'a, X> Trait<'a, X> for () {} + + reuse Trait::<'_, _>::method::<'_, _> as foo; + + reuse <_ as Trait<'_, _>>::method::<'_, _> as foo1; + reuse <() as Trait<'_, _>>::method::<'_, _> as foo2; + + reuse <_ as Trait<'_, _>>::r#static::<_, _> as foo3; + reuse <() as Trait<'_, _>>::r#static::<_, _> as foo4; + + reuse Trait::<'_, _>::r#static::<_, _> as foo5; + } + + mod late_bound_lifetimes { + fn foo<'a, 'b, 'c: 'c, 'd>(_: &'a &'b &'c &'d ()) {} + + // 'c corresponds to infer. + reuse foo::<'_> as foo1; + + // Only 'c is generated in desugaring, second infer remains just infer in call path. + reuse foo::<'_, '_> as foo2; + //~^ ERROR: function takes 1 lifetime argument but 2 lifetime arguments were supplied + + reuse foo as foo3; + reuse foo::<'static> as foo4; + } + + mod non_angle_bracketed_args { + fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + + reuse foo::('_, _, _, _) as bar; + //~^ ERROR: lifetimes must be followed by `+` to form a trait object type + //~| ERROR: at least one trait is required for an object type + //~| ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214] + //~| ERROR: function takes 1 lifetime argument but 0 lifetime arguments were supplied [E0107] + //~| ERROR: function takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + } +} + +// All other stuff: +mod legacy_tests { + trait Trait { + fn foo(&self, _: U, _: T) {} + } + + impl Trait for u8 {} + + reuse Trait::<_>::foo:: as generic_arguments1; + reuse >::foo as generic_arguments2; + reuse <_ as Trait<_>>::foo as generic_arguments3; +} + +mod free_to_free { + fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + + reuse foo::<> as foo1; + reuse foo::<'_, _, _, _> as foo2; + reuse foo::<'static, String, _, _> as foo3; + reuse foo::<'_, _, 123, _> as foo4; + + reuse foo::<'_, '_, '_, _, _, _,> as foo5; + //~^ ERROR: function takes 3 generic arguments but 5 generic arguments were supplied + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + //~^ ERROR: function takes 3 generic arguments but 6 generic arguments were supplied [E0107] + //~| ERROR: function takes 1 lifetime argument but 3 lifetime arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse foo::<_, '_, _, _> as foo7; + //~^ ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse foo::<'_, '_, '_, '_> as foo8; + //~^ ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse foo::<_> as foo9; + //~^ ERROR: function takes 3 generic arguments but 0 generic arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + + reuse foo::, _, _, ()> as foo10; + //~^ ERROR: function takes 1 lifetime argument but 0 lifetime arguments were supplied [E0107] + //~| ERROR: function takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied [E0107] + //~| ERROR: struct takes at least 1 generic argument but 0 generic arguments were supplied [E0107] + + reuse foo::, _, _, ()> as foo11; + //~^ ERROR: function takes 1 lifetime argument but 0 lifetime arguments were supplied [E0107] + //~| ERROR: function takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + + reuse foo::<'____, ___, _, ___> as foo12; + //~^ ERROR: use of undeclared lifetime name `'____` [E0261] + //~| ERROR: cannot find type `___` in this scope [E0425] + //~| ERROR: cannot find type `___` in this scope [E0425] + + reuse foo::<'_, Vec<_>, Vec>, _> as foo13; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: type provided when a constant was expected [E0747] + + reuse foo::<'_, unresolved_, _, _> as foo14; + //~^ ERROR: cannot find type `unresolved_` in this scope + + reuse foo::<_, _, _> as foo15; + //~^ ERROR: function takes 3 generic arguments but 2 generic arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ +} + +mod free_to_trait { + pub trait Trait<'a, 'b, X, const C: usize, Y> { + fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + } + + struct X; + impl<'a, 'b, Some, Params, X, const C: usize, Y> Trait<'a, 'b, X, C, Y> for X {} + //~^ ERROR: the type parameter `Some` is not constrained by the impl trait, self type, or predicates [E0207] + //~| ERROR: the type parameter `Params` is not constrained by the impl trait, self type, or predicates [E0207] + + mod child_only { + use super::*; + + reuse Trait::foo::<> as foo1; + reuse Trait::foo::<'_, _, _, _> as foo2; + reuse Trait::foo::<'static, String, _, _> as foo3; + reuse Trait::foo::<'_, _, 123, _> as foo4; + + reuse Trait::foo::<'_, '_, '_, _, _, _,> as foo5; + //~^ ERROR: method takes 3 generic arguments but 5 generic arguments were supplied + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + //~^ ERROR: method takes 3 generic arguments but 6 generic arguments were supplied [E0107] + //~| ERROR: method takes 1 lifetime argument but 3 lifetime arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::foo::<_, '_, _, _> as foo7; + //~^ ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::foo::<'_, '_, '_, '_> as foo8; + //~^ ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::foo::<_> as foo9; + //~^ ERROR: method takes 3 generic arguments but 0 generic arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + + reuse Trait::foo::, _, _, ()> as foo10; + //~^ ERROR: method takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied [E0107] + //~| ERROR: struct takes at least 1 generic argument but 0 generic arguments were supplied [E0107] + //~| ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied + + reuse Trait::foo::, _, _, ()> as foo11; + //~^ ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied [E0107] + //~| ERROR: method takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + + reuse Trait::foo::<'____, ___, _, ___> as foo12; + //~^ ERROR: use of undeclared lifetime name `'____` [E0261] + //~| ERROR: cannot find type `___` in this scope [E0425] + //~| ERROR: cannot find type `___` in this scope [E0425] + + reuse Trait::foo::<'_, Vec<_>, Vec>, _> as foo13; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: type provided when a constant was expected [E0747] + + reuse Trait::foo::<'_, unresolved_, _, _> as foo14; + //~^ ERROR: cannot find type `unresolved_` in this scope + + reuse Trait::foo::<_, _, _> as foo15; + //~^ ERROR: method takes 3 generic arguments but 2 generic arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + } + + mod parent_only { + use super::*; + + reuse Trait::<'_, 'static, _, _, _>::foo as foo1; + reuse Trait::<'_, '_, _, _, _>::foo as foo2; + + reuse Trait::<'_, (), _, '_, _>::foo as foo3; + //~^ ERROR: trait takes 2 lifetime arguments but 1 lifetime argument was supplied [E0107] + //~| ERROR: trait takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::<>::foo as foo4; + + reuse Trait::<_, _>::foo as foo5; + //~^ ERROR: trait takes 3 generic arguments but 0 generic arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected '_, found: _ + + reuse Trait::<'_, '_>::foo as foo6; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions + + reuse Trait::<'_, '_, Vec<_>, 123, Vec>>::foo as foo7; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + + reuse Trait::<'static, 'static, (), 123, ()>::foo as foo8; + reuse Trait::<'static, 'static, _, _, _>::foo as foo9; + + reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo as foo10; + //~^ ERROR: trait takes 3 generic arguments but 7 generic arguments were supplied + + reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_, '_>::foo as foo11; + //~^ ERROR: trait takes 2 lifetime arguments but 6 lifetime arguments were supplied + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::<'static, 'static, _>::foo as foo12; + //~^ ERROR: trait takes 3 generic arguments but 1 generic argument was supplied + } + + mod parent_and_child_random { + use super::*; + + reuse Trait::<'_, 'static, _, _, _>::foo::<> as foo1; + reuse Trait::<'_, '_, _, _, _>::foo::<'_, _, _, _> as foo2; + + reuse Trait::<'_, (), _, '_, _>::foo::<'static, String, _, _> as foo3; + //~^ ERROR: trait takes 2 lifetime arguments but 1 lifetime argument was supplied [E0107] + //~| ERROR: trait takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::<>::foo::<'_, _, 123, _> as foo4; + + reuse Trait::<_, _>::foo::<'_, '_, '_, _, _, _,> as foo5; + //~^ ERROR: trait takes 3 generic arguments but 0 generic arguments were supplied + //~| ERROR: method takes 3 generic arguments but 5 generic arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::<'_, '_>::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: method takes 3 generic arguments but 6 generic arguments were supplied [E0107] + //~| ERROR: method takes 1 lifetime argument but 3 lifetime arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::<'_, '_, Vec<_>, 123, Vec>>::foo::<_, '_, _, _> as foo7; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: wrong infer used: expected '_, found: _ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::<'static, 'static, (), 123, ()>::foo::<'_, '_, '_, '_> as foo8; + //~^ ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::<'static, 'static, _, _, _>::foo::<_> as foo9; + //~^ ERROR: method takes 3 generic arguments but 0 generic arguments were supplied + //~| ERROR: wrong infer used: expected '_, found: _ + + reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::, _, _, ()> as foo10; + //~^ ERROR: trait takes 3 generic arguments but 7 generic arguments were supplied [E0107] + //~| ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied [E0107] + //~| ERROR: method takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied [E0107] + //~| ERROR: struct takes at least 1 generic argument but 0 generic arguments were supplied [E0107] + + reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + //~^ ERROR: trait takes 2 lifetime arguments but 5 lifetime arguments were supplied [E0107] + //~| ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied [E0107] + //~| ERROR: method takes 3 generic arguments but 4 generic arguments were supplied [E0107] + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + //~| ERROR: wrong infer used: expected _, found: '_ + + reuse Trait::<'static, 'static, _>::foo::<'____, ___, _, ___> as foo12; + //~^ ERROR: cannot find type `___` in this scope + //~| ERROR: cannot find type `___` in this scope + //~| ERROR: use of undeclared lifetime name `'____` + //~| ERROR: trait takes 3 generic arguments but 1 generic argument was supplied + } +} + +mod trait_impl_to_free { + pub trait Trait<'a, 'b, X, const C: usize, Y> { + fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self) {} + } + + struct S; + impl<'a, 'b, X, const C: usize, Y> Trait<'a, 'b, X, C, Y> for S {} + + mod to_reuse { + pub fn foo(_: ()) {} + } + + struct F1(S); + impl<'a, 'b, X, const C: usize, Y> Trait<'a, 'b, X, C, Y> for F1 { + reuse to_reuse::foo::<_, _, _> { self.0 } + //~^ ERROR: mismatched types + } + + struct F2(S); + impl<'a, 'b, X, const C: usize, Y> Trait<'a, 'b, X, C, Y> for F2 { + reuse to_reuse::foo { self.0 } + //~^ ERROR: mismatched types + //~| ERROR: function takes 0 lifetime arguments but 1 lifetime argument was supplied + } + + struct F3(S); + impl<'a, 'b, X, const C: usize, Y> Trait<'a, 'b, X, C, Y> for F3 { + reuse to_reuse::foo::<(), 123, ()> { self.0 } + //~^ ERROR: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/delegation/generics/infers.stderr b/tests/ui/delegation/generics/infers.stderr new file mode 100644 index 0000000000000..1ab3ef232832e --- /dev/null +++ b/tests/ui/delegation/generics/infers.stderr @@ -0,0 +1,1296 @@ +error: lifetimes must be followed by `+` to form a trait object type + --> $DIR/infers.rs:54:21 + | +LL | reuse foo::('_, _, _, _) as bar; + | ^^ + | +help: consider adding a trait bound after the potential lifetime bound + | +LL | reuse foo::('_ + /* Trait */, _, _, _) as bar; + | +++++++++++++ + +error[E0261]: use of undeclared lifetime name `'____` + --> $DIR/infers.rs:123:17 + | +LL | reuse foo::<'____, ___, _, ___> as foo12; + | ^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'____` here + | +LL | reuse foo'____, ::<'____, ___, _, ___> as foo12; + | ++++++ + +error[E0261]: use of undeclared lifetime name `'____` + --> $DIR/infers.rs:195:28 + | +LL | reuse Trait::foo::<'____, ___, _, ___> as foo12; + | ^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'____` here + | +LL | reuse Trait::foo'____, ::<'____, ___, _, ___> as foo12; + | ++++++ + +error[E0261]: use of undeclared lifetime name `'____` + --> $DIR/infers.rs:316:51 + | +LL | reuse Trait::<'static, 'static, _>::foo::<'____, ___, _, ___> as foo12; + | ^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'____` here + | +LL | reuse Trait::<'static, 'static, _>::foo'____, ::<'____, ___, _, ___> as foo12; + | ++++++ + +error[E0425]: cannot find type `___` in this scope + --> $DIR/infers.rs:123:24 + | +LL | reuse foo::<'____, ___, _, ___> as foo12; + | ^^^ not found in this scope + +error[E0425]: cannot find type `___` in this scope + --> $DIR/infers.rs:123:32 + | +LL | reuse foo::<'____, ___, _, ___> as foo12; + | ^^^ not found in this scope + +error[E0425]: cannot find type `unresolved_` in this scope + --> $DIR/infers.rs:132:21 + | +LL | reuse foo::<'_, unresolved_, _, _> as foo14; + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `___` in this scope + --> $DIR/infers.rs:195:35 + | +LL | reuse Trait::foo::<'____, ___, _, ___> as foo12; + | ^^^ not found in this scope + +error[E0425]: cannot find type `___` in this scope + --> $DIR/infers.rs:195:43 + | +LL | reuse Trait::foo::<'____, ___, _, ___> as foo12; + | ^^^ not found in this scope + +error[E0425]: cannot find type `unresolved_` in this scope + --> $DIR/infers.rs:204:32 + | +LL | reuse Trait::foo::<'_, unresolved_, _, _> as foo14; + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `___` in this scope + --> $DIR/infers.rs:316:58 + | +LL | reuse Trait::<'static, 'static, _>::foo::<'____, ___, _, ___> as foo12; + | ^^^ not found in this scope + +error[E0425]: cannot find type `___` in this scope + --> $DIR/infers.rs:316:66 + | +LL | reuse Trait::<'static, 'static, _>::foo::<'____, ___, _, ___> as foo12; + | ^^^ not found in this scope + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:11:21 + | +LL | reuse foo::<_, '_, '_, '_> as bar; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:11:24 + | +LL | reuse foo::<_, '_, '_, '_> as bar; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:11:28 + | +LL | reuse foo::<_, '_, '_, '_> as bar; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:11:32 + | +LL | reuse foo::<_, '_, '_, '_> as bar; + | ^^ + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/infers.rs:54:15 + | +LL | reuse foo::('_, _, _, _) as bar; + | ^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL - reuse foo::('_, _, _, _) as bar; +LL + reuse foo::<'_, _, _, _> as bar; + | + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:86:21 + | +LL | reuse foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:86:25 + | +LL | reuse foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:91:17 + | +LL | reuse foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:91:26 + | +LL | reuse foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:97:17 + | +LL | reuse foo::<_, '_, _, _> as foo7; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:97:20 + | +LL | reuse foo::<_, '_, _, _> as foo7; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:101:21 + | +LL | reuse foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:101:25 + | +LL | reuse foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:101:29 + | +LL | reuse foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:106:17 + | +LL | reuse foo::<_> as foo9; + | ^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:135:17 + | +LL | reuse foo::<_, _, _> as foo15; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:158:32 + | +LL | reuse Trait::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:158:36 + | +LL | reuse Trait::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:163:28 + | +LL | reuse Trait::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:163:37 + | +LL | reuse Trait::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:169:28 + | +LL | reuse Trait::foo::<_, '_, _, _> as foo7; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:169:31 + | +LL | reuse Trait::foo::<_, '_, _, _> as foo7; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:173:32 + | +LL | reuse Trait::foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:173:36 + | +LL | reuse Trait::foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:173:40 + | +LL | reuse Trait::foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:178:28 + | +LL | reuse Trait::foo::<_> as foo9; + | ^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:207:28 + | +LL | reuse Trait::foo::<_, _, _> as foo15; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:218:34 + | +LL | reuse Trait::<'_, (), _, '_, _>::foo as foo3; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:226:23 + | +LL | reuse Trait::<_, _>::foo as foo5; + | ^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:226:26 + | +LL | reuse Trait::<_, _>::foo as foo5; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:244:41 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_, '_>::foo as foo11; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:244:44 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_, '_>::foo as foo11; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:244:48 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_, '_>::foo as foo11; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:260:34 + | +LL | reuse Trait::<'_, (), _, '_, _>::foo::<'static, String, _, _> as foo3; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:268:23 + | +LL | reuse Trait::<_, _>::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:268:26 + | +LL | reuse Trait::<_, _>::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:268:40 + | +LL | reuse Trait::<_, _>::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:268:44 + | +LL | reuse Trait::<_, _>::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:276:38 + | +LL | reuse Trait::<'_, '_>::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:276:47 + | +LL | reuse Trait::<'_, '_>::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:283:64 + | +LL | reuse Trait::<'_, '_, Vec<_>, 123, Vec>>::foo::<_, '_, _, _> as foo7; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:283:67 + | +LL | reuse Trait::<'_, '_, Vec<_>, 123, Vec>>::foo::<_, '_, _, _> as foo7; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:289:65 + | +LL | reuse Trait::<'static, 'static, (), 123, ()>::foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:289:69 + | +LL | reuse Trait::<'static, 'static, (), 123, ()>::foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:289:73 + | +LL | reuse Trait::<'static, 'static, (), 123, ()>::foo::<'_, '_, '_, '_> as foo8; + | ^^ + +error: wrong infer used: expected '_, found: _ + --> $DIR/infers.rs:294:57 + | +LL | reuse Trait::<'static, 'static, _, _, _>::foo::<_> as foo9; + | ^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:306:41 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:306:44 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + | ^^ + +error: wrong infer used: expected _, found: '_ + --> $DIR/infers.rs:306:48 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + | ^^ + +error[E0107]: function takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/infers.rs:44:15 + | +LL | reuse foo::<'_, '_> as foo2; + | ^^^--------- help: remove the lifetime argument + | | + | expected 1 lifetime argument + | +note: function defined here, with 1 lifetime parameter: `'c` + --> $DIR/infers.rs:38:12 + | +LL | fn foo<'a, 'b, 'c: 'c, 'd>(_: &'a &'b &'c &'d ()) {} + | ^^^ -- + +error[E0107]: function takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/infers.rs:54:15 + | +LL | reuse foo::('_, _, _, _) as bar; + | ^^^ expected 1 lifetime argument + | +note: function defined here, with 1 lifetime parameter: `'b` + --> $DIR/infers.rs:52:12 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ -- +help: add missing lifetime argument + | +LL | reuse foo::('b, '_, _, _, _) as bar; + | +++ + +error[E0107]: function takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:54:15 + | +LL | reuse foo::('_, _, _, _) as bar; + | ^^^ --- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `X`, `M`, `Y` + --> $DIR/infers.rs:52:12 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ - -------------- - + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:54:15 + | +LL | reuse foo::('_, _, _, _) as bar; + | ^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/infers.rs:54:21 + | +LL | reuse foo::('_, _, _, _) as bar; + | ^^ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:54:25 + | +LL | reuse foo::('_, _, _, _) as bar; + | ^ not allowed in type signatures + +error[E0107]: function takes 3 generic arguments but 5 generic arguments were supplied + --> $DIR/infers.rs:86:11 + | +LL | reuse foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^^---------------------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `X`, `M`, `Y` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ - -------------- - + +error[E0107]: function takes 1 lifetime argument but 3 lifetime arguments were supplied + --> $DIR/infers.rs:91:11 + | +LL | reuse foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^^---------------------- help: remove the lifetime arguments + | | + | expected 1 lifetime argument + | +note: function defined here, with 1 lifetime parameter: `'b` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ -- + +error[E0107]: function takes 3 generic arguments but 6 generic arguments were supplied + --> $DIR/infers.rs:91:11 + | +LL | reuse foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^^------------------------------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `X`, `M`, `Y` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ - -------------- - + +error[E0107]: function takes 3 generic arguments but 0 generic arguments were supplied + --> $DIR/infers.rs:106:11 + | +LL | reuse foo::<_> as foo9; + | ^^^ expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `X`, `M`, `Y` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ - -------------- - +help: add missing generic arguments + | +LL | reuse fooX, M, Y::<_> as foo9; + | +++++++ + +error[E0107]: function takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/infers.rs:110:11 + | +LL | reuse foo::, _, _, ()> as foo10; + | ^^^ expected 1 lifetime argument + | +note: function defined here, with 1 lifetime parameter: `'b` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ -- +help: add missing lifetime argument + | +LL | reuse foo::<'b, Vec<'_>, _, _, ()> as foo10; + | +++ + +error[E0107]: function takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:110:11 + | +LL | reuse foo::, _, _, ()> as foo10; + | ^^^-------------------- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `X`, `M`, `Y` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ - -------------- - + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:110:11 + | +LL | reuse foo::, _, _, ()> as foo10; + | ^^^ + +error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/infers.rs:110:17 + | +LL | reuse foo::, _, _, ()> as foo10; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 lifetime arguments + +error[E0107]: struct takes at least 1 generic argument but 0 generic arguments were supplied + --> $DIR/infers.rs:110:17 + | +LL | reuse foo::, _, _, ()> as foo10; + | ^^^ expected at least 1 generic argument + | +help: add missing generic argument + | +LL | reuse foo::, _, _, ()> as foo10; + | +++ + +error[E0107]: function takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/infers.rs:117:11 + | +LL | reuse foo::, _, _, ()> as foo11; + | ^^^ expected 1 lifetime argument + | +note: function defined here, with 1 lifetime parameter: `'b` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ -- +help: add missing lifetime argument + | +LL | reuse foo::<'b, Vec<_>, _, _, ()> as foo11; + | +++ + +error[E0107]: function takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:117:11 + | +LL | reuse foo::, _, _, ()> as foo11; + | ^^^------------------- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: function defined here, with 3 generic parameters: `X`, `M`, `Y` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ - -------------- - + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:117:11 + | +LL | reuse foo::, _, _, ()> as foo11; + | ^^^ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:117:21 + | +LL | reuse foo::, _, _, ()> as foo11; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:128:25 + | +LL | reuse foo::<'_, Vec<_>, Vec>, _> as foo13; + | ^ not allowed in type signatures + +error[E0747]: type provided when a constant was expected + --> $DIR/infers.rs:128:29 + | +LL | reuse foo::<'_, Vec<_>, Vec>, _> as foo13; + | ^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | reuse foo::<'_, Vec<_>, { Vec> }, _> as foo13; + | + + + +error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied + --> $DIR/infers.rs:135:11 + | +LL | reuse foo::<_, _, _> as foo15; + | ^^^ + | | + | expected 3 generic arguments + | supplied 2 generic arguments + | +note: function defined here, with 3 generic parameters: `X`, `M`, `Y` + --> $DIR/infers.rs:79:8 + | +LL | fn foo<'a, 'b: 'b, 'c, X, const M: usize, Y>(_: &'a &'b &'c ()) {} + | ^^^ - -------------- - +help: add missing generic argument + | +LL | reuse fooY::<_, _, _> as foo15; + | + + +error[E0207]: the type parameter `Some` is not constrained by the impl trait, self type, or predicates + --> $DIR/infers.rs:146:18 + | +LL | impl<'a, 'b, Some, Params, X, const C: usize, Y> Trait<'a, 'b, X, C, Y> for X {} + | ^^^^ unconstrained type parameter + +error[E0207]: the type parameter `Params` is not constrained by the impl trait, self type, or predicates + --> $DIR/infers.rs:146:24 + | +LL | impl<'a, 'b, Some, Params, X, const C: usize, Y> Trait<'a, 'b, X, C, Y> for X {} + | ^^^^^^ unconstrained type parameter + +error[E0107]: method takes 3 generic arguments but 5 generic arguments were supplied + --> $DIR/infers.rs:158:22 + | +LL | reuse Trait::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^^---------------------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- + +error[E0107]: method takes 1 lifetime argument but 3 lifetime arguments were supplied + --> $DIR/infers.rs:163:22 + | +LL | reuse Trait::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^^---------------------- help: remove the lifetime arguments + | | + | expected 1 lifetime argument + | +note: method defined here, with 1 lifetime parameter: `'bb` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ --- + +error[E0107]: method takes 3 generic arguments but 6 generic arguments were supplied + --> $DIR/infers.rs:163:22 + | +LL | reuse Trait::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^^------------------------------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- + +error[E0107]: method takes 3 generic arguments but 0 generic arguments were supplied + --> $DIR/infers.rs:178:22 + | +LL | reuse Trait::foo::<_> as foo9; + | ^^^ expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- +help: add missing generic arguments + | +LL | reuse Trait::fooXX, M, YY::<_> as foo9; + | +++++++++ + +error[E0107]: method takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/infers.rs:182:22 + | +LL | reuse Trait::foo::, _, _, ()> as foo10; + | ^^^ expected 1 lifetime argument + | +note: method defined here, with 1 lifetime parameter: `'bb` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ --- +help: add missing lifetime argument + | +LL | reuse Trait::foo::<'a, Vec<'_>, _, _, ()> as foo10; + | +++ + +error[E0107]: method takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:182:22 + | +LL | reuse Trait::foo::, _, _, ()> as foo10; + | ^^^-------------------- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:182:22 + | +LL | reuse Trait::foo::, _, _, ()> as foo10; + | ^^^ + +error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/infers.rs:182:28 + | +LL | reuse Trait::foo::, _, _, ()> as foo10; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 lifetime arguments + +error[E0107]: struct takes at least 1 generic argument but 0 generic arguments were supplied + --> $DIR/infers.rs:182:28 + | +LL | reuse Trait::foo::, _, _, ()> as foo10; + | ^^^ expected at least 1 generic argument + | +help: add missing generic argument + | +LL | reuse Trait::foo::, _, _, ()> as foo10; + | +++ + +error[E0107]: method takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/infers.rs:189:22 + | +LL | reuse Trait::foo::, _, _, ()> as foo11; + | ^^^ expected 1 lifetime argument + | +note: method defined here, with 1 lifetime parameter: `'bb` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ --- +help: add missing lifetime argument + | +LL | reuse Trait::foo::<'a, Vec<_>, _, _, ()> as foo11; + | +++ + +error[E0107]: method takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:189:22 + | +LL | reuse Trait::foo::, _, _, ()> as foo11; + | ^^^------------------- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:189:22 + | +LL | reuse Trait::foo::, _, _, ()> as foo11; + | ^^^ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:189:32 + | +LL | reuse Trait::foo::, _, _, ()> as foo11; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:200:36 + | +LL | reuse Trait::foo::<'_, Vec<_>, Vec>, _> as foo13; + | ^ not allowed in type signatures + +error[E0747]: type provided when a constant was expected + --> $DIR/infers.rs:200:40 + | +LL | reuse Trait::foo::<'_, Vec<_>, Vec>, _> as foo13; + | ^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | reuse Trait::foo::<'_, Vec<_>, { Vec> }, _> as foo13; + | + + + +error[E0107]: method takes 3 generic arguments but 2 generic arguments were supplied + --> $DIR/infers.rs:207:22 + | +LL | reuse Trait::foo::<_, _, _> as foo15; + | ^^^ + | | + | expected 3 generic arguments + | supplied 2 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- +help: add missing generic argument + | +LL | reuse Trait::fooYY::<_, _, _> as foo15; + | ++ + +error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/infers.rs:218:15 + | +LL | reuse Trait::<'_, (), _, '_, _>::foo as foo3; + | ^^^^^ --- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ -- -- +help: add missing lifetime argument + | +LL | reuse Trait::<'_, (), _, '_, _>::foo, 'a as foo3; + | ++++ + +error[E0107]: trait takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:218:15 + | +LL | reuse Trait::<'_, (), _, '_, _>::foo as foo3; + | ^^^^^ --- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: trait defined here, with 3 generic parameters: `X`, `C`, `Y` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ - -------------- - + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:218:15 + | +LL | reuse Trait::<'_, (), _, '_, _>::foo as foo3; + | ^^^^^ + +error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied + --> $DIR/infers.rs:226:15 + | +LL | reuse Trait::<_, _>::foo as foo5; + | ^^^^^ expected 3 generic arguments + | +note: trait defined here, with 3 generic parameters: `X`, `C`, `Y` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ - -------------- - +help: add missing generic arguments + | +LL | reuse Trait::<_, _>::foo, X, C, Y as foo5; + | +++++++++ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:231:15 + | +LL | reuse Trait::<'_, '_>::foo as foo6; + | ^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:234:35 + | +LL | reuse Trait::<'_, '_, Vec<_>, 123, Vec>>::foo as foo7; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:234:52 + | +LL | reuse Trait::<'_, '_, Vec<_>, 123, Vec>>::foo as foo7; + | ^ not allowed in type signatures + +error[E0107]: trait takes 3 generic arguments but 7 generic arguments were supplied + --> $DIR/infers.rs:241:15 + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo as foo10; + | ^^^^^ expected 3 generic arguments ------- help: remove the unnecessary generic arguments + | +note: trait defined here, with 3 generic parameters: `X`, `C`, `Y` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ - -------------- - + +error[E0107]: trait takes 2 lifetime arguments but 6 lifetime arguments were supplied + --> $DIR/infers.rs:244:15 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_, '_>::foo as foo11; + | ^^^^^ --------------------------- help: remove the lifetime arguments + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ -- -- + +error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied + --> $DIR/infers.rs:250:15 + | +LL | reuse Trait::<'static, 'static, _>::foo as foo12; + | ^^^^^ --- supplied 1 generic argument + | | + | expected 3 generic arguments + | +note: trait defined here, with 3 generic parameters: `X`, `C`, `Y` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ - -------------- - +help: add missing generic arguments + | +LL | reuse Trait::<'static, 'static, _>::foo, C, Y as foo12; + | ++++++ + +error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/infers.rs:260:15 + | +LL | reuse Trait::<'_, (), _, '_, _>::foo::<'static, String, _, _> as foo3; + | ^^^^^ --- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ -- -- +help: add missing lifetime argument + | +LL | reuse Trait::<'_, (), _, '_, _>::foo, 'a::<'static, String, _, _> as foo3; + | ++++ + +error[E0107]: trait takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:260:15 + | +LL | reuse Trait::<'_, (), _, '_, _>::foo::<'static, String, _, _> as foo3; + | ^^^^^ --- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: trait defined here, with 3 generic parameters: `X`, `C`, `Y` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ - -------------- - + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:260:15 + | +LL | reuse Trait::<'_, (), _, '_, _>::foo::<'static, String, _, _> as foo3; + | ^^^^^ + +error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied + --> $DIR/infers.rs:268:15 + | +LL | reuse Trait::<_, _>::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^^^^ expected 3 generic arguments + | +note: trait defined here, with 3 generic parameters: `X`, `C`, `Y` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ - -------------- - +help: add missing generic arguments + | +LL | reuse Trait::<_, _>::foo, X, C, Y::<'_, '_, '_, _, _, _,> as foo5; + | +++++++++ + +error[E0107]: method takes 3 generic arguments but 5 generic arguments were supplied + --> $DIR/infers.rs:268:30 + | +LL | reuse Trait::<_, _>::foo::<'_, '_, '_, _, _, _,> as foo5; + | ^^^---------------------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:276:15 + | +LL | reuse Trait::<'_, '_>::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^^^^ not allowed in type signatures + +error[E0107]: method takes 1 lifetime argument but 3 lifetime arguments were supplied + --> $DIR/infers.rs:276:32 + | +LL | reuse Trait::<'_, '_>::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^^---------------------- help: remove the lifetime arguments + | | + | expected 1 lifetime argument + | +note: method defined here, with 1 lifetime parameter: `'bb` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ --- + +error[E0107]: method takes 3 generic arguments but 6 generic arguments were supplied + --> $DIR/infers.rs:276:32 + | +LL | reuse Trait::<'_, '_>::foo::<_, _, _, '_, '_, '_, _, _, _,> as foo6; + | ^^^------------------------------- help: remove the unnecessary generic arguments + | | + | expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:283:35 + | +LL | reuse Trait::<'_, '_, Vec<_>, 123, Vec>>::foo::<_, '_, _, _> as foo7; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:283:52 + | +LL | reuse Trait::<'_, '_, Vec<_>, 123, Vec>>::foo::<_, '_, _, _> as foo7; + | ^ not allowed in type signatures + +error[E0107]: method takes 3 generic arguments but 0 generic arguments were supplied + --> $DIR/infers.rs:294:51 + | +LL | reuse Trait::<'static, 'static, _, _, _>::foo::<_> as foo9; + | ^^^ expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- +help: add missing generic arguments + | +LL | reuse Trait::<'static, 'static, _, _, _>::fooXX, M, YY::<_> as foo9; + | +++++++++ + +error[E0107]: trait takes 3 generic arguments but 7 generic arguments were supplied + --> $DIR/infers.rs:298:15 + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::, _, _, ()> as foo10; + | ^^^^^ expected 3 generic arguments ------- help: remove the unnecessary generic arguments + | +note: trait defined here, with 3 generic parameters: `X`, `C`, `Y` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ - -------------- - + +error[E0107]: method takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/infers.rs:298:63 + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::, _, _, ()> as foo10; + | ^^^ expected 1 lifetime argument + | +note: method defined here, with 1 lifetime parameter: `'bb` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ --- +help: add missing lifetime argument + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::<'bb, Vec<'_>, _, _, ()> as foo10; + | ++++ + +error[E0107]: method takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:298:63 + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::, _, _, ()> as foo10; + | ^^^-------------------- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:298:63 + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::, _, _, ()> as foo10; + | ^^^ + +error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/infers.rs:298:69 + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::, _, _, ()> as foo10; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 lifetime arguments + +error[E0107]: struct takes at least 1 generic argument but 0 generic arguments were supplied + --> $DIR/infers.rs:298:69 + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::, _, _, ()> as foo10; + | ^^^ expected at least 1 generic argument + | +help: add missing generic argument + | +LL | reuse Trait::<'static, 'static, _, _, _, _, _, _, _>::foo::, _, _, ()> as foo10; + | +++ + +error[E0107]: trait takes 2 lifetime arguments but 5 lifetime arguments were supplied + --> $DIR/infers.rs:306:15 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + | ^^^^^ ----------------------- help: remove the lifetime arguments + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ -- -- + +error[E0107]: method takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/infers.rs:306:65 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + | ^^^ expected 1 lifetime argument + | +note: method defined here, with 1 lifetime parameter: `'bb` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ --- +help: add missing lifetime argument + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::<'bb, Vec<_>, _, _, ()> as foo11; + | ++++ + +error[E0107]: method takes 3 generic arguments but 4 generic arguments were supplied + --> $DIR/infers.rs:306:65 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + | ^^^------------------- help: remove the unnecessary generic argument + | | + | expected 3 generic arguments + | +note: method defined here, with 3 generic parameters: `XX`, `M`, `YY` + --> $DIR/infers.rs:142:12 + | +LL | fn foo<'aa, 'bb: 'bb, 'cc, XX, const M: usize, YY>(&self, _: &'aa &'b &'cc ()) {} + | ^^^ -- -------------- -- + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/infers.rs:306:65 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + | ^^^ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/infers.rs:306:75 + | +LL | reuse Trait::<'static, 'static, '_,'_, '_, '_, '_, '_>::foo::, _, _, ()> as foo11; + | ^ not allowed in type signatures + +error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied + --> $DIR/infers.rs:316:15 + | +LL | reuse Trait::<'static, 'static, _>::foo::<'____, ___, _, ___> as foo12; + | ^^^^^ --- supplied 1 generic argument + | | + | expected 3 generic arguments + | +note: trait defined here, with 3 generic parameters: `X`, `C`, `Y` + --> $DIR/infers.rs:141:15 + | +LL | pub trait Trait<'a, 'b, X, const C: usize, Y> { + | ^^^^^ - -------------- - +help: add missing generic arguments + | +LL | reuse Trait::<'static, 'static, _>::foo, C, Y::<'____, ___, _, ___> as foo12; + | ++++++ + +error[E0308]: mismatched types + --> $DIR/infers.rs:338:42 + | +LL | reuse to_reuse::foo::<_, _, _> { self.0 } + | --- ^^^^^^ expected `()`, found `S` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/infers.rs:333:16 + | +LL | pub fn foo(_: ()) {} + | ^^^ ----- + +error[E0107]: function takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/infers.rs:344:25 + | +LL | reuse to_reuse::foo { self.0 } + | ^^^ + | | + | expected 0 lifetime arguments + | help: remove the lifetime argument + | +note: function defined here, with 0 lifetime parameters + --> $DIR/infers.rs:333:16 + | +LL | pub fn foo(_: ()) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/infers.rs:344:31 + | +LL | reuse to_reuse::foo { self.0 } + | --- ^^^^^^ expected `()`, found `S` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/infers.rs:333:16 + | +LL | pub fn foo(_: ()) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/infers.rs:351:46 + | +LL | reuse to_reuse::foo::<(), 123, ()> { self.0 } + | --- ^^^^^^ expected `()`, found `S` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/infers.rs:333:16 + | +LL | pub fn foo(_: ()) {} + | ^^^ ----- + +error: aborting due to 138 previous errors + +Some errors have detailed explanations: E0107, E0121, E0207, E0214, E0224, E0261, E0308, E0425, E0747. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/delegation/generics/trait-impl-wrong-args-count.rs b/tests/ui/delegation/generics/trait-impl-wrong-args-count.rs index 4073e5ce88607..7b33e1d16eadf 100644 --- a/tests/ui/delegation/generics/trait-impl-wrong-args-count.rs +++ b/tests/ui/delegation/generics/trait-impl-wrong-args-count.rs @@ -26,6 +26,7 @@ mod test_1 { reuse to_reuse::bar1; //~^ ERROR: function takes 0 generic arguments but 3 generic arguments were supplied + //~| ERROR: function takes 0 lifetime arguments but 2 lifetime arguments were supplied reuse to_reuse::bar2; //~^ ERROR: type annotations needed @@ -59,8 +60,10 @@ mod test_2 { impl Trait for X { reuse ::bar; //~^ ERROR: missing generics for trait + //~| ERROR: associated function takes 1 lifetime argument but 2 lifetime arguments were supplied reuse >::bar as bar1; + //~^ ERROR: associated function takes 1 lifetime argument but 2 lifetime arguments were supplied reuse >::bar::<'static, u32, u32, 1> as bar2; @@ -94,9 +97,11 @@ mod test_3 { impl Trait for X { reuse >::bar; //~^ ERROR: associated function takes 0 generic arguments but 3 generic arguments were supplied + //~| ERROR: associated function takes 0 lifetime arguments but 2 lifetime arguments were supplied reuse >::bar as bar1; //~^ ERROR: associated function takes 0 generic arguments but 3 generic arguments were supplied + //~| ERROR: associated function takes 0 lifetime arguments but 2 lifetime arguments were supplied reuse >::foo as bar2; //~^ ERROR: type annotations needed diff --git a/tests/ui/delegation/generics/trait-impl-wrong-args-count.stderr b/tests/ui/delegation/generics/trait-impl-wrong-args-count.stderr index 09281768bbf73..931b61ef0ca85 100644 --- a/tests/ui/delegation/generics/trait-impl-wrong-args-count.stderr +++ b/tests/ui/delegation/generics/trait-impl-wrong-args-count.stderr @@ -13,11 +13,29 @@ note: function defined here, with at most 2 generic parameters: `A`, `B` LL | pub fn bar<'a: 'a, 'b: 'b, A, B>(x: &super::XX) {} | ^^^ - - +error[E0107]: function takes 0 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/trait-impl-wrong-args-count.rs:27:25 + | +LL | reuse to_reuse::bar1; + | ^^^^ + | | + | expected 0 lifetime arguments + | help: remove the lifetime arguments + | +note: function defined here, with 0 lifetime parameters + --> $DIR/trait-impl-wrong-args-count.rs:7:16 + | +LL | pub fn bar1(x: &super::XX) {} + | ^^^^ + error[E0107]: function takes 0 generic arguments but 3 generic arguments were supplied --> $DIR/trait-impl-wrong-args-count.rs:27:25 | LL | reuse to_reuse::bar1; - | ^^^^ expected 0 generic arguments + | ^^^^ + | | + | expected 0 generic arguments + | help: remove the unnecessary generic arguments | note: function defined here, with 0 generic parameters --> $DIR/trait-impl-wrong-args-count.rs:7:16 @@ -26,7 +44,7 @@ LL | pub fn bar1(x: &super::XX) {} | ^^^^ error[E0284]: type annotations needed - --> $DIR/trait-impl-wrong-args-count.rs:30:25 + --> $DIR/trait-impl-wrong-args-count.rs:31:25 | LL | reuse to_reuse::bar2; | ^^^^ cannot infer the value of the const parameter `X` declared on the function `bar2` @@ -42,7 +60,7 @@ LL | reuse to_reuse::bar2::; | ++++++++++++++++++++++++++ error[E0284]: type annotations needed - --> $DIR/trait-impl-wrong-args-count.rs:30:25 + --> $DIR/trait-impl-wrong-args-count.rs:31:25 | LL | reuse to_reuse::bar2; | ^^^^ cannot infer the value of the const parameter `Y` declared on the function `bar2` @@ -58,13 +76,13 @@ LL | reuse to_reuse::bar2::; | ++++++++++++++++++++++++++ error[E0107]: missing generics for trait `test_2::Trait1` - --> $DIR/trait-impl-wrong-args-count.rs:60:21 + --> $DIR/trait-impl-wrong-args-count.rs:61:21 | LL | reuse ::bar; | ^^^^^^ expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `A`, `B` - --> $DIR/trait-impl-wrong-args-count.rs:51:11 + --> $DIR/trait-impl-wrong-args-count.rs:52:11 | LL | trait Trait1 { | ^^^^^^ - - @@ -73,14 +91,44 @@ help: add missing generic arguments LL | reuse >::bar; | ++++++ +error[E0107]: associated function takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/trait-impl-wrong-args-count.rs:61:30 + | +LL | reuse ::bar; + | ^^^ + | | + | expected 1 lifetime argument + | help: remove the lifetime argument + | +note: associated function defined here, with 1 lifetime parameter: `'x` + --> $DIR/trait-impl-wrong-args-count.rs:53:12 + | +LL | fn bar<'x: 'x, AA, BB, const NN: usize>() {} + | ^^^ -- + +error[E0107]: associated function takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/trait-impl-wrong-args-count.rs:65:44 + | +LL | reuse >::bar as bar1; + | ^^^ + | | + | expected 1 lifetime argument + | help: remove the lifetime argument + | +note: associated function defined here, with 1 lifetime parameter: `'x` + --> $DIR/trait-impl-wrong-args-count.rs:53:12 + | +LL | fn bar<'x: 'x, AA, BB, const NN: usize>() {} + | ^^^ -- + error[E0107]: missing generics for trait `test_2::Trait1` - --> $DIR/trait-impl-wrong-args-count.rs:67:21 + --> $DIR/trait-impl-wrong-args-count.rs:70:21 | LL | reuse ::bar::<'static, u32, u32, 1> as bar3; | ^^^^^^ expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `A`, `B` - --> $DIR/trait-impl-wrong-args-count.rs:51:11 + --> $DIR/trait-impl-wrong-args-count.rs:52:11 | LL | trait Trait1 { | ^^^^^^ - - @@ -90,13 +138,13 @@ LL | reuse >::bar::<'static, u32, u32, 1> as bar3; | ++++++ error[E0107]: missing generics for trait `test_2::Trait1` - --> $DIR/trait-impl-wrong-args-count.rs:70:21 + --> $DIR/trait-impl-wrong-args-count.rs:73:21 | LL | reuse ::bar as bar4; | ^^^^^^ expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `A`, `B` - --> $DIR/trait-impl-wrong-args-count.rs:51:11 + --> $DIR/trait-impl-wrong-args-count.rs:52:11 | LL | trait Trait1 { | ^^^^^^ - - @@ -105,38 +153,74 @@ help: add missing generic arguments LL | reuse >::bar as bar4; | ++++++ +error[E0107]: associated function takes 0 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/trait-impl-wrong-args-count.rs:98:40 + | +LL | reuse >::bar; + | ^^^ + | | + | expected 0 lifetime arguments + | help: remove the lifetime arguments + | +note: associated function defined here, with 0 lifetime parameters + --> $DIR/trait-impl-wrong-args-count.rs:89:12 + | +LL | fn bar() {} + | ^^^ + error[E0107]: associated function takes 0 generic arguments but 3 generic arguments were supplied - --> $DIR/trait-impl-wrong-args-count.rs:95:40 + --> $DIR/trait-impl-wrong-args-count.rs:98:40 | LL | reuse >::bar; - | ^^^ expected 0 generic arguments + | ^^^ + | | + | expected 0 generic arguments + | help: remove the unnecessary generic arguments | note: associated function defined here, with 0 generic parameters - --> $DIR/trait-impl-wrong-args-count.rs:86:12 + --> $DIR/trait-impl-wrong-args-count.rs:89:12 + | +LL | fn bar() {} + | ^^^ + +error[E0107]: associated function takes 0 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/trait-impl-wrong-args-count.rs:102:40 + | +LL | reuse >::bar as bar1; + | ^^^ + | | + | expected 0 lifetime arguments + | help: remove the lifetime arguments + | +note: associated function defined here, with 0 lifetime parameters + --> $DIR/trait-impl-wrong-args-count.rs:89:12 | LL | fn bar() {} | ^^^ error[E0107]: associated function takes 0 generic arguments but 3 generic arguments were supplied - --> $DIR/trait-impl-wrong-args-count.rs:98:40 + --> $DIR/trait-impl-wrong-args-count.rs:102:40 | LL | reuse >::bar as bar1; - | ^^^ expected 0 generic arguments + | ^^^ + | | + | expected 0 generic arguments + | help: remove the unnecessary generic arguments | note: associated function defined here, with 0 generic parameters - --> $DIR/trait-impl-wrong-args-count.rs:86:12 + --> $DIR/trait-impl-wrong-args-count.rs:89:12 | LL | fn bar() {} | ^^^ error[E0282]: type annotations needed - --> $DIR/trait-impl-wrong-args-count.rs:101:40 + --> $DIR/trait-impl-wrong-args-count.rs:106:40 | LL | reuse >::foo as bar2; | ^^^ cannot infer type of the type parameter `X` declared on the associated function `foo` error[E0107]: associated function takes at most 2 generic arguments but 3 generic arguments were supplied - --> $DIR/trait-impl-wrong-args-count.rs:104:40 + --> $DIR/trait-impl-wrong-args-count.rs:109:40 | LL | reuse >::foo as bar3; | ^^^ @@ -145,12 +229,12 @@ LL | reuse >::foo as bar3; | help: remove the unnecessary generic argument | note: associated function defined here, with at most 2 generic parameters: `X`, `Y` - --> $DIR/trait-impl-wrong-args-count.rs:87:12 + --> $DIR/trait-impl-wrong-args-count.rs:90:12 | LL | fn foo() {} | ^^^ - - -error: aborting due to 11 previous errors +error: aborting due to 16 previous errors Some errors have detailed explanations: E0107, E0282, E0284. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.rs b/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.rs index fad06b37ae416..1f97f7c652c35 100644 --- a/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.rs +++ b/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.rs @@ -1,3 +1,4 @@ +//@ check-pass //@ compile-flags: -Z deduplicate-diagnostics=yes #![feature(fn_delegation)] @@ -12,11 +13,8 @@ impl Trait for F {} struct S(F); impl S { reuse Trait::foo::<> { self.0 } - //~^ ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + reuse Trait::foo::<'_> as bar { self.0 } - //~^ ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature - //~| WARN: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - //~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } fn main() {} diff --git a/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.stderr b/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.stderr deleted file mode 100644 index 464b6a3a76819..0000000000000 --- a/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/unelided-lifetime-in-sig-ice-156848.rs:14:18 - | -LL | reuse Trait::foo::<> { self.0 } - | ^^^ - -warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/unelided-lifetime-in-sig-ice-156848.rs:16:24 - | -LL | fn foo<'a: 'a>(&self) {} - | - the late bound lifetime parameter is introduced here -... -LL | reuse Trait::foo::<'_> as bar { self.0 } - | ^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #42868 - = note: `#[warn(late_bound_lifetime_arguments)]` (part of `#[warn(future_incompatible)]`) on by default - -error: inferred lifetimes are not allowed in delegations as we need to inherit signature - --> $DIR/unelided-lifetime-in-sig-ice-156848.rs:16:24 - | -LL | reuse Trait::foo::<'_> as bar { self.0 } - | ^^ - -error: aborting due to 2 previous errors; 1 warning emitted - diff --git a/tests/ui/delegation/self-ty-ice-156388.rs b/tests/ui/delegation/self-ty-ice-156388.rs index 542f56867b2b2..74cad01236375 100644 --- a/tests/ui/delegation/self-ty-ice-156388.rs +++ b/tests/ui/delegation/self-ty-ice-156388.rs @@ -1,8 +1,9 @@ //@ compile-flags: -Z deduplicate-diagnostics=yes +#![feature(const_trait_impl)] #![feature(fn_delegation)] reuse Default::default; -//~^ ERROR: delegation self type is not specified +//~^ ERROR: the trait bound `Self: [const] Default` is not satisfied fn main() {} diff --git a/tests/ui/delegation/self-ty-ice-156388.stderr b/tests/ui/delegation/self-ty-ice-156388.stderr index c2323cf1c6082..a311635db608a 100644 --- a/tests/ui/delegation/self-ty-ice-156388.stderr +++ b/tests/ui/delegation/self-ty-ice-156388.stderr @@ -1,10 +1,14 @@ -error: delegation self type is not specified - --> $DIR/self-ty-ice-156388.rs:5:16 +error[E0277]: the trait bound `Self: [const] Default` is not satisfied + --> $DIR/self-ty-ice-156388.rs:6:16 | LL | reuse Default::default; | ^^^^^^^ | - = help: consider explicitly specifying self type: `reuse ::function` +help: consider restricting type parameter `Self` with trait `Default` + | +LL | reuse Default::default [const] std::default::Default; + | +++++++++++++++++++++++++++++ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/target-expr.rs b/tests/ui/delegation/target-expr.rs index 14232d194a740..b4b3a31f437fc 100644 --- a/tests/ui/delegation/target-expr.rs +++ b/tests/ui/delegation/target-expr.rs @@ -15,7 +15,6 @@ fn foo(x: i32) -> i32 { x } fn bar(_: T) { reuse Trait::static_method { - //~^ ERROR: delegation self type is not specified let _ = T::Default(); //~^ ERROR can't use generic parameters from outer item } diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr index 9126234a2c3cd..2ceefbf929b9f 100644 --- a/tests/ui/delegation/target-expr.stderr +++ b/tests/ui/delegation/target-expr.stderr @@ -1,18 +1,17 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/target-expr.rs:19:17 + --> $DIR/target-expr.rs:18:17 | LL | fn bar(_: T) { | - type parameter from outer item LL | reuse Trait::static_method { | ------------- generic parameter used in this inner delegated function -LL | LL | let _ = T::Default(); | ^ use of generic parameter from outer item | = note: nested items are independent from their parent item for everything except for privacy and name resolution error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/target-expr.rs:27:17 + --> $DIR/target-expr.rs:26:17 | LL | let x = y; | ^ @@ -20,7 +19,7 @@ LL | let x = y; = help: use the `|| { ... }` closure form instead error[E0424]: expected value, found module `self` - --> $DIR/target-expr.rs:34:5 + --> $DIR/target-expr.rs:33:5 | LL | fn main() { | ---- this function can't have a `self` parameter @@ -29,26 +28,18 @@ LL | self.0; | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0425]: cannot find value `x` in this scope - --> $DIR/target-expr.rs:36:13 + --> $DIR/target-expr.rs:35:13 | LL | let z = x; | ^ | help: the binding `x` is available in a different scope in the same function - --> $DIR/target-expr.rs:27:13 + --> $DIR/target-expr.rs:26:13 | LL | let x = y; | ^ -error: delegation self type is not specified - --> $DIR/target-expr.rs:17:18 - | -LL | reuse Trait::static_method { - | ^^^^^^^^^^^^^ - | - = help: consider explicitly specifying self type: `reuse ::function` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0401, E0424, E0425, E0434. For more information about an error, try `rustc --explain E0401`. diff --git a/tests/ui/delegation/unsupported.current.stderr b/tests/ui/delegation/unsupported.current.stderr index fdfd9251b4650..6cdd54e2e27fc 100644 --- a/tests/ui/delegation/unsupported.current.stderr +++ b/tests/ui/delegation/unsupported.current.stderr @@ -20,14 +20,6 @@ LL | reuse ToReuse::opaque_ret; = note: cycle used when checking assoc item `opaque::::opaque_ret` is compatible with trait definition = note: for more information, see and -error: delegation self type is not specified - --> $DIR/unsupported.rs:54:18 - | -LL | reuse Trait::foo; - | ^^^ - | - = help: consider explicitly specifying self type: `reuse ::function` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/delegation/unsupported.next.stderr b/tests/ui/delegation/unsupported.next.stderr index fdfd9251b4650..6cdd54e2e27fc 100644 --- a/tests/ui/delegation/unsupported.next.stderr +++ b/tests/ui/delegation/unsupported.next.stderr @@ -20,14 +20,6 @@ LL | reuse ToReuse::opaque_ret; = note: cycle used when checking assoc item `opaque::::opaque_ret` is compatible with trait definition = note: for more information, see and -error: delegation self type is not specified - --> $DIR/unsupported.rs:54:18 - | -LL | reuse Trait::foo; - | ^^^ - | - = help: consider explicitly specifying self type: `reuse ::function` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs index 3349c4ec27ab1..3da1206b5b2df 100644 --- a/tests/ui/delegation/unsupported.rs +++ b/tests/ui/delegation/unsupported.rs @@ -52,7 +52,6 @@ mod effects { } reuse Trait::foo; - //~^ ERROR: delegation self type is not specified } fn main() {} diff --git a/tests/ui/issues/issue-28561.rs b/tests/ui/derives/derive-compound-arities.rs similarity index 96% rename from tests/ui/issues/issue-28561.rs rename to tests/ui/derives/derive-compound-arities.rs index 642b2193a4f9b..704d6747f7e07 100644 --- a/tests/ui/issues/issue-28561.rs +++ b/tests/ui/derives/derive-compound-arities.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/28561 //@ check-pass #[derive(Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Clone, Copy)] struct Array { diff --git a/tests/ui/issues/issue-33571.rs b/tests/ui/derives/derive-error-identifies-unsafe-trait-name.rs similarity index 73% rename from tests/ui/issues/issue-33571.rs rename to tests/ui/derives/derive-error-identifies-unsafe-trait-name.rs index 2713f47ad2ff6..586c5acf21611 100644 --- a/tests/ui/issues/issue-33571.rs +++ b/tests/ui/derives/derive-error-identifies-unsafe-trait-name.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/33571 #[derive(Clone, Sync, //~ ERROR cannot find derive macro `Sync` in this scope //~| ERROR cannot find derive macro `Sync` in this scope diff --git a/tests/ui/issues/issue-33571.stderr b/tests/ui/derives/derive-error-identifies-unsafe-trait-name.stderr similarity index 69% rename from tests/ui/issues/issue-33571.stderr rename to tests/ui/derives/derive-error-identifies-unsafe-trait-name.stderr index 819a533ddbe2f..862571cb2aecd 100644 --- a/tests/ui/issues/issue-33571.stderr +++ b/tests/ui/derives/derive-error-identifies-unsafe-trait-name.stderr @@ -1,23 +1,23 @@ error: cannot find derive macro `Sync` in this scope - --> $DIR/issue-33571.rs:2:10 + --> $DIR/derive-error-identifies-unsafe-trait-name.rs:3:10 | LL | Sync, | ^^^^ | note: unsafe traits like `Sync` should be implemented explicitly - --> $DIR/issue-33571.rs:2:10 + --> $DIR/derive-error-identifies-unsafe-trait-name.rs:3:10 | LL | Sync, | ^^^^ error: cannot find derive macro `Sync` in this scope - --> $DIR/issue-33571.rs:2:10 + --> $DIR/derive-error-identifies-unsafe-trait-name.rs:3:10 | LL | Sync, | ^^^^ | note: unsafe traits like `Sync` should be implemented explicitly - --> $DIR/issue-33571.rs:2:10 + --> $DIR/derive-error-identifies-unsafe-trait-name.rs:3:10 | LL | Sync, | ^^^^ diff --git a/tests/ui/issues/issue-27340.rs b/tests/ui/derives/derived-trait-requires-field-impl.rs similarity index 70% rename from tests/ui/issues/issue-27340.rs rename to tests/ui/derives/derived-trait-requires-field-impl.rs index 9966c24a7441e..fb1a98c10d843 100644 --- a/tests/ui/issues/issue-27340.rs +++ b/tests/ui/derives/derived-trait-requires-field-impl.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/27340 struct Foo; #[derive(Copy, Clone)] struct Bar(Foo); diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/derives/derived-trait-requires-field-impl.stderr similarity index 88% rename from tests/ui/issues/issue-27340.stderr rename to tests/ui/derives/derived-trait-requires-field-impl.stderr index 3b4ad58b1f080..6ca75fac56937 100644 --- a/tests/ui/issues/issue-27340.stderr +++ b/tests/ui/derives/derived-trait-requires-field-impl.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-27340.rs:3:8 + --> $DIR/derived-trait-requires-field-impl.rs:4:8 | LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion @@ -7,7 +7,7 @@ LL | struct Bar(Foo); | ^^^ --- this field does not implement `Copy` error[E0277]: the trait bound `Foo: Clone` is not satisfied - --> $DIR/issue-27340.rs:3:12 + --> $DIR/derived-trait-requires-field-impl.rs:4:12 | LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion diff --git a/tests/ui/derives/hash-on-compound-types.rs b/tests/ui/derives/hash-on-compound-types.rs index 6d950df99d65c..be7094bccc4c3 100644 --- a/tests/ui/derives/hash-on-compound-types.rs +++ b/tests/ui/derives/hash-on-compound-types.rs @@ -1,5 +1,4 @@ -//! Regression test for . - +//! Regression test for https://github.com/rust-lang/rust/issues/21402 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-32324.rs b/tests/ui/derives/no-ice-on-derived-copy-with-associated-type-field.rs similarity index 83% rename from tests/ui/issues/issue-32324.rs rename to tests/ui/derives/no-ice-on-derived-copy-with-associated-type-field.rs index 50ecfe993d438..755ec1f9d5229 100644 --- a/tests/ui/issues/issue-32324.rs +++ b/tests/ui/derives/no-ice-on-derived-copy-with-associated-type-field.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/32324 //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/issues/issue-46101.rs b/tests/ui/derives/no-ice-on-path-style-derive-macro.rs similarity index 65% rename from tests/ui/issues/issue-46101.rs rename to tests/ui/derives/no-ice-on-path-style-derive-macro.rs index 86b06f7c61d0a..664fe3f241115 100644 --- a/tests/ui/issues/issue-46101.rs +++ b/tests/ui/derives/no-ice-on-path-style-derive-macro.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/46101 trait Foo {} #[derive(Foo::Anything)] //~ ERROR cannot find //~| ERROR cannot find diff --git a/tests/ui/issues/issue-46101.stderr b/tests/ui/derives/no-ice-on-path-style-derive-macro.stderr similarity index 83% rename from tests/ui/issues/issue-46101.stderr rename to tests/ui/derives/no-ice-on-path-style-derive-macro.stderr index 1dada87d72d64..3e05d7b384704 100644 --- a/tests/ui/issues/issue-46101.stderr +++ b/tests/ui/derives/no-ice-on-path-style-derive-macro.stderr @@ -1,11 +1,11 @@ error[E0433]: cannot find derive macro `Anything` in trait `Foo` - --> $DIR/issue-46101.rs:2:10 + --> $DIR/no-ice-on-path-style-derive-macro.rs:3:10 | LL | #[derive(Foo::Anything)] | ^^^^^^^^^^^^^ a derive macro can't exist within a trait error[E0433]: cannot find derive macro `Anything` in trait `Foo` - --> $DIR/issue-46101.rs:2:10 + --> $DIR/no-ice-on-path-style-derive-macro.rs:3:10 | LL | #[derive(Foo::Anything)] | ^^^^^^^^^^^^^ a derive macro can't exist within a trait diff --git a/tests/ui/issues/issue-32292.rs b/tests/ui/derives/no-spurious-unused-variable-warning-on-derive-hash.rs similarity index 67% rename from tests/ui/issues/issue-32292.rs rename to tests/ui/derives/no-spurious-unused-variable-warning-on-derive-hash.rs index 2181dff505ace..4609730dff385 100644 --- a/tests/ui/issues/issue-32292.rs +++ b/tests/ui/derives/no-spurious-unused-variable-warning-on-derive-hash.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/32292 //@ run-pass #![deny(warnings)] diff --git a/tests/ui/drop/rc-trait-object-double-drop.rs b/tests/ui/drop/rc-trait-object-double-drop.rs new file mode 100644 index 0000000000000..cbed5b659c583 --- /dev/null +++ b/tests/ui/drop/rc-trait-object-double-drop.rs @@ -0,0 +1,30 @@ +//! Regression test for . +//! Test we don't drop twice when we take a reference through other +//! object like `Rc`. +//! +//! This used to drop Foo twice while coerced to a trait object. +//! `&T`, `Rc` and `&mut` dropped any unsized item each time +//! reference was taken. +//! +//! Value was being dropped when taking the address of an unsized field. +//@ run-pass + +use std::rc::Rc; + +struct Foo<'r>(&'r mut i32); + +impl<'r> Drop for Foo<'r> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +fn main() { + let mut drops = 0; + + { + let _: Rc = Rc::new(Foo(&mut drops)); + } + + assert_eq!(1, drops); +} diff --git a/tests/ui/issues/issue-22777.rs b/tests/ui/dropck/no-dropck-overflow-on-deep-nesting.rs similarity index 82% rename from tests/ui/issues/issue-22777.rs rename to tests/ui/dropck/no-dropck-overflow-on-deep-nesting.rs index c95bb9cc3bb99..6553374189a32 100644 --- a/tests/ui/issues/issue-22777.rs +++ b/tests/ui/dropck/no-dropck-overflow-on-deep-nesting.rs @@ -1,7 +1,10 @@ +//! Regression test for . +//! +//! This test is reduced from librustc_ast. It is just checking that we +//! can successfully deal with a "deep" structure, which the drop-check +//! was hitting a recursion limit on at one point. + //@ check-pass -// This test is reduced from librustc_ast. It is just checking that we -// can successfully deal with a "deep" structure, which the drop-check -// was hitting a recursion limit on at one point. #![allow(non_camel_case_types)] diff --git a/tests/ui/issues/issue-23261.rs b/tests/ui/dst/match-dst-struct.rs similarity index 87% rename from tests/ui/issues/issue-23261.rs rename to tests/ui/dst/match-dst-struct.rs index 69f141e8bf870..1c3fca77c19b7 100644 --- a/tests/ui/issues/issue-23261.rs +++ b/tests/ui/dst/match-dst-struct.rs @@ -1,5 +1,6 @@ +//! Regression test for . +//! Matching on a DST struct should not trigger an LLVM assertion. //@ run-pass -// Matching on a DST struct should not trigger an LLVM assertion. struct Foo { a: i32, diff --git a/tests/ui/issues/issue-26056.rs b/tests/ui/dyn-compatibility/supertrait-with-self-in-type-arg.rs similarity index 79% rename from tests/ui/issues/issue-26056.rs rename to tests/ui/dyn-compatibility/supertrait-with-self-in-type-arg.rs index 99d43ec792b3c..c4969b7f331bd 100644 --- a/tests/ui/issues/issue-26056.rs +++ b/tests/ui/dyn-compatibility/supertrait-with-self-in-type-arg.rs @@ -1,3 +1,5 @@ +//! Regression test for . + trait MapLookup { type MapValue; } diff --git a/tests/ui/issues/issue-26056.stderr b/tests/ui/dyn-compatibility/supertrait-with-self-in-type-arg.stderr similarity index 86% rename from tests/ui/issues/issue-26056.stderr rename to tests/ui/dyn-compatibility/supertrait-with-self-in-type-arg.stderr index c2168af94969b..1eff8855f760f 100644 --- a/tests/ui/issues/issue-26056.stderr +++ b/tests/ui/dyn-compatibility/supertrait-with-self-in-type-arg.stderr @@ -1,12 +1,12 @@ error[E0038]: the trait `Map` is not dyn compatible - --> $DIR/issue-26056.rs:20:17 + --> $DIR/supertrait-with-self-in-type-arg.rs:22:17 | LL | as &dyn Map; | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Map` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/issue-26056.rs:9:12 + --> $DIR/supertrait-with-self-in-type-arg.rs:11:12 | LL | trait Map: MapLookup<::Key> { | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter diff --git a/tests/ui/error-codes/E0264.rs b/tests/ui/error-codes/E0264.rs index 855644796ed45..ef3c8a1c3acd1 100644 --- a/tests/ui/error-codes/E0264.rs +++ b/tests/ui/error-codes/E0264.rs @@ -1,8 +1,8 @@ #![feature(lang_items)] extern "C" { - #[lang = "copy"] - fn copy(); //~ ERROR E0264 + #[lang = "copy"] //~ ERROR E0264 + fn copy(); } fn main() {} diff --git a/tests/ui/error-codes/E0264.stderr b/tests/ui/error-codes/E0264.stderr index 6442f42e689d6..b15ba468aa1a7 100644 --- a/tests/ui/error-codes/E0264.stderr +++ b/tests/ui/error-codes/E0264.stderr @@ -1,8 +1,8 @@ error[E0264]: unknown external lang item: `copy` - --> $DIR/E0264.rs:5:5 + --> $DIR/E0264.rs:4:5 | -LL | fn copy(); - | ^^^^^^^^^^ +LL | #[lang = "copy"] + | ^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0718.rs b/tests/ui/error-codes/E0718.rs index 358bc348ec76d..87e366c91a609 100644 --- a/tests/ui/error-codes/E0718.rs +++ b/tests/ui/error-codes/E0718.rs @@ -1,7 +1,7 @@ #![feature(lang_items)] // Box is expected to be a struct, so this will error. -#[lang = "owned_box"] //~ ERROR lang item must be applied to a struct +#[lang = "owned_box"] //~ ERROR `#[lang = "owned_box"]` attribute cannot be used on statics static X: u32 = 42; fn main() {} diff --git a/tests/ui/error-codes/E0718.stderr b/tests/ui/error-codes/E0718.stderr index e7784d193ba7b..873c714df8c2f 100644 --- a/tests/ui/error-codes/E0718.stderr +++ b/tests/ui/error-codes/E0718.stderr @@ -1,9 +1,10 @@ -error[E0718]: `owned_box` lang item must be applied to a struct +error: `#[lang = "owned_box"]` attribute cannot be used on statics --> $DIR/E0718.rs:4:1 | LL | #[lang = "owned_box"] - | ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[lang = "owned_box"]` can only be applied to structs error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0718`. diff --git a/tests/ui/explicit-tail-calls/no-unsized-arguments.aarch64.stderr b/tests/ui/explicit-tail-calls/no-unsized-arguments.aarch64.stderr new file mode 100644 index 0000000000000..33e190e1a4a7f --- /dev/null +++ b/tests/ui/explicit-tail-calls/no-unsized-arguments.aarch64.stderr @@ -0,0 +1,31 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/no-unsized-arguments.rs:40:42 + | +LL | extern "tail" fn unsized_argument(x: [u8]) -> u8 { + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +help: function arguments must have a statically known size, borrowed slices always have a known size + | +LL | extern "tail" fn unsized_argument(x: &[u8]) -> u8 { + | + + +error: unsized arguments cannot be used in a tail call + --> $DIR/no-unsized-arguments.rs:33:5 + | +LL | become unsized_argument(b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unsized argument of type `[u8]` + +error: unsized arguments cannot be used in a tail call + --> $DIR/no-unsized-arguments.rs:48:5 + | +LL | become unsized_argument(*b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unsized argument of type `[u8]` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/explicit-tail-calls/no-unsized-arguments.rs b/tests/ui/explicit-tail-calls/no-unsized-arguments.rs new file mode 100644 index 0000000000000..a0c5b53d8df0c --- /dev/null +++ b/tests/ui/explicit-tail-calls/no-unsized-arguments.rs @@ -0,0 +1,50 @@ +//@ add-minicore +//@ ignore-backends: gcc +//@ min-llvm-version: 22 +// +//@ revisions: x86 x86_64 aarch64 +// +//@ [x86] compile-flags: --target=i686-unknown-linux-gnu +//@ [x86] needs-llvm-components: x86 +//@ [x86_64] compile-flags: --target=x86_64-unknown-linux-gnu +//@ [x86_64] needs-llvm-components: x86 +//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [aarch64] needs-llvm-components: aarch64 +#![feature(explicit_tail_calls, rust_tail_cc, unsized_fn_params, no_core)] +#![allow(incomplete_features, internal_features)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn extract(_: [u8]) -> u8; +} + +fn vanilla(b: [u8]) -> u8 { + fn unsized_argument(x: [u8]) -> u8 { + unsafe { extract(x) } + } + + // Non-tail call. + let _ = unsized_argument(b); + + become unsized_argument(b); + //~^ ERROR unsized arguments cannot be used in a tail call +} + +extern "tail" fn tailcc(b: &[u8]) -> u8 { + // `extern "tail"` is special because we also can't unsized parameters in standard definitions + // and calls. + extern "tail" fn unsized_argument(x: [u8]) -> u8 { + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + unsafe { extract(x) } + } + + // Vanilla call. + let _ = unsized_argument(*b); + + become unsized_argument(*b); + //~^ ERROR unsized arguments cannot be used in a tail call +} diff --git a/tests/ui/explicit-tail-calls/no-unsized-arguments.x86.stderr b/tests/ui/explicit-tail-calls/no-unsized-arguments.x86.stderr new file mode 100644 index 0000000000000..33e190e1a4a7f --- /dev/null +++ b/tests/ui/explicit-tail-calls/no-unsized-arguments.x86.stderr @@ -0,0 +1,31 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/no-unsized-arguments.rs:40:42 + | +LL | extern "tail" fn unsized_argument(x: [u8]) -> u8 { + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +help: function arguments must have a statically known size, borrowed slices always have a known size + | +LL | extern "tail" fn unsized_argument(x: &[u8]) -> u8 { + | + + +error: unsized arguments cannot be used in a tail call + --> $DIR/no-unsized-arguments.rs:33:5 + | +LL | become unsized_argument(b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unsized argument of type `[u8]` + +error: unsized arguments cannot be used in a tail call + --> $DIR/no-unsized-arguments.rs:48:5 + | +LL | become unsized_argument(*b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unsized argument of type `[u8]` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/explicit-tail-calls/no-unsized-arguments.x86_64.stderr b/tests/ui/explicit-tail-calls/no-unsized-arguments.x86_64.stderr new file mode 100644 index 0000000000000..33e190e1a4a7f --- /dev/null +++ b/tests/ui/explicit-tail-calls/no-unsized-arguments.x86_64.stderr @@ -0,0 +1,31 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/no-unsized-arguments.rs:40:42 + | +LL | extern "tail" fn unsized_argument(x: [u8]) -> u8 { + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +help: function arguments must have a statically known size, borrowed slices always have a known size + | +LL | extern "tail" fn unsized_argument(x: &[u8]) -> u8 { + | + + +error: unsized arguments cannot be used in a tail call + --> $DIR/no-unsized-arguments.rs:33:5 + | +LL | become unsized_argument(b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unsized argument of type `[u8]` + +error: unsized arguments cannot be used in a tail call + --> $DIR/no-unsized-arguments.rs:48:5 + | +LL | become unsized_argument(*b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unsized argument of type `[u8]` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/explicit-tail-calls/signature-mismatch.rs b/tests/ui/explicit-tail-calls/signature-mismatch.rs index a32ac9d8bfee3..bed480f60f63b 100644 --- a/tests/ui/explicit-tail-calls/signature-mismatch.rs +++ b/tests/ui/explicit-tail-calls/signature-mismatch.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(explicit_tail_calls)] +#![feature(explicit_tail_calls, rust_tail_cc)] #![feature(c_variadic)] fn _f0((): ()) { @@ -8,26 +8,30 @@ fn _f0((): ()) { fn _g0() {} - fn _f1() { become _g1(()); //~ error: mismatched signatures } fn _g1((): ()) {} - extern "C" fn _f2() { become _g2(); //~ error: mismatched function ABIs } fn _g2() {} - fn _f3() { become _g3(); //~ error: mismatched function ABIs } extern "C" fn _g3() {} +extern "tail" fn _tailcc() {} + +fn _f4() { + // tailcc does not need the signatures to match, + // but only tailcc can tail call tailcc. + become _tailcc(); //~ error: mismatched function ABIs +} fn main() {} diff --git a/tests/ui/explicit-tail-calls/signature-mismatch.stderr b/tests/ui/explicit-tail-calls/signature-mismatch.stderr index ba9e9dcb98483..6e26f1c075539 100644 --- a/tests/ui/explicit-tail-calls/signature-mismatch.stderr +++ b/tests/ui/explicit-tail-calls/signature-mismatch.stderr @@ -9,7 +9,7 @@ LL | become _g0(); = note: callee signature: `fn()` error: mismatched signatures - --> $DIR/signature-mismatch.rs:13:5 + --> $DIR/signature-mismatch.rs:12:5 | LL | become _g1(()); | ^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | become _g1(()); = note: callee signature: `fn(())` error: mismatched function ABIs - --> $DIR/signature-mismatch.rs:20:5 + --> $DIR/signature-mismatch.rs:18:5 | LL | become _g2(); | ^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | become _g2(); = note: caller ABI is `"C"`, while callee ABI is `"Rust"` error: mismatched function ABIs - --> $DIR/signature-mismatch.rs:27:5 + --> $DIR/signature-mismatch.rs:24:5 | LL | become _g3(); | ^^^^^^^^^^^^ @@ -36,5 +36,14 @@ LL | become _g3(); = note: `become` requires caller and callee to have the same ABI = note: caller ABI is `"Rust"`, while callee ABI is `"C"` -error: aborting due to 4 previous errors +error: mismatched function ABIs + --> $DIR/signature-mismatch.rs:34:5 + | +LL | become _tailcc(); + | ^^^^^^^^^^^^^^^^ + | + = note: `become` requires caller and callee to have the same ABI + = note: caller ABI is `"Rust"`, while callee ABI is `"tail"` + +error: aborting due to 5 previous errors diff --git a/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs b/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs new file mode 100644 index 0000000000000..9c9085ca1daca --- /dev/null +++ b/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs @@ -0,0 +1,49 @@ +//@ run-pass +//@ ignore-backends: gcc +//@ min-llvm-version: 22 +//@ revisions: x86_64 aarch64 +// +// FIXME: enable x86 on LLVM 23. +//@ [x86_64] only-x86_64 +//@ [aarch64] only-aarch64 +#![feature(explicit_tail_calls, rust_tail_cc)] + +#[inline(never)] +pub extern "tail" fn add() -> u64 { + #[inline(never)] + extern "tail" fn add(a: u64, b: u64) -> u64 { + a.wrapping_add(b) + } + + become add(1, 2); +} + +#[inline(never)] +pub extern "tail" fn pass_struct(a: u64, d: u64) -> u64 { + #[derive(Clone, Copy)] + pub struct Large { + pub a: u64, + pub b: u64, + pub c: u64, + pub d: u64, + } + + #[inline(never)] + extern "tail" fn add(large: Large) -> u64 { + let _ = large.b; + let _ = large.c; + large.a.wrapping_add(large.d) + } + + let large = Large { a, b: 0xBBBB_BBBB_BBBB_BBBB, c: 0xCCCC_CCCC_CCCC_CCCC, d }; + become add(large); +} + +fn main() { + assert_eq!(add(), 3); + + // FIXME: LLVM 22 has a bug which makes this miscompile. + if false { + assert_eq!(pass_struct(5, 6), 5 + 6); + } +} diff --git a/tests/ui/issues/issue-26217.rs b/tests/ui/higher-ranked/forall-implies-static.rs similarity index 66% rename from tests/ui/issues/issue-26217.rs rename to tests/ui/higher-ranked/forall-implies-static.rs index 422625e73c161..ef3e7a8303f4a 100644 --- a/tests/ui/issues/issue-26217.rs +++ b/tests/ui/higher-ranked/forall-implies-static.rs @@ -1,3 +1,5 @@ +//! Regression test for . + fn foo() where for<'a> T: 'a {} fn bar<'a>() { diff --git a/tests/ui/issues/issue-26217.stderr b/tests/ui/higher-ranked/forall-implies-static.stderr similarity index 83% rename from tests/ui/issues/issue-26217.stderr rename to tests/ui/higher-ranked/forall-implies-static.stderr index a875056781955..c74b6a12e7800 100644 --- a/tests/ui/issues/issue-26217.stderr +++ b/tests/ui/higher-ranked/forall-implies-static.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-26217.rs:4:5 + --> $DIR/forall-implies-static.rs:6:5 | LL | fn bar<'a>() { | -- lifetime `'a` defined here @@ -7,7 +7,7 @@ LL | foo::<&'a i32>(); | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` | note: due to a current limitation of the type system, this implies a `'static` lifetime - --> $DIR/issue-26217.rs:1:19 + --> $DIR/forall-implies-static.rs:3:19 | LL | fn foo() where for<'a> T: 'a {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-22872.rs b/tests/ui/higher-ranked/leak-check/trait-object-assoc-type-bound-unsatisfied.rs similarity index 85% rename from tests/ui/issues/issue-22872.rs rename to tests/ui/higher-ranked/leak-check/trait-object-assoc-type-bound-unsatisfied.rs index 5db2891e65e75..a171e6cdee453 100644 --- a/tests/ui/issues/issue-22872.rs +++ b/tests/ui/higher-ranked/leak-check/trait-object-assoc-type-bound-unsatisfied.rs @@ -1,3 +1,5 @@ +//! Regression test for . + trait Wrap<'b> { fn foo(&'b mut self); } diff --git a/tests/ui/issues/issue-22872.stderr b/tests/ui/higher-ranked/leak-check/trait-object-assoc-type-bound-unsatisfied.stderr similarity index 90% rename from tests/ui/issues/issue-22872.stderr rename to tests/ui/higher-ranked/leak-check/trait-object-assoc-type-bound-unsatisfied.stderr index 6ff710b113325..79ee006579e0b 100644 --- a/tests/ui/issues/issue-22872.stderr +++ b/tests/ui/higher-ranked/leak-check/trait-object-assoc-type-bound-unsatisfied.stderr @@ -1,12 +1,12 @@ error[E0277]: `

>::Item` is not an iterator - --> $DIR/issue-22872.rs:20:40 + --> $DIR/trait-object-assoc-type-bound-unsatisfied.rs:22:40 | LL | let _: Box Wrap<'b>> = Box::new(Wrapper(process)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `

>::Item` is not an iterator | = help: the trait `Iterator` is not implemented for `

>::Item` note: required for `Wrapper

` to implement `for<'b> Wrap<'b>` - --> $DIR/issue-22872.rs:7:13 + --> $DIR/trait-object-assoc-type-bound-unsatisfied.rs:9:13 | LL | impl<'b, P> Wrap<'b> for Wrapper

| ^^^^^^^^ ^^^^^^^^^^ diff --git a/tests/ui/issues/issue-25810.rs b/tests/ui/higher-ranked/trait-bounds/infer-assoc-type-projection-type.rs similarity index 84% rename from tests/ui/issues/issue-25810.rs rename to tests/ui/higher-ranked/trait-bounds/infer-assoc-type-projection-type.rs index aa60e8afbef57..0e788a2a746bb 100644 --- a/tests/ui/issues/issue-25810.rs +++ b/tests/ui/higher-ranked/trait-bounds/infer-assoc-type-projection-type.rs @@ -1,4 +1,6 @@ +//! Regression test for . //@ run-pass + fn main() { let x = X(15); let y = x.foo(); diff --git a/tests/ui/issues/issue-23041.rs b/tests/ui/inference/downcast-fn-ptr-placeholder.rs similarity index 54% rename from tests/ui/issues/issue-23041.rs rename to tests/ui/inference/downcast-fn-ptr-placeholder.rs index a1371521a0aa0..3b2d2c2857f9d 100644 --- a/tests/ui/issues/issue-23041.rs +++ b/tests/ui/inference/downcast-fn-ptr-placeholder.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Previously ICEd with cat_expr error, fixed by delaying bug. + use std::any::Any; fn main() { diff --git a/tests/ui/issues/issue-23041.stderr b/tests/ui/inference/downcast-fn-ptr-placeholder.stderr similarity index 86% rename from tests/ui/issues/issue-23041.stderr rename to tests/ui/inference/downcast-fn-ptr-placeholder.stderr index b348a8695f6f2..0d1801ac644df 100644 --- a/tests/ui/issues/issue-23041.stderr +++ b/tests/ui/inference/downcast-fn-ptr-placeholder.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/issue-23041.rs:6:22 + --> $DIR/downcast-fn-ptr-placeholder.rs:9:22 | LL | b.downcast_ref::_>(); | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the method `downcast_ref` diff --git a/tests/ui/issues/issue-21974.rs b/tests/ui/issues/issue-21974.rs deleted file mode 100644 index 24e92ce7b9177..0000000000000 --- a/tests/ui/issues/issue-21974.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Test that (for now) we report an ambiguity error here, because -// specific trait relationships are ignored for the purposes of trait -// matching. This behavior should likely be improved such that this -// test passes. See #21974 for more details. - -trait Foo { - fn foo(self); -} - -fn foo<'a,'b,T>(x: &'a T, y: &'b T) - where &'a T : Foo, //~ ERROR type annotations needed - &'b T : Foo -{ - x.foo(); //~ ERROR type annotations needed - y.foo(); -} - -fn main() { } diff --git a/tests/ui/issues/issue-22008.rs b/tests/ui/issues/issue-22008.rs deleted file mode 100644 index b537ce8c2721c..0000000000000 --- a/tests/ui/issues/issue-22008.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass -pub fn main() { - let command = "a"; - - match command { - "foo" => println!("foo"), - _ => println!("{}", command), - } -} diff --git a/tests/ui/issues/issue-22370.rs b/tests/ui/issues/issue-22370.rs deleted file mode 100644 index bab0469c01193..0000000000000 --- a/tests/ui/issues/issue-22370.rs +++ /dev/null @@ -1,6 +0,0 @@ -trait A {} - -fn f(a: &dyn A) {} -//~^ ERROR E0393 - -fn main() {} diff --git a/tests/ui/issues/issue-22370.stderr b/tests/ui/issues/issue-22370.stderr deleted file mode 100644 index cd1580e844cad..0000000000000 --- a/tests/ui/issues/issue-22370.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0393]: the type parameter `T` must be explicitly specified - --> $DIR/issue-22370.rs:3:14 - | -LL | trait A {} - | --------------- type parameter `T` must be specified for this -LL | -LL | fn f(a: &dyn A) {} - | ^ - | - = note: because the parameter default references `Self`, the parameter must be specified on the trait object type -help: explicitly specify the type parameter - | -LL | fn f(a: &dyn A) {} - | +++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/issues/issue-22629.rs b/tests/ui/issues/issue-22629.rs deleted file mode 100644 index 22da414650f85..0000000000000 --- a/tests/ui/issues/issue-22629.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ run-pass -#![allow(unused_imports)] -// Test transitive analysis for associated types. Collected types -// should be normalized and new obligations generated. - - -use std::borrow::{ToOwned, Cow}; - -fn assert_send(_: T) {} - -fn main() { - assert_send(Cow::Borrowed("foo")); -} diff --git a/tests/ui/issues/issue-22886.rs b/tests/ui/issues/issue-22886.rs deleted file mode 100644 index f8b576e094d8c..0000000000000 --- a/tests/ui/issues/issue-22886.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Regression test for #22886. - -fn crash_please() { - let mut iter = Newtype(Some(Box::new(0))); - let saved = iter.next().unwrap(); - println!("{}", saved); - iter.0 = None; - println!("{}", saved); -} - -struct Newtype(Option>); - -impl<'a> Iterator for Newtype { //~ ERROR E0207 - type Item = &'a Box; - - fn next(&mut self) -> Option<&Box> { - self.0.as_ref() - } -} - -fn main() { } diff --git a/tests/ui/issues/issue-23311.rs b/tests/ui/issues/issue-23311.rs deleted file mode 100644 index e827fa1670fb3..0000000000000 --- a/tests/ui/issues/issue-23311.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass - -// Test that we do not ICE when pattern matching an array against a slice. - -fn main() { - match "foo".as_bytes() { - b"food" => (), - &[b'f', ..] => (), - _ => () - } -} diff --git a/tests/ui/issues/issue-23354-2.rs b/tests/ui/issues/issue-23354-2.rs deleted file mode 100644 index a296477215ed1..0000000000000 --- a/tests/ui/issues/issue-23354-2.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-fail -//@ error-pattern:panic evaluated -//@ needs-subprocess - -#[allow(unused_variables)] -fn main() { - // This used to trigger an LLVM assertion during compilation - let x = [panic!("panic evaluated"); 2]; -} diff --git a/tests/ui/issues/issue-25515.rs b/tests/ui/issues/issue-25515.rs deleted file mode 100644 index 5eaea683e2128..0000000000000 --- a/tests/ui/issues/issue-25515.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ run-pass -use std::rc::Rc; - -struct Foo<'r>(&'r mut i32); - -impl<'r> Drop for Foo<'r> { - fn drop(&mut self) { - *self.0 += 1; - } -} - -fn main() { - let mut drops = 0; - - { - let _: Rc = Rc::new(Foo(&mut drops)); - } - - assert_eq!(1, drops); -} diff --git a/tests/ui/issues/issue-25343.rs b/tests/ui/label/label-in-closure-no-self-shadow.rs similarity index 52% rename from tests/ui/issues/issue-25343.rs rename to tests/ui/label/label-in-closure-no-self-shadow.rs index 878f248867766..ba573a598a945 100644 --- a/tests/ui/issues/issue-25343.rs +++ b/tests/ui/label/label-in-closure-no-self-shadow.rs @@ -1,4 +1,8 @@ +//! Regression test for . +//! Ensure we're not wrongly producing shadowing label warning. +//! More cases added from issue . //@ run-pass + #[allow(unused)] fn main() { || { @@ -6,8 +10,6 @@ fn main() { } }; - // More cases added from issue 31754 - 'label2: loop { break; } diff --git a/tests/ui/macros/format-foreign-dollar-without-spec.stderr b/tests/ui/macros/format-foreign-dollar-without-spec.stderr index d5a07c50f00d0..c4c241048abb0 100644 --- a/tests/ui/macros/format-foreign-dollar-without-spec.stderr +++ b/tests/ui/macros/format-foreign-dollar-without-spec.stderr @@ -2,15 +2,14 @@ error: argument never used --> $DIR/format-foreign-dollar-without-spec.rs:3:25 | LL | println!("%65536$", 1); - | ^ argument never used + | --------- ^ argument never used + | | + | formatting specifier missing | -note: format specifiers use curly braces, and the conversion specifier ` - ` is unknown or unsupported - --> $DIR/format-foreign-dollar-without-spec.rs:3:15 +help: format specifiers use curly braces, consider adding a format specifier | -LL | println!("%65536$", 1); - | ^^^^^^^^ - = note: printf formatting is not supported; see the documentation for `std::fmt` +LL | println!("%65536${}", 1); + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-92267.stderr b/tests/ui/macros/issue-92267.stderr index 4259815328b30..2318d5d565a1d 100644 --- a/tests/ui/macros/issue-92267.stderr +++ b/tests/ui/macros/issue-92267.stderr @@ -2,15 +2,14 @@ error: argument never used --> $DIR/issue-92267.rs:3:34 | LL | pub fn main() { println!("🦀%%%", 0) } - | ^ argument never used + | ------- ^ argument never used + | | + | formatting specifier missing | -note: format specifiers use curly braces, and the conversion specifier ` - ` is unknown or unsupported - --> $DIR/issue-92267.rs:3:30 +help: format specifiers use curly braces, consider adding a format specifier | -LL | pub fn main() { println!("🦀%%%", 0) } - | ^^ - = note: printf formatting is not supported; see the documentation for `std::fmt` +LL | pub fn main() { println!("🦀%%%{}", 0) } + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-26237.rs b/tests/ui/macros/non-function-call-in-macro.rs similarity index 78% rename from tests/ui/issues/issue-26237.rs rename to tests/ui/macros/non-function-call-in-macro.rs index 71e96677d4bbc..b23fd74c4fd16 100644 --- a/tests/ui/issues/issue-26237.rs +++ b/tests/ui/macros/non-function-call-in-macro.rs @@ -1,3 +1,5 @@ +//! Regression test for . + macro_rules! macro_panic { ($not_a_function:expr, $some_argument:ident) => { $not_a_function($some_argument) diff --git a/tests/ui/issues/issue-26237.stderr b/tests/ui/macros/non-function-call-in-macro.stderr similarity index 91% rename from tests/ui/issues/issue-26237.stderr rename to tests/ui/macros/non-function-call-in-macro.stderr index d15e5753a25e7..6e38c5e8e3493 100644 --- a/tests/ui/issues/issue-26237.stderr +++ b/tests/ui/macros/non-function-call-in-macro.stderr @@ -1,5 +1,5 @@ error[E0618]: expected function, found `{integer}` - --> $DIR/issue-26237.rs:10:18 + --> $DIR/non-function-call-in-macro.rs:12:18 | LL | $not_a_function($some_argument) | ------------------------------- call expression requires function diff --git a/tests/ui/macros/trailing-percent-format-hint-issue-158216.rs b/tests/ui/macros/trailing-percent-format-hint-issue-158216.rs new file mode 100644 index 0000000000000..bebea2dfe48c6 --- /dev/null +++ b/tests/ui/macros/trailing-percent-format-hint-issue-158216.rs @@ -0,0 +1,7 @@ +//@ check-fail +//@ compile-flags: --crate-type=lib + +pub fn f(x: f64) { + println!("{x:>8.2}%", "foo"); + //~^ ERROR argument never used +} diff --git a/tests/ui/macros/trailing-percent-format-hint-issue-158216.stderr b/tests/ui/macros/trailing-percent-format-hint-issue-158216.stderr new file mode 100644 index 0000000000000..b5c120f939b40 --- /dev/null +++ b/tests/ui/macros/trailing-percent-format-hint-issue-158216.stderr @@ -0,0 +1,15 @@ +error: argument never used + --> $DIR/trailing-percent-format-hint-issue-158216.rs:5:27 + | +LL | println!("{x:>8.2}%", "foo"); + | ----------- ^^^^^ argument never used + | | + | formatting specifier missing + | +help: format specifiers use curly braces, consider adding a format specifier + | +LL | println!("{x:>8.2}%{}", "foo"); + | ++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/issues/issue-22814.rs b/tests/ui/macros/trait-bound-not-parsed-as-matcher.rs similarity index 68% rename from tests/ui/issues/issue-22814.rs rename to tests/ui/macros/trait-bound-not-parsed-as-matcher.rs index 95ddeb15b57dd..0230df4aeb30c 100644 --- a/tests/ui/issues/issue-22814.rs +++ b/tests/ui/macros/trait-bound-not-parsed-as-matcher.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ check-pass trait Test {} diff --git a/tests/ui/match/match-str-proper-optimization.rs b/tests/ui/match/match-str-proper-optimization.rs new file mode 100644 index 0000000000000..79c56b22d0569 --- /dev/null +++ b/tests/ui/match/match-str-proper-optimization.rs @@ -0,0 +1,14 @@ +//! Regression test for . +//! Ensure matching against `str` doesn't cause segfault when compiled +//! with `opt-level` >= 2. +// +//@ compile-flags: -C opt-level=2 +//@ run-pass +pub fn main() { + let command = "a"; + + match command { + "foo" => println!("foo"), + _ => println!("{}", command), + } +} diff --git a/tests/ui/issues/issue-21622.rs b/tests/ui/methods/nested-fn-call-shadowed-assoc-fn-variable.rs similarity index 77% rename from tests/ui/issues/issue-21622.rs rename to tests/ui/methods/nested-fn-call-shadowed-assoc-fn-variable.rs index 8dbc2c21ba951..65059cf38cd3c 100644 --- a/tests/ui/issues/issue-21622.rs +++ b/tests/ui/methods/nested-fn-call-shadowed-assoc-fn-variable.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ check-pass #![allow(dead_code)] #![allow(unused_variables)] diff --git a/tests/ui/issues/issue-2590.rs b/tests/ui/moves/move-field-out-of-shared-self.rs similarity index 75% rename from tests/ui/issues/issue-2590.rs rename to tests/ui/moves/move-field-out-of-shared-self.rs index a9a0e5ca4ec16..05c19a8a7a8fb 100644 --- a/tests/ui/issues/issue-2590.rs +++ b/tests/ui/moves/move-field-out-of-shared-self.rs @@ -1,3 +1,5 @@ +//! Regression test for . + struct Parser { tokens: Vec , } diff --git a/tests/ui/issues/issue-2590.stderr b/tests/ui/moves/move-field-out-of-shared-self.stderr similarity index 90% rename from tests/ui/issues/issue-2590.stderr rename to tests/ui/moves/move-field-out-of-shared-self.stderr index 822856652e9df..3720b2bd963f2 100644 --- a/tests/ui/issues/issue-2590.stderr +++ b/tests/ui/moves/move-field-out-of-shared-self.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `self.tokens` which is behind a shared reference - --> $DIR/issue-2590.rs:11:9 + --> $DIR/move-field-out-of-shared-self.rs:13:9 | LL | self.tokens | ^^^^^^^^^^^ move occurs because `self.tokens` has type `Vec`, which does not implement the `Copy` trait diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.rs b/tests/ui/panic-handler/panic-handler-wrong-location.rs index 8fff7067136e2..22f6b6e724890 100644 --- a/tests/ui/panic-handler/panic-handler-wrong-location.rs +++ b/tests/ui/panic-handler/panic-handler-wrong-location.rs @@ -3,7 +3,7 @@ #![no_std] #![no_main] -#[panic_handler] //~ ERROR `panic_impl` lang item must be applied to a function +#[panic_handler] //~ ERROR attribute cannot be used on statics static X: u32 = 42; //~? ERROR `#[panic_handler]` function required, but not found diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.stderr b/tests/ui/panic-handler/panic-handler-wrong-location.stderr index 9b361bf8d603f..7af0a4326d9a0 100644 --- a/tests/ui/panic-handler/panic-handler-wrong-location.stderr +++ b/tests/ui/panic-handler/panic-handler-wrong-location.stderr @@ -1,11 +1,12 @@ -error[E0718]: `panic_impl` lang item must be applied to a function +error: `#[panic_handler]` function required, but not found + +error: `#[panic_handler]` attribute cannot be used on statics --> $DIR/panic-handler-wrong-location.rs:6:1 | LL | #[panic_handler] - | ^^^^^^^^^^^^^^^^ attribute should be applied to a function, not a static - -error: `#[panic_handler]` function required, but not found + | ^^^^^^^^^^^^^^^^ + | + = help: `#[panic_handler]` can only be applied to functions error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0718`. diff --git a/tests/ui/pattern/match-array-against-slice.rs b/tests/ui/pattern/match-array-against-slice.rs new file mode 100644 index 0000000000000..a396e2adab822 --- /dev/null +++ b/tests/ui/pattern/match-array-against-slice.rs @@ -0,0 +1,11 @@ +//! Regression test for . +//! Test that we do not ICE when pattern matching an array against a slice. +//@ run-pass + +fn main() { + match "foo".as_bytes() { + b"food" => (), + &[b'f', ..] => (), + _ => () + } +} diff --git a/tests/ui/proc-macro/auxiliary/nonfatal-parsing-body.rs b/tests/ui/proc-macro/auxiliary/nonfatal-parsing-body.rs index f58aa1b228e31..258f77067ce9c 100644 --- a/tests/ui/proc-macro/auxiliary/nonfatal-parsing-body.rs +++ b/tests/ui/proc-macro/auxiliary/nonfatal-parsing-body.rs @@ -15,26 +15,38 @@ enum Mode { OtherWithPanic, } +fn print_unspanned(s: &str) -> Result +where + T: FromStr + Debug, +{ + let t = T::from_str(s); + let mut s = format!("{t:?}"); + while let Some((l, r)) = s.split_once("span: #") { + let (_, r) = r.split_once(")").unwrap(); + s = format!("{l}span: Span{r}"); + } + println!("{s}"); + t +} + fn parse(s: &str, mode: Mode) where T: FromStr + Debug, { match mode { NormalOk => { - let t = T::from_str(s); - println!("{:?}", t); + let t = print_unspanned::(s); assert!(t.is_ok()); } NormalErr => { - let t = T::from_str(s); - println!("{:?}", t); + let t = print_unspanned::(s); assert!(t.is_err()); } OtherError => { - println!("{:?}", T::from_str(s)); + print_unspanned::(s); } OtherWithPanic => { - if catch_unwind(|| println!("{:?}", T::from_str(s))).is_ok() { + if catch_unwind(|| print_unspanned::(s)).is_ok() { eprintln!("{s} did not panic"); } } @@ -64,7 +76,10 @@ fn lit(s: &str, mode: Mode) { } pub fn run() { + assert_eq!("\'", "'"); // returns Ok(valid instance) + lit("r\"g\"", NormalOk); + lit("r#\"g\"#", NormalOk); lit("123", NormalOk); lit("\"ab\"", NormalOk); lit("\'b\'", NormalOk); @@ -72,6 +87,7 @@ pub fn run() { lit("b\"b\"", NormalOk); lit("c\"b\"", NormalOk); lit("cr\"b\"", NormalOk); + lit("'\\''", NormalOk); lit("b'b'", NormalOk); lit("256u8", NormalOk); lit("-256u8", NormalOk); @@ -99,10 +115,13 @@ pub fn run() { NormalOk, ); stream("/*a*/ //", NormalOk); + lit("\"\"", NormalOk); + stream("", NormalOk); println!("### ERRORS"); // returns Err(LexError) + lit("", NormalErr); lit("\'c\'/**/", NormalErr); lit(" 0", NormalErr); lit("0 ", NormalErr); @@ -119,10 +138,12 @@ pub fn run() { // emits diagnostics and returns LexError lit("r'r'", OtherError); lit("c'r'", OtherError); + lit("\u{2000}", OtherError); // emits diagnostic and returns a seemingly valid tokenstream stream("r'r'", OtherError); stream("c'r'", OtherError); + stream("\u{2000}", OtherError); for parse in [stream as fn(&str, Mode), lit] { // emits diagnostic(s), then panics diff --git a/tests/ui/proc-macro/nonfatal-parsing.stderr b/tests/ui/proc-macro/nonfatal-parsing.stderr index 874a7a2f410d9..cb6e243eebc9b 100644 --- a/tests/ui/proc-macro/nonfatal-parsing.stderr +++ b/tests/ui/proc-macro/nonfatal-parsing.stderr @@ -22,6 +22,17 @@ help: consider inserting whitespace here LL | c 'r' | + +error: unknown start of token: \u{2000} + --> :1:1 + | +LL |   + | ^ + | +help: Unicode character ' ' (En Quad) looks like ' ' (Space), but it is not + | +LL | + | + error: prefix `r` is unknown --> $DIR/nonfatal-parsing.rs:15:5 | @@ -40,6 +51,19 @@ LL | nonfatal_parsing::run!(); = note: prefixed identifiers and literals are reserved since Rust 2021 = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info) +error: unknown start of token: \u{2000} + --> $DIR/nonfatal-parsing.rs:15:5 + | +LL | nonfatal_parsing::run!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info) +help: Unicode character ' ' (En Quad) looks like ' ' (Space), but it is not + --> :1:1 + | +LL | + | + error: found invalid character; only `#` is allowed in raw string delimitation: \u{0} --> $DIR/nonfatal-parsing.rs:15:5 | @@ -175,6 +199,6 @@ error: invalid digit for a base 2 literal LL | /*a*/ 0b2 // | ^ -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0768`. diff --git a/tests/ui/proc-macro/nonfatal-parsing.stdout b/tests/ui/proc-macro/nonfatal-parsing.stdout index 2b92474fb8b4c..a46ef66f0f9d0 100644 --- a/tests/ui/proc-macro/nonfatal-parsing.stdout +++ b/tests/ui/proc-macro/nonfatal-parsing.stdout @@ -1,34 +1,40 @@ -Ok(Literal { kind: Integer, symbol: "123", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Str, symbol: "ab", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Char, symbol: "b", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Char, symbol: "b", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: ByteStr, symbol: "b", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: CStr, symbol: "b", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: CStrRaw(0), symbol: "b", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Byte, symbol: "b", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Integer, symbol: "256", suffix: Some("u8"), span: #44 bytes(361..385) }) -Ok(Literal { kind: Integer, symbol: "-256", suffix: Some("u8"), span: #44 bytes(361..385) }) -Ok(TokenStream [Punct { ch: '-', spacing: Alone, span: #44 bytes(361..385) }, Literal { kind: Integer, symbol: "256", suffix: Some("u8"), span: #44 bytes(361..385) }]) -Ok(Literal { kind: Integer, symbol: "0b11111000000001111", suffix: Some("i16"), span: #44 bytes(361..385) }) -Ok(Literal { kind: Integer, symbol: "0xf32", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Integer, symbol: "0b0", suffix: Some("f32"), span: #44 bytes(361..385) }) -Ok(Literal { kind: Float, symbol: "2E4", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Float, symbol: "2.2E-4", suffix: Some("f64"), span: #44 bytes(361..385) }) -Ok(Literal { kind: Integer, symbol: "18", suffix: Some("u8E"), span: #44 bytes(361..385) }) -Ok(Literal { kind: Float, symbol: "18.0", suffix: Some("u8E"), span: #44 bytes(361..385) }) -Ok(Literal { kind: CStrRaw(1), symbol: "// /* // \n */", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Char, symbol: "\'", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: Char, symbol: "\'", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: StrRaw(255), symbol: "a", suffix: None, span: #44 bytes(361..385) }) -Ok(TokenStream [Ident { ident: "fn", span: #44 bytes(361..385) }, Ident { ident: "main", span: #44 bytes(361..385) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #44 bytes(361..385) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "println", span: #44 bytes(361..385) }, Punct { ch: '!', spacing: Alone, span: #44 bytes(361..385) }, Group { delimiter: Parenthesis, stream: TokenStream [Literal { kind: Str, symbol: "Hello, world!", suffix: None, span: #44 bytes(361..385) }], span: #44 bytes(361..385) }], span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: Integer, symbol: "18", suffix: None, span: #44 bytes(361..385) }, Punct { ch: '.', spacing: Alone, span: #44 bytes(361..385) }, Ident { ident: "u8E", span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: Float, symbol: "18.0", suffix: Some("f32"), span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: Float, symbol: "18.0", suffix: Some("f34"), span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: Integer, symbol: "18", suffix: None, span: #44 bytes(361..385) }, Punct { ch: '.', spacing: Alone, span: #44 bytes(361..385) }, Ident { ident: "bu8", span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: Integer, symbol: "3", suffix: None, span: #44 bytes(361..385) }, Literal { kind: Integer, symbol: "4", suffix: None, span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: Char, symbol: "c", suffix: None, span: #44 bytes(361..385) }]) +Ok(Literal { kind: StrRaw(0), symbol: "g", suffix: None, span: Span }) +Ok(Literal { kind: StrRaw(1), symbol: "g", suffix: None, span: Span }) +Ok(Literal { kind: Integer, symbol: "123", suffix: None, span: Span }) +Ok(Literal { kind: Str, symbol: "ab", suffix: None, span: Span }) +Ok(Literal { kind: Char, symbol: "b", suffix: None, span: Span }) +Ok(Literal { kind: Char, symbol: "b", suffix: None, span: Span }) +Ok(Literal { kind: ByteStr, symbol: "b", suffix: None, span: Span }) +Ok(Literal { kind: CStr, symbol: "b", suffix: None, span: Span }) +Ok(Literal { kind: CStrRaw(0), symbol: "b", suffix: None, span: Span }) +Ok(Literal { kind: Char, symbol: "\'", suffix: None, span: Span }) +Ok(Literal { kind: Byte, symbol: "b", suffix: None, span: Span }) +Ok(Literal { kind: Integer, symbol: "256", suffix: Some("u8"), span: Span }) +Ok(Literal { kind: Integer, symbol: "-256", suffix: Some("u8"), span: Span }) +Ok(TokenStream [Punct { ch: '-', spacing: Alone, span: Span }, Literal { kind: Integer, symbol: "256", suffix: Some("u8"), span: Span }]) +Ok(Literal { kind: Integer, symbol: "0b11111000000001111", suffix: Some("i16"), span: Span }) +Ok(Literal { kind: Integer, symbol: "0xf32", suffix: None, span: Span }) +Ok(Literal { kind: Integer, symbol: "0b0", suffix: Some("f32"), span: Span }) +Ok(Literal { kind: Float, symbol: "2E4", suffix: None, span: Span }) +Ok(Literal { kind: Float, symbol: "2.2E-4", suffix: Some("f64"), span: Span }) +Ok(Literal { kind: Integer, symbol: "18", suffix: Some("u8E"), span: Span }) +Ok(Literal { kind: Float, symbol: "18.0", suffix: Some("u8E"), span: Span }) +Ok(Literal { kind: CStrRaw(1), symbol: "// /* // \n */", suffix: None, span: Span }) +Ok(Literal { kind: Char, symbol: "\'", suffix: None, span: Span }) +Ok(Literal { kind: Char, symbol: "\'", suffix: None, span: Span }) +Ok(Literal { kind: StrRaw(255), symbol: "a", suffix: None, span: Span }) +Ok(TokenStream [Ident { ident: "fn", span: Span }, Ident { ident: "main", span: Span }, Group { delimiter: Parenthesis, stream: TokenStream [], span: Span }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "println", span: Span }, Punct { ch: '!', spacing: Alone, span: Span }, Group { delimiter: Parenthesis, stream: TokenStream [Literal { kind: Str, symbol: "Hello, world!", suffix: None, span: Span }], span: Span }], span: Span }]) +Ok(TokenStream [Literal { kind: Integer, symbol: "18", suffix: None, span: Span }, Punct { ch: '.', spacing: Alone, span: Span }, Ident { ident: "u8E", span: Span }]) +Ok(TokenStream [Literal { kind: Float, symbol: "18.0", suffix: Some("f32"), span: Span }]) +Ok(TokenStream [Literal { kind: Float, symbol: "18.0", suffix: Some("f34"), span: Span }]) +Ok(TokenStream [Literal { kind: Integer, symbol: "18", suffix: None, span: Span }, Punct { ch: '.', spacing: Alone, span: Span }, Ident { ident: "bu8", span: Span }]) +Ok(TokenStream [Literal { kind: Integer, symbol: "3", suffix: None, span: Span }, Literal { kind: Integer, symbol: "4", suffix: None, span: Span }]) +Ok(TokenStream [Literal { kind: Char, symbol: "c", suffix: None, span: Span }]) +Ok(TokenStream []) +Ok(Literal { kind: Str, symbol: "", suffix: None, span: Span }) Ok(TokenStream []) ### ERRORS +Err(LexError("not a literal")) Err(LexError("comment or whitespace around literal")) Err(LexError("comment or whitespace around literal")) Err(LexError("comment or whitespace around literal")) @@ -42,17 +48,19 @@ Err(LexError("unexpected closing delimiter: `)`")) Err(LexError("unexpected closing delimiter: `]`")) Err(LexError("not a literal")) Err(LexError("not a literal")) -Ok(TokenStream [Ident { ident: "r", span: #44 bytes(361..385) }, Literal { kind: Char, symbol: "r", suffix: None, span: #44 bytes(361..385) }]) -Ok(TokenStream [Ident { ident: "c", span: #44 bytes(361..385) }, Literal { kind: Char, symbol: "r", suffix: None, span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b", suffix: Some("f32"), span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b0.0", suffix: Some("f32"), span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "'''", suffix: None, span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "'\n'", suffix: None, span: #44 bytes(361..385) }]) -Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: #44 bytes(361..385) }]) -Ok(Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: ErrWithGuar, symbol: "0b", suffix: Some("f32"), span: #44 bytes(361..385) }) -Ok(Literal { kind: ErrWithGuar, symbol: "0b0.0", suffix: Some("f32"), span: #44 bytes(361..385) }) -Ok(Literal { kind: ErrWithGuar, symbol: "'''", suffix: None, span: #44 bytes(361..385) }) -Ok(Literal { kind: ErrWithGuar, symbol: "'\n'", suffix: None, span: #44 bytes(361..385) }) +Err(LexError("not a literal")) +Ok(TokenStream [Ident { ident: "r", span: Span }, Literal { kind: Char, symbol: "r", suffix: None, span: Span }]) +Ok(TokenStream [Ident { ident: "c", span: Span }, Literal { kind: Char, symbol: "r", suffix: None, span: Span }]) +Ok(TokenStream []) +Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: Span }]) +Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b", suffix: Some("f32"), span: Span }]) +Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b0.0", suffix: Some("f32"), span: Span }]) +Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "'''", suffix: None, span: Span }]) +Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "'\n'", suffix: None, span: Span }]) +Ok(TokenStream [Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: Span }]) +Ok(Literal { kind: ErrWithGuar, symbol: "0b2", suffix: None, span: Span }) +Ok(Literal { kind: ErrWithGuar, symbol: "0b", suffix: Some("f32"), span: Span }) +Ok(Literal { kind: ErrWithGuar, symbol: "0b0.0", suffix: Some("f32"), span: Span }) +Ok(Literal { kind: ErrWithGuar, symbol: "'''", suffix: None, span: Span }) +Ok(Literal { kind: ErrWithGuar, symbol: "'\n'", suffix: None, span: Span }) Err(LexError("comment or whitespace around literal")) diff --git a/tests/ui/issues/issue-2150.rs b/tests/ui/reachable/unreachable-ret-after-panic.rs similarity index 76% rename from tests/ui/issues/issue-2150.rs rename to tests/ui/reachable/unreachable-ret-after-panic.rs index baa1dde0fc2e8..db8673e5fd59b 100644 --- a/tests/ui/issues/issue-2150.rs +++ b/tests/ui/reachable/unreachable-ret-after-panic.rs @@ -1,3 +1,5 @@ +//! Regression test for . + #![deny(unreachable_code)] #![allow(unused_variables)] #![allow(dead_code)] diff --git a/tests/ui/issues/issue-2150.stderr b/tests/ui/reachable/unreachable-ret-after-panic.stderr similarity index 79% rename from tests/ui/issues/issue-2150.stderr rename to tests/ui/reachable/unreachable-ret-after-panic.stderr index a9268646edfcb..7b73ddc723042 100644 --- a/tests/ui/issues/issue-2150.stderr +++ b/tests/ui/reachable/unreachable-ret-after-panic.stderr @@ -1,5 +1,5 @@ error: unreachable statement - --> $DIR/issue-2150.rs:8:5 + --> $DIR/unreachable-ret-after-panic.rs:10:5 | LL | panic!(); | -------- any code following this expression is unreachable @@ -7,7 +7,7 @@ LL | for x in &v { i += 1; } | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here - --> $DIR/issue-2150.rs:1:9 + --> $DIR/unreachable-ret-after-panic.rs:3:9 | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-22638.rs b/tests/ui/recursion/infinite-instantiation-via-nested-closures.rs similarity index 93% rename from tests/ui/issues/issue-22638.rs rename to tests/ui/recursion/infinite-instantiation-via-nested-closures.rs index be9304e5829f0..6961d9a4dfde8 100644 --- a/tests/ui/issues/issue-22638.rs +++ b/tests/ui/recursion/infinite-instantiation-via-nested-closures.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ build-fail #![allow(unused)] diff --git a/tests/ui/issues/issue-22638.stderr b/tests/ui/recursion/infinite-instantiation-via-nested-closures.stderr similarity index 59% rename from tests/ui/issues/issue-22638.stderr rename to tests/ui/recursion/infinite-instantiation-via-nested-closures.stderr index 96f1794486838..c4171e23b5917 100644 --- a/tests/ui/issues/issue-22638.stderr +++ b/tests/ui/recursion/infinite-instantiation-via-nested-closures.stderr @@ -1,11 +1,11 @@ -error: reached the recursion limit while instantiating `A::matches::<{closure@$DIR/issue-22638.rs:42:23: 42:25}>` - --> $DIR/issue-22638.rs:54:9 +error: reached the recursion limit while instantiating `A::matches::<{closure@$DIR/infinite-instantiation-via-nested-closures.rs:43:23: 43:25}>` + --> $DIR/infinite-instantiation-via-nested-closures.rs:55:9 | LL | a.matches(f) | ^^^^^^^^^^^^ | note: `A::matches` defined here - --> $DIR/issue-22638.rs:13:5 + --> $DIR/infinite-instantiation-via-nested-closures.rs:14:5 | LL | pub fn matches(&self, f: &F) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-21546.rs b/tests/ui/resolve/module-type-name-conflict.rs similarity index 77% rename from tests/ui/issues/issue-21546.rs rename to tests/ui/resolve/module-type-name-conflict.rs index 9f3974b431470..b054fead6bc1f 100644 --- a/tests/ui/issues/issue-21546.rs +++ b/tests/ui/resolve/module-type-name-conflict.rs @@ -1,4 +1,7 @@ -// Also works as a test for #14564 +//! Regression test for . +//! Ensure structs, enums and modules cannot share name in namespace. +//! +//! Also works as a test for . #[allow(non_snake_case)] mod Foo { } diff --git a/tests/ui/issues/issue-21546.stderr b/tests/ui/resolve/module-type-name-conflict.stderr similarity index 87% rename from tests/ui/issues/issue-21546.stderr rename to tests/ui/resolve/module-type-name-conflict.stderr index 5fd06fc673361..fd5649cfc4512 100644 --- a/tests/ui/issues/issue-21546.stderr +++ b/tests/ui/resolve/module-type-name-conflict.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-21546.rs:7:1 + --> $DIR/module-type-name-conflict.rs:10:1 | LL | mod Foo { } | ------- previous definition of the module `Foo` here @@ -10,7 +10,7 @@ LL | struct Foo; = note: `Foo` must be defined only once in the type namespace of this module error[E0428]: the name `Bar` is defined multiple times - --> $DIR/issue-21546.rs:14:1 + --> $DIR/module-type-name-conflict.rs:17:1 | LL | mod Bar { } | ------- previous definition of the module `Bar` here @@ -21,7 +21,7 @@ LL | struct Bar(i32); = note: `Bar` must be defined only once in the type namespace of this module error[E0428]: the name `Baz` is defined multiple times - --> $DIR/issue-21546.rs:22:1 + --> $DIR/module-type-name-conflict.rs:25:1 | LL | struct Baz(i32); | ---------------- previous definition of the type `Baz` here @@ -32,7 +32,7 @@ LL | mod Baz { } = note: `Baz` must be defined only once in the type namespace of this module error[E0428]: the name `Qux` is defined multiple times - --> $DIR/issue-21546.rs:30:1 + --> $DIR/module-type-name-conflict.rs:33:1 | LL | struct Qux { x: bool } | ---------- previous definition of the type `Qux` here @@ -43,7 +43,7 @@ LL | mod Qux { } = note: `Qux` must be defined only once in the type namespace of this module error[E0428]: the name `Quux` is defined multiple times - --> $DIR/issue-21546.rs:38:1 + --> $DIR/module-type-name-conflict.rs:41:1 | LL | struct Quux; | ------------ previous definition of the type `Quux` here @@ -54,7 +54,7 @@ LL | mod Quux { } = note: `Quux` must be defined only once in the type namespace of this module error[E0428]: the name `Corge` is defined multiple times - --> $DIR/issue-21546.rs:46:1 + --> $DIR/module-type-name-conflict.rs:49:1 | LL | enum Corge { A, B } | ---------- previous definition of the type `Corge` here diff --git a/tests/ui/traits/ambiguous-trait-matching-distinct-lifetimes.rs b/tests/ui/traits/ambiguous-trait-matching-distinct-lifetimes.rs new file mode 100644 index 0000000000000..d5cf73b42f561 --- /dev/null +++ b/tests/ui/traits/ambiguous-trait-matching-distinct-lifetimes.rs @@ -0,0 +1,20 @@ +//! . +//! +//! Test that (for now) we report an ambiguity error here, because +//! specific trait relationships are ignored for the purposes of trait +//! matching. This behavior should likely be improved such that this +//! test passes. + +trait Foo { + fn foo(self); +} + +fn foo<'a,'b,T>(x: &'a T, y: &'b T) + where &'a T : Foo, //~ ERROR type annotations needed + &'b T : Foo +{ + x.foo(); //~ ERROR type annotations needed + y.foo(); +} + +fn main() { } diff --git a/tests/ui/issues/issue-21974.stderr b/tests/ui/traits/ambiguous-trait-matching-distinct-lifetimes.stderr similarity index 73% rename from tests/ui/issues/issue-21974.stderr rename to tests/ui/traits/ambiguous-trait-matching-distinct-lifetimes.stderr index cc9164e5621b8..d2d7df466512d 100644 --- a/tests/ui/issues/issue-21974.stderr +++ b/tests/ui/traits/ambiguous-trait-matching-distinct-lifetimes.stderr @@ -1,11 +1,11 @@ error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo` - --> $DIR/issue-21974.rs:11:19 + --> $DIR/ambiguous-trait-matching-distinct-lifetimes.rs:13:19 | LL | where &'a T : Foo, | ^^^ | note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found - --> $DIR/issue-21974.rs:11:19 + --> $DIR/ambiguous-trait-matching-distinct-lifetimes.rs:13:19 | LL | where &'a T : Foo, | ^^^ @@ -13,13 +13,13 @@ LL | &'b T : Foo | ^^^ error[E0283]: type annotations needed: cannot satisfy `&T: Foo` - --> $DIR/issue-21974.rs:14:7 + --> $DIR/ambiguous-trait-matching-distinct-lifetimes.rs:16:7 | LL | x.foo(); | ^^^ | note: multiple `impl`s or `where` clauses satisfying `&T: Foo` found - --> $DIR/issue-21974.rs:11:19 + --> $DIR/ambiguous-trait-matching-distinct-lifetimes.rs:13:19 | LL | where &'a T : Foo, | ^^^ diff --git a/tests/ui/issues/issue-22471.rs b/tests/ui/type-alias/where-clause-on-generic-type-alias.rs similarity index 55% rename from tests/ui/issues/issue-22471.rs rename to tests/ui/type-alias/where-clause-on-generic-type-alias.rs index a983fec05c865..9e306e1fdfac6 100644 --- a/tests/ui/issues/issue-22471.rs +++ b/tests/ui/type-alias/where-clause-on-generic-type-alias.rs @@ -1,5 +1,6 @@ +//! Regression test for . + //@ check-pass -#![allow(dead_code)] #![allow(type_alias_bounds)] type Foo where T: Copy = Box; diff --git a/tests/ui/type-inference/index-expr-ambiguous-type.rs b/tests/ui/type-inference/index-expr-ambiguous-type.rs new file mode 100644 index 0000000000000..061699c8a013f --- /dev/null +++ b/tests/ui/type-inference/index-expr-ambiguous-type.rs @@ -0,0 +1,54 @@ +// Regression test for #156738 +// +// When the index type in `arr[idx]` is ambiguous, the error should point +// at the index sub-expression, not the whole indexing expression or +// surrounding operators. + +fn with_cast() { + let bad_idx = 0u8; + let _foo = [1, 2, 3][bad_idx.into()] as i32; + //~^ ERROR type annotations needed +} + +fn with_binop() { + let bad_idx = 0u8; + let _foo = 0 + [1, 2, 3][bad_idx.into()]; + //~^ ERROR type annotations needed +} + +fn standalone() { + let bad_idx = 0u8; + let _foo = [1, 2, 3][bad_idx.into()]; + //~^ ERROR type annotations needed +} + +fn with_known_index_type() { + let bad_idx = 0u8; + let _foo = [1, 2, 3][Into::::into(bad_idx)] as i32; +} + +fn invalid_operator_with_ambiguous_index() { + let bad_idx = 0u8; + let _foo = true + [1, 2, 3][bad_idx.into()]; + //~^ ERROR cannot add +} + +fn mismatched_numeric_binop_with_ambiguous_index() { + let bad_idx = 0u8; + let _foo = 0u64 + [1i32, 2, 3][bad_idx.into()]; + //~^ ERROR type annotations needed +} + +fn shift_with_ambiguous_index() { + let bad_idx = 0u8; + let _foo = 1u32 << [0u8][bad_idx.into()]; + //~^ ERROR type annotations needed +} + +fn string_add_with_ambiguous_index() { + let bad_idx = 0u8; + let _foo = String::new() + [""][bad_idx.into()]; + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/type-inference/index-expr-ambiguous-type.stderr b/tests/ui/type-inference/index-expr-ambiguous-type.stderr new file mode 100644 index 0000000000000..83de98d80cae6 --- /dev/null +++ b/tests/ui/type-inference/index-expr-ambiguous-type.stderr @@ -0,0 +1,70 @@ +error[E0282]: type annotations needed + --> $DIR/index-expr-ambiguous-type.rs:9:34 + | +LL | let _foo = [1, 2, 3][bad_idx.into()] as i32; + | ^^^^ cannot infer type + +error[E0284]: type annotations needed + --> $DIR/index-expr-ambiguous-type.rs:15:38 + | +LL | let _foo = 0 + [1, 2, 3][bad_idx.into()]; + | ^^^^ cannot infer type + | + = note: cannot satisfy `>::Output == _` + +error[E0283]: type annotations needed + --> $DIR/index-expr-ambiguous-type.rs:21:34 + | +LL | let _foo = [1, 2, 3][bad_idx.into()]; + | ^^^^ + | + = note: the type must implement `From` + = note: required for `u8` to implement `Into<_>` +help: try using a fully qualified path to specify the expected types + | +LL - let _foo = [1, 2, 3][bad_idx.into()]; +LL + let _foo = [1, 2, 3][>::into(bad_idx)]; + | + +error[E0369]: cannot add `_` to `bool` + --> $DIR/index-expr-ambiguous-type.rs:32:21 + | +LL | let _foo = true + [1, 2, 3][bad_idx.into()]; + | ---- ^ ------------------------- _ + | | + | bool + +error[E0284]: type annotations needed + --> $DIR/index-expr-ambiguous-type.rs:38:21 + | +LL | let _foo = 0u64 + [1i32, 2, 3][bad_idx.into()]; + | ^ cannot infer type + | + = note: cannot satisfy `>::Output == _` + +error[E0284]: type annotations needed + --> $DIR/index-expr-ambiguous-type.rs:44:38 + | +LL | let _foo = 1u32 << [0u8][bad_idx.into()]; + | ^^^^ cannot infer type + | + = note: cannot satisfy `>::Output == _` + +error[E0283]: type annotations needed + --> $DIR/index-expr-ambiguous-type.rs:50:45 + | +LL | let _foo = String::new() + [""][bad_idx.into()]; + | ^^^^ + | + = note: the type must implement `From` + = note: required for `u8` to implement `Into<_>` +help: try using a fully qualified path to specify the expected types + | +LL - let _foo = String::new() + [""][bad_idx.into()]; +LL + let _foo = String::new() + [""][>::into(bad_idx)]; + | + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0282, E0283, E0284, E0369. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-21701.rs b/tests/ui/typeck/call-non-fn-type-param.rs similarity index 74% rename from tests/ui/issues/issue-21701.rs rename to tests/ui/typeck/call-non-fn-type-param.rs index bfa03c5e42f8d..993d585bd2185 100644 --- a/tests/ui/issues/issue-21701.rs +++ b/tests/ui/typeck/call-non-fn-type-param.rs @@ -1,3 +1,5 @@ +//! Regression test for . + fn foo(t: U) { let y = t(); //~^ ERROR: expected function, found `U` diff --git a/tests/ui/issues/issue-21701.stderr b/tests/ui/typeck/call-non-fn-type-param.stderr similarity index 89% rename from tests/ui/issues/issue-21701.stderr rename to tests/ui/typeck/call-non-fn-type-param.stderr index 9f1fe7dde735a..f62b571a5d9ad 100644 --- a/tests/ui/issues/issue-21701.stderr +++ b/tests/ui/typeck/call-non-fn-type-param.stderr @@ -1,5 +1,5 @@ error[E0618]: expected function, found `U` - --> $DIR/issue-21701.rs:2:13 + --> $DIR/call-non-fn-type-param.rs:4:13 | LL | fn foo(t: U) { | - `t` has type `U` @@ -9,7 +9,7 @@ LL | let y = t(); | call expression requires function error[E0618]: expected function, found struct `Bar` - --> $DIR/issue-21701.rs:9:13 + --> $DIR/call-non-fn-type-param.rs:11:13 | LL | struct Bar; | ---------- struct `Bar` defined here diff --git a/tests/ui/issues/issue-22781.rs b/tests/ui/typeck/match-boxed-fn-entry-type-inference.rs similarity index 82% rename from tests/ui/issues/issue-22781.rs rename to tests/ui/typeck/match-boxed-fn-entry-type-inference.rs index 36314afd6222d..8d2b1603a6fa6 100644 --- a/tests/ui/issues/issue-22781.rs +++ b/tests/ui/typeck/match-boxed-fn-entry-type-inference.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ check-pass #![allow(unused_variables)] use std::collections::HashMap; diff --git a/tests/ui/issues/issue-22603.rs b/tests/ui/unboxed-closures/fnonce-impl-on-unit-struct.rs similarity index 76% rename from tests/ui/issues/issue-22603.rs rename to tests/ui/unboxed-closures/fnonce-impl-on-unit-struct.rs index 63d5e3b2ae6cb..bee2b91c6b430 100644 --- a/tests/ui/issues/issue-22603.rs +++ b/tests/ui/unboxed-closures/fnonce-impl-on-unit-struct.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ check-pass #![feature(unboxed_closures, fn_traits)] diff --git a/tests/ui/uninhabited/void-branch.rs b/tests/ui/uninhabited/void-branch.rs index b9e1d70382910..0f3e6987fead5 100644 --- a/tests/ui/uninhabited/void-branch.rs +++ b/tests/ui/uninhabited/void-branch.rs @@ -29,4 +29,13 @@ fn with_infallible() { println!() } +fn infallible_with_arg(x: T) -> (T, std::convert::Infallible) { + (x, loop {}) + //~^ ERROR unreachable expression +} + +fn in_if_else(x: String) -> Result { + if x.len() > 0 { Err(infallible_with_arg(x)) } else { Ok(x) } +} + fn main() {} diff --git a/tests/ui/uninhabited/void-branch.stderr b/tests/ui/uninhabited/void-branch.stderr index 15693fc85f4b6..7d886056098aa 100644 --- a/tests/ui/uninhabited/void-branch.stderr +++ b/tests/ui/uninhabited/void-branch.stderr @@ -1,3 +1,18 @@ +error: unreachable expression + --> $DIR/void-branch.rs:33:5 + | +LL | (x, loop {}) + | ^^^^-------^ + | | | + | | any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/void-branch.rs:1:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + error: unreachable expression --> $DIR/void-branch.rs:10:13 | @@ -11,11 +26,6 @@ note: this expression has type `Void`, which is uninhabited | LL | std::mem::uninitialized::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/void-branch.rs:1:9 - | -LL | #![deny(unreachable_code)] - | ^^^^^^^^^^^^^^^^ error: unreachable expression --> $DIR/void-branch.rs:25:9 @@ -31,5 +41,5 @@ note: this expression has type `Infallible`, which is uninhabited LL | infallible(); | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-22874.rs b/tests/ui/unsized/unsized-slice-element.rs similarity index 72% rename from tests/ui/issues/issue-22874.rs rename to tests/ui/unsized/unsized-slice-element.rs index c4500aacb6184..8ac81463be7e4 100644 --- a/tests/ui/issues/issue-22874.rs +++ b/tests/ui/unsized/unsized-slice-element.rs @@ -1,3 +1,5 @@ +//! Regression test for . + struct Table { rows: [[String]], //~^ ERROR the size for values of type diff --git a/tests/ui/issues/issue-22874.stderr b/tests/ui/unsized/unsized-slice-element.stderr similarity index 90% rename from tests/ui/issues/issue-22874.stderr rename to tests/ui/unsized/unsized-slice-element.stderr index 7d5b601ed494f..1707e5f7a2aa5 100644 --- a/tests/ui/issues/issue-22874.stderr +++ b/tests/ui/unsized/unsized-slice-element.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[String]` cannot be known at compilation time - --> $DIR/issue-22874.rs:2:11 + --> $DIR/unsized-slice-element.rs:4:11 | LL | rows: [[String]], | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -8,7 +8,7 @@ LL | rows: [[String]], = note: slice and array elements must have `Sized` type error[E0277]: the size for values of type `[String]` cannot be known at compilation time - --> $DIR/issue-22874.rs:7:6 + --> $DIR/unsized-slice-element.rs:9:6 | LL | &table.rows[0] | ^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/triagebot.toml b/triagebot.toml index d68e4a4882159..9fd7bad75160f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1155,7 +1155,6 @@ otherwise, make sure you bump the `FORMAT_VERSION` constant. """ cc = [ "@CraftSpider", - "@aDotInTheVoid", "@Enselic", "@obi1kenobi", ] @@ -1313,7 +1312,7 @@ Please ensure that if you've changed the output: - It's intentional. - The `FORMAT_VERSION` in `src/librustdoc-json-types` is bumped if necessary. """ -cc = ["@aDotInTheVoid", "@obi1kenobi"] +cc = ["@obi1kenobi"] [mentions."tests/ui/derives/deriving-all-codegen.stdout"] message = "Changes to the code generated for builtin derived traits." @@ -1698,7 +1697,7 @@ dep-bumps = [ "/tests/rustdoc-gui" = ["rustdoc"] "/tests/rustdoc-js-std" = ["rustdoc"] "/tests/rustdoc-js/" = ["rustdoc"] -"/tests/rustdoc-json" = ["@aDotInTheVoid"] +"/tests/rustdoc-json" = ["rustdoc"] "/tests/rustdoc-ui" = ["rustdoc"] "/tests/ui" = ["compiler"] "/tests/ui-fulldeps" = ["compiler"]