Auto merge of #97717 - matthiaskrgr:rollup-lalaii2, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #97446 (Make hir().get_generics and generics_of consistent.)
 - #97656 (Add a suggestion to replace parentheses with angle brackets on associated trait constraint)
 - #97692 (Add `#T-types/nominated` zulip notification)
 - #97696 (Do not ICE when failing to normalize during inlining.)
 - #97702 (Remove useless LocalDefId in ImplTraitContext::Universal.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-06-04 02:10:35 +00:00
commit c3384ea35c
10 changed files with 156 additions and 107 deletions

View File

@ -266,7 +266,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let body_id = let body_id =
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); 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 (generics, decl) = this.lower_generics(generics, id, itctx, |this| {
let ret_id = asyncness.opt_return_id(); let ret_id = asyncness.opt_return_id();
this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_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 // method, it will not be considered an in-band
// lifetime to be added, but rather a reference to a // lifetime to be added, but rather a reference to a
// parent lifetime. // parent lifetime.
let itctx = ImplTraitContext::Universal(self.current_hir_id_owner); let itctx = ImplTraitContext::Universal;
let (generics, (trait_ref, lowered_ty)) = let (generics, (trait_ref, lowered_ty)) =
self.lower_generics(ast_generics, id, itctx, |this| { self.lower_generics(ast_generics, id, itctx, |this| {
let trait_ref = trait_ref.as_ref().map(|trait_ref| { let trait_ref = trait_ref.as_ref().map(|trait_ref| {
@ -655,7 +655,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
kind: match i.kind { kind: match i.kind {
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
let fdec = &sig.decl; let fdec = &sig.decl;
let itctx = ImplTraitContext::Universal(self.current_hir_id_owner); let itctx = ImplTraitContext::Universal;
let (generics, (fn_dec, fn_args)) = let (generics, (fn_dec, fn_args)) =
self.lower_generics(generics, i.id, itctx, |this| { self.lower_generics(generics, i.id, itctx, |this| {
( (
@ -1237,7 +1237,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
is_async: Option<NodeId>, is_async: Option<NodeId>,
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header); 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| { let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
this.lower_fn_decl(&sig.decl, Some(id), kind, is_async) this.lower_fn_decl(&sig.decl, Some(id), kind, is_async)
}); });

View File

@ -46,7 +46,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc; 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 as hir;
use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID}; use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID};
@ -253,7 +253,7 @@ enum ImplTraitContext {
/// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`. /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
/// ///
/// Newly generated parameters should be inserted into the given `Vec`. /// Newly generated parameters should be inserted into the given `Vec`.
Universal(LocalDefId), Universal,
/// Treat `impl Trait` as shorthand for a new opaque type. /// Treat `impl Trait` as shorthand for a new opaque type.
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
@ -857,7 +857,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
itctx: ImplTraitContext, itctx: ImplTraitContext,
) -> hir::TypeBinding<'hir> { ) -> hir::TypeBinding<'hir> {
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
// lower generic arguments of identifier in constraint // lower generic arguments of identifier in constraint
let gen_args = if let Some(ref gen_args) = constraint.gen_args { let gen_args = if let Some(ref gen_args) = constraint.gen_args {
let gen_args_ctor = match gen_args { let gen_args_ctor = match gen_args {
@ -865,12 +864,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0 self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
} }
GenericArgs::Parenthesized(ref data) => { GenericArgs::Parenthesized(ref data) => {
let mut err = self.sess.struct_span_err( self.assoc_ty_contraint_param_error_emit(data);
gen_args.span(),
"parenthesized generic arguments cannot be used in associated type constraints"
);
// FIXME: try to write a suggestion here
err.emit();
self.lower_angle_bracketed_parameter_data( self.lower_angle_bracketed_parameter_data(
&data.as_angle_bracketed_args(), &data.as_angle_bracketed_args(),
ParamMode::Explicit, ParamMode::Explicit,
@ -893,7 +887,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::TypeBindingKind::Equality { term } hir::TypeBindingKind::Equality { term }
} }
AssocConstraintKind::Bound { ref bounds } => { 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. // Piggy-back on the `impl Trait` context to figure out the correct behavior.
let (desugar_to_impl_trait, itctx) = match itctx { let (desugar_to_impl_trait, itctx) = match itctx {
// We are in the return position: // We are in the return position:
@ -913,10 +906,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// so desugar to // so desugar to
// //
// fn foo(x: dyn Iterator<Item = impl Debug>) // fn foo(x: dyn Iterator<Item = impl Debug>)
ImplTraitContext::Universal(parent) if self.is_in_dyn_type => { ImplTraitContext::Universal if self.is_in_dyn_type => (true, itctx),
parent_def_id = parent;
(true, itctx)
}
// In `type Foo = dyn Iterator<Item: Debug>` we desugar to // In `type Foo = dyn Iterator<Item: Debug>` we desugar to
// `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the // `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the
@ -942,6 +932,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
// constructing the HIR for `impl bounds...` and then lowering that. // 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(); let impl_trait_node_id = self.resolver.next_node_id();
self.resolver.create_def( self.resolver.create_def(
parent_def_id, parent_def_id,
@ -984,6 +975,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<params...>`
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( fn lower_generic_arg(
&mut self, &mut self,
arg: &ast::GenericArg, arg: &ast::GenericArg,
@ -1184,12 +1211,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|this| this.lower_param_bounds(bounds, nested_itctx), |this| this.lower_param_bounds(bounds, nested_itctx),
) )
} }
ImplTraitContext::Universal(parent_def_id) => { ImplTraitContext::Universal => {
// Add a definition for the in-band `Param`. // Add a definition for the in-band `Param`.
let def_id = self.resolver.local_def_id(def_node_id); let def_id = self.resolver.local_def_id(def_node_id);
let hir_bounds = self let hir_bounds =
.lower_param_bounds(bounds, ImplTraitContext::Universal(parent_def_id)); self.lower_param_bounds(bounds, ImplTraitContext::Universal);
// Set the name to `impl Bound1 + Bound2`. // Set the name to `impl Bound1 + Bound2`.
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
let param = hir::GenericParam { let param = hir::GenericParam {
@ -1399,10 +1426,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
if fn_node_id.is_some() { if fn_node_id.is_some() {
self.lower_ty_direct( self.lower_ty_direct(&param.ty, ImplTraitContext::Universal)
&param.ty,
ImplTraitContext::Universal(self.current_hir_id_owner),
)
} else { } else {
self.lower_ty_direct( self.lower_ty_direct(
&param.ty, &param.ty,

View File

@ -3004,13 +3004,12 @@ impl ItemKind<'_> {
Some(match *self { Some(match *self {
ItemKind::Fn(_, ref generics, _) ItemKind::Fn(_, ref generics, _)
| ItemKind::TyAlias(_, ref generics) | ItemKind::TyAlias(_, ref generics)
| ItemKind::OpaqueTy(OpaqueTy { | ItemKind::OpaqueTy(OpaqueTy { ref generics, .. })
ref generics, origin: OpaqueTyOrigin::TyAlias, ..
})
| ItemKind::Enum(_, ref generics) | ItemKind::Enum(_, ref generics)
| ItemKind::Struct(_, ref generics) | ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics) | ItemKind::Union(_, ref generics)
| ItemKind::Trait(_, _, ref generics, _, _) | ItemKind::Trait(_, _, ref generics, _, _)
| ItemKind::TraitAlias(ref generics, _)
| ItemKind::Impl(Impl { ref generics, .. }) => generics, | ItemKind::Impl(Impl { ref generics, .. }) => generics,
_ => return None, _ => return None,
}) })
@ -3210,13 +3209,8 @@ impl<'hir> OwnerNode<'hir> {
} }
} }
pub fn generics(&self) -> Option<&'hir Generics<'hir>> { pub fn generics(self) -> Option<&'hir Generics<'hir>> {
match self { Node::generics(self.into())
OwnerNode::TraitItem(TraitItem { generics, .. })
| OwnerNode::ImplItem(ImplItem { generics, .. }) => Some(generics),
OwnerNode::Item(item) => item.kind.generics(),
_ => None,
}
} }
pub fn def_id(self) -> LocalDefId { 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 { match self {
Node::TraitItem(TraitItem { generics, .. }) Node::ForeignItem(ForeignItem {
kind: ForeignItemKind::Fn(_, _, generics), ..
})
| Node::TraitItem(TraitItem { generics, .. })
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics), | Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
Node::Item(item) => item.kind.generics(), Node::Item(item) => item.kind.generics(),
_ => None, _ => None,

View File

@ -361,27 +361,7 @@ impl<'hir> Map<'hir> {
pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> {
let node = self.tcx.hir_owner(id)?; let node = self.tcx.hir_owner(id)?;
match node.node { node.node.generics()
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,
}
} }
pub fn item(self, id: ItemId) -> &'hir Item<'hir> { pub fn item(self, id: ItemId) -> &'hir Item<'hir> {

View File

@ -158,11 +158,13 @@ impl<'tcx> Inliner<'tcx> {
return Err("optimization fuel exhausted"); 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.tcx,
self.param_env, self.param_env,
callee_body.clone(), callee_body.clone(),
); ) else {
return Err("failed to normalize callee body");
};
let old_blocks = caller_body.basic_blocks().next_index(); let old_blocks = caller_body.basic_blocks().next_index();
self.inline_call(caller_body, &callsite, callee_body); self.inline_call(caller_body, &callsite, callee_body);
@ -253,7 +255,7 @@ impl<'tcx> Inliner<'tcx> {
let func_ty = func.ty(caller_body, self.tcx); let func_ty = func.ty(caller_body, self.tcx);
if let ty::FnDef(def_id, substs) = *func_ty.kind() { if let ty::FnDef(def_id, substs) = *func_ty.kind() {
// To resolve an instance its substs have to be fully normalized. // 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 = let callee =
Instance::resolve(self.tcx, self.param_env, def_id, substs).ok().flatten()?; Instance::resolve(self.tcx, self.param_env, def_id, substs).ok().flatten()?;
@ -408,14 +410,17 @@ impl<'tcx> Inliner<'tcx> {
if let ty::FnDef(def_id, substs) = if let ty::FnDef(def_id, substs) =
*callsite.callee.subst_mir(self.tcx, &f.literal.ty()).kind() *callsite.callee.subst_mir(self.tcx, &f.literal.ty()).kind()
{ {
let substs = self.tcx.normalize_erasing_regions(self.param_env, substs); if let Ok(substs) =
if let Ok(Some(instance)) = self.tcx.try_normalize_erasing_regions(self.param_env, substs)
Instance::resolve(self.tcx, self.param_env, def_id, substs)
{ {
if callsite.callee.def_id() == instance.def_id() { if let Ok(Some(instance)) =
return Err("self-recursion"); Instance::resolve(self.tcx, self.param_env, def_id, substs)
} else if self.history.contains(&instance) { {
return Err("already inlined"); 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 // Don't give intrinsics the extra penalty for calls

View File

@ -1588,41 +1588,20 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
_ => None, _ => None,
}; };
let mut opt_self = None;
let mut allow_defaults = false;
let no_generics = hir::Generics::empty(); let no_generics = hir::Generics::empty();
let ast_generics = match node { let ast_generics = node.generics().unwrap_or(&no_generics);
Node::TraitItem(item) => &item.generics, let (opt_self, allow_defaults) = match node {
Node::ImplItem(item) => &item.generics,
Node::Item(item) => { Node::Item(item) => {
match item.kind { match item.kind {
ItemKind::Fn(.., ref generics, _) ItemKind::Trait(..) | ItemKind::TraitAlias(..) => {
| 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, ..) => {
// Add in the self type parameter. // Add in the self type parameter.
// //
// Something of a hack: use the node id for the trait, also as // Something of a hack: use the node id for the trait, also as
// the node id for the Self type parameter. // the node id for the Self type parameter.
let param_id = item.def_id; let opt_self = Some(ty::GenericParamDef {
opt_self = Some(ty::GenericParamDef {
index: 0, index: 0,
name: kw::SelfUpper, name: kw::SelfUpper,
def_id: param_id.to_def_id(), def_id,
pure_wrt_drop: false, pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type {
has_default: false, has_default: false,
@ -1631,21 +1610,17 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
}, },
}); });
allow_defaults = true; (opt_self, true)
generics
} }
ItemKind::TyAlias(..)
_ => &no_generics, | ItemKind::Enum(..)
| ItemKind::Struct(..)
| ItemKind::OpaqueTy(..)
| ItemKind::Union(..) => (None, true),
_ => (None, false),
} }
} }
_ => (None, false),
Node::ForeignItem(item) => match item.kind {
ForeignItemKind::Static(..) => &no_generics,
ForeignItemKind::Fn(_, _, ref generics) => generics,
ForeignItemKind::Type => &no_generics,
},
_ => &no_generics,
}; };
let has_self = opt_self.is_some(); let has_self = opt_self.is_some();

View File

@ -10,4 +10,9 @@ fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
//~| ERROR this associated type takes 0 generic arguments but 1 generic argument //~| ERROR this associated type takes 0 generic arguments but 1 generic argument
//~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments
fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
//~^ ERROR: parenthesized generic arguments cannot be used
//~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments
fn main() {} fn main() {}

View File

@ -9,6 +9,19 @@ error: parenthesized generic arguments cannot be used in associated type constra
| |
LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
| ^^^^^ | ^^^^^
|
help: use angle brackets instead
|
LL | fn foo<'a>(arg: Box<dyn X<Y<'a> = &'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<dyn X<Y() = ()>>) {}
| ^--
| |
| help: remove these parentheses
error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/gat-trait-path-parenthesised-args.rs:7:27 --> $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>; 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<dyn X<Y() = ()>>) {}
| ^ 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<dyn X<Y('a) = ()>>) {}
| ++
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0107`. For more information about this error, try `rustc --explain E0107`.

View File

@ -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<T> {
fn create() -> Self;
}
pub fn oh_no<'a, T>()
where
Wrap<'a>: Associate,
<Wrap<'a> as Associate>::Associated: Create<T>,
{
<Wrap<'a> as Associate>::Associated::create();
}
pub fn main() {}

View File

@ -183,6 +183,16 @@ message_on_add = """\
""" """
message_on_remove = "Issue #{number}'s nomination request has been removed." 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"] [notify-zulip."A-edition-2021"]
required_labels = ["C-bug"] required_labels = ["C-bug"]
zulip_stream = 268952 # #edition 2021 zulip_stream = 268952 # #edition 2021