From 7b6f25a2fa26a156f197fdbf7337145364e4cd83 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 3 Jun 2022 07:08:17 -0700 Subject: [PATCH 1/5] Add `#T-types/nominated` zulip notification --- triagebot.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index e161adcd6e024..25e2c384624e9 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -183,6 +183,16 @@ message_on_add = """\ """ message_on_remove = "Issue #{number}'s nomination request has been removed." +[notify-zulip."I-types-nominated"] +zulip_stream = 326866 # #T-types/nominated +topic = "#{number}: {title}" +message_on_add = """\ +@*T-types* issue #{number} "{title}" has been nominated for team discussion. +""" +message_on_remove = "Issue #{number}'s nomination has been removed. Thanks all for participating!" +message_on_close = "Issue #{number} has been closed. Thanks for participating!" +message_on_reopen = "Issue #{number} has been reopened. Pinging @*T-types*." + [notify-zulip."A-edition-2021"] required_labels = ["C-bug"] zulip_stream = 268952 # #edition 2021 From cd03fe18d8a24434c1510d08c88231fbe9d6b8bf Mon Sep 17 00:00:00 2001 From: EdwinRy Date: Thu, 2 Jun 2022 18:22:25 +0100 Subject: [PATCH 2/5] Suggest replace parentheses with angle brackets --- compiler/rustc_ast_lowering/src/lib.rs | 46 +++++++++++++++---- .../gat-trait-path-parenthesised-args.rs | 5 ++ .../gat-trait-path-parenthesised-args.stderr | 31 ++++++++++++- 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e59bc9aa6b399..2a41aeca8d7ec 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -46,7 +46,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID}; @@ -901,7 +901,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); - // lower generic arguments of identifier in constraint let gen_args = if let Some(ref gen_args) = constraint.gen_args { let gen_args_ctor = match gen_args { @@ -914,12 +913,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .0 } GenericArgs::Parenthesized(ref data) => { - let mut err = self.sess.struct_span_err( - gen_args.span(), - "parenthesized generic arguments cannot be used in associated type constraints" - ); - // FIXME: try to write a suggestion here - err.emit(); + self.assoc_ty_contraint_param_error_emit(data); self.lower_angle_bracketed_parameter_data( &data.as_angle_bracketed_args(), ParamMode::Explicit, @@ -1033,6 +1027,42 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + fn assoc_ty_contraint_param_error_emit(&self, data: &ParenthesizedArgs) -> () { + let mut err = self.sess.struct_span_err( + data.span, + "parenthesized generic arguments cannot be used in associated type constraints", + ); + // Suggest removing empty parentheses: "Trait()" -> "Trait" + if data.inputs.is_empty() { + let parentheses_span = + data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi()); + err.multipart_suggestion( + "remove these parentheses", + vec![(parentheses_span, String::new())], + Applicability::MaybeIncorrect, + ); + } + // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` + else { + // Start of parameters to the 1st argument + let open_param = data.inputs_span.shrink_to_lo().to(data + .inputs + .first() + .unwrap() + .span + .shrink_to_lo()); + // End of last argument to end of parameters + let close_param = + data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi()); + err.multipart_suggestion( + &format!("use angle brackets instead",), + vec![(open_param, String::from("<")), (close_param, String::from(">"))], + Applicability::MaybeIncorrect, + ); + } + err.emit(); + } + fn lower_generic_arg( &mut self, arg: &ast::GenericArg, diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs index f01da8c61ed1d..c55b0530c9da8 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -10,4 +10,9 @@ fn foo<'a>(arg: Box>) {} //~| ERROR this associated type takes 0 generic arguments but 1 generic argument //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + +fn bar<'a>(arg: Box>) {} + //~^ ERROR: parenthesized generic arguments cannot be used + //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + fn main() {} diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr index 6014a02c4d96f..162214063e7d2 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -9,6 +9,19 @@ error: parenthesized generic arguments cannot be used in associated type constra | LL | fn foo<'a>(arg: Box>) {} | ^^^^^ + | +help: use angle brackets instead + | +LL | fn foo<'a>(arg: Box = &'a ()>>) {} + | ~ ~ + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/gat-trait-path-parenthesised-args.rs:14:27 + | +LL | fn bar<'a>(arg: Box>) {} + | ^-- + | | + | help: remove these parentheses error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied --> $DIR/gat-trait-path-parenthesised-args.rs:7:27 @@ -40,6 +53,22 @@ note: associated type defined here, with 0 generic parameters LL | type Y<'a>; | ^ -error: aborting due to 4 previous errors +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:14:27 + | +LL | fn bar<'a>(arg: Box>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-parenthesised-args.rs:4:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn bar<'a>(arg: Box>) {} + | ++ + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0107`. From 2e301c89c714c2126f2221664c3f754541f9b77b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 3 Jun 2022 18:44:46 +0200 Subject: [PATCH 3/5] Do not ICE when failing to normalize during inlining. --- compiler/rustc_mir_transform/src/inline.rs | 25 +++++++++++-------- .../issue-97695-double-trivial-bound.rs | 24 ++++++++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/traits/issue-97695-double-trivial-bound.rs diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 66fb01bd4646d..221f4b18a58a6 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -157,11 +157,13 @@ impl<'tcx> Inliner<'tcx> { return Err("optimization fuel exhausted"); } - let callee_body = callsite.callee.subst_mir_and_normalize_erasing_regions( + let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions( self.tcx, self.param_env, callee_body.clone(), - ); + ) else { + return Err("failed to normalize callee body"); + }; let old_blocks = caller_body.basic_blocks().next_index(); self.inline_call(caller_body, &callsite, callee_body); @@ -252,7 +254,7 @@ impl<'tcx> Inliner<'tcx> { let func_ty = func.ty(caller_body, self.tcx); if let ty::FnDef(def_id, substs) = *func_ty.kind() { // To resolve an instance its substs have to be fully normalized. - let substs = self.tcx.normalize_erasing_regions(self.param_env, substs); + let substs = self.tcx.try_normalize_erasing_regions(self.param_env, substs).ok()?; let callee = Instance::resolve(self.tcx, self.param_env, def_id, substs).ok().flatten()?; @@ -407,14 +409,17 @@ impl<'tcx> Inliner<'tcx> { if let ty::FnDef(def_id, substs) = *callsite.callee.subst_mir(self.tcx, &f.literal.ty()).kind() { - let substs = self.tcx.normalize_erasing_regions(self.param_env, substs); - if let Ok(Some(instance)) = - Instance::resolve(self.tcx, self.param_env, def_id, substs) + if let Ok(substs) = + self.tcx.try_normalize_erasing_regions(self.param_env, substs) { - if callsite.callee.def_id() == instance.def_id() { - return Err("self-recursion"); - } else if self.history.contains(&instance) { - return Err("already inlined"); + if let Ok(Some(instance)) = + Instance::resolve(self.tcx, self.param_env, def_id, substs) + { + if callsite.callee.def_id() == instance.def_id() { + return Err("self-recursion"); + } else if self.history.contains(&instance) { + return Err("already inlined"); + } } } // Don't give intrinsics the extra penalty for calls diff --git a/src/test/ui/traits/issue-97695-double-trivial-bound.rs b/src/test/ui/traits/issue-97695-double-trivial-bound.rs new file mode 100644 index 0000000000000..213605b51142c --- /dev/null +++ b/src/test/ui/traits/issue-97695-double-trivial-bound.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zinline-mir --emit=mir +// build-pass + +pub trait Associate { + type Associated; +} + +pub struct Wrap<'a> { + pub field: &'a i32, +} + +pub trait Create { + fn create() -> Self; +} + +pub fn oh_no<'a, T>() +where + Wrap<'a>: Associate, + as Associate>::Associated: Create, +{ + as Associate>::Associated::create(); +} + +pub fn main() {} From 4120080d66cd5fc9469718b847db3429b6770d65 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 3 Jun 2022 20:17:12 +0200 Subject: [PATCH 4/5] Remove useless LocalDefId in ImplTraitContext::Universal. --- compiler/rustc_ast_lowering/src/item.rs | 8 ++++---- compiler/rustc_ast_lowering/src/lib.rs | 20 +++++++------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 85d3bf66d8e1c..f46d5f77b5a16 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -266,7 +266,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_id = this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); - let itctx = ImplTraitContext::Universal(this.current_hir_id_owner); + let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, id, itctx, |this| { let ret_id = asyncness.opt_return_id(); this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id) @@ -385,7 +385,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // method, it will not be considered an in-band // lifetime to be added, but rather a reference to a // parent lifetime. - let itctx = ImplTraitContext::Universal(self.current_hir_id_owner); + let itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = self.lower_generics(ast_generics, id, itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { @@ -655,7 +655,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: match i.kind { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { let fdec = &sig.decl; - let itctx = ImplTraitContext::Universal(self.current_hir_id_owner); + let itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = self.lower_generics(generics, i.id, itctx, |this| { ( @@ -1237,7 +1237,7 @@ impl<'hir> LoweringContext<'_, 'hir> { is_async: Option, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); - let itctx = ImplTraitContext::Universal(self.current_hir_id_owner); + let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { this.lower_fn_decl(&sig.decl, Some(id), kind, is_async) }); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 96db40cb95b97..ecfada996a65b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -253,7 +253,7 @@ enum ImplTraitContext { /// equivalent to a fresh universal parameter like `fn foo(x: T)`. /// /// Newly generated parameters should be inserted into the given `Vec`. - Universal(LocalDefId), + Universal, /// Treat `impl Trait` as shorthand for a new opaque type. /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually @@ -895,7 +895,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBindingKind::Equality { term } } AssocConstraintKind::Bound { ref bounds } => { - let mut parent_def_id = self.current_hir_id_owner; // Piggy-back on the `impl Trait` context to figure out the correct behavior. let (desugar_to_impl_trait, itctx) = match itctx { // We are in the return position: @@ -915,10 +914,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // so desugar to // // fn foo(x: dyn Iterator) - ImplTraitContext::Universal(parent) if self.is_in_dyn_type => { - parent_def_id = parent; - (true, itctx) - } + ImplTraitContext::Universal if self.is_in_dyn_type => (true, itctx), // In `type Foo = dyn Iterator` we desugar to // `type Foo = dyn Iterator` but we have to override the @@ -944,6 +940,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by // constructing the HIR for `impl bounds...` and then lowering that. + let parent_def_id = self.current_hir_id_owner; let impl_trait_node_id = self.resolver.next_node_id(); self.resolver.create_def( parent_def_id, @@ -1186,12 +1183,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { |this| this.lower_param_bounds(bounds, nested_itctx), ) } - ImplTraitContext::Universal(parent_def_id) => { + ImplTraitContext::Universal => { // Add a definition for the in-band `Param`. let def_id = self.resolver.local_def_id(def_node_id); - let hir_bounds = self - .lower_param_bounds(bounds, ImplTraitContext::Universal(parent_def_id)); + let hir_bounds = + self.lower_param_bounds(bounds, ImplTraitContext::Universal); // Set the name to `impl Bound1 + Bound2`. let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); let param = hir::GenericParam { @@ -1401,10 +1398,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { if fn_node_id.is_some() { - self.lower_ty_direct( - ¶m.ty, - ImplTraitContext::Universal(self.current_hir_id_owner), - ) + self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal) } else { self.lower_ty_direct( ¶m.ty, From 623ea5f5d283dfb57e17e2671bebe63ff7d1e936 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 27 May 2022 09:35:28 +0200 Subject: [PATCH 5/5] Make hir().get_generics and generics_of consistent. --- compiler/rustc_hir/src/hir.rs | 21 +++++----- compiler/rustc_middle/src/hir/map/mod.rs | 22 +--------- compiler/rustc_typeck/src/collect.rs | 51 ++++++------------------ 3 files changed, 23 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b98d434111862..cb2e66090e7c3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3004,13 +3004,12 @@ impl ItemKind<'_> { Some(match *self { ItemKind::Fn(_, ref generics, _) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { - ref generics, origin: OpaqueTyOrigin::TyAlias, .. - }) + | ItemKind::OpaqueTy(OpaqueTy { ref generics, .. }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) | ItemKind::Trait(_, _, ref generics, _, _) + | ItemKind::TraitAlias(ref generics, _) | ItemKind::Impl(Impl { ref generics, .. }) => generics, _ => return None, }) @@ -3210,13 +3209,8 @@ impl<'hir> OwnerNode<'hir> { } } - pub fn generics(&self) -> Option<&'hir Generics<'hir>> { - match self { - OwnerNode::TraitItem(TraitItem { generics, .. }) - | OwnerNode::ImplItem(ImplItem { generics, .. }) => Some(generics), - OwnerNode::Item(item) => item.kind.generics(), - _ => None, - } + pub fn generics(self) -> Option<&'hir Generics<'hir>> { + Node::generics(self.into()) } pub fn def_id(self) -> LocalDefId { @@ -3403,9 +3397,12 @@ impl<'hir> Node<'hir> { } } - pub fn generics(&self) -> Option<&'hir Generics<'hir>> { + pub fn generics(self) -> Option<&'hir Generics<'hir>> { match self { - Node::TraitItem(TraitItem { generics, .. }) + Node::ForeignItem(ForeignItem { + kind: ForeignItemKind::Fn(_, _, generics), .. + }) + | Node::TraitItem(TraitItem { generics, .. }) | Node::ImplItem(ImplItem { generics, .. }) => Some(generics), Node::Item(item) => item.kind.generics(), _ => None, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index aab84b718d406..779af7a382765 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -361,27 +361,7 @@ impl<'hir> Map<'hir> { pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { let node = self.tcx.hir_owner(id)?; - match node.node { - OwnerNode::ImplItem(impl_item) => Some(&impl_item.generics), - OwnerNode::TraitItem(trait_item) => Some(&trait_item.generics), - OwnerNode::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(_, _, generics), - .. - }) - | OwnerNode::Item(Item { - kind: - ItemKind::Fn(_, generics, _) - | ItemKind::TyAlias(_, generics) - | ItemKind::Enum(_, generics) - | ItemKind::Struct(_, generics) - | ItemKind::Union(_, generics) - | ItemKind::Trait(_, _, generics, ..) - | ItemKind::TraitAlias(generics, _) - | ItemKind::Impl(Impl { generics, .. }), - .. - }) => Some(generics), - _ => None, - } + node.node.generics() } pub fn item(self, id: ItemId) -> &'hir Item<'hir> { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 34d107349e7c7..838980e08aa04 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1588,41 +1588,20 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { _ => None, }; - let mut opt_self = None; - let mut allow_defaults = false; - let no_generics = hir::Generics::empty(); - let ast_generics = match node { - Node::TraitItem(item) => &item.generics, - - Node::ImplItem(item) => &item.generics, - + let ast_generics = node.generics().unwrap_or(&no_generics); + let (opt_self, allow_defaults) = match node { Node::Item(item) => { match item.kind { - ItemKind::Fn(.., ref generics, _) - | ItemKind::Impl(hir::Impl { ref generics, .. }) => generics, - - ItemKind::TyAlias(_, ref generics) - | ItemKind::Enum(_, ref generics) - | ItemKind::Struct(_, ref generics) - | ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, .. }) - | ItemKind::Union(_, ref generics) => { - allow_defaults = true; - generics - } - - ItemKind::Trait(_, _, ref generics, ..) - | ItemKind::TraitAlias(ref generics, ..) => { + ItemKind::Trait(..) | ItemKind::TraitAlias(..) => { // Add in the self type parameter. // // Something of a hack: use the node id for the trait, also as // the node id for the Self type parameter. - let param_id = item.def_id; - - opt_self = Some(ty::GenericParamDef { + let opt_self = Some(ty::GenericParamDef { index: 0, name: kw::SelfUpper, - def_id: param_id.to_def_id(), + def_id, pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, @@ -1631,21 +1610,17 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { }, }); - allow_defaults = true; - generics + (opt_self, true) } - - _ => &no_generics, + ItemKind::TyAlias(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::OpaqueTy(..) + | ItemKind::Union(..) => (None, true), + _ => (None, false), } } - - Node::ForeignItem(item) => match item.kind { - ForeignItemKind::Static(..) => &no_generics, - ForeignItemKind::Fn(_, _, ref generics) => generics, - ForeignItemKind::Type => &no_generics, - }, - - _ => &no_generics, + _ => (None, false), }; let has_self = opt_self.is_some();